Repository: sohutv/cachecloud Branch: main Commit: abbd3e3582c5 Files: 1298 Total size: 32.7 MB Directory structure: gitextract_rpc3q3g2/ ├── .github/ │ └── workflows/ │ └── maven.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_CN.md ├── README_EN.md ├── cachecloud-custom/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── sohu/ │ └── cache/ │ ├── DefaultCustomConfiguration.java │ ├── alert/ │ │ ├── EmailComponent.java │ │ ├── WeChatComponent.java │ │ ├── impl/ │ │ │ ├── DefaultEmailComponent.java │ │ │ └── DefaultWeChatComponent.java │ │ └── utils/ │ │ └── AlertUtils.java │ ├── configuration/ │ │ └── DefaultRestTemplateConfig.java │ ├── login/ │ │ ├── LoginComponent.java │ │ └── impl/ │ │ └── DefaultLoginComponent.java │ ├── report/ │ │ ├── ReportDataComponent.java │ │ └── impl/ │ │ └── DefaultReportDataComponent.java │ └── utils/ │ └── EnvCustomUtil.java ├── cachecloud-web/ │ ├── pom.xml │ ├── sql/ │ │ ├── 2.0.sql │ │ ├── 3.0.sql │ │ ├── 3.1.sql │ │ ├── 3.2.sql │ │ ├── 3.3.sql │ │ ├── function-support_custom_password.sql │ │ ├── update 2.0 to 3.0.sql │ │ ├── update 3.0 to 3.1.sql │ │ ├── update 3.1 to 3.2.sql │ │ ├── update 3.2 to 3.3.sql │ │ ├── update-system_resource.sql │ │ └── update2.0-2.1.sql │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── sohu/ │ │ └── cache/ │ │ ├── ApplicationStarter.java │ │ ├── alert/ │ │ │ ├── InstanceAlertService.java │ │ │ ├── bean/ │ │ │ │ └── AlertConfigBaseData.java │ │ │ ├── impl/ │ │ │ │ ├── BaseAlertService.java │ │ │ │ └── InstanceAlertServiceImpl.java │ │ │ └── strategy/ │ │ │ ├── AlertConfigStrategy.java │ │ │ ├── AofCurrentSizeAlertStrategy.java │ │ │ ├── ClientBiggestInputBufAlertStrategy.java │ │ │ ├── ClientLongestOutputListAlertStrategy.java │ │ │ ├── ClusterSlotsOkAlertStrategy.java │ │ │ ├── ClusterStateAlertStrategy.java │ │ │ ├── DefaultCommonAlertStrategy.java │ │ │ ├── InstantaneousOpsPerSecAlertStrategy.java │ │ │ ├── LatestForkUsecAlertStrategy.java │ │ │ ├── MasterSlaveOffsetAlertStrategy.java │ │ │ ├── MemFragmentationRatioAlertStrategy.java │ │ │ ├── MinuteAofDelayedFsyncAlertStrategy.java │ │ │ ├── MinuteRejectedConnectionsAlertStrategy.java │ │ │ ├── MinuteSyncFullAlertStrategy.java │ │ │ ├── MinuteSyncPartialErrAlertStrategy.java │ │ │ ├── MinuteSyncPartialOkAlertStrategy.java │ │ │ ├── MinuteTotalNetInputMBytesAlertStrategy.java │ │ │ ├── MinuteTotalNetOutputMBytesAlertStrategy.java │ │ │ ├── MinuteUsedCpuSysChStrategy.java │ │ │ ├── MinuteUsedCpuSysStrategy.java │ │ │ ├── MinuteUsedCpuUserChStrategy.java │ │ │ ├── MinuteUsedCpuUserStrategy.java │ │ │ └── RdbLastBgsaveStatusAlertStrategy.java │ │ ├── async/ │ │ │ ├── AsyncService.java │ │ │ ├── AsyncThreadPoolFactory.java │ │ │ ├── CounterRejectedExecutionHandler.java │ │ │ ├── KeyCallable.java │ │ │ ├── KeyFuture.java │ │ │ ├── NamedThreadFactory.java │ │ │ └── impl/ │ │ │ └── AsyncServiceImpl.java │ │ ├── client/ │ │ │ ├── AppClientReportConstant.java │ │ │ ├── AppClientReportModel.java │ │ │ ├── command/ │ │ │ │ ├── AppClientCommand.java │ │ │ │ └── AppClientParams.java │ │ │ ├── heartbeat/ │ │ │ │ ├── RedisClientController.java │ │ │ │ ├── RedisClientOldController.java │ │ │ │ └── RedisClientReportDataController.java │ │ │ └── service/ │ │ │ ├── AppClientReportCommandService.java │ │ │ ├── AppClientReportExceptionService.java │ │ │ ├── AppClientService.java │ │ │ ├── AppClientStatisticGatherService.java │ │ │ ├── AppInstanceClientRelationService.java │ │ │ ├── ClientReportExceptionService.java │ │ │ ├── ClientReportInstanceService.java │ │ │ ├── ClientVersionService.java │ │ │ ├── DealClientReportService.java │ │ │ └── impl/ │ │ │ ├── AppClientReportCommandServiceImpl.java │ │ │ ├── AppClientReportExceptionServiceImpl.java │ │ │ ├── AppClientServiceImpl.java │ │ │ ├── AppClientStatisticGatherServiceImpl.java │ │ │ ├── AppInstanceClientRelationServiceImpl.java │ │ │ ├── ClientReportExceptionServiceImpl.java │ │ │ ├── ClientReportInstanceServiceImpl.java │ │ │ ├── ClientVersionServiceImpl.java │ │ │ └── DealClientReportServiceImpl.java │ │ ├── configuration/ │ │ │ ├── AppClientReportBean.java │ │ │ ├── AsynExecutorConfiguration.java │ │ │ ├── AsyncConfiguration.java │ │ │ ├── DataSourceConfig.java │ │ │ ├── FreemakerCustomConfig.java │ │ │ ├── SSHPoolConfig.java │ │ │ └── WebAntPathConfig.java │ │ ├── constant/ │ │ │ ├── AppAuditLogTypeEnum.java │ │ │ ├── AppAuditType.java │ │ │ ├── AppCheckEnum.java │ │ │ ├── AppDataMigrateEnum.java │ │ │ ├── AppDataMigrateResult.java │ │ │ ├── AppDataMigrateStatusEnum.java │ │ │ ├── AppDescEnum.java │ │ │ ├── AppEnvNameEnum.java │ │ │ ├── AppStatusEnum.java │ │ │ ├── AppTopology.java │ │ │ ├── AppUserAlertEnum.java │ │ │ ├── AppUserTypeEnum.java │ │ │ ├── BaseConstant.java │ │ │ ├── ChmodEnum.java │ │ │ ├── ClientStatusEnum.java │ │ │ ├── ClusterOperateResult.java │ │ │ ├── CommandResult.java │ │ │ ├── DataFormatCheckResult.java │ │ │ ├── DiagnosticTypeEnum.java │ │ │ ├── EmptyObjectConstant.java │ │ │ ├── ErrorMessageEnum.java │ │ │ ├── HorizontalResult.java │ │ │ ├── ImportAppResult.java │ │ │ ├── InstanceStatusEnum.java │ │ │ ├── MachineConstant.java │ │ │ ├── MachineInfoEnum.java │ │ │ ├── OperateResult.java │ │ │ ├── PipelineEnum.java │ │ │ ├── RedisConfigTemplateChangeEnum.java │ │ │ ├── RedisConstant.java │ │ │ ├── RedisExcludeCommand.java │ │ │ ├── RedisMigrateToolConstant.java │ │ │ ├── RedisShakeEnum.java │ │ │ ├── ReshardStatusEnum.java │ │ │ ├── SymbolConstant.java │ │ │ ├── TimeDimensionalityEnum.java │ │ │ ├── UserLoginTypeEnum.java │ │ │ └── ValueSizeDistriEnum.java │ │ ├── dao/ │ │ │ ├── AppAlertRecordDao.java │ │ │ ├── AppAuditDao.java │ │ │ ├── AppAuditLogDao.java │ │ │ ├── AppBizDao.java │ │ │ ├── AppCapacityMonitorDao.java │ │ │ ├── AppClientCommandStatisticsDao.java │ │ │ ├── AppClientCostTimeStatDao.java │ │ │ ├── AppClientCostTimeTotalStatDao.java │ │ │ ├── AppClientExceptionStatDao.java │ │ │ ├── AppClientExceptionStatisticsDao.java │ │ │ ├── AppClientLatencyCommandDao.java │ │ │ ├── AppClientReportDataSizeDao.java │ │ │ ├── AppClientStatisticGatherDao.java │ │ │ ├── AppClientVersionDao.java │ │ │ ├── AppDailyDao.java │ │ │ ├── AppDao.java │ │ │ ├── AppDataMigrateStatusDao.java │ │ │ ├── AppImportDao.java │ │ │ ├── AppInstanceClientRelationDao.java │ │ │ ├── AppStatsDao.java │ │ │ ├── AppToUserDao.java │ │ │ ├── AppUserDao.java │ │ │ ├── ConfigDao.java │ │ │ ├── ConfigRestartRecordDao.java │ │ │ ├── DiagnosticTaskRecordDao.java │ │ │ ├── InstanceAlertConfigDao.java │ │ │ ├── InstanceBigKeyDao.java │ │ │ ├── InstanceConfigDao.java │ │ │ ├── InstanceDao.java │ │ │ ├── InstanceFaultDao.java │ │ │ ├── InstanceLatencyHistoryDao.java │ │ │ ├── InstanceReshardProcessDao.java │ │ │ ├── InstanceSlowLogDao.java │ │ │ ├── InstanceStatsDao.java │ │ │ ├── MachineDao.java │ │ │ ├── MachineRelationDao.java │ │ │ ├── MachineRoomDao.java │ │ │ ├── MachineStatsDao.java │ │ │ ├── QuartzDao.java │ │ │ ├── ResourceDao.java │ │ │ ├── ServerStatusDao.java │ │ │ ├── StandardStatsDao.java │ │ │ ├── TaskQueueDao.java │ │ │ ├── TaskStepFlowDao.java │ │ │ └── TaskStepMetaDao.java │ │ ├── entity/ │ │ │ ├── AppAlertRecord.java │ │ │ ├── AppAudit.java │ │ │ ├── AppAuditLog.java │ │ │ ├── AppBiz.java │ │ │ ├── AppCapacityMonitor.java │ │ │ ├── AppCapacityStatisticsResult.java │ │ │ ├── AppClientCommandStatistics.java │ │ │ ├── AppClientCostTimeStat.java │ │ │ ├── AppClientCostTimeTotalStat.java │ │ │ ├── AppClientDataSizeStat.java │ │ │ ├── AppClientExceptionStat.java │ │ │ ├── AppClientExceptionStatistics.java │ │ │ ├── AppClientLatencyCommand.java │ │ │ ├── AppClientStatisticGather.java │ │ │ ├── AppClientValueDistriSimple.java │ │ │ ├── AppClientValueDistriStatTotal.java │ │ │ ├── AppClientVersion.java │ │ │ ├── AppCommandGroup.java │ │ │ ├── AppCommandStats.java │ │ │ ├── AppDailyData.java │ │ │ ├── AppDataMigrateSearch.java │ │ │ ├── AppDataMigrateStatus.java │ │ │ ├── AppDesc.java │ │ │ ├── AppImport.java │ │ │ ├── AppInfoApi.java │ │ │ ├── AppInstanceClientRelation.java │ │ │ ├── AppMonitorStatisticsResult.java │ │ │ ├── AppSearch.java │ │ │ ├── AppStatisticsSearch.java │ │ │ ├── AppStats.java │ │ │ ├── AppToUser.java │ │ │ ├── AppTopMemFragRatio.java │ │ │ ├── AppUser.java │ │ │ ├── BrevityScheduleTask.java │ │ │ ├── ClientInstanceException.java │ │ │ ├── ConfigRestartRecord.java │ │ │ ├── DbPoolStat.java │ │ │ ├── DeployInfo.java │ │ │ ├── DeployInfoStat.java │ │ │ ├── DiagnosticTaskRecord.java │ │ │ ├── InstanceAlertConfig.java │ │ │ ├── InstanceAlertValueResult.java │ │ │ ├── InstanceCommandStats.java │ │ │ ├── InstanceConfig.java │ │ │ ├── InstanceFault.java │ │ │ ├── InstanceInfo.java │ │ │ ├── InstanceLatencyHistory.java │ │ │ ├── InstanceMinuteStats.java │ │ │ ├── InstanceReshardProcess.java │ │ │ ├── InstanceSlotModel.java │ │ │ ├── InstanceSlowLog.java │ │ │ ├── InstanceStats.java │ │ │ ├── LoginResult.java │ │ │ ├── MachineInfo.java │ │ │ ├── MachineInstanceStat.java │ │ │ ├── MachineMemInfo.java │ │ │ ├── MachineMemStatInfo.java │ │ │ ├── MachineRelation.java │ │ │ ├── MachineRoom.java │ │ │ ├── MachineStats.java │ │ │ ├── OperationAlertValueResult.java │ │ │ ├── ParamCount.java │ │ │ ├── RedisVersion.java │ │ │ ├── RedisVersionStat.java │ │ │ ├── ServerInfo.java │ │ │ ├── ServerStatus.java │ │ │ ├── StandardStats.java │ │ │ ├── SystemConfig.java │ │ │ ├── SystemResource.java │ │ │ ├── ThreadPoolStat.java │ │ │ ├── TimeBetween.java │ │ │ ├── TimeDimensionality.java │ │ │ ├── TopologyExamResult.java │ │ │ └── TriggerInfo.java │ │ ├── exception/ │ │ │ ├── IllegalParamException.java │ │ │ └── SSHException.java │ │ ├── inspect/ │ │ │ ├── InspectHandler.java │ │ │ ├── InspectParamEnum.java │ │ │ ├── Inspector.java │ │ │ ├── InspectorJob.java │ │ │ └── impl/ │ │ │ ├── AbstractInspectHandler.java │ │ │ ├── AppClientConnInspector.java │ │ │ ├── AppHitPrecentInspector.java │ │ │ ├── AppInspectHandler.java │ │ │ ├── AppMemInspector.java │ │ │ ├── HostInspectHandler.java │ │ │ ├── InstanceRunInspector.java │ │ │ ├── InstanceStateInspector.java │ │ │ └── RedisIsolationPersistenceInspector.java │ │ ├── interceptor/ │ │ │ ├── AppAndInstanceAuthorityInterceptor.java │ │ │ ├── FrontUserLoginInterceptor.java │ │ │ └── ManageUserLoginInterceptor.java │ │ ├── log/ │ │ │ ├── CustLogAppenderInit.java │ │ │ └── TaskFlowRecordAppender.java │ │ ├── machine/ │ │ │ ├── MachineCenter.java │ │ │ ├── MachineDeployCenter.java │ │ │ ├── MachineProperty.java │ │ │ ├── PortGenerator.java │ │ │ └── impl/ │ │ │ ├── MachineCenterImpl.java │ │ │ └── MachineDeployCenterImpl.java │ │ ├── protocol/ │ │ │ ├── MachineProtocol.java │ │ │ └── RedisProtocol.java │ │ ├── redis/ │ │ │ ├── AssistRedisService.java │ │ │ ├── RedisCenter.java │ │ │ ├── RedisClusterNode.java │ │ │ ├── RedisClusterReshard.java │ │ │ ├── RedisConfigTemplateService.java │ │ │ ├── RedisDeployCenter.java │ │ │ ├── enums/ │ │ │ │ ├── AppTypeToAlertTypeEnum.java │ │ │ │ ├── DirEnum.java │ │ │ │ ├── InstanceAlertCheckCycleEnum.java │ │ │ │ ├── InstanceAlertCompareTypeEnum.java │ │ │ │ ├── InstanceAlertStatusEnum.java │ │ │ │ ├── InstanceAlertTypeEnum.java │ │ │ │ ├── RedisAlertConfigEnum.java │ │ │ │ ├── RedisClusterConfigEnum.java │ │ │ │ ├── RedisClusterInfoEnum.java │ │ │ │ ├── RedisConfigEnum.java │ │ │ │ ├── RedisInfoEnum.java │ │ │ │ ├── RedisReadOnlyCommandEnum.java │ │ │ │ └── RedisSentinelConfigEnum.java │ │ │ ├── impl/ │ │ │ │ ├── AssistRedisServiceImpl.java │ │ │ │ ├── RedisCenterImpl.java │ │ │ │ ├── RedisConfigTemplateServiceImpl.java │ │ │ │ └── RedisDeployCenterImpl.java │ │ │ └── util/ │ │ │ ├── AuthUtil.java │ │ │ ├── ClusterNodeInformation.java │ │ │ ├── ClusterNodeInformationParser.java │ │ │ ├── Command.java │ │ │ ├── JedisUtil.java │ │ │ ├── Keyword.java │ │ │ ├── LatencyHistoryItem.java │ │ │ ├── LatencyItem.java │ │ │ ├── PipelineUtil.java │ │ │ ├── ProtostuffSerializer.java │ │ │ └── VO.java │ │ ├── schedule/ │ │ │ ├── SchedulerCenter.java │ │ │ ├── TriggerCenter.java │ │ │ ├── brevity/ │ │ │ │ ├── BrevityScheduleType.java │ │ │ │ ├── BrevityScheduler.java │ │ │ │ ├── BrevitySchedulerJob.java │ │ │ │ ├── DispatcherBrevityScheduleJob.java │ │ │ │ └── impl/ │ │ │ │ ├── BrevitySchedulerImpl.java │ │ │ │ └── BrevitySchedulerImpl_Original.java │ │ │ ├── impl/ │ │ │ │ ├── SchedulerCenterImpl.java │ │ │ │ └── TriggerCenterImpl.java │ │ │ └── jobs/ │ │ │ ├── AppCapacityMonitorJob.java │ │ │ ├── AppDailyJob.java │ │ │ ├── AppPersistenceCheckJob.java │ │ │ ├── CacheBaseJob.java │ │ │ ├── CleanupDayAppClientStatJob.java │ │ │ ├── CleanupDayDimensionalityJob.java │ │ │ ├── CleanupMinuteDimensionalityJob.java │ │ │ ├── ExpAppsDailyJob.java │ │ │ ├── GatherAppClientStatisticsJob.java │ │ │ ├── GatherAppClientStatisticsServerCmdCountJob.java │ │ │ ├── InstanceAlertValueJob.java │ │ │ ├── InstanceStatJob.java │ │ │ ├── ReviseAppClientStatisGatherJob.java │ │ │ ├── SystemConfigRefreshJob.java │ │ │ └── TaskExecuteJob.java │ │ ├── server/ │ │ │ ├── ServerStatusCollector.java │ │ │ ├── data/ │ │ │ │ ├── CPU.java │ │ │ │ ├── Connection.java │ │ │ │ ├── Disk.java │ │ │ │ ├── LineParser.java │ │ │ │ ├── Load.java │ │ │ │ ├── Memory.java │ │ │ │ ├── Net.java │ │ │ │ ├── OS.java │ │ │ │ ├── OSInfo.java │ │ │ │ └── Server.java │ │ │ └── nmon/ │ │ │ └── NMONService.java │ │ ├── ssh/ │ │ │ ├── SSHClient.java │ │ │ ├── SSHMachineInfo.java │ │ │ ├── SSHService.java │ │ │ ├── SSHServiceImpl.java │ │ │ ├── SSHSessionPooledObjectFactory.java │ │ │ ├── SSHTemplate.java │ │ │ └── SSHUtil.java │ │ ├── stats/ │ │ │ ├── admin/ │ │ │ │ ├── CoreAppsStatCenter.java │ │ │ │ └── impl/ │ │ │ │ └── CoreAppsStatCenterImpl.java │ │ │ ├── app/ │ │ │ │ ├── AppDailyDataCenter.java │ │ │ │ ├── AppDataMigrateCenter.java │ │ │ │ ├── AppDeployCenter.java │ │ │ │ ├── AppPersistenceCheckCenter.java │ │ │ │ ├── AppStatsCenter.java │ │ │ │ ├── ImportAppCenter.java │ │ │ │ ├── RedisMigrateToolCenter.java │ │ │ │ ├── RedisShakeCenter.java │ │ │ │ └── impl/ │ │ │ │ ├── AppDailyDataCenterImpl.java │ │ │ │ ├── AppDataMigrateCenterImpl.java │ │ │ │ ├── AppDeployCenterImpl.java │ │ │ │ ├── AppPersistenceCheckCenterImpl.java │ │ │ │ ├── AppStatsCenterImpl.java │ │ │ │ ├── ImportAppCenterImpl.java │ │ │ │ ├── RedisMigrateToolCenterImpl.java │ │ │ │ └── RedisShakeCenterImpl.java │ │ │ └── instance/ │ │ │ ├── InstanceAlertConfigService.java │ │ │ ├── InstanceDeployCenter.java │ │ │ ├── InstanceStatsCenter.java │ │ │ └── impl/ │ │ │ ├── InstanceAlertConfigServiceImpl.java │ │ │ ├── InstanceDeployCenterImpl.java │ │ │ └── InstanceStatsCenterImpl.java │ │ ├── swagger/ │ │ │ └── Swagger2.java │ │ ├── task/ │ │ │ ├── BaseTask.java │ │ │ ├── TaskService.java │ │ │ ├── constant/ │ │ │ │ ├── IdleTimeDistriEnum.java │ │ │ │ ├── InstanceInfoEnum.java │ │ │ │ ├── InstanceRoleEnum.java │ │ │ │ ├── MachineExamContants.java │ │ │ │ ├── MachineSyncEnum.java │ │ │ │ ├── PikaNode.java │ │ │ │ ├── PushEnum.java │ │ │ │ ├── RedisDataStructureTypeEnum.java │ │ │ │ ├── ResourceEnum.java │ │ │ │ ├── ScanCleanConstants.java │ │ │ │ ├── TaskConstants.java │ │ │ │ ├── TaskQueueEnum.java │ │ │ │ ├── TaskStepFlowEnum.java │ │ │ │ ├── TopoloyExamContants.java │ │ │ │ ├── TtlTimeDistriEnum.java │ │ │ │ └── ValueSizeDistriEnum.java │ │ │ ├── entity/ │ │ │ │ ├── InstanceBigKey.java │ │ │ │ ├── NutCrackerNode.java │ │ │ │ ├── RedisSentinelNode.java │ │ │ │ ├── RedisServerNode.java │ │ │ │ ├── TaskQueue.java │ │ │ │ ├── TaskSearch.java │ │ │ │ ├── TaskStepFlow.java │ │ │ │ └── TaskStepMeta.java │ │ │ ├── impl/ │ │ │ │ └── TaskServiceImpl.java │ │ │ ├── tasks/ │ │ │ │ ├── AppKeyAnalysisTask.java │ │ │ │ ├── MachineSyncTask.java │ │ │ │ ├── OffLineAppTask.java │ │ │ │ ├── RedisClusterAppDeployTask.java │ │ │ │ ├── RedisSentinelAppDeployTask.java │ │ │ │ ├── RedisStandaloneAppDeployTask.java │ │ │ │ ├── TwemproxyAppDeployTask.java │ │ │ │ ├── analysis/ │ │ │ │ │ ├── RedisServerBigKeyAnalysisTask.java │ │ │ │ │ ├── RedisServerIdleKeyAnalysisTask.java │ │ │ │ │ ├── RedisServerKeyTtlAnalysisTask.java │ │ │ │ │ ├── RedisServerKeyTypeAnalysisTask.java │ │ │ │ │ └── RedisServerKeyValueAnalysisTask.java │ │ │ │ ├── daily/ │ │ │ │ │ ├── MachineExamTask.java │ │ │ │ │ └── TopologyExamTask.java │ │ │ │ ├── diagnosticTask/ │ │ │ │ │ ├── AppBigKeyTask.java │ │ │ │ │ ├── AppDelKeyTask.java │ │ │ │ │ ├── AppHotKeyTask.java │ │ │ │ │ ├── AppIdleKeyTask.java │ │ │ │ │ ├── AppScanCleanKeyTask.java │ │ │ │ │ ├── AppScanKeyTask.java │ │ │ │ │ ├── AppSlotAnalysisTask.java │ │ │ │ │ ├── InstanceBigKeyTask.java │ │ │ │ │ ├── InstanceDelKeyTask.java │ │ │ │ │ ├── InstanceHotKeyTask.java │ │ │ │ │ ├── InstanceIdleKeyTask.java │ │ │ │ │ ├── InstanceScanCleanKeyTask.java │ │ │ │ │ ├── InstanceScanKeyTask.java │ │ │ │ │ └── InstanceSlotAnalysisTask.java │ │ │ │ ├── install/ │ │ │ │ │ ├── RedisSentinelInstallTask.java │ │ │ │ │ └── RedisServerInstallTask.java │ │ │ │ └── resource/ │ │ │ │ └── PackCompileTask.java │ │ │ └── util/ │ │ │ ├── AppWechatUtil.java │ │ │ └── SpringContextUtil.java │ │ ├── util/ │ │ │ ├── AppKeyUtil.java │ │ │ ├── ConstUtils.java │ │ │ ├── DemoCodeUtil.java │ │ │ ├── EnvUtil.java │ │ │ ├── IdempotentConfirmer.java │ │ │ ├── IntegerUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── MD5Util.java │ │ │ ├── MapUtil.java │ │ │ ├── NMONFileFactory.java │ │ │ ├── NamedArg.java │ │ │ ├── NumberUtil.java │ │ │ ├── OSFactory.java │ │ │ ├── ObjectConvert.java │ │ │ ├── Pair.java │ │ │ ├── PandectUtil.java │ │ │ ├── RedisConstUtils.java │ │ │ ├── ScheduleUtil.java │ │ │ ├── StringUtil.java │ │ │ └── TypeUtil.java │ │ └── web/ │ │ ├── chart/ │ │ │ ├── key/ │ │ │ │ └── ChartKeysUtil.java │ │ │ └── model/ │ │ │ ├── AreaChartEntity.java │ │ │ ├── ChartEntity.java │ │ │ ├── HighchartDoublePoint.java │ │ │ ├── HighchartPoint.java │ │ │ ├── SimpleChartData.java │ │ │ └── SplineChartEntity.java │ │ ├── controller/ │ │ │ ├── AnalysisController.java │ │ │ ├── AppAutomationApiController.java │ │ │ ├── AppClientDataShowController.java │ │ │ ├── AppController.java │ │ │ ├── AppDataMigrateController.java │ │ │ ├── AppManageController.java │ │ │ ├── AppMigrateController.java │ │ │ ├── AppScrollRestartController.java │ │ │ ├── AppStatController.java │ │ │ ├── AppToolController.java │ │ │ ├── BaseController.java │ │ │ ├── ClientManageController.java │ │ │ ├── ConfigManageController.java │ │ │ ├── ExamToolController.java │ │ │ ├── ImportAppController.java │ │ │ ├── IndexController.java │ │ │ ├── InstanceAlertValueController.java │ │ │ ├── InstanceController.java │ │ │ ├── InstanceManageController.java │ │ │ ├── InstanceOperationController.java │ │ │ ├── LoginController.java │ │ │ ├── MachineManageController.java │ │ │ ├── NoticeManageController.java │ │ │ ├── OperationController.java │ │ │ ├── QuartzManageController.java │ │ │ ├── RedisConfigTemplateController.java │ │ │ ├── RedisVersionUpgradeController.java │ │ │ ├── ResourceController.java │ │ │ ├── ServerController.java │ │ │ ├── TaskController.java │ │ │ ├── TotalManageController.java │ │ │ ├── TriggerController.java │ │ │ ├── UserController.java │ │ │ ├── UserManageController.java │ │ │ ├── WebResourceController.java │ │ │ └── WikiController.java │ │ ├── enums/ │ │ │ ├── AdminEnum.java │ │ │ ├── AlertTypeEnum.java │ │ │ ├── AppImportStatusEnum.java │ │ │ ├── AppOrderByEnum.java │ │ │ ├── AppTypeEnum.java │ │ │ ├── BooleanEnum.java │ │ │ ├── CheckEnum.java │ │ │ ├── ClientTypeEnum.java │ │ │ ├── CompareTypeEnum.java │ │ │ ├── ConfigRestartOperateEnum.java │ │ │ ├── DeployInfoEnum.java │ │ │ ├── ExamToolEnum.java │ │ │ ├── ImportantLevelTypeEnum.java │ │ │ ├── LoginEnum.java │ │ │ ├── MachineMemoryDistriEnum.java │ │ │ ├── MachineTaskEnum.java │ │ │ ├── MasterSlaveExistEnum.java │ │ │ ├── NodeEnum.java │ │ │ ├── PodStatusEnum.java │ │ │ ├── RedisOperateEnum.java │ │ │ ├── RedisVersionEnum.java │ │ │ ├── RestartStatusEnum.java │ │ │ ├── SshAuthTypeEnum.java │ │ │ ├── StatEnum.java │ │ │ ├── SuccessEnum.java │ │ │ ├── TriggerStateEnum.java │ │ │ ├── UseTypeEnum.java │ │ │ └── WebClients.java │ │ ├── service/ │ │ │ ├── AppAlertRecordService.java │ │ │ ├── AppAutoCapacityService.java │ │ │ ├── AppImportService.java │ │ │ ├── AppRedisCommandCheckService.java │ │ │ ├── AppRedisConfigCheckService.java │ │ │ ├── AppScrollRestartService.java │ │ │ ├── AppService.java │ │ │ ├── ConfigService.java │ │ │ ├── DiagnosticToolService.java │ │ │ ├── InstancePortService.java │ │ │ ├── MigrateService.java │ │ │ ├── ResourceService.java │ │ │ ├── ServerDataService.java │ │ │ ├── ToolService.java │ │ │ ├── UserLoginStatusService.java │ │ │ ├── UserService.java │ │ │ ├── WebClientComponent.java │ │ │ └── impl/ │ │ │ ├── AppAlertRecordServiceImpl.java │ │ │ ├── AppAutoCapacityServiceImpl.java │ │ │ ├── AppImportServiceImpl.java │ │ │ ├── AppRedisCommandCheckServiceImpl.java │ │ │ ├── AppRedisConfigCheckServiceImpl.java │ │ │ ├── AppScrollRestartServiceImpl.java │ │ │ ├── AppServiceImpl.java │ │ │ ├── ConfigServiceImpl.java │ │ │ ├── DiagnosticToolServiceImpl.java │ │ │ ├── InstancePortServiceImpl.java │ │ │ ├── MigrateServiceImpl.java │ │ │ ├── ResourceServiceImpl.java │ │ │ ├── ServerDataServiceImpl.java │ │ │ ├── ToolServiceImpl.java │ │ │ ├── UserLoginStatusCookieServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ ├── util/ │ │ │ ├── AESCoder.java │ │ │ ├── AppEmailUtil.java │ │ │ ├── DateUtil.java │ │ │ ├── FreemakerUtils.java │ │ │ ├── IpUtil.java │ │ │ ├── Page.java │ │ │ ├── SimpleFileUtil.java │ │ │ └── WebUtil.java │ │ └── vo/ │ │ ├── AlertConfig.java │ │ ├── AppDetailVO.java │ │ ├── AppRedisCommandCheckResult.java │ │ ├── AppRedisCommandCheckVo.java │ │ ├── AppRedisConfigCheckResult.java │ │ ├── AppRedisConfigCheckVo.java │ │ ├── AppRedisConfigVo.java │ │ ├── AppUserVo.java │ │ ├── ExecuteResult.java │ │ ├── GeneralResponse.java │ │ ├── InstanceRedisCommandCheckResult.java │ │ ├── InstanceRedisConfigCheckResult.java │ │ ├── MachineEnv.java │ │ ├── MachineStatsVo.java │ │ ├── MasterSlaveGroupBo.java │ │ ├── RedisClusterNode.java │ │ ├── RedisCommandCheckResult.java │ │ ├── RedisConfigCheckResult.java │ │ ├── RedisConfigVo.java │ │ ├── RedisInfo.java │ │ └── RedisSlowLog.java │ ├── resources/ │ │ ├── application-local.yml │ │ ├── application-online.yml │ │ ├── application-open.yml │ │ ├── application-test.yml │ │ ├── application.yml │ │ ├── assets/ │ │ │ ├── css/ │ │ │ │ ├── buttons.css │ │ │ │ ├── common.css │ │ │ │ ├── custom.css │ │ │ │ ├── githubmd.css │ │ │ │ ├── jobindex.css │ │ │ │ └── mem-cloud.css │ │ │ ├── dist/ │ │ │ │ ├── css/ │ │ │ │ │ ├── adminlte.css │ │ │ │ │ └── alt/ │ │ │ │ │ ├── adminlte.components.css │ │ │ │ │ ├── adminlte.core.css │ │ │ │ │ ├── adminlte.extra-components.css │ │ │ │ │ ├── adminlte.light.css │ │ │ │ │ ├── adminlte.pages.css │ │ │ │ │ └── adminlte.plugins.css │ │ │ │ └── js/ │ │ │ │ ├── adminlte.js │ │ │ │ └── demo.js │ │ │ ├── js/ │ │ │ │ ├── custom/ │ │ │ │ │ ├── appDeploy.js │ │ │ │ │ ├── appDetail.js │ │ │ │ │ ├── appInit.js │ │ │ │ │ ├── auditManage.js │ │ │ │ │ ├── getInstancesByAppId.js │ │ │ │ │ ├── jquery-console.js │ │ │ │ │ ├── machineManage.js │ │ │ │ │ ├── myPopover.js │ │ │ │ │ └── userManage.js │ │ │ │ ├── main.js │ │ │ │ └── myhighchart.js │ │ │ ├── plugins/ │ │ │ │ ├── fontawesome-free/ │ │ │ │ │ └── css/ │ │ │ │ │ ├── all.css │ │ │ │ │ ├── brands.css │ │ │ │ │ ├── fontawesome.css │ │ │ │ │ ├── regular.css │ │ │ │ │ ├── solid.css │ │ │ │ │ ├── svg-with-js.css │ │ │ │ │ └── v4-shims.css │ │ │ │ └── overlayScrollbars/ │ │ │ │ ├── css/ │ │ │ │ │ └── OverlayScrollbars.css │ │ │ │ └── js/ │ │ │ │ ├── OverlayScrollbars.js │ │ │ │ └── jquery.overlayScrollbars.js │ │ │ └── vendor/ │ │ │ ├── apexcharts/ │ │ │ │ ├── apexcharts.amd.js │ │ │ │ ├── apexcharts.common.js │ │ │ │ ├── apexcharts.css │ │ │ │ ├── apexcharts.esm.js │ │ │ │ ├── apexcharts.js │ │ │ │ └── locales/ │ │ │ │ ├── ar.json │ │ │ │ ├── ca.json │ │ │ │ ├── cs.json │ │ │ │ ├── de.json │ │ │ │ ├── el.json │ │ │ │ ├── en.json │ │ │ │ ├── es.json │ │ │ │ ├── et.json │ │ │ │ ├── fa.json │ │ │ │ ├── fi.json │ │ │ │ ├── fr.json │ │ │ │ ├── he.json │ │ │ │ ├── hi.json │ │ │ │ ├── hr.json │ │ │ │ ├── hu.json │ │ │ │ ├── hy.json │ │ │ │ ├── id.json │ │ │ │ ├── it.json │ │ │ │ ├── ja.json │ │ │ │ ├── ka.json │ │ │ │ ├── ko.json │ │ │ │ ├── lt.json │ │ │ │ ├── lv.json │ │ │ │ ├── nb.json │ │ │ │ ├── nl.json │ │ │ │ ├── pl.json │ │ │ │ ├── pt-br.json │ │ │ │ ├── pt.json │ │ │ │ ├── rs.json │ │ │ │ ├── ru.json │ │ │ │ ├── se.json │ │ │ │ ├── sk.json │ │ │ │ ├── sl.json │ │ │ │ ├── sq.json │ │ │ │ ├── th.json │ │ │ │ ├── tr.json │ │ │ │ ├── ua.json │ │ │ │ ├── zh-cn.json │ │ │ │ └── zh-tw.json │ │ │ ├── bootstrap/ │ │ │ │ ├── css/ │ │ │ │ │ ├── bootstrap-grid.css │ │ │ │ │ ├── bootstrap-grid.rtl.css │ │ │ │ │ ├── bootstrap-reboot.css │ │ │ │ │ ├── bootstrap-reboot.rtl.css │ │ │ │ │ ├── bootstrap-utilities.css │ │ │ │ │ ├── bootstrap-utilities.rtl.css │ │ │ │ │ ├── bootstrap.css │ │ │ │ │ └── bootstrap.rtl.css │ │ │ │ └── js/ │ │ │ │ ├── bootstrap.bundle.js │ │ │ │ ├── bootstrap.esm.js │ │ │ │ └── bootstrap.js │ │ │ ├── bootstrap-icons/ │ │ │ │ ├── bootstrap-icons.css │ │ │ │ ├── bootstrap-icons.json │ │ │ │ └── bootstrap-icons.scss │ │ │ ├── bootstrap-select/ │ │ │ │ ├── bootstrap-select.css │ │ │ │ └── bootstrap-select.js │ │ │ ├── boxicons/ │ │ │ │ └── css/ │ │ │ │ ├── animations.css │ │ │ │ ├── boxicons.css │ │ │ │ └── transformations.css │ │ │ ├── chart.js/ │ │ │ │ ├── chart.cjs │ │ │ │ ├── chart.js │ │ │ │ ├── chart.umd.js │ │ │ │ ├── chunks/ │ │ │ │ │ ├── helpers.segment.cjs │ │ │ │ │ └── helpers.segment.js │ │ │ │ ├── controllers/ │ │ │ │ │ ├── controller.bar.d.ts │ │ │ │ │ ├── controller.bubble.d.ts │ │ │ │ │ ├── controller.doughnut.d.ts │ │ │ │ │ ├── controller.line.d.ts │ │ │ │ │ ├── controller.pie.d.ts │ │ │ │ │ ├── controller.polarArea.d.ts │ │ │ │ │ ├── controller.radar.d.ts │ │ │ │ │ ├── controller.scatter.d.ts │ │ │ │ │ └── index.d.ts │ │ │ │ ├── core/ │ │ │ │ │ ├── core.adapters.d.ts │ │ │ │ │ ├── core.animation.d.ts │ │ │ │ │ ├── core.animations.d.ts │ │ │ │ │ ├── core.animations.defaults.d.ts │ │ │ │ │ ├── core.animator.d.ts │ │ │ │ │ ├── core.config.d.ts │ │ │ │ │ ├── core.controller.d.ts │ │ │ │ │ ├── core.datasetController.d.ts │ │ │ │ │ ├── core.defaults.d.ts │ │ │ │ │ ├── core.element.d.ts │ │ │ │ │ ├── core.interaction.d.ts │ │ │ │ │ ├── core.layouts.d.ts │ │ │ │ │ ├── core.layouts.defaults.d.ts │ │ │ │ │ ├── core.plugins.d.ts │ │ │ │ │ ├── core.registry.d.ts │ │ │ │ │ ├── core.scale.autoskip.d.ts │ │ │ │ │ ├── core.scale.d.ts │ │ │ │ │ ├── core.scale.defaults.d.ts │ │ │ │ │ ├── core.ticks.d.ts │ │ │ │ │ ├── core.typedRegistry.d.ts │ │ │ │ │ └── index.d.ts │ │ │ │ ├── elements/ │ │ │ │ │ ├── element.arc.d.ts │ │ │ │ │ ├── element.bar.d.ts │ │ │ │ │ ├── element.line.d.ts │ │ │ │ │ ├── element.point.d.ts │ │ │ │ │ └── index.d.ts │ │ │ │ ├── helpers/ │ │ │ │ │ ├── helpers.canvas.d.ts │ │ │ │ │ ├── helpers.collection.d.ts │ │ │ │ │ ├── helpers.color.d.ts │ │ │ │ │ ├── helpers.config.d.ts │ │ │ │ │ ├── helpers.core.d.ts │ │ │ │ │ ├── helpers.curve.d.ts │ │ │ │ │ ├── helpers.dom.d.ts │ │ │ │ │ ├── helpers.easing.d.ts │ │ │ │ │ ├── helpers.extras.d.ts │ │ │ │ │ ├── helpers.interpolation.d.ts │ │ │ │ │ ├── helpers.intl.d.ts │ │ │ │ │ ├── helpers.math.d.ts │ │ │ │ │ ├── helpers.options.d.ts │ │ │ │ │ ├── helpers.rtl.d.ts │ │ │ │ │ ├── helpers.segment.d.ts │ │ │ │ │ ├── index.d.ts │ │ │ │ │ └── types.d.ts │ │ │ │ ├── helpers.cjs │ │ │ │ ├── helpers.js │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.umd.d.ts │ │ │ │ ├── platform/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── platform.base.d.ts │ │ │ │ │ ├── platform.basic.d.ts │ │ │ │ │ └── platform.dom.d.ts │ │ │ │ ├── plugins/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── plugin.colors.d.ts │ │ │ │ │ ├── plugin.decimation.d.ts │ │ │ │ │ ├── plugin.filler/ │ │ │ │ │ │ ├── filler.drawing.d.ts │ │ │ │ │ │ ├── filler.helper.d.ts │ │ │ │ │ │ ├── filler.options.d.ts │ │ │ │ │ │ ├── filler.segment.d.ts │ │ │ │ │ │ ├── filler.target.d.ts │ │ │ │ │ │ ├── filler.target.stack.d.ts │ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ │ └── simpleArc.d.ts │ │ │ │ │ ├── plugin.legend.d.ts │ │ │ │ │ ├── plugin.subtitle.d.ts │ │ │ │ │ ├── plugin.title.d.ts │ │ │ │ │ └── plugin.tooltip.d.ts │ │ │ │ ├── scales/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── scale.category.d.ts │ │ │ │ │ ├── scale.linear.d.ts │ │ │ │ │ ├── scale.linearbase.d.ts │ │ │ │ │ ├── scale.logarithmic.d.ts │ │ │ │ │ ├── scale.radialLinear.d.ts │ │ │ │ │ ├── scale.time.d.ts │ │ │ │ │ └── scale.timeseries.d.ts │ │ │ │ ├── types/ │ │ │ │ │ ├── animation.d.ts │ │ │ │ │ ├── basic.d.ts │ │ │ │ │ ├── color.d.ts │ │ │ │ │ ├── geometric.d.ts │ │ │ │ │ ├── helpers/ │ │ │ │ │ │ ├── helpers.canvas.d.ts │ │ │ │ │ │ ├── helpers.segment.d.ts │ │ │ │ │ │ └── index.d.ts │ │ │ │ │ ├── index.d.ts │ │ │ │ │ ├── layout.d.ts │ │ │ │ │ └── utils.d.ts │ │ │ │ └── types.d.ts │ │ │ ├── clipboard/ │ │ │ │ └── clipboard.js │ │ │ ├── data-tables/ │ │ │ │ ├── css/ │ │ │ │ │ ├── dataTables.bootstrap.css │ │ │ │ │ ├── dataTables.bootstrap4.css │ │ │ │ │ ├── dataTables.bootstrap5.css │ │ │ │ │ ├── dataTables.bulma.css │ │ │ │ │ ├── dataTables.dataTables.css │ │ │ │ │ ├── dataTables.foundation.css │ │ │ │ │ ├── dataTables.jqueryui.css │ │ │ │ │ ├── dataTables.semanticui.css │ │ │ │ │ └── jquery.dataTables.css │ │ │ │ ├── datatables.css │ │ │ │ ├── datatables.js │ │ │ │ ├── js/ │ │ │ │ │ ├── dataTables.bootstrap.js │ │ │ │ │ ├── dataTables.bootstrap4.js │ │ │ │ │ ├── dataTables.bootstrap5.js │ │ │ │ │ ├── dataTables.bulma.js │ │ │ │ │ ├── dataTables.dataTables.js │ │ │ │ │ ├── dataTables.foundation.js │ │ │ │ │ ├── dataTables.jqueryui.js │ │ │ │ │ ├── dataTables.semanticui.js │ │ │ │ │ └── jquery.dataTables.js │ │ │ │ └── scrolling.js │ │ │ ├── echarts/ │ │ │ │ ├── echarts.common.js │ │ │ │ ├── echarts.esm.js │ │ │ │ ├── echarts.js │ │ │ │ ├── echarts.simple.js │ │ │ │ └── extension/ │ │ │ │ ├── bmap.js │ │ │ │ └── dataTool.js │ │ │ ├── fonts/ │ │ │ │ └── fonts-googleapis-source-sans-pro.css │ │ │ ├── highchart/ │ │ │ │ └── highcharts.js │ │ │ ├── jquery/ │ │ │ │ └── jquery.md5.js │ │ │ ├── paginator/ │ │ │ │ └── bootstrap-paginator.js │ │ │ ├── php-email-form/ │ │ │ │ └── validate.js │ │ │ ├── quill/ │ │ │ │ ├── quill.bubble.css │ │ │ │ ├── quill.core.css │ │ │ │ ├── quill.core.js │ │ │ │ ├── quill.js │ │ │ │ └── quill.snow.css │ │ │ ├── remixicon/ │ │ │ │ ├── remixicon.css │ │ │ │ └── remixicon.less │ │ │ ├── simple-datatables/ │ │ │ │ ├── simple-datatables.js │ │ │ │ └── style.css │ │ │ └── tinymce/ │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── bower.json │ │ │ ├── composer.json │ │ │ ├── icons/ │ │ │ │ └── default/ │ │ │ │ ├── icons.js │ │ │ │ └── index.js │ │ │ ├── license.txt │ │ │ ├── models/ │ │ │ │ └── dom/ │ │ │ │ ├── index.js │ │ │ │ └── model.js │ │ │ ├── package.json │ │ │ ├── plugins/ │ │ │ │ ├── advlist/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── anchor/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── autolink/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── autoresize/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── autosave/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── charmap/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── code/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── codesample/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── directionality/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── emoticons/ │ │ │ │ │ ├── index.js │ │ │ │ │ ├── js/ │ │ │ │ │ │ ├── emojiimages.js │ │ │ │ │ │ └── emojis.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── fullscreen/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── help/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── image/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── importcss/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── insertdatetime/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── link/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── lists/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── media/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── nonbreaking/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── pagebreak/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── preview/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── quickbars/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── save/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── searchreplace/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── table/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── template/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── visualblocks/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ ├── visualchars/ │ │ │ │ │ ├── index.js │ │ │ │ │ └── plugin.js │ │ │ │ └── wordcount/ │ │ │ │ ├── index.js │ │ │ │ └── plugin.js │ │ │ ├── skins/ │ │ │ │ ├── content/ │ │ │ │ │ ├── dark/ │ │ │ │ │ │ └── content.css │ │ │ │ │ ├── default/ │ │ │ │ │ │ └── content.css │ │ │ │ │ ├── document/ │ │ │ │ │ │ └── content.css │ │ │ │ │ ├── tinymce-5/ │ │ │ │ │ │ └── content.css │ │ │ │ │ ├── tinymce-5-dark/ │ │ │ │ │ │ └── content.css │ │ │ │ │ └── writer/ │ │ │ │ │ └── content.css │ │ │ │ └── ui/ │ │ │ │ ├── oxide/ │ │ │ │ │ ├── content.css │ │ │ │ │ ├── content.inline.css │ │ │ │ │ ├── skin.css │ │ │ │ │ └── skin.shadowdom.css │ │ │ │ ├── oxide-dark/ │ │ │ │ │ ├── content.css │ │ │ │ │ ├── content.inline.css │ │ │ │ │ ├── skin.css │ │ │ │ │ └── skin.shadowdom.css │ │ │ │ ├── tinymce-5/ │ │ │ │ │ ├── content.css │ │ │ │ │ ├── content.inline.css │ │ │ │ │ ├── skin.css │ │ │ │ │ └── skin.shadowdom.css │ │ │ │ └── tinymce-5-dark/ │ │ │ │ ├── content.css │ │ │ │ ├── content.inline.css │ │ │ │ ├── skin.css │ │ │ │ └── skin.shadowdom.css │ │ │ ├── themes/ │ │ │ │ └── silver/ │ │ │ │ ├── index.js │ │ │ │ └── theme.js │ │ │ ├── tinymce.d.ts │ │ │ └── tinymce.js │ │ ├── cachecloud-web.conf │ │ ├── logback-spring.xml │ │ ├── mapper/ │ │ │ ├── AppAlertRecordDao.xml │ │ │ ├── AppAuditDao.xml │ │ │ ├── AppAuditLogDao.xml │ │ │ ├── AppBizDao.xml │ │ │ ├── AppCapacityMonitorDao.xml │ │ │ ├── AppClientCommandStatisticsDao.xml │ │ │ ├── AppClientCostTimeStatDao.xml │ │ │ ├── AppClientCostTimeTotalStatDao.xml │ │ │ ├── AppClientExceptionStatDao.xml │ │ │ ├── AppClientExceptionStatisticsDao.xml │ │ │ ├── AppClientLatencyCommandDao.xml │ │ │ ├── AppClientReportDataSizeDao.xml │ │ │ ├── AppClientStatisticGatherDao.xml │ │ │ ├── AppClientVersionDao.xml │ │ │ ├── AppDailyDao.xml │ │ │ ├── AppDao.xml │ │ │ ├── AppDataMigrateStatusDao.xml │ │ │ ├── AppImportDao.xml │ │ │ ├── AppInstanceClientRelationDao.xml │ │ │ ├── AppStatsDao.xml │ │ │ ├── AppToUserDao.xml │ │ │ ├── AppUserDao.xml │ │ │ ├── ConfigDao.xml │ │ │ ├── ConfigRestartRecordDao.xml │ │ │ ├── DiagnosticTaskRecordDao.xml │ │ │ ├── InstanceAlertConfigDao.xml │ │ │ ├── InstanceBigKeyDao.xml │ │ │ ├── InstanceConfigDao.xml │ │ │ ├── InstanceDao.xml │ │ │ ├── InstanceFaultDao.xml │ │ │ ├── InstanceLatencyHistoryDao.xml │ │ │ ├── InstanceReshardProcessDao.xml │ │ │ ├── InstanceSlowLogDao.xml │ │ │ ├── InstanceStatsDao.xml │ │ │ ├── MachineDao.xml │ │ │ ├── MachineRelationDao.xml │ │ │ ├── MachineStatsDao.xml │ │ │ ├── QuartzDao.xml │ │ │ ├── ResourceDao.xml │ │ │ ├── ServerStatusDao.xml │ │ │ ├── StandardStatsDao.xml │ │ │ ├── TaskQueueDao.xml │ │ │ ├── TaskStepFlowDao.xml │ │ │ └── TaskStepMetaDao.xml │ │ ├── mybatis-config.xml │ │ ├── spring/ │ │ │ ├── spring-client-report.xml │ │ │ ├── spring-data.xml │ │ │ ├── spring-inspector.xml │ │ │ ├── spring-mvc.xml │ │ │ ├── spring-mybatis.xml │ │ │ ├── spring-quartz.xml │ │ │ └── spring.xml │ │ ├── static/ │ │ │ └── wiki/ │ │ │ ├── access/ │ │ │ │ ├── client.md │ │ │ │ ├── client.toc.md │ │ │ │ ├── config.md │ │ │ │ ├── docker.md │ │ │ │ ├── docker.toc.md │ │ │ │ ├── index.md │ │ │ │ ├── init.md │ │ │ │ ├── init.toc.md │ │ │ │ ├── resource.md │ │ │ │ └── resource.toc.md │ │ │ ├── architecture/ │ │ │ │ ├── index.md │ │ │ │ ├── service.md │ │ │ │ └── tech.md │ │ │ ├── function/ │ │ │ │ ├── client-analysis.md │ │ │ │ ├── client-appStats.md │ │ │ │ ├── client-cmd.md │ │ │ │ ├── client-cmdexe.md │ │ │ │ ├── client-conn.md │ │ │ │ ├── client-daily.md │ │ │ │ ├── client-desc.md │ │ │ │ ├── client-instances.md │ │ │ │ ├── client-latency.md │ │ │ │ ├── client-register.md │ │ │ │ ├── client-statistic.md │ │ │ │ ├── client.md │ │ │ │ ├── index.md │ │ │ │ ├── job.md │ │ │ │ ├── operation-alert.md │ │ │ │ ├── operation-app.md │ │ │ │ ├── operation-diagnostic.md │ │ │ │ ├── operation-import.md │ │ │ │ ├── operation-instance.md │ │ │ │ ├── operation-job.md │ │ │ │ ├── operation-machine.md │ │ │ │ ├── operation-migrate.md │ │ │ │ ├── operation-module.md │ │ │ │ ├── operation-resource.md │ │ │ │ ├── operation-schedule.md │ │ │ │ ├── operation-systemalert.md │ │ │ │ ├── operation-task.md │ │ │ │ ├── operation-template.md │ │ │ │ ├── operation-user.md │ │ │ │ ├── operations.md │ │ │ │ ├── server-statistic.md │ │ │ │ ├── server-statistic.toc.md │ │ │ │ ├── statistics.md │ │ │ │ └── system-alert.md │ │ │ ├── intro/ │ │ │ │ ├── index.md │ │ │ │ ├── redisVersion.md │ │ │ │ ├── redisVersion.toc.md │ │ │ │ ├── releaseNote.md │ │ │ │ └── releaseNote.toc.md │ │ │ ├── operate/ │ │ │ │ ├── appAlert.md │ │ │ │ ├── appDeploy.md │ │ │ │ ├── appMigrate.md │ │ │ │ ├── appUpgrade.md │ │ │ │ ├── baseConcept.md │ │ │ │ ├── baseOperate.md │ │ │ │ ├── baseOperate.toc.md │ │ │ │ ├── baseOptimize.md │ │ │ │ ├── index.md │ │ │ │ ├── migrateTool.md │ │ │ │ ├── redisVersion.toc.md │ │ │ │ ├── rediscode.md │ │ │ │ └── ssh.md │ │ │ ├── quickstart/ │ │ │ │ ├── index.md │ │ │ │ └── index.toc.md │ │ │ └── troubleshooting/ │ │ │ ├── activefrag.md │ │ │ ├── activefrag.toc.md │ │ │ ├── bigkey.md │ │ │ ├── cachecloud.md │ │ │ ├── exception.md │ │ │ ├── hotkey.md │ │ │ ├── index.md │ │ │ ├── jedispoolconfig.md │ │ │ ├── jedispoolconfig.toc.md │ │ │ ├── liunx.md │ │ │ ├── liunx.toc.md │ │ │ ├── memory.md │ │ │ └── memory.toc.md │ │ └── templates/ │ │ ├── 404.html │ │ ├── OperationAlert.ftl │ │ ├── analysis/ │ │ │ ├── appKey.html │ │ │ └── keyAnalysis.html │ │ ├── app/ │ │ │ ├── appClientList.html │ │ │ ├── appCommand.html │ │ │ ├── appCommandAnalysis.html │ │ │ ├── appDaily.html │ │ │ ├── appDetail.html │ │ │ ├── appHitRatio.html │ │ │ ├── appInstanceCpuStat.html │ │ │ ├── appInstanceExpiredEvictedKeysStat.html │ │ │ ├── appInstanceMemFragRatioStat.html │ │ │ ├── appInstanceNetStat.html │ │ │ ├── appLatencyInfoDetail.html │ │ │ ├── appList.html │ │ │ ├── appMachineInstancesTopology.html │ │ │ ├── appStat.html │ │ │ ├── appTopology.html │ │ │ ├── jobIndex/ │ │ │ │ ├── appAlertConfig.html │ │ │ │ ├── appAlterConfigIndex.html │ │ │ │ ├── appCleanIndex.html │ │ │ │ ├── appConfig.html │ │ │ │ ├── appConfigIndex.html │ │ │ │ ├── appDataMigrate.html │ │ │ │ ├── appDataMigrateIndex.html │ │ │ │ ├── appDel.html │ │ │ │ ├── appDiagnostic.html │ │ │ │ ├── appDiagnosticIndex.html │ │ │ │ ├── appImport.html │ │ │ │ ├── appImportIndex.html │ │ │ │ ├── appInit.html │ │ │ │ ├── appInitIndex.html │ │ │ │ ├── appKeyAnalysis.html │ │ │ │ ├── appKeyAnalysisIndex.html │ │ │ │ ├── appOffline.html │ │ │ │ ├── appOfflineIndex.html │ │ │ │ ├── appScale.html │ │ │ │ ├── appScaleIndex.html │ │ │ │ ├── appScanClean.html │ │ │ │ ├── appScanCleanIndex.html │ │ │ │ ├── appTrailInit.html │ │ │ │ ├── appTrailInitIndex.html │ │ │ │ ├── head.html │ │ │ │ ├── index.html │ │ │ │ ├── myJobs.html │ │ │ │ └── nav.html │ │ │ ├── slowLog.html │ │ │ └── userAppsIndex.html │ │ ├── appAlert.ftl │ │ ├── appAudit.ftl │ │ ├── appDaily.ftl │ │ ├── client/ │ │ │ ├── appClientIndex.html │ │ │ ├── clientCommandStatistics.html │ │ │ ├── clientExceptionStatistics.html │ │ │ ├── cmdExceptionCommandDetail.html │ │ │ ├── cmdExceptionStatisticsByClient.html │ │ │ ├── commandStatisticsByClient.html │ │ │ └── connExceptionStatisticsByClient.html │ │ ├── error.html │ │ ├── expAppsDaily.ftl │ │ ├── inc/ │ │ │ ├── contact.html │ │ │ ├── daily.html │ │ │ ├── footer.html │ │ │ ├── frontResources.html │ │ │ ├── head.html │ │ │ ├── page.html │ │ │ ├── wikiHead.html │ │ │ └── wikiLeft.html │ │ ├── instance/ │ │ │ ├── instanceAdvancedAnalysis.html │ │ │ ├── instanceClientList.html │ │ │ ├── instanceCommand.html │ │ │ ├── instanceConfigSelect.html │ │ │ ├── instanceFault.html │ │ │ ├── instanceIndex.html │ │ │ ├── instanceSlowSelect.html │ │ │ └── instanceStat.html │ │ ├── instanceAlert.ftl │ │ ├── instanceRecover.ftl │ │ ├── instanceState.ftl │ │ ├── manage/ │ │ │ ├── appAudit/ │ │ │ │ ├── appAudit.html │ │ │ │ ├── appAuditList.html │ │ │ │ ├── appConfigChangeDetail.html │ │ │ │ ├── appIntanceReferList.html │ │ │ │ ├── appScaleApplyDetail.html │ │ │ │ ├── deploy/ │ │ │ │ │ ├── appDeployDetail.html │ │ │ │ │ └── initAppDeploy.html │ │ │ │ ├── handleHorizontalScale.html │ │ │ │ ├── handleHorizontalScaleDetail.html │ │ │ │ ├── horizontalScaleApplyDetail.html │ │ │ │ ├── horizontalScaleProcessList.html │ │ │ │ ├── initAppConfigChange.html │ │ │ │ ├── initAppScaleApply.html │ │ │ │ ├── initHorizontalScaleApply.html │ │ │ │ ├── initInstanceConfigChange.html │ │ │ │ ├── instanceConfig.html │ │ │ │ ├── instanceConfigChangeDetail.html │ │ │ │ └── list.html │ │ │ ├── appImport/ │ │ │ │ ├── appImport.html │ │ │ │ ├── index.html │ │ │ │ └── list.html │ │ │ ├── appOps/ │ │ │ │ ├── appCodeInit.html │ │ │ │ ├── appInfoAndAudit.html │ │ │ │ ├── appInstance.html │ │ │ │ ├── appMachine.html │ │ │ │ ├── appMigrate.html │ │ │ │ └── appOpsIndex.html │ │ │ ├── appStat/ │ │ │ │ ├── appStatList.html │ │ │ │ ├── appStatListServer.html │ │ │ │ ├── list.html │ │ │ │ └── listServer.html │ │ │ ├── appTool/ │ │ │ │ └── appKeysDealTool.html │ │ │ ├── backendTemplate.html │ │ │ ├── config/ │ │ │ │ ├── init.html │ │ │ │ └── initConfigDetail.html │ │ │ ├── diagnosticTool/ │ │ │ │ ├── diagnosticDelKey.html │ │ │ │ ├── diagnosticHotKey.html │ │ │ │ ├── diagnosticIdleKey.html │ │ │ │ ├── diagnosticMemUsed.html │ │ │ │ ├── diagnosticResult.html │ │ │ │ ├── diagnosticSampleCompare.html │ │ │ │ ├── diagnosticSampleCompareResult.html │ │ │ │ ├── diagnosticScan.html │ │ │ │ ├── diagnosticScanClean.html │ │ │ │ ├── diagnosticSlot.html │ │ │ │ ├── diagnosticTool.html │ │ │ │ ├── index.html │ │ │ │ ├── list.html │ │ │ │ └── resultList.html │ │ │ ├── fault/ │ │ │ │ ├── list.html │ │ │ │ └── memFaultList.html │ │ │ ├── inc/ │ │ │ │ ├── backendEndResources.html │ │ │ │ ├── backendResources.html │ │ │ │ ├── footer.html │ │ │ │ ├── head.html │ │ │ │ ├── left.html │ │ │ │ └── page.html │ │ │ ├── instance/ │ │ │ │ └── log.html │ │ │ ├── instanceAlert/ │ │ │ │ ├── init.html │ │ │ │ ├── initConfigDetail.html │ │ │ │ └── tendisAlert/ │ │ │ │ ├── init.html │ │ │ │ └── initConfigDetail.html │ │ │ ├── instanceOps/ │ │ │ │ ├── instanceCommandCheckList.html │ │ │ │ ├── instanceConfigCheckList.html │ │ │ │ ├── instanceOpsIndex.html │ │ │ │ ├── instanceOpsList.html │ │ │ │ └── page.html │ │ │ ├── login.html │ │ │ ├── machine/ │ │ │ │ ├── addMachine.html │ │ │ │ ├── addRoom.html │ │ │ │ ├── downCrashMachine.html │ │ │ │ ├── index.html │ │ │ │ ├── list.html │ │ │ │ ├── machineInstances.html │ │ │ │ ├── machineInstancesDetail.html │ │ │ │ ├── machineList.html │ │ │ │ ├── roomList.html │ │ │ │ ├── taskInfo.html │ │ │ │ └── taskInfo_bak.html │ │ │ ├── migrate/ │ │ │ │ ├── index.html │ │ │ │ ├── list.html │ │ │ │ ├── taskIndex.html │ │ │ │ └── tasklist.html │ │ │ ├── notice/ │ │ │ │ ├── initNotice.html │ │ │ │ └── initNoticeDetail.html │ │ │ ├── pod/ │ │ │ │ ├── changeList.html │ │ │ │ └── list.html │ │ │ ├── quartz/ │ │ │ │ ├── list.html │ │ │ │ └── quartzList.html │ │ │ ├── redisConfig/ │ │ │ │ ├── contrast.html │ │ │ │ ├── init.html │ │ │ │ ├── initConfigDetail.html │ │ │ │ └── preview.html │ │ │ ├── resource/ │ │ │ │ ├── addDir.html │ │ │ │ ├── addRedis.html │ │ │ │ ├── addScript.html │ │ │ │ ├── addTool.html │ │ │ │ ├── dir.html │ │ │ │ ├── index.html │ │ │ │ ├── list.html │ │ │ │ ├── redis.html │ │ │ │ ├── respo.html │ │ │ │ ├── script.html │ │ │ │ └── tool.html │ │ │ ├── task/ │ │ │ │ ├── flowList.html │ │ │ │ ├── queueList.html │ │ │ │ ├── taskFlowList.html │ │ │ │ └── taskQueueList.html │ │ │ ├── total/ │ │ │ │ ├── list.html │ │ │ │ ├── totalList.html │ │ │ │ └── upgradeRedis.html │ │ │ ├── totalstat/ │ │ │ │ ├── list.html │ │ │ │ └── totalList.html │ │ │ └── user/ │ │ │ ├── addBiz.html │ │ │ ├── addUser.html │ │ │ ├── list.html │ │ │ ├── overUser.html │ │ │ ├── updateUser.html │ │ │ ├── updateUserPwd.html │ │ │ └── userList.html │ │ ├── migrate/ │ │ │ ├── checkData.html │ │ │ ├── checkDataLog.html │ │ │ ├── config.html │ │ │ ├── init.html │ │ │ ├── log.html │ │ │ └── process.html │ │ ├── noPower.html │ │ ├── server/ │ │ │ ├── cpu.html │ │ │ ├── disk.html │ │ │ ├── index.html │ │ │ ├── net.html │ │ │ └── overview.html │ │ ├── topologyExam.ftl │ │ ├── user/ │ │ │ └── userRegister.html │ │ ├── wikiAccessClientTemplate.html │ │ └── wikiTemplate.html │ └── webapp/ │ └── WEB-INF/ │ └── web.xml ├── pom.xml └── redis-ecs/ ├── help.md └── script/ ├── cachecloud-init.sh ├── redis-install.sh ├── redisShake-install.sh └── ssh-keygen.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/maven.yml ================================================ name: Java CI on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Set up JDK 1.8 uses: actions/setup-java@v1 with: java-version: 1.8 - name: Build with Maven run: mvn -B package --file pom.xml ================================================ FILE: .gitignore ================================================ .idea/ *.iml .svn/* target/ *.class .settings .classpath .project ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ [中文](README_CN.md) | [EN](README_EN.md) ![cachecloud云平台](cachecloud-web/src/main/resources/static/img/readme/cachecloud-head.png) [![CI checks on main badge]][CI checks on main link] [![latest release badge]][latest release link] [![github stars badge]][github stars link] [![github forks badge]][github forks link] [![github open issues badge]][github open issues link] [![github open prs badge]][github open prs link] [![latest commit to main badge]][latest commit to main link] [CI checks on main badge]: https://flat.badgen.net/github/checks/sohutv/cachecloud/main?label=CI%20status%20on%20main&cache=900&icon=github [CI checks on main link]:https://github.com/sohutv/cachecloud/actions?query=branch%3Amain [github forks badge]: https://flat.badgen.net/github/forks/sohutv/cachecloud?icon=github [github forks link]: https://useful-forks.github.io/?repo=sohutv%2Fcachecloud [github open issues badge]: https://flat.badgen.net/github/open-issues/sohutv/cachecloud?icon=github [github open issues link]: https://github.com/sohutv/cachecloud/issues?q=is%3Aissue+is%3Aopen [github open prs badge]: https://flat.badgen.net/github/open-prs/sohutv/cachecloud?icon=github [github open prs link]: https://github.com/sohutv/cachecloud/pulls?q=is%3Apr+is%3Aopen [github stars badge]: https://flat.badgen.net/github/stars/sohutv/cachecloud?icon=github [github stars link]: https://github.com/sohutv/cachecloud/stargazers [latest commit to main badge]: https://flat.badgen.net/github/last-commit/sohutv/cachecloud/main?icon=github&color=yellow&label=last%20dev%20commit&cache=900 [latest commit to main link]: https://github.com/sohutv/cachecloud/commits/main [latest release badge]: https://flat.badgen.net/github/release/sohutv/cachecloud/development?icon=github [latest release link]: https://github.com/sohutv/cachecloud/releases

CacheCloud云平台

Quickstart   •   Client   •   Docs   •   FAQ   •   Demo   •   Feedback   •   Contact
## CacheCloud是什么? CacheCloud是一个Redis云管理平台:支持Redis多种架构(Standalone、Sentinel、Cluster)高效管理、有效降低大规模redis运维成本,提升资源管控能力和利用率。平台提供快速搭建/迁移,运维管理,弹性伸缩,统计监控,客户端整合接入等功能。 ## CacheCloud功能架构 + Redis搭建:宿主环境初始化、实例部署安装、类型架构支持; + 运维管理:宿主环境、资源管理、应用审计、应用运维、质量监控、诊断分析; + 统计监控:日志采集、实例采集、机器采集、应用统计、监控告警、问题诊断; + 客户端接入:SDK接入、语言接入、客户端监控; + 弹性伸缩:资源收缩、应用伸缩、外部接入; ## CacheCloud使用规模 + 800亿+ commands/day + 18T+ Memory Total + 420+ app Total / 4800+ Instances Total + 80+ Physical machine/ 360+ K8s Pod Total ## CacheCloud VS 云厂商
Redis 主从/集群部署成本
## 贡献成员
## 感谢支持者 ![Stargazers repo roster for @sohutv/cachecloud](https://bytecrank.com/nastyox/reporoster/php/stargazersSVG.php?user=sohutv&repo=cachecloud) ![Forkers repo roster for @sohutv/cachecloud](https://bytecrank.com/nastyox/reporoster/php/forkersSVG.php?user=sohutv&repo=cachecloud) ## 联系我们 + QQ群: 534429768(已满) / 2群:894022242 / 3群:908821300 + 微信群: + 微信:如果大家有公网资源可以联系我,会加入到开源版本服务资源部署试用,提高大家的用户体验。 如果你觉得CacheCloud对你有帮助,欢迎Star⭐。 ================================================ FILE: README_CN.md ================================================ [中文](README_CN.md) | [EN](README_EN.md) ![cachecloud云平台](cachecloud-web/src/main/resources/static/img/readme/cachecloud-head.png) [![CI checks on main badge]][CI checks on main link] [![latest release badge]][latest release link] [![github stars badge]][github stars link] [![github forks badge]][github forks link] [![github open issues badge]][github open issues link] [![github open prs badge]][github open prs link] [![latest commit to main badge]][latest commit to main link] [CI checks on main badge]: https://flat.badgen.net/github/checks/sohutv/cachecloud/main?label=CI%20status%20on%20main&cache=900&icon=github [CI checks on main link]:https://github.com/sohutv/cachecloud/actions?query=branch%3Amain [github forks badge]: https://flat.badgen.net/github/forks/sohutv/cachecloud?icon=github [github forks link]: https://useful-forks.github.io/?repo=sohutv%2Fcachecloud [github open issues badge]: https://flat.badgen.net/github/open-issues/sohutv/cachecloud?icon=github [github open issues link]: https://github.com/sohutv/cachecloud/issues?q=is%3Aissue+is%3Aopen [github open prs badge]: https://flat.badgen.net/github/open-prs/sohutv/cachecloud?icon=github [github open prs link]: https://github.com/sohutv/cachecloud/pulls?q=is%3Apr+is%3Aopen [github stars badge]: https://flat.badgen.net/github/stars/sohutv/cachecloud?icon=github [github stars link]: https://github.com/sohutv/cachecloud/stargazers [latest commit to main badge]: https://flat.badgen.net/github/last-commit/sohutv/cachecloud/main?icon=github&color=yellow&label=last%20dev%20commit&cache=900 [latest commit to main link]: https://github.com/sohutv/cachecloud/commits/main [latest release badge]: https://flat.badgen.net/github/release/sohutv/cachecloud/development?icon=github [latest release link]: https://github.com/sohutv/cachecloud/releases

CacheCloud云平台

Quickstart   •   Client   •   Docs   •   FAQ   •   Demo   •   Feedback   •   Contact
## CacheCloud是什么? CacheCloud是一个Redis云管理平台:支持Redis多种架构(Standalone、Sentinel、Cluster)高效管理、有效降低大规模redis运维成本,提升资源管控能力和利用率。平台提供快速搭建/迁移,运维管理,弹性伸缩,统计监控,客户端整合接入等功能。 ## CacheCloud功能架构 + Redis搭建:宿主环境初始化、实例部署安装、类型架构支持; + 运维管理:宿主环境、资源管理、应用审计、应用运维、质量监控、诊断分析; + 统计监控:日志采集、实例采集、机器采集、应用统计、监控告警、问题诊断; + 客户端接入:SDK接入、语言接入、客户端监控; + 弹性伸缩:资源收缩、应用伸缩、外部接入; ## CacheCloud使用规模 + 800亿+ commands/day + 18T+ Memory Total + 420+ app Total / 4800+ Instances Total + 80+ Physical machine/ 360+ K8s Pod Total ## CacheCloud VS 云厂商
Redis 主从/集群部署成本
## 贡献成员
## 感谢支持者 [![Stargazers repo roster for @sohutv/cachecloud](https://reporoster.com/stars/sohutv/cachecloud)](https://github.com/sohutv/cachecloud/stargazers) [![Forkers repo roster for @sohutv/cachecloud](https://reporoster.com/forks/sohutv/cachecloud)](https://github.com/sohutv/cachecloud/network/members) ## 联系我们 + QQ群: 534429768(已满) / 2群:894022242 / 3群:908821300 + 微信群: + 微信:如果大家有公网资源可以联系我,会加入到开源版本服务资源部署试用,提高大家的用户体验。 如果你觉得CacheCloud对你有帮助,欢迎Star⭐。 ================================================ FILE: README_EN.md ================================================ [中文](README_CN.md) | [EN](README_EN.md) ![cachecloud云平台](cachecloud-web/src/main/resources/static/img/readme/cachecloud-head.png) [![CI checks on main badge]][CI checks on main link] [![latest release badge]][latest release link] [![github stars badge]][github stars link] [![github forks badge]][github forks link] [![github open issues badge]][github open issues link] [![github open prs badge]][github open prs link] [![latest commit to main badge]][latest commit to main link] [CI checks on main badge]: https://flat.badgen.net/github/checks/sohutv/cachecloud/main?label=CI%20status%20on%20main&cache=900&icon=github [CI checks on main link]:https://github.com/sohutv/cachecloud/actions?query=branch%3Amain [github forks badge]: https://flat.badgen.net/github/forks/sohutv/cachecloud?icon=github [github forks link]: https://useful-forks.github.io/?repo=sohutv%2Fcachecloud [github open issues badge]: https://flat.badgen.net/github/open-issues/sohutv/cachecloud?icon=github [github open issues link]: https://github.com/sohutv/cachecloud/issues?q=is%3Aissue+is%3Aopen [github open prs badge]: https://flat.badgen.net/github/open-prs/sohutv/cachecloud?icon=github [github open prs link]: https://github.com/sohutv/cachecloud/pulls?q=is%3Apr+is%3Aopen [github stars badge]: https://flat.badgen.net/github/stars/sohutv/cachecloud?icon=github [github stars link]: https://github.com/sohutv/cachecloud/stargazers [latest commit to main badge]: https://flat.badgen.net/github/last-commit/sohutv/cachecloud/main?icon=github&color=yellow&label=last%20dev%20commit&cache=900 [latest commit to main link]: https://github.com/sohutv/cachecloud/commits/main [latest release badge]: https://flat.badgen.net/github/release/sohutv/cachecloud/development?icon=github [latest release link]: https://github.com/sohutv/cachecloud/releases

CacheCloud云平台

Quickstart   •   Client   •   Docs   •   FAQ   •   Demo   •   Feedback   •   Contact
## What is CacheCloud? CacheCloud is a Redis cloud management platform that supports efficient management of multiple Redis architectures (Standalone, Sentinel, and Cluster), effectively reduces large-scale redis Operation and Maintenance costs, and improves resource management capabilities and utilization. The platform provides functions such as rapid construction/migration, operation and maintenance management, elastic scaling, statistical monitoring, and client integration and access. ## CacheCloud Function Architecture + Redis build: Machine environment initialization, Instance deployment and installation, Redis architecture support; + DevOps: Machine environment, Resource management, Application audit, Application operation and maintenance, Quality monitoring, Diagnostic analysis; + Statistical monitoring: Redis log collection, Instance indicator collection, Machine indicator collection, Application statistics, Monitoring alarms, Problem diagnosis; + Client access: SDK access support, Language access support, Client monitoring; + Elastic scaling: Memory Resource shrinkage, Application scaling, External access; ## CacheCloud Scale + 800亿+ commands/day + 18T+ Memory Total + 420+ app Total / 4800+ Instances Total + 80+ Physical machine/ 360+ K8s Pod Total ## CacheCloud VS Cloud vendor
Redis Sentinel/Cluster deploy cost
## Contributing member
## Supporters [![Stargazers repo roster for @sohutv/cachecloud](https://reporoster.com/stars/sohutv/cachecloud)](https://github.com/sohutv/cachecloud/stargazers) [![Forkers repo roster for @sohutv/cachecloud](https://reporoster.com/forks/sohutv/cachecloud)](https://github.com/sohutv/cachecloud/network/members) ## Contact us + QQ: 534429768(Full) / 2群:894022242 / 3群:908821300 + Wechat Group: + Wechat:If you have public network resources can contact me, I will join the open source version service resource deployment trial, improve everyone's user experience. If you find CacheCloud is helpful, welcome to Star⭐️. ================================================ FILE: cachecloud-custom/pom.xml ================================================ cachecloud-parent com.sohu.tv 1.0-SNAPSHOT 4.0.0 com.sohu.tv.custom cachecloud-custom org.springframework.boot spring-boot-dependencies ${spring.boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring.cloud.version} pom import org.springframework.boot spring-boot-starter-web compile log4j-api org.apache.logging.log4j org.apache.commons commons-lang3 org.apache.maven.plugins maven-deploy-plugin true ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/DefaultCustomConfiguration.java ================================================ package com.sohu.cache; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.alert.WeChatComponent; import com.sohu.cache.alert.impl.DefaultEmailComponent; import com.sohu.cache.alert.impl.DefaultWeChatComponent; import com.sohu.cache.login.LoginComponent; import com.sohu.cache.login.impl.DefaultLoginComponent; import com.sohu.cache.report.ReportDataComponent; import com.sohu.cache.report.impl.DefaultReportDataComponent; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by yijunzhang */ @Configuration public class DefaultCustomConfiguration { @Bean("emailComponent") @ConditionalOnMissingBean public EmailComponent emailComponent() { return new DefaultEmailComponent(); } @Bean("weChatComponent") @ConditionalOnMissingBean public WeChatComponent weChatComponent() { return new DefaultWeChatComponent(); } @Bean("loginComponent") @ConditionalOnMissingBean public LoginComponent loginComponent() { return new DefaultLoginComponent(); } @Bean("reportDataComponent") @ConditionalOnMissingBean public ReportDataComponent reportDataComponent() { return new DefaultReportDataComponent(); } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/alert/EmailComponent.java ================================================ package com.sohu.cache.alert; import java.util.List; /** * 邮件服务 * @author leifu */ public interface EmailComponent { /** * 发送邮件 * @param title * @param content * @param emailList * @param ccList(抄送) * @return */ boolean sendMail(String title, String content, List emailList, List ccList); boolean sendDailyMail(String title, String content, List emailList, List ccList); /** * 发送邮件 * @param title * @param content * @param emailList * @return */ boolean sendMail(String title, String content, List emailList); /** * 发送管理员邮件 * @param title * @param content * @return */ boolean sendMailToAdmin(String title, String content); /** * 获取管理员邮件组 * @return */ String getAdminEmail(); } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/alert/WeChatComponent.java ================================================ package com.sohu.cache.alert; import java.util.List; /** * 微信报警 * Created by rucao */ public interface WeChatComponent { /** * 发送微信报警 * @param message * @param weChatList * @return */ boolean sendWeChat(String title, String message, List weChatList); /** * 发送微信报警给所有相关人员 * @param title * @param message * @param weChatList * @return */ boolean sendWeChatToAll(String title, String message, List weChatList); /** * 发送微信报警给管理员 * @param message * @return */ boolean sendWeChatToAdmin(String title, String message); } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/alert/impl/DefaultEmailComponent.java ================================================ package com.sohu.cache.alert.impl; import com.sohu.cache.alert.EmailComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * 邮件报警组件默认空实现 * Created by yijunzhang */ public class DefaultEmailComponent implements EmailComponent { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public boolean sendMail(String title, String content, List emailList, List ccList) { logger.warn("Please implement the sendMail logic."); return true; } @Override public boolean sendDailyMail(String title, String content, List emailList, List ccList) { logger.warn("Please implement the sendDailyMail logic."); return true; } @Override public boolean sendMail(String title, String content, List emailList) { logger.warn("Please implement the sendMail logic."); return true; } @Override public boolean sendMailToAdmin(String title, String content) { logger.warn("Please implement the sendMailToAdmin logic."); return true; } @Override public String getAdminEmail() { logger.warn("Please implement the getAdminEmail logic."); return ""; } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/alert/impl/DefaultWeChatComponent.java ================================================ package com.sohu.cache.alert.impl; import com.sohu.cache.alert.WeChatComponent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * Created by yijunzhang */ public class DefaultWeChatComponent implements WeChatComponent { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public boolean sendWeChat(String title, String message, List weChatList) { logger.warn("Please implement the sendWeChat logic."); return true; } @Override public boolean sendWeChatToAll(String title, String message, List weChatList) { logger.warn("Please implement the sendWeChatToAll logic."); return true; } @Override public boolean sendWeChatToAdmin(String title, String message) { logger.warn("Please implement the sendWeChatToAdmin logic."); return true; } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/alert/utils/AlertUtils.java ================================================ package com.sohu.cache.alert.utils; /** * Created by yijunzhang */ public class AlertUtils { /** * 邮箱报警接口 */ public static String EMAIL_ALERT_INTERFACE; /** * 短信报警接口 */ public static String MOBILE_ALERT_INTERFACE; /** * 微信报警接口 */ public static String WECHAT_ALERT_INTERFACE; /** * 报警邮箱 */ public static String EMAILS; /** * 报警电话 */ public static String PHONES; /** * 报警微信 */ public static String WECHAT; } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/configuration/DefaultRestTemplateConfig.java ================================================ package com.sohu.cache.configuration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; /** * Created by rucao on 2020/4/2 */ @Configuration public class DefaultRestTemplateConfig { private static int connectTimeout = 4000; private static int readTimeout = 5000; @ConditionalOnMissingBean(name = "restTemplate") @Bean RestTemplate restTemplate() { HttpComponentsClientHttpRequestFactory f = new HttpComponentsClientHttpRequestFactory(); f.setConnectTimeout(connectTimeout); f.setReadTimeout(readTimeout); f.setConnectionRequestTimeout(connectTimeout); RestTemplate restTemplate = new RestTemplate(f); return restTemplate; } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/login/LoginComponent.java ================================================ package com.sohu.cache.login; import javax.servlet.http.HttpServletRequest; /** * Created by yijunzhang */ public interface LoginComponent { /** * 检测登录状态 * * @param userName * @param password * @return */ boolean passportCheck(String userName, String password); /** * 根据ticket获取email * @param ticket * @return */ String getEmail(String ticket); /** * 获取登录跳转地址 * * @param request * @return * @throws Exception */ String getRedirectUrl(HttpServletRequest request); /** * SSO logout url * * @return * @throws Exception */ String getLogoutUrl(); } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/login/impl/DefaultLoginComponent.java ================================================ package com.sohu.cache.login.impl; import com.sohu.cache.login.LoginComponent; import com.sohu.cache.utils.EnvCustomUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.client.RestTemplate; import javax.servlet.http.HttpServletRequest; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URLEncoder; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; /** * Created by yijunzhang */ public class DefaultLoginComponent implements LoginComponent { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private RestTemplate restTemplate; @Value(value = "${server.port:8080}") private String serverPort; private static final String RELATIVE_URL = "/manage/loginCheck"; /** * it is open for change * @param userName * @param password * @return */ @Override public boolean passportCheck(String userName, String password) { //default password login check if(EnvCustomUtil.pwdswitch){ String url = getUrl() + RELATIVE_URL; Map requestMap = new HashMap<>(); requestMap.put("name", userName); requestMap.put("password", password); Map map = restTemplate.postForObject(url, requestMap, Map.class); if(map != null && map.get("status") != null && Integer.parseInt(map.get("status").toString()) == 200){ return true; } return false; } //todo need to implement by your own business return true; } private String getUrl() { InetAddress address = null; try { address = InetAddress.getLocalHost(); } catch (UnknownHostException e) { logger.error(e.getMessage(), e); } if(address != null){ return "http://" + address.getHostAddress() + ":" + this.serverPort; } return "http://127.0.0.1:" + this.serverPort; } @Override public String getEmail(String ticket) { return null; } @Override public String getRedirectUrl(HttpServletRequest request) { StringBuffer redirectUrl = new StringBuffer(); redirectUrl.append(request.getSession(true).getServletContext().getContextPath()); redirectUrl.append("/manage/login?"); // 跳转地址 redirectUrl.append("redirectUrl"); redirectUrl.append("="); redirectUrl.append(request.getRequestURI()); // 跳转参数 String query = request.getQueryString(); if (StringUtils.isNotBlank(query)) { redirectUrl.append("?"); try { redirectUrl.append(URLEncoder.encode(request.getQueryString(), "UTF-8")); } catch (UnsupportedEncodingException e) { logger.error(e.getMessage(), e); } } return redirectUrl.toString(); } @Override public String getLogoutUrl() { return null; } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/report/ReportDataComponent.java ================================================ package com.sohu.cache.report; /** * @Author: zengyizhao * @DateTime: 2022/2/21 11:16 * @Description: 上报数据服务 */ public interface ReportDataComponent { //上报命令数据 void reportCommandData(Object msg); //上报异常数据 void reportExceptionData(Object msg); //上报redis info信息 void reportRedisInfoData(Object msg); //上报慢查询数据 void reportSlowLogData(Object msg); //上报延迟事件数据 void reportLatencyData(Object msg); //上报机器监控数据 void reportMachineData(Object msg); } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/report/impl/DefaultReportDataComponent.java ================================================ package com.sohu.cache.report.impl; import com.sohu.cache.report.ReportDataComponent; /** * @Author: zengyizhao * @DateTime: 2022/2/21 11:22 * @Description: 上报数据默认实现 */ public class DefaultReportDataComponent implements ReportDataComponent { @Override public void reportCommandData(Object msg) { //todo } @Override public void reportExceptionData(Object msg) { //todo } @Override public void reportRedisInfoData(Object msg) { //todo } @Override public void reportSlowLogData(Object msg) { //todo } @Override public void reportLatencyData(Object msg) { //todo } @Override public void reportMachineData(Object msg) { //todo } } ================================================ FILE: cachecloud-custom/src/main/java/com/sohu/cache/utils/EnvCustomUtil.java ================================================ package com.sohu.cache.utils; /** * custom environment setting */ public class EnvCustomUtil { //是否启用默认密码 public static boolean pwdswitch = false; } ================================================ FILE: cachecloud-web/pom.xml ================================================ com.sohu.tv cachecloud-parent 1.0-SNAPSHOT 4.0.0 cachecloud-web com.sohu.tv cachecloud-web 1.0-SNAPSHOT war org.springframework.boot spring-boot-dependencies ${spring.boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring.cloud.version} pom import org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-starter-test org.springframework.boot spring-boot-starter-logging log4j-api org.apache.logging.log4j org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-starter-freemarker org.apache.tomcat.embed tomcat-embed-jasper org.springframework spring-context-support javax.servlet jstl 1.2 org.quartz-scheduler quartz slf4j-api org.slf4j HikariCP-java7 com.zaxxer ch.qos.logback logback-classic mysql mysql-connector-java org.mybatis.spring.boot mybatis-spring-boot-starter org.jolokia jolokia-core redis.clients jedis ${jedis.version} com.dyuproject.protostuff protostuff-runtime ${protostuff.version} com.dyuproject.protostuff protostuff-core ${protostuff.version} org.apache.httpcomponents httpclient org.projectlombok lombok 1.18.30 provided org.apache.sshd sshd-core ${ssh-version} org.apache.sshd sshd-scp ${ssh-version} org.apache.commons commons-collections4 com.zaxxer HikariCP 3.3.1 net.sf.json-lib json-lib jdk15 commons-configuration commons-configuration org.apache.struts struts-taglib 1.3.10 com.alibaba fastjson com.netflix.hystrix hystrix-core com.google.guava guava org.codehaus.janino janino ${janino.version} net.logstash.logback logstash-logback-encoder ${logstash-logback-encoder.version} com.vladsch.flexmark flexmark com.vladsch.flexmark flexmark-ext-tables com.sohu.tv.custom cachecloud-custom io.springfox springfox-swagger2 io.springfox springfox-swagger-ui org.apache.ant ant cachecloud-web org.apache.maven.plugins maven-deploy-plugin true org.apache.maven.plugins maven-surefire-plugin org.springframework.boot spring-boot-maven-plugin ${spring.boot.version} com.sohu.cache.ApplicationStarter false true false repackage 1 org.apache.maven.plugins maven-resources-plugin UTF-8 true ttf woff woff2 org.apache.maven.plugins maven-compiler-plugin 1.8 1.8 src/main/resources true ${project.basedir}/bin ${project.build.directory} ================================================ FILE: cachecloud-web/sql/2.0.sql ================================================ -- MySQL dump 10.15 Distrib 10.0.16-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: cachecloud_open -- ------------------------------------------------------ -- Server version 10.0.16-MariaDB-log SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for table `app_audit` -- DROP TABLE IF EXISTS `app_audit`; CREATE TABLE `app_audit` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '申请人的id', `user_name` varchar(64) NOT NULL COMMENT '用户名', `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置', `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1', `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2', `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3', `info` varchar(360) NOT NULL COMMENT '申请描述', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由', `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `operate_id` bigint(20) DEFAULT NULL COMMENT '工单处理人', PRIMARY KEY (`id`), KEY `idx_appid` (`app_id`), KEY `idx_create_time` (`create_time`), KEY `idx_status_create_time` (`status`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_audit_log` -- DROP TABLE IF EXISTS `app_audit_log`; CREATE TABLE `app_audit_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '审批操作人id', `info` longtext NOT NULL COMMENT 'app审批的详细信息', `type` tinyint(4) NOT NULL, `create_time` datetime NOT NULL, `app_audit_id` bigint(20) NOT NULL COMMENT '审批id', PRIMARY KEY (`id`), KEY `idx_audit_appid` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_client_command_minute_statistics` -- DROP TABLE IF EXISTS `app_client_command_minute_statistics`; CREATE TABLE `app_client_command_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `app_id` bigint(20) NOT NULL COMMENT '应用id', `command` varchar(20) NOT NULL COMMENT '命令明文', `cost` bigint(20) DEFAULT NULL COMMENT '命令累计毫秒耗时', `bytes_in` bigint(20) DEFAULT NULL COMMENT '输入流量', `bytes_out` bigint(20) DEFAULT NULL COMMENT '输出流量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx__appid_client_command_currentMin` (`app_id`,`client_ip`,`command`,`current_min`), KEY `idx_currentmin_appid_count_cost` (`current_min`,`app_id`,`count`,`cost`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟命令调用上报数据'; -- -- Table structure for table `app_client_exception_minute_statistics` -- DROP TABLE IF EXISTS `app_client_exception_minute_statistics`; CREATE TABLE `app_client_exception_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `type` tinyint(4) NOT NULL COMMENT '0:connect exception;1:command exception', `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `node` varchar(30) NOT NULL COMMENT '节点信息host:port', `count` bigint(20) DEFAULT NULL COMMENT '累计连接失败次数', `cost` bigint(20) DEFAULT NULL COMMENT '累计连接失败毫秒耗时', `latency_commands` varchar(255) DEFAULT NULL COMMENT '统计命令topN id,逗号分隔', `redis_pool_config` varchar(255) DEFAULT NULL COMMENT 'redis连接池配置信息', PRIMARY KEY (`id`), UNIQUE KEY `idx__client_node_type_currentMin` (`client_ip`,`node`,`type`,`current_min`), KEY `idx_appid_current_min` (`app_id`,`current_min`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据'; -- -- Table structure for table `app_client_latency_command` -- DROP TABLE IF EXISTS `app_client_latency_command`; CREATE TABLE `app_client_latency_command` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `command` varchar(255) NOT NULL COMMENT '命令明文', `size` bigint(20) DEFAULT NULL COMMENT '参数长度', `args` varchar(255) DEFAULT NULL COMMENT '裁剪后参数明文', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `invoke_time` bigint(20) DEFAULT NULL COMMENT '命令调用时间戳', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端异常命令调用详情'; -- -- Table structure for table `app_client_statistic_gather` -- DROP TABLE IF EXISTS `app_client_statistic_gather`; CREATE TABLE `app_client_statistic_gather` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gather_time` varchar(20) NOT NULL COMMENT '统计时间,格式yyyy-mm-dd', `app_id` bigint(20) NOT NULL COMMENT '应用id', `cmd_count` bigint(20) DEFAULT '0' COMMENT '命令调用次数', `conn_exp_count` bigint(20) DEFAULT '0' COMMENT '连接异常次数', `avg_cmd_cost` double DEFAULT '0' COMMENT '命令调用平均耗时,单位毫秒', `avg_cmd_exp_cost` double DEFAULT '0' COMMENT '命令超时平均耗时,单位毫秒', `avg_conn_exp_cost` double DEFAULT '0' COMMENT '连接异常平均耗时,单位毫秒', `cmd_exp_count` bigint(20) DEFAULT '0' COMMENT '命令超时次数', `instance_count` int(11) DEFAULT NULL COMMENT '应用实例数', `avg_mem_frag_ratio` double DEFAULT NULL COMMENT '平均碎片率', `mem_used_ratio` double DEFAULT NULL COMMENT '内存使用率', `exception_count` bigint(20) DEFAULT '0' COMMENT '异常数(旧,待下线)', `slow_log_count` bigint(20) DEFAULT '0' COMMENT '慢查询次数', `latency_count` bigint(20) DEFAULT '0' COMMENT '延迟事件次数', `object_size` bigint(20) DEFAULT '0' COMMENT '存储对象数', `used_memory` bigint(20) DEFAULT '0' COMMENT '内存占用 byte', `used_memory_rss` bigint(20) DEFAULT '0' COMMENT '物理内存占用 byte', `max_cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗(单位:秒)', `max_cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗(单位:秒)', `connected_clients` bigint(20) DEFAULT '0' COMMENT '应用客户端连接数', `topology_exam_result` tinyint(4) DEFAULT NULL COMMENT '拓扑诊断结果,0:正常,1:异常', PRIMARY KEY (`id`), UNIQUE KEY `idx_appid_gathertime` (`app_id`,`gather_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报数据全天统计'; -- -- Table structure for table `app_client_value_minute_stat` -- DROP TABLE IF EXISTS `app_client_value_minute_stat`; CREATE TABLE `app_client_value_minute_stat` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用appid', `collect_time` bigint(20) NOT NULL COMMENT '数据收集时间yyyyMMddHHmm00', `update_time` datetime NOT NULL COMMENT '更新时间', `command` varchar(20) NOT NULL COMMENT '执行命令', `distribute_type` tinyint(4) NOT NULL COMMENT '值分布', `count` int(11) NOT NULL COMMENT '命令执行次数', PRIMARY KEY (`id`), UNIQUE KEY `app_collect_command_dis` (`app_id`,`collect_time`,`command`,`distribute_type`), KEY `idx_collect_time` (`collect_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计'; -- -- Table structure for table `app_client_version_statistic` -- DROP TABLE IF EXISTS `app_client_version_statistic`; CREATE TABLE `app_client_version_statistic` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址', `client_version` varchar(20) NOT NULL COMMENT '客户端版本', `report_time` datetime DEFAULT NULL COMMENT '上报时间', PRIMARY KEY (`id`), UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`), KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_daily` -- DROP TABLE IF EXISTS `app_daily`; CREATE TABLE `app_daily` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `date` date NOT NULL COMMENT '日期', `create_time` datetime NOT NULL, `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数', `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数', `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数', `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数', `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数', `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数', `avg_hit_ratio` double NOT NULL COMMENT '平均命中率', `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率', `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率', `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量', `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量', `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数', `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数', `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量', `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量', `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量', `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量', `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值', `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值', `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数', `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情', `client_cmd_count` bigint(20) NOT NULL COMMENT '累计命令调用次数', `client_avg_cmd_cost` double NOT NULL COMMENT '平均命令调用耗时', `client_conn_exp_count` bigint(20) NOT NULL COMMENT '累计连接异常事件次数', `client_avg_conn_exp_cost` double NOT NULL COMMENT '平均连接异常事件耗时', `client_cmd_exp_count` bigint(20) NOT NULL COMMENT '累计命令超时事件次数', `client_avg_cmd_exp_cost` double NOT NULL COMMENT '平均命令超时事件耗时', PRIMARY KEY (`id`), KEY `idx_appid_date` (`app_id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报'; -- -- Table structure for table `app_data_migrate_status` -- DROP TABLE IF EXISTS `app_data_migrate_status`; CREATE TABLE `app_data_migrate_status` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip', `migrate_machine_port` int(11) NOT NULL COMMENT '迁移工具所占port', `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表', `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表', `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id', `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id', `user_id` bigint(20) NOT NULL COMMENT '操作人', `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常', `start_time` datetime NOT NULL COMMENT '迁移开始执行时间', `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间', `log_path` varchar(255) NOT NULL COMMENT '日志文件路径', `config_path` varchar(255) NOT NULL COMMENT '配置文件路径', `migrate_id` varchar(50) DEFAULT NULL COMMENT 'migrate id', `migrate_tool` tinyint(4) DEFAULT NULL COMMENT 'migrate_tool, 0:redis-shake,1:redis-migrate-tool', `redis_source_version` varchar(20) DEFAULT NULL, `redis_target_version` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用迁移记录详情'; -- -- Table structure for table `app_desc` -- DROP TABLE IF EXISTS `app_desc`; CREATE TABLE `app_desc` ( `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id', `name` varchar(36) NOT NULL COMMENT '应用名', `user_id` bigint(20) NOT NULL COMMENT '申请人id', `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配,1申请未审批,2审批并发布 3:应用下线', `intro` varchar(255) NOT NULL COMMENT '应用描述', `create_time` datetime NOT NULL COMMENT '创建时间', `passed_time` datetime NOT NULL COMMENT '审批通过时间', `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型,1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud ,5. redis-sentinel ,6.redis-standalone ', `officer` varchar(32) NOT NULL COMMENT '负责人,中文', `ver_id` int(11) NOT NULL COMMENT '版本', `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试:1是0否', `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否', `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否', `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否', `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps', `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数', `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值', `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息', `client_conn_alert_value` int(11) DEFAULT '2000' COMMENT '客户端连接报警阀值', `app_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥', `important_level` tinyint(4) NOT NULL DEFAULT '2' COMMENT '应用级别,1:最重要,2:一般重要,3:一般', `password` varchar(255) DEFAULT '' COMMENT 'redis密码', `hit_precent_alert_value` int(11) DEFAULT '0' COMMENT '命中率报警阀值 0:不报警 ', `is_access_monitor` int(11) DEFAULT '0' COMMENT '是否接入全局监控报警 默认0,0:不接入监控 1:接入监控', `app_fsync_value` int(11) DEFAULT '1' COMMENT '应用刷盘策略 1:主从节点appdendfsync=everysec 2:主从节点 appdendfsync=no', `version_id` int(11) NOT NULL DEFAULT '1' COMMENT 'Redis版本表主键id', PRIMARY KEY (`app_id`), UNIQUE KEY `uidx_app_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app应用描述' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_command_statistics` -- DROP TABLE IF EXISTS `app_hour_command_statistics`; CREATE TABLE `app_hour_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_statistics` -- DROP TABLE IF EXISTS `app_hour_statistics`; CREATE TABLE `app_hour_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH', `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和', `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和', `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值', `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '每小时修改时间最大值', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_command_statistics` -- DROP TABLE IF EXISTS `app_minute_command_statistics`; CREATE TABLE `app_minute_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_statistics` -- DROP TABLE IF EXISTS `app_minute_statistics`; CREATE TABLE `app_minute_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `hits` bigint(20) NOT NULL COMMENT '命中数量', `misses` bigint(20) NOT NULL COMMENT '未命中数量', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '内存占用', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量', `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '客户端连接数', `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_to_user` -- DROP TABLE IF EXISTS `app_to_user`; CREATE TABLE `app_to_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '用户id', `app_id` bigint(20) NOT NULL COMMENT '应用id', PRIMARY KEY (`id`), KEY `app_id` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_user` -- DROP TABLE IF EXISTS `app_user`; CREATE TABLE `app_user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '用户名', `ch_name` varchar(255) NOT NULL COMMENT '中文名', `email` varchar(64) NOT NULL COMMENT '邮箱', `mobile` varchar(16) NOT NULL COMMENT '手机', `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员,1预留,2普通用户,-1无效', `weChat` varchar(32) DEFAULT NULL COMMENT '微信号', `isAlert` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户是否接收报警 0:不接收 1:接收', PRIMARY KEY (`id`), UNIQUE KEY `uidx_user_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' /* `compression`='tokudb_zlib' */; -- ---------------------------- -- Records of `app_user` -- ---------------------------- BEGIN; INSERT INTO `app_user` VALUES ('1', 'admin', 'admin', 'admin@xxx.com', '13500000000', '0', null, '1'); COMMIT; -- -- Table structure for table `brevity_schedule_resources` -- DROP TABLE IF EXISTS `brevity_schedule_resources`; CREATE TABLE `brevity_schedule_resources` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(4) NOT NULL COMMENT '类型,见:BrevityScheduleType', `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '时间版本', `host` varchar(16) NOT NULL COMMENT '资源ip', `port` int(11) NOT NULL DEFAULT '0' COMMENT '端口', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_type_host_port` (`type`,`host`,`port`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='短频任务表'; -- -- Table structure for table `diagnostic_task_record` -- DROP TABLE IF EXISTS `diagnostic_task_record`; CREATE TABLE `diagnostic_task_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `type` int(11) DEFAULT NULL COMMENT '诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam', `task_id` bigint(20) DEFAULT NULL COMMENT '任务流id', `audit_id` bigint(20) DEFAULT NULL COMMENT '审批id', `status` int(11) DEFAULT NULL COMMENT '诊断状态:0开始 1结束 2异常', `cost` bigint(20) DEFAULT NULL COMMENT '耗时,毫秒', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `redis_key` varchar(100) DEFAULT NULL COMMENT '结果的key', `node` varchar(100) DEFAULT NULL COMMENT '实例,host:port', `parent_task_id` bigint(20) DEFAULT NULL COMMENT '父任务id', `diagnostic_condition` varchar(100) DEFAULT NULL COMMENT '诊断条件', `param1` varchar(100) DEFAULT NULL COMMENT '备用参数1', `param2` varchar(100) DEFAULT NULL COMMENT '备用参数2', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用诊断记录'; -- -- Table structure for table `instance_alert_configs` -- DROP TABLE IF EXISTS `instance_alert_configs`; CREATE TABLE `instance_alert_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `alert_config` varchar(255) NOT NULL COMMENT '报警配置', `alert_value` varchar(512) NOT NULL COMMENT '报警阀值', `config_info` varchar(255) NOT NULL COMMENT '配置说明', `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警', `instance_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0:全局配置,其他代表实例id', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `compare_type` tinyint(4) NOT NULL COMMENT '比较类型:1小于,2等于,3大于,4不等于', `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天', `update_time` datetime NOT NULL COMMENT '报警配置更新时间', `last_check_time` datetime NOT NULL COMMENT '上次检查时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置'; -- ---------------------------- -- Records of `instance_alert_configs` -- ---------------------------- BEGIN; INSERT INTO `instance_alert_configs` VALUES ('9', 'aof_current_size', '6000', 'aof当前尺寸(单位:MB)', '1', '0', '1', '3', '3', '2017-06-19 09:43:22', '2020-09-17 10:52:00'), ('10', 'aof_delayed_fsync', '3', '分钟aof阻塞个数', '1', '0', '1', '3', '1', '2017-06-19 10:38:19', '2020-09-17 11:09:00'), ('11', 'client_biggest_input_buf', '10', '输入缓冲区最大buffer大小(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 10:47:03', '2020-09-17 11:09:00'), ('12', 'client_longest_output_list', '50000', '输出缓冲区最大队列长度', '1', '0', '1', '3', '1', '2017-06-19 10:55:45', '2020-09-17 11:09:00'), ('13', 'instantaneous_ops_per_sec', '60000', '实时ops', '1', '0', '1', '3', '1', '2017-06-19 11:02:38', '2020-09-17 11:09:00'), ('14', 'latest_fork_usec', '400000', '上次fork所用时间(单位:微秒)', '1', '0', '1', '3', '5', '2017-06-19 11:21:35', '2020-09-16 16:51:00'), ('15', 'mem_fragmentation_ratio', '1.5', '内存碎片率(检测大于500MB)', '1', '0', '1', '3', '5', '2017-06-19 12:49:16', '2020-09-16 16:51:00'), ('16', 'rdb_last_bgsave_status', 'ok', '上一次bgsave状态', '1', '0', '1', '4', '4', '2017-06-19 14:15:21', '2020-09-17 10:19:00'), ('17', 'total_net_output_bytes', '5000', '分钟网络输出流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:39:44', '2020-09-17 11:09:00'), ('19', 'total_net_input_bytes', '1200', '分钟网络输入流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:45:44', '2020-09-17 11:09:00'), ('20', 'sync_partial_err', '0', '分钟部分复制失败次数', '1', '0', '1', '3', '1', '2017-06-19 18:34:41', '2020-09-17 11:09:00'), ('21', 'sync_partial_ok', '0', '分钟部分复制成功次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:01', '2020-09-17 11:09:00'), ('22', 'sync_full', '0', '分钟全量复制执行次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:17', '2020-09-17 11:09:00'), ('23', 'rejected_connections', '0', '分钟拒绝连接数', '1', '0', '1', '3', '1', '2017-06-19 18:35:36', '2020-09-17 11:09:00'), ('54', 'master_slave_offset_diff', '20000000', '主从节点偏移量差(单位:字节)', '1', '0', '1', '3', '2', '2017-06-20 18:58:56', '2020-09-17 11:06:00'), ('56', 'cluster_state', 'ok', '集群状态', '1', '0', '1', '4', '1', '2017-06-21 18:01:52', '2020-09-17 11:09:00'), ('57', 'cluster_slots_ok', '16384', '集群成功分配槽个数', '1', '0', '1', '4', '1', '2017-06-21 18:02:04', '2020-09-17 11:09:00'); COMMIT; -- -- Table structure for table `instance_big_key` -- DROP TABLE IF EXISTS `instance_big_key`; CREATE TABLE `instance_big_key` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `audit_id` bigint(20) NOT NULL COMMENT 'audit id', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从,详见InstanceRoleEnum', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `big_key` varchar(255) NOT NULL COMMENT '键', `type` varchar(16) NOT NULL COMMENT '类型:string,hash,list,set,zset', `length` int(11) NOT NULL COMMENT '长度', `create_time` datetime NOT NULL COMMENT '记录创建时间', PRIMARY KEY (`id`), KEY `idx_app_audit` (`app_id`,`audit_id`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例bigkey列表'; -- -- Table structure for table `instance_config` -- DROP TABLE IF EXISTS `instance_config`; CREATE TABLE `instance_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Redis版本表主键id', `refresh` mediumint(9) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例配置模板'; -- ---------------------------- -- Records of `instance_config` -- ---------------------------- BEGIN; INSERT INTO `instance_config` VALUES ('1', 'cluster-enabled', 'yes', '是否开启集群模式', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('2', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('3', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('4', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('5', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('6', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2016-07-05 15:08:31', '2', '1', '29', '0'), ('7', 'port', '%d', 'sentinel实例端口', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('8', 'dir', '%s', '工作目录', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('9', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('10', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('11', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('12', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('13', 'daemonize', 'no', '是否守护进程', '2016-07-14 14:00:05', '6', '1', '29', '0'), ('14', 'tcp-backlog', '511', 'TCP连接完成队列', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('15', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('16', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2016-12-06 11:40:46', '6', '1', '29', '0'), ('17', 'loglevel', 'notice', '日志级别', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('18', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('19', 'dir', '%s', 'redis工作目录', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('20', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('21', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('22', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('23', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('24', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('25', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('26', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('27', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('28', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('29', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('30', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('31', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('32', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('33', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('34', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('35', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('36', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('37', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('38', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('39', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('40', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('41', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2016-11-24 10:24:21', '6', '1', '29', '0'), ('42', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('43', 'hz', '10', '执行后台task数量,默认:10', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('44', 'port', '%d', '端口', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('45', 'maxmemory', '%dmb', '当前实例最大可用内存', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('46', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('47', 'appendonly', 'yes', '开启append only持久化模式', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('48', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('49', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('50', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('51', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('52', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('53', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('54', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('55', 'maxclients', '10000', '客户端最大连接数', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('126', 'cluster-enabled', 'yes', '是否开启集群模式', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('127', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('128', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('129', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('130', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('131', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('132', 'port', '%d', 'sentinel实例端口', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('133', 'dir', '%s', '工作目录', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('134', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('135', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('136', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('137', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('138', 'daemonize', 'no', '是否守护进程', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('139', 'tcp-backlog', '511', 'TCP连接完成队列', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('140', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('141', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('142', 'loglevel', 'notice', '日志级别', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('143', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('144', 'dir', '%s', 'redis工作目录', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('145', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('146', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('147', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('148', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('149', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('150', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('151', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('152', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('153', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('154', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('155', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('156', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('157', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('158', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('159', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2018-09-18 18:25:32', '6', '0', '31', '0'), ('160', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2018-09-18 18:25:40', '6', '0', '31', '0'), ('161', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('162', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('163', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('164', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('165', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('166', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('167', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('168', 'hz', '10', '执行后台task数量,默认:10', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('169', 'port', '%d', '端口', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('170', 'maxmemory', '%dmb', '当前实例最大可用内存', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('171', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('172', 'appendonly', 'yes', '开启append only持久化模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('173', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('174', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('175', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('176', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('177', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('178', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('179', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('180', 'maxclients', '10000', '客户端最大连接数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('181', 'protected-mode', 'yes', '开启保护模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('182', 'bind', '0.0.0.0', '默认客户端都可连接', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('185', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2018-09-18 18:26:32', '6', '1', '31', '0'), ('186', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2018-09-18 18:27:12', '6', '1', '31', '0'), ('253', 'protected-mode', 'no', '关闭保护模式', '2018-11-01 16:10:59', '5', '1', '31', '0'), ('354', 'cluster-enabled', 'yes', '是否开启集群模式', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('355', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('356', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('357', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('358', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('359', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('360', 'port', '%d', 'sentinel实例端口', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('361', 'dir', '%s', '工作目录', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('362', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('363', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('364', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('365', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('366', 'daemonize', 'no', '是否守护进程', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('367', 'tcp-backlog', '511', 'TCP连接完成队列', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('368', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('369', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('370', 'loglevel', 'notice', '日志级别', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('371', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('372', 'dir', '%s', 'redis工作目录', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('373', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('374', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('375', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('376', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('377', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('378', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('379', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('380', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('381', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('382', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('383', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('384', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('385', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('386', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('387', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('388', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('389', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('390', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('391', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('392', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('393', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('394', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('395', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('396', 'hz', '10', '执行后台task数量,默认:10', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('397', 'port', '%d', '端口', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('398', 'maxmemory', '%dmb', '当前实例最大可用内存', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('399', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('400', 'appendonly', 'yes', '开启append only持久化模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('401', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('402', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('403', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('404', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('405', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('406', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('407', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('408', 'maxclients', '10000', '客户端最大连接数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('409', 'protected-mode', 'yes', '开启保护模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('410', 'bind', '0.0.0.0', '默认客户端都可连接', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('411', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('412', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('413', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('414', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('415', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('416', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('417', 'slave-lazy-flush', 'yes', 'slave发起全量复制,是否采用flushall async清理老数据 默认值 no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('418', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2019-10-31 11:15:57', '6', '1', '12', '0'), ('419', 'protected-mode', 'no', '关闭sentinel保护模式', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('420', 'activedefrag', 'no', '碎片整理开启', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('421', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('422', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('423', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('424', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('425', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('506', 'cluster-enabled', 'yes', '是否开启集群模式', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('507', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('508', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('509', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('510', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('511', 'port', '%d', 'sentinel实例端口', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('512', 'dir', '%s', '工作目录', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('513', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('514', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('515', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('516', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('517', 'daemonize', 'no', '是否守护进程', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('518', 'tcp-backlog', '511', 'TCP连接完成队列', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('519', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('520', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('521', 'loglevel', 'notice', '日志级别', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('522', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('523', 'dir', '%s', 'redis工作目录', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('524', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('525', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('526', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('527', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('528', 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('529', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('530', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('531', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('532', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('533', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('534', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('535', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('536', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('537', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('538', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('539', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('540', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('541', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('542', 'hz', '10', '执行后台task数量,默认:10', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('543', 'port', '%d', '端口', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('544', 'maxmemory', '%dmb', '当前实例最大可用内存', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('545', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('546', 'appendonly', 'yes', '开启append only持久化模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('547', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('548', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('549', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('550', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('551', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('552', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('553', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('554', 'maxclients', '10000', '客户端最大连接数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('555', 'protected-mode', 'yes', '开启保护模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('556', 'bind', '0.0.0.0', '默认客户端都可连接', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('557', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('558', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('559', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('560', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('561', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('562', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('563', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('564', 'protected-mode', 'no', '关闭sentinel保护模式', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('565', 'activedefrag', 'yes', '碎片整理开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('566', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('567', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('568', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('569', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('570', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('571', 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('572', 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('573', 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('574', 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('575', 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('576', 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('577', 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('578', 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('579', 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('580', 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('581', 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('582', 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('583', 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('585', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:45:22', '6', '1', '37', '0'), ('587', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:18', '6', '1', '12', '0'), ('589', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:49', '6', '1', '31', '0'), ('590', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:49:47', '6', '1', '29', '0'); COMMIT; -- -- Table structure for table `instance_fault` -- DROP TABLE IF EXISTS `instance_fault`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `instance_fault` ( `id` int(11) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `inst_id` bigint(20) NOT NULL COMMENT '实例id', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `type` mediumint(4) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `reason` mediumtext NOT NULL COMMENT '故障原因描述', PRIMARY KEY (`id`), KEY `idx_ip_port` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `inst_id` (`inst_id`) ) ENGINE=InnoDB AUTO_INCREMENT=8927 DEFAULT CHARSET=utf8 COMMENT='实例故障表' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `instance_host` -- DROP TABLE IF EXISTS `instance_host`; CREATE TABLE `instance_host` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `ip` varchar(16) NOT NULL COMMENT '机器ip', `ssh_user` varchar(32) DEFAULT NULL COMMENT 'ssh用户', `ssh_pwd` varchar(32) DEFAULT NULL COMMENT 'ssh密码', `warn` int(5) DEFAULT '1' COMMENT '0不报警,1报警', PRIMARY KEY (`id`), UNIQUE KEY `uidx_host_ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_info` -- DROP TABLE IF EXISTS `instance_info`; CREATE TABLE `instance_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'memcached instance id', `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id', `app_id` bigint(20) NOT NULL COMMENT '应用id,与app_desc关联', `host_id` bigint(20) NOT NULL COMMENT '对应的主机id,与instance_host关联', `ip` varchar(16) NOT NULL COMMENT '实例的ip', `port` int(11) NOT NULL COMMENT '实例端口', `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线', `mem` int(11) NOT NULL COMMENT '内存大小', `conn` int(11) NOT NULL COMMENT '连接数', `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName', `type` mediumint(11) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`) USING BTREE, KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_latency_history` -- DROP TABLE IF EXISTS `instance_latency_history`; CREATE TABLE `instance_latency_history` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `event` varchar(255) NOT NULL COMMENT '事件名称', `execute_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `execution_cost` bigint(20) NOT NULL COMMENT '耗时(微妙)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `latencyistorykey` (`instance_id`,`event`,`execute_date`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executedate` (`app_id`,`execute_date`), KEY `idx_executedate` (`execute_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例延迟事件信息表'; -- -- Table structure for table `instance_minute_stats` -- DROP TABLE IF EXISTS `instance_minute_stats`; CREATE TABLE `instance_minute_stats` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `json` text NOT NULL COMMENT '统计json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例分钟统计表'; -- -- Table structure for table `instance_reshard_process` -- DROP TABLE IF EXISTS `instance_reshard_process`; CREATE TABLE `instance_reshard_process` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `audit_id` bigint(20) NOT NULL COMMENT '审核id', `source_instance_id` int(11) NOT NULL COMMENT '源实例id', `target_instance_id` int(11) NOT NULL COMMENT '目标实例id', `start_slot` int(11) NOT NULL COMMENT '开始slot', `end_slot` int(11) NOT NULL COMMENT '结束slot', `migrating_slot` int(11) NOT NULL COMMENT '正在迁移的slot', `is_pipeline` tinyint(4) NOT NULL COMMENT '是否为pipeline,0:否,1:是', `finish_slot_num` int(11) NOT NULL COMMENT '已经完成迁移的slot数量', `status` tinyint(4) NOT NULL COMMENT '0:运行中 1:完成 2:出错', `start_time` datetime NOT NULL COMMENT '迁移开始时间', `end_time` datetime NOT NULL COMMENT '迁移结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_audit` (`audit_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度'; -- -- Table structure for table `instance_slow_log` -- DROP TABLE IF EXISTS `instance_slow_log`; CREATE TABLE `instance_slow_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id', `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)', `command` varchar(255) NOT NULL COMMENT '执行命令', `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间', PRIMARY KEY (`id`), UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executetime` (`app_id`,`execute_time`), KEY `idx_executetime` (`execute_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表'; -- -- Table structure for table `instance_statistics` -- DROP TABLE IF EXISTS `instance_statistics`; CREATE TABLE `instance_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `inst_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `host_id` bigint(20) NOT NULL COMMENT '机器的id', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `port` int(255) NOT NULL COMMENT 'port', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从', `max_memory` bigint(255) NOT NULL COMMENT '预分配内存,单位byte', `used_memory` bigint(255) NOT NULL COMMENT '已使用内存,单位byte', `curr_items` bigint(255) NOT NULL COMMENT '当前item数量', `curr_connections` int(255) NOT NULL COMMENT '当前连接数', `misses` bigint(255) NOT NULL COMMENT 'miss数', `hits` bigint(255) NOT NULL COMMENT '命中数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mem_fragmentation_ratio` double DEFAULT '0' COMMENT '碎片率', `aof_delayed_fsync` int(11) DEFAULT '0' COMMENT 'aof阻塞次数', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `machine_id` (`host_id`), KEY `idx_inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_info` -- DROP TABLE IF EXISTS `machine_info`; CREATE TABLE `machine_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id', `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户', `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房', `mem` int(11) unsigned NOT NULL COMMENT '内存大小,单位G', `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量', `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟,0表示否,1表示是', `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip', `service_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上线时间', `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警,0不启用,1启用', `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用,1表示可用,0表示不可用;', `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组,默认为0,表示原生资源,非0表示外部提供的资源(可扩展)', `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他', `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))', `collect` int(11) DEFAULT '1' COMMENT 'switch of collect server status, 1:open, 0:close', `version_install` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '机器安装redis版本状态', `use_type` tinyint(4) DEFAULT '2' COMMENT '使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis-Sentinel机器(3)', `k8s_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否k8s容器:0:不是 1:是', `rack` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '机器所在机架信息', `is_allocating` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否在分配中,1是0否', `disk` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '磁盘空间:G', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='机器信息表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_relation` -- DROP TABLE IF EXISTS `machine_relation`; CREATE TABLE `machine_relation` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `ip` varchar(64) NOT NULL COMMENT '虚拟机ip', `real_ip` varchar(64) NOT NULL COMMENT '宿主机ip', `extra_desc` varchar(128) DEFAULT NULL COMMENT '实例描述信息', `status` int(255) NOT NULL COMMENT '实例变更状态 0:offline ,1:online', `is_sync` tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据同步状态 0: 未同步数据 -1:同步中 1:数据已同步 -2:同步失败 ', `sync_time` timestamp NULL DEFAULT NULL COMMENT '同步时间', `update_time` timestamp NULL DEFAULT NULL COMMENT 'pod最后更新时间', `taskid` bigint(11) DEFAULT NULL COMMENT '任务id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `machine_room` -- DROP TABLE IF EXISTS `machine_room`; CREATE TABLE `machine_room` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机房id', `name` varchar(255) NOT NULL COMMENT '机房名称', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `desc` varchar(255) DEFAULT NULL COMMENT '机房描述信息', `ip_network` varchar(32) NOT NULL DEFAULT '' COMMENT '机房网段信息', `operator` varchar(255) DEFAULT NULL COMMENT '运营商', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `machine_room` -- ---------------------------- BEGIN; INSERT INTO `machine_room` VALUES ('1', '阿里云杭州', '1', '阿里云-杭州机房', '172.27.*.*', '阿里云'); COMMIT; -- -- Table structure for table `machine_statistics` -- DROP TABLE IF EXISTS `machine_statistics`; CREATE TABLE `machine_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `host_id` bigint(20) NOT NULL COMMENT '机器id', `ip` varchar(16) NOT NULL COMMENT '机器ip', `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率', `load` varchar(120) NOT NULL COMMENT '机器负载', `traffic` varchar(120) NOT NULL COMMENT 'io网络流量', `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率', `memory_free` varchar(120) NOT NULL COMMENT '内存剩余', `memory_total` varchar(120) NOT NULL COMMENT '总内存量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `max_memory` int(11) DEFAULT '0' COMMENT '机器分配内存,单位MB', `instance_count` int(11) DEFAULT '0' COMMENT '机器实例数量', `machine_memory` int(11) DEFAULT '0' COMMENT '机器入库总内存,单位MB', PRIMARY KEY (`id`), UNIQUE KEY `uidx_ip` (`ip`), KEY `host_id` (`host_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_blob_triggers` -- DROP TABLE IF EXISTS `qrtz_blob_triggers`; CREATE TABLE `qrtz_blob_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_calendars` -- DROP TABLE IF EXISTS `qrtz_calendars`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `qrtz_calendars` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称', `CALENDAR` blob NOT NULL COMMENT 'calendar信息', PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `qrtz_cron_triggers` -- DROP TABLE IF EXISTS `qrtz_cron_triggers`; CREATE TABLE `qrtz_cron_triggers` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_fired_triggers` -- DROP TABLE IF EXISTS `qrtz_fired_triggers`; CREATE TABLE `qrtz_fired_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(195) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(13) NOT NULL, `SCHED_TIME` bigint(13) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化', PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息,以及关联 Job 的执行信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_job_details` -- DROP TABLE IF EXISTS `qrtz_job_details`; CREATE TABLE `qrtz_job_details` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化,0不持久化,1持久化', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发,0非并发,1并发', `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复,0不恢复,1恢复', `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_locks` -- DROP TABLE IF EXISTS `qrtz_locks`; CREATE TABLE `qrtz_locks` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_paused_trigger_grps` -- DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; CREATE TABLE `qrtz_paused_trigger_grps` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_scheduler_state` -- DROP TABLE IF EXISTS `qrtz_scheduler_state`; CREATE TABLE `qrtz_scheduler_state` ( `SCHED_NAME` varchar(120) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_simple_triggers` -- DROP TABLE IF EXISTS `qrtz_simple_triggers`; CREATE TABLE `qrtz_simple_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_simprop_triggers` -- DROP TABLE IF EXISTS `qrtz_simprop_triggers`; CREATE TABLE `qrtz_simprop_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `STR_PROP_1` varchar(512) DEFAULT NULL, `STR_PROP_2` varchar(512) DEFAULT NULL, `STR_PROP_3` varchar(512) DEFAULT NULL, `INT_PROP_1` int(11) DEFAULT NULL, `INT_PROP_2` int(11) DEFAULT NULL, `LONG_PROP_1` bigint(20) DEFAULT NULL, `LONG_PROP_2` bigint(20) DEFAULT NULL, `DEC_PROP_1` decimal(13,4) DEFAULT NULL, `DEC_PROP_2` decimal(13,4) DEFAULT NULL, `BOOL_PROP_1` varchar(1) DEFAULT NULL, `BOOL_PROP_2` varchar(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_triggers` -- DROP TABLE IF EXISTS `qrtz_triggers`; CREATE TABLE `qrtz_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(13) NOT NULL, `END_TIME` bigint(13) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(2) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `server` -- DROP TABLE IF EXISTS `server`; CREATE TABLE `server` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `host` varchar(255) DEFAULT NULL COMMENT 'host', `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version', `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num', `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号', `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息', `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息', `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u', `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `server_stat` -- DROP TABLE IF EXISTS `server_stat`; CREATE TABLE `server_stat` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `cdate` date NOT NULL COMMENT '数据收集天', `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟', `cuser` float DEFAULT NULL COMMENT '用户态占比', `csys` float DEFAULT NULL COMMENT '内核态占比', `cwio` float DEFAULT NULL COMMENT 'wio占比', `c_ext` text COMMENT '子cpu占比', `cload1` float DEFAULT NULL COMMENT '1分钟load', `cload5` float DEFAULT NULL COMMENT '5分钟load', `cload15` float DEFAULT NULL COMMENT '15分钟load', `mtotal` float DEFAULT NULL COMMENT '总内存,单位M', `mfree` float DEFAULT NULL COMMENT '空闲内存', `mcache` float DEFAULT NULL COMMENT 'cache', `mbuffer` float DEFAULT NULL COMMENT 'buffer', `mswap` float DEFAULT NULL COMMENT 'cache', `mswap_free` float DEFAULT NULL COMMENT 'cache', `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s', `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s', `nin_ext` text COMMENT '各网卡入流量详情', `nout_ext` text COMMENT '各网卡出流量详情', `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数', `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数', `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数', `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s', `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s', `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s', `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比', `d_ext` text COMMENT '磁盘各分区占比', `dspace` text COMMENT '磁盘各分区空间使用率', PRIMARY KEY (`ip`,`cdate`,`ctime`), KEY `idx_cdate` (`cdate`), KEY `idx_cdate_ctime` (`cdate`,`ctime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `system_config` -- DROP TABLE IF EXISTS `system_config`; CREATE TABLE `system_config` ( `config_key` varchar(255) NOT NULL COMMENT '配置key', `config_value` varchar(512) NOT NULL COMMENT '配置value', `info` varchar(255) NOT NULL COMMENT '配置说明', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `order_id` int(11) NOT NULL COMMENT '顺序', PRIMARY KEY (`config_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置'; -- ---------------------------- -- Records of `system_config` -- ---------------------------- BEGIN; INSERT INTO `system_config` VALUES ('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,11),('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,12),('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,33),('cachecloud.base.dir','/opt','cachecloud根目录,要和cachecloud-init.sh脚本中的目录一致',1,31),('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)
user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14),('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,22),('cachecloud.email.alert.interface','','邮件报警接口(参考报警接口规范)',1,24),('cachecloud.machine.ssh.name','cachecloud-open','机器ssh用户名',1,2),('cachecloud.machine.ssh.password','cachecloud-open','机器ssh密码',1,3),('cachecloud.machine.ssh.port','22','机器ssh端口',1,10),('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,35),('cachecloud.nmon.dir','/opt/cachecloud','nmon安装目录',1,32),('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,21),('cachecloud.owner.phone','xxx,yyy','手机号报警(逗号隔开)',1,21),('cachecloud.owner.weChat','xxx,yyy','微信号报警(逗号隔开)',1,21),('cachecloud.public.key.pem','/opt/ssh/id_rsa','密钥路径',1,5),('cachecloud.public.user.name','cachecloud-open','公钥用户名',1,4),('cachecloud.ssh.auth.type','1','ssh授权方式',1,1),('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,13),('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,22),('cachecloud.weChat.alert.interface','','微信报警接口(参考报警接口规范)',1,23),('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,34),('machine.load.alert.ratio','8.0','机器负载报警阀值',1,32); COMMIT; -- ---------------------------- -- Table structure for `system_resource` -- ---------------------------- DROP TABLE IF EXISTS `system_resource`; CREATE TABLE `system_resource` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '资源ID', `name` varchar(64) NOT NULL COMMENT '资源名称', `intro` varchar(255) DEFAULT NULL COMMENT '资源说明', `type` tinyint(4) NOT NULL COMMENT '1:仓库地址 2:脚本 3:资源包 4:公钥/私钥 6:目录管理 7:迁移工具管理', `lastmodify` datetime DEFAULT NULL COMMENT '最后更新时间', `dir` varchar(128) DEFAULT NULL COMMENT '资源路径', `url` varchar(128) DEFAULT NULL COMMENT '仓库地址', `ispush` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:未推送 1:已推送', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `username` varchar(255) DEFAULT NULL COMMENT '最后修改人', `task_id` bigint(11) DEFAULT NULL COMMENT '迁移任务id', `compile_info` varchar(255) DEFAULT NULL COMMENT '编译信息', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `system_resource` -- ---------------------------- BEGIN; INSERT INTO `system_resource` VALUES (1,'cachecloud-init.sh','容器初始化脚本',2,'2020-07-15 18:35:41','/script','',0,1,NULL,NULL,NULL),(2,'x.x.x.x',NULL,1,'2020-08-10 10:31:51','/opt/download/software/cachecloud/resource','http://x.x.x.x/software/cachecloud/resource',0,1,'admin',0,NULL),(4,'cachecloud-env.sh','宿主环境脚本',2,'2020-07-15 18:36:28','/script','',0,1,NULL,NULL,NULL),(5,'id_rsa','私钥文件',4,'2020-07-07 10:45:39','/ssh','',0,1,NULL,NULL,NULL),(6,'id_rsa.pub','公钥文件',4,'2020-07-07 10:45:45','/ssh','',0,1,NULL,NULL,NULL),(12,'redis-4.0.14','redis 4.0.14资源包',3,'2020-08-10 09:52:41','/redis','http://download.redis.io/releases/redis-4.0.14.tar.gz',0,1,'admin',532,NULL),(21,'/script','脚本目录管理',6,'2020-08-10 10:51:34','',NULL,0,1,'admin',0,NULL),(28,'/ssh','ssh目录',6,'2020-07-20 17:55:03',NULL,NULL,0,1,'admin',0,NULL),(29,'redis-3.0.7','redis3.0.7 资源包',3,'2020-08-10 09:53:32','/redis','http://download.redis.io/releases/redis-3.0.7.tar.gz',0,1,'admin',529,NULL),(31,'redis-3.2.12','redis 3.2.12 资源包',3,'2020-08-10 15:08:21','/redis','http://download.redis.io/releases/redis-3.2.12.tar.gz',0,1,'admin',530,NULL),(32,'/redis','redis资源包管理',6,'2020-07-20 17:54:59',NULL,NULL,0,1,'admin',0,NULL),(33,'/tool','迁移工具资源包',6,'2020-07-20 17:54:53',NULL,NULL,0,1,'admin',0,NULL),(37,'redis-5.0.9','redis5.0.9 资源包',3,'2020-08-10 09:51:41','/redis','http://download.redis.io/releases/redis-5.0.9.tar.gz',0,1,'admin',533,NULL),(40,'redis-shake-2.0.3','redis 2.0.3\n修复fix 5.0迁移类型问题',7,'2020-08-11 10:53:26','/tool','https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz',0,1,'admin',518,NULL); COMMIT; -- -- Table structure for table `task_queue` -- DROP TABLE IF EXISTS `task_queue`; CREATE TABLE `task_queue` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `class_name` varchar(255) NOT NULL COMMENT '类名', `important_info` varchar(255) NOT NULL DEFAULT '' COMMENT '重要信息', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `param` longtext NOT NULL COMMENT '任务参数(json):随着任务变化', `init_param` longtext NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2中断,3失败', `parent_task_id` bigint(20) NOT NULL COMMENT '父任务id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `priority` int(11) NOT NULL COMMENT '优先级', `error_code` int(11) NOT NULL COMMENT '错误代码', `error_msg` varchar(255) NOT NULL COMMENT '错误消息', `task_note` varchar(255) NOT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务表'; -- -- Table structure for table `task_step_flow` -- DROP TABLE IF EXISTS `task_step_flow`; CREATE TABLE `task_step_flow` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `task_id` bigint(20) NOT NULL COMMENT '任务id', `child_task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '子任务id', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `order_no` int(11) NOT NULL COMMENT '序号', `status` tinyint(4) NOT NULL COMMENT '状态:0未开始、1成功、2中断、3跳过、4失败', `log` text COMMENT '日志', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_task_class_step` (`task_id`,`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤流表'; -- -- Table structure for table `task_step_meta` -- DROP TABLE IF EXISTS `task_step_meta`; CREATE TABLE `task_step_meta` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `step_desc` varchar(255) NOT NULL COMMENT '步骤描述', `ops_device` varchar(255) NOT NULL COMMENT '运维建议', `timeout` int(11) NOT NULL COMMENT '超时时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `order_no` int(11) NOT NULL COMMENT '序号', PRIMARY KEY (`id`), UNIQUE KEY `uk_class_step` (`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤元数据表'; /*!40101 SET character_set_client = @saved_cs_client */; -- ---------------------------- -- Table structure for `standard_statistics` -- ---------------------------- DROP TABLE IF EXISTS `standard_statistics`; CREATE TABLE `standard_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `info_json` text NOT NULL COMMENT '收集的json数据', `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `cluster_info_json` varchar(20480) NOT NULL DEFAULT '' COMMENT '收集的cluster info json数据', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_create_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; ================================================ FILE: cachecloud-web/sql/3.0.sql ================================================ -- MySQL dump 10.15 Distrib 10.0.16-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: cachecloud_open -- ------------------------------------------------------ -- Server version 10.0.16-MariaDB-log SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for table `app_audit` -- DROP TABLE IF EXISTS `app_audit`; CREATE TABLE `app_audit` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '申请人的id', `user_name` varchar(64) NOT NULL COMMENT '用户名', `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置', `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1', `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2', `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3', `info` varchar(360) NOT NULL COMMENT '申请描述', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由', `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `operate_id` bigint(20) DEFAULT NULL COMMENT '工单处理人', PRIMARY KEY (`id`), KEY `idx_appid` (`app_id`), KEY `idx_create_time` (`create_time`), KEY `idx_status_create_time` (`status`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_audit_log` -- DROP TABLE IF EXISTS `app_audit_log`; CREATE TABLE `app_audit_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '审批操作人id', `info` longtext NOT NULL COMMENT 'app审批的详细信息', `type` tinyint(4) NOT NULL, `create_time` datetime NOT NULL, `app_audit_id` bigint(20) NOT NULL COMMENT '审批id', PRIMARY KEY (`id`), KEY `idx_audit_appid` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_client_command_minute_statistics` -- DROP TABLE IF EXISTS `app_client_command_minute_statistics`; CREATE TABLE `app_client_command_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `app_id` bigint(20) NOT NULL COMMENT '应用id', `command` varchar(20) NOT NULL COMMENT '命令明文', `cost` bigint(20) DEFAULT NULL COMMENT '命令累计毫秒耗时', `bytes_in` bigint(20) DEFAULT NULL COMMENT '输入流量', `bytes_out` bigint(20) DEFAULT NULL COMMENT '输出流量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx__appid_client_command_currentMin` (`app_id`,`client_ip`,`command`,`current_min`), KEY `idx_currentmin_appid_count_cost` (`current_min`,`app_id`,`count`,`cost`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟命令调用上报数据'; -- -- Table structure for table `app_client_exception_minute_statistics` -- DROP TABLE IF EXISTS `app_client_exception_minute_statistics`; CREATE TABLE `app_client_exception_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `type` tinyint(4) NOT NULL COMMENT '0:connect exception;1:command exception', `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `node` varchar(30) NOT NULL COMMENT '节点信息host:port', `count` bigint(20) DEFAULT NULL COMMENT '累计连接失败次数', `cost` bigint(20) DEFAULT NULL COMMENT '累计连接失败毫秒耗时', `latency_commands` varchar(255) DEFAULT NULL COMMENT '统计命令topN id,逗号分隔', `redis_pool_config` varchar(255) DEFAULT NULL COMMENT 'redis连接池配置信息', PRIMARY KEY (`id`), UNIQUE KEY `idx__client_node_type_currentMin` (`client_ip`,`node`,`type`,`current_min`), KEY `idx_appid_current_min` (`app_id`,`current_min`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据'; -- -- Table structure for table `app_client_latency_command` -- DROP TABLE IF EXISTS `app_client_latency_command`; CREATE TABLE `app_client_latency_command` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `command` varchar(255) NOT NULL COMMENT '命令明文', `size` bigint(20) DEFAULT NULL COMMENT '参数长度', `args` varchar(255) DEFAULT NULL COMMENT '裁剪后参数明文', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `invoke_time` bigint(20) DEFAULT NULL COMMENT '命令调用时间戳', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端异常命令调用详情'; -- -- Table structure for table `app_client_statistic_gather` -- DROP TABLE IF EXISTS `app_client_statistic_gather`; CREATE TABLE `app_client_statistic_gather` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gather_time` varchar(20) NOT NULL COMMENT '统计时间,格式yyyy-mm-dd', `app_id` bigint(20) NOT NULL COMMENT '应用id', `cmd_count` bigint(20) DEFAULT '0' COMMENT '命令调用次数', `conn_exp_count` bigint(20) DEFAULT '0' COMMENT '连接异常次数', `avg_cmd_cost` double DEFAULT '0' COMMENT '命令调用平均耗时,单位毫秒', `avg_cmd_exp_cost` double DEFAULT '0' COMMENT '命令超时平均耗时,单位毫秒', `avg_conn_exp_cost` double DEFAULT '0' COMMENT '连接异常平均耗时,单位毫秒', `cmd_exp_count` bigint(20) DEFAULT '0' COMMENT '命令超时次数', `instance_count` int(11) DEFAULT NULL COMMENT '应用实例数', `avg_mem_frag_ratio` double DEFAULT NULL COMMENT '平均碎片率', `mem_used_ratio` double DEFAULT NULL COMMENT '内存使用率', `exception_count` bigint(20) DEFAULT '0' COMMENT '异常数(旧,待下线)', `slow_log_count` bigint(20) DEFAULT '0' COMMENT '慢查询次数', `latency_count` bigint(20) DEFAULT '0' COMMENT '延迟事件次数', `object_size` bigint(20) DEFAULT '0' COMMENT '存储对象数', `used_memory` bigint(20) DEFAULT '0' COMMENT '内存占用 byte', `used_memory_rss` bigint(20) DEFAULT '0' COMMENT '物理内存占用 byte', `max_cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗(单位:秒)', `max_cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗(单位:秒)', `connected_clients` bigint(20) DEFAULT '0' COMMENT '应用客户端连接数', `topology_exam_result` tinyint(4) DEFAULT NULL COMMENT '拓扑诊断结果,0:正常,1:异常', PRIMARY KEY (`id`), UNIQUE KEY `idx_appid_gathertime` (`app_id`,`gather_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报数据全天统计'; -- -- Table structure for table `app_client_value_minute_stat` -- DROP TABLE IF EXISTS `app_client_value_minute_stat`; CREATE TABLE `app_client_value_minute_stat` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用appid', `collect_time` bigint(20) NOT NULL COMMENT '数据收集时间yyyyMMddHHmm00', `update_time` datetime NOT NULL COMMENT '更新时间', `command` varchar(20) NOT NULL COMMENT '执行命令', `distribute_type` tinyint(4) NOT NULL COMMENT '值分布', `count` int(11) NOT NULL COMMENT '命令执行次数', PRIMARY KEY (`id`), UNIQUE KEY `app_collect_command_dis` (`app_id`,`collect_time`,`command`,`distribute_type`), KEY `idx_collect_time` (`collect_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计'; -- -- Table structure for table `app_client_version_statistic` -- DROP TABLE IF EXISTS `app_client_version_statistic`; CREATE TABLE `app_client_version_statistic` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址', `client_version` varchar(20) NOT NULL COMMENT '客户端版本', `report_time` datetime DEFAULT NULL COMMENT '上报时间', PRIMARY KEY (`id`), UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`), KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_daily` -- DROP TABLE IF EXISTS `app_daily`; CREATE TABLE `app_daily` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `date` date NOT NULL COMMENT '日期', `create_time` datetime NOT NULL, `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数', `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数', `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数', `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数', `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数', `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数', `avg_hit_ratio` double NOT NULL COMMENT '平均命中率', `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率', `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率', `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量', `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量', `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数', `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数', `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量', `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量', `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量', `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量', `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值', `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值', `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数', `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情', `client_cmd_count` bigint(20) NOT NULL COMMENT '累计命令调用次数', `client_avg_cmd_cost` double NOT NULL COMMENT '平均命令调用耗时', `client_conn_exp_count` bigint(20) NOT NULL COMMENT '累计连接异常事件次数', `client_avg_conn_exp_cost` double NOT NULL COMMENT '平均连接异常事件耗时', `client_cmd_exp_count` bigint(20) NOT NULL COMMENT '累计命令超时事件次数', `client_avg_cmd_exp_cost` double NOT NULL COMMENT '平均命令超时事件耗时', PRIMARY KEY (`id`), KEY `idx_appid_date` (`app_id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报'; -- -- Table structure for table `app_data_migrate_status` -- DROP TABLE IF EXISTS `app_data_migrate_status`; CREATE TABLE `app_data_migrate_status` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip', `migrate_machine_port` int(11) NOT NULL COMMENT '迁移工具所占port', `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表', `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表', `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id', `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id', `user_id` bigint(20) NOT NULL COMMENT '操作人', `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常', `start_time` datetime NOT NULL COMMENT '迁移开始执行时间', `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间', `log_path` varchar(255) NOT NULL COMMENT '日志文件路径', `config_path` varchar(255) NOT NULL COMMENT '配置文件路径', `migrate_id` varchar(50) DEFAULT NULL COMMENT 'migrate id', `migrate_tool` tinyint(4) DEFAULT NULL COMMENT 'migrate_tool, 0:redis-shake,1:redis-migrate-tool', `redis_source_version` varchar(20) DEFAULT NULL, `redis_target_version` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用迁移记录详情'; -- -- Table structure for table `app_desc` -- DROP TABLE IF EXISTS `app_desc`; CREATE TABLE `app_desc` ( `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id', `name` varchar(36) NOT NULL COMMENT '应用名', `user_id` bigint(20) NOT NULL COMMENT '申请人id', `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配,1申请未审批,2审批并发布 3:应用下线', `intro` varchar(255) NOT NULL COMMENT '应用描述', `create_time` datetime NOT NULL COMMENT '创建时间', `passed_time` datetime NOT NULL COMMENT '审批通过时间', `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型,1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud ,5. redis-sentinel ,6.redis-standalone ', `officer` varchar(32) NOT NULL COMMENT '负责人,中文', `ver_id` int(11) NOT NULL COMMENT '版本', `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试:1是0否', `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否', `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否', `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否', `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps', `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数', `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值', `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息', `client_conn_alert_value` int(11) DEFAULT '2000' COMMENT '客户端连接报警阀值', `app_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥', `important_level` tinyint(4) NOT NULL DEFAULT '2' COMMENT '应用级别,1:最重要,2:一般重要,3:一般', `password` varchar(255) DEFAULT '' COMMENT 'redis密码', `custom_password` varchar(255) DEFAULT NULL COMMENT '自定义密码', `hit_precent_alert_value` int(11) DEFAULT '0' COMMENT '命中率报警阀值 0:不报警 ', `is_access_monitor` int(11) DEFAULT '0' COMMENT '是否接入全局监控报警 默认0,0:不接入监控 1:接入监控', `app_fsync_value` int(11) DEFAULT '1' COMMENT '应用刷盘策略 1:主从节点appdendfsync=everysec 2:主从节点 appdendfsync=no', `version_id` int(11) NOT NULL DEFAULT '1' COMMENT 'Redis版本表主键id', PRIMARY KEY (`app_id`), UNIQUE KEY `uidx_app_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app应用描述' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_command_statistics` -- DROP TABLE IF EXISTS `app_hour_command_statistics`; CREATE TABLE `app_hour_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_statistics` -- DROP TABLE IF EXISTS `app_hour_statistics`; CREATE TABLE `app_hour_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH', `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和', `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和', `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值', `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '每小时修改时间最大值', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_command_statistics` -- DROP TABLE IF EXISTS `app_minute_command_statistics`; CREATE TABLE `app_minute_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_statistics` -- DROP TABLE IF EXISTS `app_minute_statistics`; CREATE TABLE `app_minute_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `hits` bigint(20) NOT NULL COMMENT '命中数量', `misses` bigint(20) NOT NULL COMMENT '未命中数量', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '内存占用', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量', `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '客户端连接数', `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_to_user` -- DROP TABLE IF EXISTS `app_to_user`; CREATE TABLE `app_to_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '用户id', `app_id` bigint(20) NOT NULL COMMENT '应用id', PRIMARY KEY (`id`), KEY `app_id` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_user` -- DROP TABLE IF EXISTS `app_user`; CREATE TABLE `app_user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '用户名', `ch_name` varchar(255) NOT NULL COMMENT '中文名', `email` varchar(64) NOT NULL COMMENT '邮箱', `mobile` varchar(16) NOT NULL COMMENT '手机', `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员,1预留,2普通用户,-1无效', `weChat` varchar(32) DEFAULT NULL COMMENT '微信号', `isAlert` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户是否接收报警 0:不接收 1:接收', `password` varchar(64) DEFAULT NULL COMMENT '密码', `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间', `purpose` varchar(255) DEFAULT NULL COMMENT '使用目的', `company` varchar(255) DEFAULT NULL COMMENT '公司名称', PRIMARY KEY (`id`), UNIQUE KEY `uidx_user_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' /* `compression`='tokudb_zlib' */; -- ---------------------------- -- Records of `app_user` -- ---------------------------- BEGIN; INSERT INTO `app_user` VALUES ('1', 'admin', 'admin', 'admin@xxx.com', '13500000000', '0', null, '1', NULL, current_timestamp(), NULL, NULL); COMMIT; -- -- Table structure for table `brevity_schedule_resources` -- DROP TABLE IF EXISTS `brevity_schedule_resources`; CREATE TABLE `brevity_schedule_resources` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(4) NOT NULL COMMENT '类型,见:BrevityScheduleType', `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '时间版本', `host` varchar(16) NOT NULL COMMENT '资源ip', `port` int(11) NOT NULL DEFAULT '0' COMMENT '端口', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_type_host_port` (`type`,`host`,`port`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='短频任务表'; -- -- Table structure for table `diagnostic_task_record` -- DROP TABLE IF EXISTS `diagnostic_task_record`; CREATE TABLE `diagnostic_task_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `type` int(11) DEFAULT NULL COMMENT '诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam', `task_id` bigint(20) DEFAULT NULL COMMENT '任务流id', `audit_id` bigint(20) DEFAULT NULL COMMENT '审批id', `status` int(11) DEFAULT NULL COMMENT '诊断状态:0开始 1结束 2异常', `cost` bigint(20) DEFAULT NULL COMMENT '耗时,毫秒', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `redis_key` varchar(100) DEFAULT NULL COMMENT '结果的key', `node` varchar(100) DEFAULT NULL COMMENT '实例,host:port', `parent_task_id` bigint(20) DEFAULT NULL COMMENT '父任务id', `diagnostic_condition` varchar(100) DEFAULT NULL COMMENT '诊断条件', `param1` varchar(100) DEFAULT NULL COMMENT '备用参数1', `param2` varchar(100) DEFAULT NULL COMMENT '备用参数2', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用诊断记录'; -- -- Table structure for table `instance_alert_configs` -- DROP TABLE IF EXISTS `instance_alert_configs`; CREATE TABLE `instance_alert_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `alert_config` varchar(255) NOT NULL COMMENT '报警配置', `alert_value` varchar(512) NOT NULL COMMENT '报警阀值', `config_info` varchar(255) NOT NULL COMMENT '配置说明', `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警', `instance_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0:全局配置,其他代表实例id', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `compare_type` tinyint(4) NOT NULL COMMENT '比较类型:1小于,2等于,3大于,4不等于', `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天', `update_time` datetime NOT NULL COMMENT '报警配置更新时间', `last_check_time` datetime NOT NULL COMMENT '上次检查时间', `important_level` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '重要程度(0:一般;1:重要;2:紧急)', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置'; -- ---------------------------- -- Records of `instance_alert_configs` -- ---------------------------- BEGIN; INSERT INTO `instance_alert_configs` VALUES ('9', 'aof_current_size', '6000', 'aof当前尺寸(单位:MB)', '1', '0', '1', '3', '3', '2017-06-19 09:43:22', '2020-09-17 10:52:00', 0), ('10', 'aof_delayed_fsync', '3', '分钟aof阻塞个数', '1', '0', '1', '3', '1', '2017-06-19 10:38:19', '2020-09-17 11:09:00', 1), ('11', 'client_biggest_input_buf', '10', '输入缓冲区最大buffer大小(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 10:47:03', '2020-09-17 11:09:00', 1), ('12', 'client_longest_output_list', '50000', '输出缓冲区最大队列长度', '1', '0', '1', '3', '1', '2017-06-19 10:55:45', '2020-09-17 11:09:00', 1), ('13', 'instantaneous_ops_per_sec', '60000', '实时ops', '1', '0', '1', '3', '1', '2017-06-19 11:02:38', '2020-09-17 11:09:00', 1),('14', 'latest_fork_usec', '400000', '上次fork所用时间(单位:微秒)', '1', '0', '1', '3', '5', '2017-06-19 11:21:35', '2020-09-16 16:51:00', 1), ('15', 'mem_fragmentation_ratio', '1.5', '内存碎片率(检测大于500MB)', '1', '0', '1', '3', '5', '2017-06-19 12:49:16', '2020-09-16 16:51:00', 0), ('16', 'rdb_last_bgsave_status', 'ok', '上一次bgsave状态', '1', '0', '1', '4', '4', '2017-06-19 14:15:21', '2020-09-17 10:19:00', 0), ('17', 'total_net_output_bytes', '5000', '分钟网络输出流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:39:44', '2020-09-17 11:09:00', 0), ('19', 'total_net_input_bytes', '1200', '分钟网络输入流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:45:44', '2020-09-17 11:09:00', 0), ('20', 'sync_partial_err', '0', '分钟部分复制失败次数', '1', '0', '1', '3', '1', '2017-06-19 18:34:41', '2020-09-17 11:09:00', 1), ('21', 'sync_partial_ok', '0', '分钟部分复制成功次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:01', '2020-09-17 11:09:00', 1), ('22', 'sync_full', '0', '分钟全量复制执行次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:17', '2020-09-17 11:09:00', 1), ('23', 'rejected_connections', '0', '分钟拒绝连接数', '1', '0', '1', '3', '1', '2017-06-19 18:35:36', '2020-09-17 11:09:00', 2), ('54', 'master_slave_offset_diff', '20000000', '主从节点偏移量差(单位:字节)', '1', '0', '1', '3', '2', '2017-06-20 18:58:56', '2020-09-17 11:06:00', 0), ('56', 'cluster_state', 'ok', '集群状态', '1', '0', '1', '4', '1', '2017-06-21 18:01:52', '2020-09-17 11:09:00', 2), ('57', 'cluster_slots_ok', '16384', '集群成功分配槽个数', '1', '0', '1', '4', '1', '2017-06-21 18:02:04', '2020-09-17 11:09:00', 2); COMMIT; -- -- Table structure for table `instance_big_key` -- DROP TABLE IF EXISTS `instance_big_key`; CREATE TABLE `instance_big_key` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `audit_id` bigint(20) NOT NULL COMMENT 'audit id', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从,详见InstanceRoleEnum', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `big_key` varchar(255) NOT NULL COMMENT '键', `type` varchar(16) NOT NULL COMMENT '类型:string,hash,list,set,zset', `length` int(11) NOT NULL COMMENT '长度', `create_time` datetime NOT NULL COMMENT '记录创建时间', PRIMARY KEY (`id`), KEY `idx_app_audit` (`app_id`,`audit_id`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例bigkey列表'; -- -- Table structure for table `instance_config` -- DROP TABLE IF EXISTS `instance_config`; CREATE TABLE `instance_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Redis版本表主键id', `refresh` mediumint(9) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例配置模板'; -- ---------------------------- -- Records of `instance_config` -- ---------------------------- BEGIN; INSERT INTO `instance_config` VALUES ('1', 'cluster-enabled', 'yes', '是否开启集群模式', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('2', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('3', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('4', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('5', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('6', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2016-07-05 15:08:31', '2', '1', '29', '0'), ('7', 'port', '%d', 'sentinel实例端口', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('8', 'dir', '%s', '工作目录', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('9', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('10', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('11', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('12', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('13', 'daemonize', 'no', '是否守护进程', '2016-07-14 14:00:05', '6', '1', '29', '0'), ('14', 'tcp-backlog', '511', 'TCP连接完成队列', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('15', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('16', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2016-12-06 11:40:46', '6', '1', '29', '0'), ('17', 'loglevel', 'notice', '日志级别', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('18', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('19', 'dir', '%s', 'redis工作目录', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('20', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('21', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('22', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('23', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('24', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('25', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('26', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('27', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('28', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('29', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('30', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('31', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('32', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('33', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('34', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('35', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('36', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('37', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('38', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('39', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('40', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('41', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2016-11-24 10:24:21', '6', '1', '29', '0'), ('42', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('43', 'hz', '10', '执行后台task数量,默认:10', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('44', 'port', '%d', '端口', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('45', 'maxmemory', '%dmb', '当前实例最大可用内存', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('46', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('47', 'appendonly', 'yes', '开启append only持久化模式', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('48', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('49', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('50', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('51', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('52', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('53', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('54', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('55', 'maxclients', '10000', '客户端最大连接数', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('126', 'cluster-enabled', 'yes', '是否开启集群模式', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('127', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('128', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('129', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('130', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('131', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('132', 'port', '%d', 'sentinel实例端口', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('133', 'dir', '%s', '工作目录', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('134', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('135', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('136', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('137', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('138', 'daemonize', 'no', '是否守护进程', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('139', 'tcp-backlog', '511', 'TCP连接完成队列', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('140', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('141', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('142', 'loglevel', 'notice', '日志级别', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('143', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('144', 'dir', '%s', 'redis工作目录', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('145', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('146', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('147', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('148', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('149', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('150', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('151', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('152', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('153', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('154', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('155', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('156', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('157', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('158', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('159', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2018-09-18 18:25:32', '6', '0', '31', '0'), ('160', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2018-09-18 18:25:40', '6', '0', '31', '0'), ('161', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('162', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('163', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('164', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('165', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('166', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('167', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('168', 'hz', '10', '执行后台task数量,默认:10', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('169', 'port', '%d', '端口', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('170', 'maxmemory', '%dmb', '当前实例最大可用内存', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('171', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('172', 'appendonly', 'yes', '开启append only持久化模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('173', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('174', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('175', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('176', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('177', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('178', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('179', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('180', 'maxclients', '10000', '客户端最大连接数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('181', 'protected-mode', 'yes', '开启保护模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('182', 'bind', '0.0.0.0', '默认客户端都可连接', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('185', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2018-09-18 18:26:32', '6', '1', '31', '0'), ('186', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2018-09-18 18:27:12', '6', '1', '31', '0'), ('253', 'protected-mode', 'no', '关闭保护模式', '2018-11-01 16:10:59', '5', '1', '31', '0'), ('354', 'cluster-enabled', 'yes', '是否开启集群模式', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('355', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('356', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('357', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('358', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('359', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('360', 'port', '%d', 'sentinel实例端口', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('361', 'dir', '%s', '工作目录', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('362', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('363', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('364', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('365', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('366', 'daemonize', 'no', '是否守护进程', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('367', 'tcp-backlog', '511', 'TCP连接完成队列', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('368', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('369', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('370', 'loglevel', 'notice', '日志级别', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('371', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('372', 'dir', '%s', 'redis工作目录', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('373', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('374', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('375', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('376', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('377', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('378', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('379', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('380', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('381', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('382', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('383', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('384', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('385', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('386', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('387', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('388', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('389', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('390', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('391', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('392', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('393', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('394', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('395', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('396', 'hz', '10', '执行后台task数量,默认:10', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('397', 'port', '%d', '端口', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('398', 'maxmemory', '%dmb', '当前实例最大可用内存', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('399', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('400', 'appendonly', 'yes', '开启append only持久化模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('401', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('402', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('403', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('404', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('405', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('406', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('407', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('408', 'maxclients', '10000', '客户端最大连接数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('409', 'protected-mode', 'yes', '开启保护模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('410', 'bind', '0.0.0.0', '默认客户端都可连接', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('411', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('412', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('413', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('414', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('415', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('416', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('417', 'slave-lazy-flush', 'yes', 'slave发起全量复制,是否采用flushall async清理老数据 默认值 no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('418', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2019-10-31 11:15:57', '6', '1', '12', '0'), ('419', 'protected-mode', 'no', '关闭sentinel保护模式', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('420', 'activedefrag', 'no', '碎片整理开启', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('421', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('422', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('423', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('424', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('425', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('506', 'cluster-enabled', 'yes', '是否开启集群模式', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('507', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('508', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('509', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('510', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('511', 'port', '%d', 'sentinel实例端口', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('512', 'dir', '%s', '工作目录', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('513', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('514', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('515', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('516', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('517', 'daemonize', 'no', '是否守护进程', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('518', 'tcp-backlog', '511', 'TCP连接完成队列', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('519', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('520', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('521', 'loglevel', 'notice', '日志级别', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('522', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('523', 'dir', '%s', 'redis工作目录', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('524', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('525', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('526', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('527', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('528', 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('529', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('530', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('531', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('532', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('533', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('534', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('535', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('536', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('537', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('538', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('539', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('540', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('541', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('542', 'hz', '10', '执行后台task数量,默认:10', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('543', 'port', '%d', '端口', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('544', 'maxmemory', '%dmb', '当前实例最大可用内存', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('545', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('546', 'appendonly', 'yes', '开启append only持久化模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('547', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('548', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('549', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('550', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('551', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('552', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('553', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('554', 'maxclients', '10000', '客户端最大连接数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('555', 'protected-mode', 'yes', '开启保护模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('556', 'bind', '0.0.0.0', '默认客户端都可连接', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('557', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('558', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('559', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('560', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('561', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('562', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('563', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('564', 'protected-mode', 'no', '关闭sentinel保护模式', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('565', 'activedefrag', 'yes', '碎片整理开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('566', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('567', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('568', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('569', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('570', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('571', 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('572', 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('573', 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('574', 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('575', 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('576', 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('577', 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('578', 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('579', 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('580', 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('581', 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('582', 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('583', 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('585', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:45:22', '6', '1', '37', '0'), ('587', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:18', '6', '1', '12', '0'), ('589', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:49', '6', '1', '31', '0'), ('590', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:49:47', '6', '1', '29', '0'); COMMIT; -- -- Table structure for table `instance_fault` -- DROP TABLE IF EXISTS `instance_fault`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `instance_fault` ( `id` int(11) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `inst_id` bigint(20) NOT NULL COMMENT '实例id', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `type` mediumint(4) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `reason` mediumtext NOT NULL COMMENT '故障原因描述', PRIMARY KEY (`id`), KEY `idx_ip_port` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `inst_id` (`inst_id`) ) ENGINE=InnoDB AUTO_INCREMENT=8927 DEFAULT CHARSET=utf8 COMMENT='实例故障表' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `instance_host` -- DROP TABLE IF EXISTS `instance_host`; CREATE TABLE `instance_host` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `ip` varchar(16) NOT NULL COMMENT '机器ip', `ssh_user` varchar(32) DEFAULT NULL COMMENT 'ssh用户', `ssh_pwd` varchar(32) DEFAULT NULL COMMENT 'ssh密码', `warn` int(5) DEFAULT '1' COMMENT '0不报警,1报警', PRIMARY KEY (`id`), UNIQUE KEY `uidx_host_ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_info` -- DROP TABLE IF EXISTS `instance_info`; CREATE TABLE `instance_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'memcached instance id', `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id', `app_id` bigint(20) NOT NULL COMMENT '应用id,与app_desc关联', `host_id` bigint(20) NOT NULL COMMENT '对应的主机id,与instance_host关联', `ip` varchar(16) NOT NULL COMMENT '实例的ip', `port` int(11) NOT NULL COMMENT '实例端口', `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线', `mem` int(11) NOT NULL COMMENT '内存大小', `conn` int(11) NOT NULL COMMENT '连接数', `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName', `type` mediumint(11) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`) USING BTREE, KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_latency_history` -- DROP TABLE IF EXISTS `instance_latency_history`; CREATE TABLE `instance_latency_history` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `event` varchar(255) NOT NULL COMMENT '事件名称', `execute_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `execution_cost` bigint(20) NOT NULL COMMENT '耗时(微妙)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `latencyistorykey` (`instance_id`,`event`,`execute_date`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executedate` (`app_id`,`execute_date`), KEY `idx_executedate` (`execute_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例延迟事件信息表'; -- -- Table structure for table `instance_minute_stats` -- DROP TABLE IF EXISTS `instance_minute_stats`; CREATE TABLE `instance_minute_stats` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `json` text NOT NULL COMMENT '统计json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例分钟统计表'; -- -- Table structure for table `instance_reshard_process` -- DROP TABLE IF EXISTS `instance_reshard_process`; CREATE TABLE `instance_reshard_process` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `audit_id` bigint(20) NOT NULL COMMENT '审核id', `source_instance_id` int(11) NOT NULL COMMENT '源实例id', `target_instance_id` int(11) NOT NULL COMMENT '目标实例id', `start_slot` int(11) NOT NULL COMMENT '开始slot', `end_slot` int(11) NOT NULL COMMENT '结束slot', `migrating_slot` int(11) NOT NULL COMMENT '正在迁移的slot', `is_pipeline` tinyint(4) NOT NULL COMMENT '是否为pipeline,0:否,1:是', `finish_slot_num` int(11) NOT NULL COMMENT '已经完成迁移的slot数量', `status` tinyint(4) NOT NULL COMMENT '0:运行中 1:完成 2:出错', `start_time` datetime NOT NULL COMMENT '迁移开始时间', `end_time` datetime NOT NULL COMMENT '迁移结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_audit` (`audit_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度'; -- -- Table structure for table `instance_slow_log` -- DROP TABLE IF EXISTS `instance_slow_log`; CREATE TABLE `instance_slow_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id', `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)', `command` varchar(255) NOT NULL COMMENT '执行命令', `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间', PRIMARY KEY (`id`), UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executetime` (`app_id`,`execute_time`), KEY `idx_executetime` (`execute_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表'; -- -- Table structure for table `instance_statistics` -- DROP TABLE IF EXISTS `instance_statistics`; CREATE TABLE `instance_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `inst_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `host_id` bigint(20) NOT NULL COMMENT '机器的id', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `port` int(255) NOT NULL COMMENT 'port', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从', `max_memory` bigint(255) NOT NULL COMMENT '预分配内存,单位byte', `used_memory` bigint(255) NOT NULL COMMENT '已使用内存,单位byte', `curr_items` bigint(255) NOT NULL COMMENT '当前item数量', `curr_connections` int(255) NOT NULL COMMENT '当前连接数', `misses` bigint(255) NOT NULL COMMENT 'miss数', `hits` bigint(255) NOT NULL COMMENT '命中数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mem_fragmentation_ratio` double DEFAULT '0' COMMENT '碎片率', `aof_delayed_fsync` int(11) DEFAULT '0' COMMENT 'aof阻塞次数', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `machine_id` (`host_id`), KEY `idx_inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_info` -- DROP TABLE IF EXISTS `machine_info`; CREATE TABLE `machine_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id', `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户', `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房', `mem` int(11) unsigned NOT NULL COMMENT '内存大小,单位G', `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量', `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟,0表示否,1表示是', `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip', `service_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上线时间', `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警,0不启用,1启用', `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用,1表示可用,0表示不可用;', `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组,默认为0,表示原生资源,非0表示外部提供的资源(可扩展)', `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他', `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))', `collect` int(11) DEFAULT '1' COMMENT 'switch of collect server status, 1:open, 0:close', `version_install` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '机器安装redis版本状态', `use_type` tinyint(4) DEFAULT '2' COMMENT '使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis-Sentinel机器(3)', `k8s_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否k8s容器:0:不是 1:是', `rack` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '机器所在机架信息', `is_allocating` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否在分配中,1是0否', `disk` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '磁盘空间:G', `dis_type` tinyint(4) DEFAULT 0 NOT NULL COMMENT '操作系统发行版本,0:centos;1:ubuntu', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='机器信息表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_relation` -- DROP TABLE IF EXISTS `machine_relation`; CREATE TABLE `machine_relation` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `ip` varchar(64) NOT NULL COMMENT '虚拟机ip', `real_ip` varchar(64) NOT NULL COMMENT '宿主机ip', `extra_desc` varchar(128) DEFAULT NULL COMMENT '实例描述信息', `status` int(255) NOT NULL COMMENT '实例变更状态 0:offline ,1:online', `is_sync` tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据同步状态 0: 未同步数据 -1:同步中 1:数据已同步 -2:同步失败 ', `sync_time` timestamp NULL DEFAULT NULL COMMENT '同步时间', `update_time` timestamp NULL DEFAULT NULL COMMENT 'pod最后更新时间', `taskid` bigint(11) DEFAULT NULL COMMENT '任务id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `machine_room` -- DROP TABLE IF EXISTS `machine_room`; CREATE TABLE `machine_room` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机房id', `name` varchar(255) NOT NULL COMMENT '机房名称', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `desc` varchar(255) DEFAULT NULL COMMENT '机房描述信息', `ip_network` varchar(32) NOT NULL DEFAULT '' COMMENT '机房网段信息', `operator` varchar(255) DEFAULT NULL COMMENT '运营商', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `machine_room` -- ---------------------------- BEGIN; INSERT INTO `machine_room` VALUES ('1', '阿里云杭州', '1', '阿里云-杭州机房', '172.27.*.*', '阿里云'); COMMIT; -- -- Table structure for table `machine_statistics` -- DROP TABLE IF EXISTS `machine_statistics`; CREATE TABLE `machine_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `host_id` bigint(20) NOT NULL COMMENT '机器id', `ip` varchar(16) NOT NULL COMMENT '机器ip', `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率', `load` varchar(120) NOT NULL COMMENT '机器负载', `traffic` varchar(120) NOT NULL COMMENT 'io网络流量', `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率', `memory_free` varchar(120) NOT NULL COMMENT '内存剩余', `memory_total` varchar(120) NOT NULL COMMENT '总内存量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `max_memory` int(11) DEFAULT '0' COMMENT '机器分配内存,单位MB', `instance_count` int(11) DEFAULT '0' COMMENT '机器实例数量', `machine_memory` int(11) DEFAULT '0' COMMENT '机器入库总内存,单位MB', PRIMARY KEY (`id`), UNIQUE KEY `uidx_ip` (`ip`), KEY `host_id` (`host_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_blob_triggers` -- DROP TABLE IF EXISTS `qrtz_blob_triggers`; CREATE TABLE `qrtz_blob_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_calendars` -- DROP TABLE IF EXISTS `qrtz_calendars`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `qrtz_calendars` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称', `CALENDAR` blob NOT NULL COMMENT 'calendar信息', PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `qrtz_cron_triggers` -- DROP TABLE IF EXISTS `qrtz_cron_triggers`; CREATE TABLE `qrtz_cron_triggers` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_fired_triggers` -- DROP TABLE IF EXISTS `qrtz_fired_triggers`; CREATE TABLE `qrtz_fired_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(195) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(13) NOT NULL, `SCHED_TIME` bigint(13) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化', PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息,以及关联 Job 的执行信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_job_details` -- DROP TABLE IF EXISTS `qrtz_job_details`; CREATE TABLE `qrtz_job_details` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化,0不持久化,1持久化', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发,0非并发,1并发', `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复,0不恢复,1恢复', `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_locks` -- DROP TABLE IF EXISTS `qrtz_locks`; CREATE TABLE `qrtz_locks` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_paused_trigger_grps` -- DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; CREATE TABLE `qrtz_paused_trigger_grps` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_scheduler_state` -- DROP TABLE IF EXISTS `qrtz_scheduler_state`; CREATE TABLE `qrtz_scheduler_state` ( `SCHED_NAME` varchar(120) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_simple_triggers` -- DROP TABLE IF EXISTS `qrtz_simple_triggers`; CREATE TABLE `qrtz_simple_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_simprop_triggers` -- DROP TABLE IF EXISTS `qrtz_simprop_triggers`; CREATE TABLE `qrtz_simprop_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `STR_PROP_1` varchar(512) DEFAULT NULL, `STR_PROP_2` varchar(512) DEFAULT NULL, `STR_PROP_3` varchar(512) DEFAULT NULL, `INT_PROP_1` int(11) DEFAULT NULL, `INT_PROP_2` int(11) DEFAULT NULL, `LONG_PROP_1` bigint(20) DEFAULT NULL, `LONG_PROP_2` bigint(20) DEFAULT NULL, `DEC_PROP_1` decimal(13,4) DEFAULT NULL, `DEC_PROP_2` decimal(13,4) DEFAULT NULL, `BOOL_PROP_1` varchar(1) DEFAULT NULL, `BOOL_PROP_2` varchar(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `qrtz_triggers` -- DROP TABLE IF EXISTS `qrtz_triggers`; CREATE TABLE `qrtz_triggers` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(13) NOT NULL, `END_TIME` bigint(13) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(2) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `server` -- DROP TABLE IF EXISTS `server`; CREATE TABLE `server` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `host` varchar(255) DEFAULT NULL COMMENT 'host', `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version', `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num', `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号', `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息', `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息', `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u', `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `server_stat` -- DROP TABLE IF EXISTS `server_stat`; CREATE TABLE `server_stat` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `cdate` date NOT NULL COMMENT '数据收集天', `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟', `cuser` float DEFAULT NULL COMMENT '用户态占比', `csys` float DEFAULT NULL COMMENT '内核态占比', `cwio` float DEFAULT NULL COMMENT 'wio占比', `c_ext` text COMMENT '子cpu占比', `cload1` float DEFAULT NULL COMMENT '1分钟load', `cload5` float DEFAULT NULL COMMENT '5分钟load', `cload15` float DEFAULT NULL COMMENT '15分钟load', `mtotal` float DEFAULT NULL COMMENT '总内存,单位M', `mfree` float DEFAULT NULL COMMENT '空闲内存', `mcache` float DEFAULT NULL COMMENT 'cache', `mbuffer` float DEFAULT NULL COMMENT 'buffer', `mswap` float DEFAULT NULL COMMENT 'cache', `mswap_free` float DEFAULT NULL COMMENT 'cache', `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s', `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s', `nin_ext` text COMMENT '各网卡入流量详情', `nout_ext` text COMMENT '各网卡出流量详情', `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数', `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数', `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数', `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s', `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s', `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s', `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比', `d_ext` text COMMENT '磁盘各分区占比', `dspace` text COMMENT '磁盘各分区空间使用率', PRIMARY KEY (`ip`,`cdate`,`ctime`), KEY `idx_cdate` (`cdate`), KEY `idx_cdate_ctime` (`cdate`,`ctime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `system_config` -- DROP TABLE IF EXISTS `system_config`; CREATE TABLE `system_config` ( `config_key` varchar(255) NOT NULL COMMENT '配置key', `config_value` varchar(512) NOT NULL COMMENT '配置value', `info` varchar(255) NOT NULL COMMENT '配置说明', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `order_id` int(11) NOT NULL COMMENT '顺序', PRIMARY KEY (`config_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置'; -- ---------------------------- -- Records of `system_config` -- ---------------------------- BEGIN; INSERT INTO `system_config` VALUES ('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,11),('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,12),('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,33),('cachecloud.base.dir','/opt','cachecloud根目录,要和cachecloud-init.sh脚本中的目录一致',1,31),('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)
user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14),('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,22),('cachecloud.email.alert.interface','','邮件报警接口(参考报警接口规范)',1,24),('cachecloud.machine.ssh.name','cachecloud-open','机器ssh用户名',1,2),('cachecloud.machine.ssh.password','cachecloud-open','机器ssh密码',1,3),('cachecloud.machine.ssh.port','22','机器ssh端口',1,10),('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,35),('cachecloud.nmon.dir','/opt/cachecloud','nmon安装目录',1,32),('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,21),('cachecloud.owner.phone','xxx,yyy','手机号报警(逗号隔开)',1,21),('cachecloud.owner.weChat','xxx,yyy','微信号报警(逗号隔开)',1,21),('cachecloud.public.key.pem','/opt/ssh/id_rsa','密钥路径',1,5),('cachecloud.public.user.name','cachecloud-open','公钥用户名',1,4),('cachecloud.ssh.auth.type','1','ssh授权方式',1,1),('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,13),('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,22),('cachecloud.weChat.alert.interface','','微信报警接口(参考报警接口规范)',1,23),('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,34),('machine.load.alert.ratio','8.0','机器负载报警阀值',1,32); COMMIT; -- ---------------------------- -- Table structure for `system_resource` -- ---------------------------- DROP TABLE IF EXISTS `system_resource`; CREATE TABLE `system_resource` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '资源ID', `name` varchar(64) NOT NULL COMMENT '资源名称', `intro` varchar(255) DEFAULT NULL COMMENT '资源说明', `type` tinyint(4) NOT NULL COMMENT '1:仓库地址 2:脚本 3:资源包 4:公钥/私钥 6:目录管理 7:迁移工具管理', `lastmodify` datetime DEFAULT NULL COMMENT '最后更新时间', `dir` varchar(128) DEFAULT NULL COMMENT '资源路径', `url` varchar(128) DEFAULT NULL COMMENT '仓库地址', `ispush` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:未推送 1:已推送', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `username` varchar(255) DEFAULT NULL COMMENT '最后修改人', `task_id` bigint(11) DEFAULT NULL COMMENT '迁移任务id', `compile_info` varchar(255) DEFAULT NULL COMMENT '编译信息', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `system_resource` -- ---------------------------- BEGIN; INSERT INTO `system_resource` VALUES (1,'cachecloud-init.sh','容器初始化脚本',2,'2020-07-15 18:35:41','/script','',0,1,NULL,NULL,NULL),(2,'x.x.x.x',NULL,1,'2020-08-10 10:31:51','/opt/download/software/cachecloud/resource','http://x.x.x.x/software/cachecloud/resource',0,1,'admin',0,NULL),(4,'cachecloud-env.sh','宿主环境脚本',2,'2020-07-15 18:36:28','/script','',0,1,NULL,NULL,NULL),(5,'id_rsa','私钥文件',4,'2020-07-07 10:45:39','/ssh','',0,1,NULL,NULL,NULL),(6,'id_rsa.pub','公钥文件',4,'2020-07-07 10:45:45','/ssh','',0,1,NULL,NULL,NULL),(12,'redis-4.0.14','redis 4.0.14资源包',3,'2020-08-10 09:52:41','/redis','http://download.redis.io/releases/redis-4.0.14.tar.gz',0,1,'admin',532,NULL),(21,'/script','脚本目录管理',6,'2020-08-10 10:51:34','',NULL,0,1,'admin',0,NULL),(28,'/ssh','ssh目录',6,'2020-07-20 17:55:03',NULL,NULL,0,1,'admin',0,NULL),(29,'redis-3.0.7','redis3.0.7 资源包',3,'2020-08-10 09:53:32','/redis','http://download.redis.io/releases/redis-3.0.7.tar.gz',0,1,'admin',529,NULL),(31,'redis-3.2.12','redis 3.2.12 资源包',3,'2020-08-10 15:08:21','/redis','http://download.redis.io/releases/redis-3.2.12.tar.gz',0,1,'admin',530,NULL),(32,'/redis','redis资源包管理',6,'2020-07-20 17:54:59',NULL,NULL,0,1,'admin',0,NULL),(33,'/tool','迁移工具资源包',6,'2020-07-20 17:54:53',NULL,NULL,0,1,'admin',0,NULL),(37,'redis-5.0.9','redis5.0.9 资源包',3,'2020-08-10 09:51:41','/redis','http://download.redis.io/releases/redis-5.0.9.tar.gz',0,1,'admin',533,NULL),(40,'redis-shake-2.0.3','redis 2.0.3\n修复fix 5.0迁移类型问题',7,'2020-08-11 10:53:26','/tool','https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz',0,1,'admin',518,NULL); COMMIT; -- -- Table structure for table `task_queue` -- DROP TABLE IF EXISTS `task_queue`; CREATE TABLE `task_queue` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `class_name` varchar(255) NOT NULL COMMENT '类名', `important_info` varchar(255) NOT NULL DEFAULT '' COMMENT '重要信息', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `param` longtext NOT NULL COMMENT '任务参数(json):随着任务变化', `init_param` longtext NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2中断,3失败', `parent_task_id` bigint(20) NOT NULL COMMENT '父任务id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `priority` int(11) NOT NULL COMMENT '优先级', `error_code` int(11) NOT NULL COMMENT '错误代码', `error_msg` varchar(255) NOT NULL COMMENT '错误消息', `task_note` varchar(255) NOT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务表'; -- -- Table structure for table `task_step_flow` -- DROP TABLE IF EXISTS `task_step_flow`; CREATE TABLE `task_step_flow` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `task_id` bigint(20) NOT NULL COMMENT '任务id', `child_task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '子任务id', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `order_no` int(11) NOT NULL COMMENT '序号', `status` tinyint(4) NOT NULL COMMENT '状态:0未开始、1成功、2中断、3跳过、4失败', `log` text COMMENT '日志', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_task_class_step` (`task_id`,`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤流表'; -- -- Table structure for table `task_step_meta` -- DROP TABLE IF EXISTS `task_step_meta`; CREATE TABLE `task_step_meta` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `step_desc` varchar(255) NOT NULL COMMENT '步骤描述', `ops_device` varchar(255) NOT NULL COMMENT '运维建议', `timeout` int(11) NOT NULL COMMENT '超时时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `order_no` int(11) NOT NULL COMMENT '序号', PRIMARY KEY (`id`), UNIQUE KEY `uk_class_step` (`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤元数据表'; /*!40101 SET character_set_client = @saved_cs_client */; -- ---------------------------- -- Table structure for `standard_statistics` -- ---------------------------- DROP TABLE IF EXISTS `standard_statistics`; CREATE TABLE `standard_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `info_json` text NOT NULL COMMENT '收集的json数据', `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `cluster_info_json` varchar(20480) NOT NULL DEFAULT '' COMMENT '收集的cluster info json数据', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_create_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_alert_record` -- DROP TABLE IF EXISTS `app_alert_record`; CREATE TABLE `app_alert_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `visible_type` int(1) NOT NULL COMMENT '可见类型(0:均可见;1:仅管理员可见;)', `important_level` int(1) NOT NULL COMMENT '重要类型(0:一般;1:重要;2:紧急)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `app_id` bigint(20) DEFAULT NULL COMMENT 'app id', `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id', `ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '机器ip', `port` int(10) DEFAULT NULL COMMENT '端口号', `title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '报警标题', `content` varchar(500) COLLATE utf8_bin NOT NULL COMMENT '报警内容', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `ip` (`ip`), KEY `idx_inst_id` (`instance_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报警记录表'; -- -- Table structure for table `config_restart_record` -- DROP TABLE IF EXISTS `config_restart_record`; CREATE TABLE `config_restart_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `app_name` varchar(36) NOT NULL COMMENT '应用名称', `operate_type` char(1) NOT NULL COMMENT '操作类型(0:滚动重启,1:修改配置强制重启;2:修改配置)', `param` varchar(2000) NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2成功,3失败,4配置修改待重启', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `log` longtext COMMENT '日志信息', `user_name` varchar(64) DEFAULT NULL COMMENT '操作人员姓名', `user_id` bigint(20) NOT NULL COMMENT '用户id', `instances` varchar(1000) DEFAULT NULL COMMENT '涉及实例id列表的json格式', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='重启记录表'; -- -- Table structure for table `module_info` -- DROP TABLE IF EXISTS `module_info`; CREATE TABLE `module_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `git_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'git resource', `info` varchar(128) DEFAULT NULL COMMENT '模块信息说明', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', PRIMARY KEY (`id`), UNIQUE KEY `NAMEKEY` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块信息表'; -- -- Table structure for table `module_version` -- DROP TABLE IF EXISTS `module_version`; CREATE TABLE `module_version` ( `id` int(11) NOT NULL AUTO_INCREMENT, `module_id` int(11) NOT NULL, `version_id` int(11) NOT NULL COMMENT '关联版本号', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `so_path` varchar(255) DEFAULT NULL COMMENT '编译后so库的地址', `tag` varchar(64) NOT NULL COMMENT '模块版本号', `status` int(255) NOT NULL DEFAULT '0' COMMENT '是否可用(关联so地址):0 不可用 1:可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块版本管理表'; -- -- Table structure for table `app_import` -- DROP TABLE IF EXISTS `app_import`; CREATE TABLE `app_import` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '目标应用id', `instance_info` text COMMENT '源redis实例信息', `redis_password` varchar(200) DEFAULT NULL COMMENT '源redis密码', `status` int(11) DEFAULT NULL COMMENT '迁移状态:PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功")', `step` int(11) DEFAULT NULL COMMENT '导入阶段', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `migrate_id` bigint(20) DEFAULT NULL COMMENT '数据迁移id', `mem_size` int(11) DEFAULT NULL COMMENT '目标应用内存大小,单位G', `redis_version_name` varchar(20) DEFAULT NULL COMMENT '目标应用redis版本,格式:redis-x.x.x', `app_build_task_id` bigint(20) DEFAULT NULL COMMENT '目标应用部署任务id', `source_type` int(11) DEFAULT NULL COMMENT '源redis类型:7:cluster, 6:sentinel, 5:standalone', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- redis_module_config definition CREATE TABLE `redis_module_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Module version版本表主键id', `refresh` tinyint(4) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', `module_id` int(11) NOT NULL DEFAULT '7' COMMENT 'Module 信息表id', `config_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '配置类型,0:加载和运行配置;1:加载时配置;2:运行时配置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='redis模块配置表'; -- app_to_module definition CREATE TABLE `app_to_module` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `app_id` bigint(20) NOT NULL COMMENT '应用id', `module_id` int(11) NOT NULL COMMENT '模块info id', `module_version_id` int(11) NOT NULL COMMENT '模块版本id', PRIMARY KEY (`id`), UNIQUE KEY `app_to_module_un` (`app_id`,`module_id`,`module_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='应用与模块关系表'; ================================================ FILE: cachecloud-web/sql/3.1.sql ================================================ -- MySQL dump 10.15 Distrib 10.0.16-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: cachecloud_open -- ------------------------------------------------------ -- Server version 10.0.16-MariaDB-log SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for table `app_audit` -- DROP TABLE IF EXISTS `app_audit`; CREATE TABLE `app_audit` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '申请人的id', `user_name` varchar(64) NOT NULL COMMENT '用户名', `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置', `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1', `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2', `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3', `info` varchar(360) NOT NULL COMMENT '申请描述', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由', `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `operate_id` bigint(20) DEFAULT NULL COMMENT '工单处理人', PRIMARY KEY (`id`), KEY `idx_appid` (`app_id`), KEY `idx_create_time` (`create_time`), KEY `idx_status_create_time` (`status`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_audit_log` -- DROP TABLE IF EXISTS `app_audit_log`; CREATE TABLE `app_audit_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '审批操作人id', `info` longtext NOT NULL COMMENT 'app审批的详细信息', `type` tinyint(4) NOT NULL, `create_time` datetime NOT NULL, `app_audit_id` bigint(20) NOT NULL COMMENT '审批id', PRIMARY KEY (`id`), KEY `idx_audit_appid` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_client_command_minute_statistics` -- DROP TABLE IF EXISTS `app_client_command_minute_statistics`; CREATE TABLE `app_client_command_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `app_id` bigint(20) NOT NULL COMMENT '应用id', `command` varchar(20) NOT NULL COMMENT '命令明文', `cost` bigint(20) DEFAULT NULL COMMENT '命令累计毫秒耗时', `bytes_in` bigint(20) DEFAULT NULL COMMENT '输入流量', `bytes_out` bigint(20) DEFAULT NULL COMMENT '输出流量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx__appid_client_command_currentMin` (`app_id`,`client_ip`,`command`,`current_min`), KEY `idx_currentmin_appid_count_cost` (`current_min`,`app_id`,`count`,`cost`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟命令调用上报数据'; -- -- Table structure for table `app_client_exception_minute_statistics` -- DROP TABLE IF EXISTS `app_client_exception_minute_statistics`; CREATE TABLE `app_client_exception_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `type` tinyint(4) NOT NULL COMMENT '0:connect exception;1:command exception', `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `node` varchar(30) NOT NULL COMMENT '节点信息host:port', `count` bigint(20) DEFAULT NULL COMMENT '累计连接失败次数', `cost` bigint(20) DEFAULT NULL COMMENT '累计连接失败毫秒耗时', `latency_commands` varchar(255) DEFAULT NULL COMMENT '统计命令topN id,逗号分隔', `redis_pool_config` varchar(255) DEFAULT NULL COMMENT 'redis连接池配置信息', PRIMARY KEY (`id`), UNIQUE KEY `idx__client_node_type_currentMin` (`client_ip`,`node`,`type`,`current_min`), KEY `idx_appid_current_min` (`app_id`,`current_min`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据'; -- -- Table structure for table `app_client_latency_command` -- DROP TABLE IF EXISTS `app_client_latency_command`; CREATE TABLE `app_client_latency_command` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `command` varchar(255) NOT NULL COMMENT '命令明文', `size` bigint(20) DEFAULT NULL COMMENT '参数长度', `args` varchar(255) DEFAULT NULL COMMENT '裁剪后参数明文', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `invoke_time` bigint(20) DEFAULT NULL COMMENT '命令调用时间戳', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端异常命令调用详情'; -- -- Table structure for table `app_client_statistic_gather` -- DROP TABLE IF EXISTS `app_client_statistic_gather`; CREATE TABLE `app_client_statistic_gather` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gather_time` varchar(20) NOT NULL COMMENT '统计时间,格式yyyy-mm-dd', `app_id` bigint(20) NOT NULL COMMENT '应用id', `cmd_count` bigint(20) DEFAULT '0' COMMENT '命令调用次数', `conn_exp_count` bigint(20) DEFAULT '0' COMMENT '连接异常次数', `avg_cmd_cost` double DEFAULT '0' COMMENT '命令调用平均耗时,单位毫秒', `avg_cmd_exp_cost` double DEFAULT '0' COMMENT '命令超时平均耗时,单位毫秒', `avg_conn_exp_cost` double DEFAULT '0' COMMENT '连接异常平均耗时,单位毫秒', `cmd_exp_count` bigint(20) DEFAULT '0' COMMENT '命令超时次数', `instance_count` int(11) DEFAULT NULL COMMENT '应用实例数', `avg_mem_frag_ratio` double DEFAULT NULL COMMENT '平均碎片率', `mem_used_ratio` double DEFAULT NULL COMMENT '内存使用率', `exception_count` bigint(20) DEFAULT '0' COMMENT '异常数(旧,待下线)', `slow_log_count` bigint(20) DEFAULT '0' COMMENT '慢查询次数', `latency_count` bigint(20) DEFAULT '0' COMMENT '延迟事件次数', `object_size` bigint(20) DEFAULT '0' COMMENT '存储对象数', `used_memory` bigint(20) DEFAULT '0' COMMENT '内存占用 byte', `used_memory_rss` bigint(20) DEFAULT '0' COMMENT '物理内存占用 byte', `max_cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗(单位:秒)', `max_cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗(单位:秒)', `connected_clients` bigint(20) DEFAULT '0' COMMENT '应用客户端连接数', `topology_exam_result` tinyint(4) DEFAULT NULL COMMENT '拓扑诊断结果,0:正常,1:异常', PRIMARY KEY (`id`), UNIQUE KEY `idx_appid_gathertime` (`app_id`,`gather_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报数据全天统计'; -- -- Table structure for table `app_client_value_minute_stat` -- DROP TABLE IF EXISTS `app_client_value_minute_stat`; CREATE TABLE `app_client_value_minute_stat` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用appid', `collect_time` bigint(20) NOT NULL COMMENT '数据收集时间yyyyMMddHHmm00', `update_time` datetime NOT NULL COMMENT '更新时间', `command` varchar(20) NOT NULL COMMENT '执行命令', `distribute_type` tinyint(4) NOT NULL COMMENT '值分布', `count` int(11) NOT NULL COMMENT '命令执行次数', PRIMARY KEY (`id`), UNIQUE KEY `app_collect_command_dis` (`app_id`,`collect_time`,`command`,`distribute_type`), KEY `idx_collect_time` (`collect_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计'; -- -- Table structure for table `app_client_version_statistic` -- DROP TABLE IF EXISTS `app_client_version_statistic`; CREATE TABLE `app_client_version_statistic` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址', `client_version` varchar(20) NOT NULL COMMENT '客户端版本', `report_time` datetime DEFAULT NULL COMMENT '上报时间', PRIMARY KEY (`id`), UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`), KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_daily` -- DROP TABLE IF EXISTS `app_daily`; CREATE TABLE `app_daily` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `date` date NOT NULL COMMENT '日期', `create_time` datetime NOT NULL, `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数', `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数', `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数', `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数', `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数', `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数', `avg_hit_ratio` double NOT NULL COMMENT '平均命中率', `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率', `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率', `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量', `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量', `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数', `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数', `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量', `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量', `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量', `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量', `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值', `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值', `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数', `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情', `client_cmd_count` bigint(20) NOT NULL COMMENT '累计命令调用次数', `client_avg_cmd_cost` double NOT NULL COMMENT '平均命令调用耗时', `client_conn_exp_count` bigint(20) NOT NULL COMMENT '累计连接异常事件次数', `client_avg_conn_exp_cost` double NOT NULL COMMENT '平均连接异常事件耗时', `client_cmd_exp_count` bigint(20) NOT NULL COMMENT '累计命令超时事件次数', `client_avg_cmd_exp_cost` double NOT NULL COMMENT '平均命令超时事件耗时', PRIMARY KEY (`id`), KEY `idx_appid_date` (`app_id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报'; -- -- Table structure for table `app_data_migrate_status` -- DROP TABLE IF EXISTS `app_data_migrate_status`; CREATE TABLE `app_data_migrate_status` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip', `migrate_machine_port` int(11) NOT NULL COMMENT '迁移工具所占port', `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表', `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表', `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id', `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id', `user_id` bigint(20) NOT NULL COMMENT '操作人', `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常', `start_time` datetime NOT NULL COMMENT '迁移开始执行时间', `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间', `log_path` varchar(255) NOT NULL COMMENT '日志文件路径', `config_path` varchar(255) NOT NULL COMMENT '配置文件路径', `migrate_id` varchar(50) DEFAULT NULL COMMENT 'migrate id', `migrate_tool` tinyint(4) DEFAULT NULL COMMENT 'migrate_tool, 0:redis-shake,1:redis-migrate-tool', `redis_source_version` varchar(20) DEFAULT NULL, `redis_target_version` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用迁移记录详情'; -- -- Table structure for table `app_desc` -- DROP TABLE IF EXISTS `app_desc`; CREATE TABLE `app_desc` ( `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id', `name` varchar(36) NOT NULL COMMENT '应用名', `user_id` bigint(20) NOT NULL COMMENT '申请人id', `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配,1申请未审批,2审批并发布 3:应用下线', `intro` varchar(255) NOT NULL COMMENT '应用描述', `create_time` datetime NOT NULL COMMENT '创建时间', `passed_time` datetime NOT NULL COMMENT '审批通过时间', `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型,1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud ,5. redis-sentinel ,6.redis-standalone ', `officer` varchar(32) NOT NULL COMMENT '负责人,中文', `ver_id` int(11) NOT NULL COMMENT '版本', `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试:1是0否', `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否', `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否', `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否', `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps', `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数', `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值', `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息', `client_conn_alert_value` int(11) DEFAULT '2000' COMMENT '客户端连接报警阀值', `app_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥', `important_level` tinyint(4) NOT NULL DEFAULT '2' COMMENT '应用级别,1:最重要,2:一般重要,3:一般', `password` varchar(255) DEFAULT '' COMMENT 'redis密码', `custom_password` varchar(255) DEFAULT NULL COMMENT '自定义密码', `hit_precent_alert_value` int(11) DEFAULT '0' COMMENT '命中率报警阀值 0:不报警 ', `is_access_monitor` int(11) DEFAULT '0' COMMENT '是否接入全局监控报警 默认0,0:不接入监控 1:接入监控', `app_fsync_value` int(11) DEFAULT '1' COMMENT '应用刷盘策略 1:主从节点appdendfsync=everysec 2:主从节点 appdendfsync=no', `version_id` int(11) NOT NULL DEFAULT '1' COMMENT 'Redis版本表主键id', PRIMARY KEY (`app_id`), UNIQUE KEY `uidx_app_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app应用描述' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_command_statistics` -- DROP TABLE IF EXISTS `app_hour_command_statistics`; CREATE TABLE `app_hour_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_statistics` -- DROP TABLE IF EXISTS `app_hour_statistics`; CREATE TABLE `app_hour_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH', `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和', `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和', `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值', `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '每小时修改时间最大值', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_command_statistics` -- DROP TABLE IF EXISTS `app_minute_command_statistics`; CREATE TABLE `app_minute_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_statistics` -- DROP TABLE IF EXISTS `app_minute_statistics`; CREATE TABLE `app_minute_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `hits` bigint(20) NOT NULL COMMENT '命中数量', `misses` bigint(20) NOT NULL COMMENT '未命中数量', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '内存占用', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量', `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '客户端连接数', `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_to_user` -- DROP TABLE IF EXISTS `app_to_user`; CREATE TABLE `app_to_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '用户id', `app_id` bigint(20) NOT NULL COMMENT '应用id', PRIMARY KEY (`id`), KEY `app_id` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_user` -- DROP TABLE IF EXISTS `app_user`; CREATE TABLE `app_user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '用户名', `ch_name` varchar(255) NOT NULL COMMENT '中文名', `email` varchar(64) NOT NULL COMMENT '邮箱', `mobile` varchar(16) NOT NULL COMMENT '手机', `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员,1预留,2普通用户,-1无效', `weChat` varchar(32) DEFAULT NULL COMMENT '微信号', `isAlert` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户是否接收报警 0:不接收 1:接收', `password` varchar(64) DEFAULT NULL COMMENT '密码', `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间', `purpose` varchar(255) DEFAULT NULL COMMENT '使用目的', `company` varchar(255) DEFAULT NULL COMMENT '公司名称', PRIMARY KEY (`id`), UNIQUE KEY `uidx_user_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' /* `compression`='tokudb_zlib' */; -- ---------------------------- -- Records of `app_user` -- ---------------------------- BEGIN; INSERT INTO `app_user` VALUES ('1', 'admin', 'admin', 'admin@xxx.com', '13500000000', '0', null, '1', NULL, current_timestamp(), NULL, NULL); COMMIT; -- -- Table structure for table `brevity_schedule_resources` -- DROP TABLE IF EXISTS `brevity_schedule_resources`; CREATE TABLE `brevity_schedule_resources` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(4) NOT NULL COMMENT '类型,见:BrevityScheduleType', `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '时间版本', `host` varchar(16) NOT NULL COMMENT '资源ip', `port` int(11) NOT NULL DEFAULT '0' COMMENT '端口', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_type_host_port` (`type`,`host`,`port`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='短频任务表'; -- -- Table structure for table `diagnostic_task_record` -- DROP TABLE IF EXISTS `diagnostic_task_record`; CREATE TABLE `diagnostic_task_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `type` int(11) DEFAULT NULL COMMENT '诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam', `task_id` bigint(20) DEFAULT NULL COMMENT '任务流id', `audit_id` bigint(20) DEFAULT NULL COMMENT '审批id', `status` int(11) DEFAULT NULL COMMENT '诊断状态:0开始 1结束 2异常', `cost` bigint(20) DEFAULT NULL COMMENT '耗时,毫秒', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `redis_key` varchar(100) DEFAULT NULL COMMENT '结果的key', `node` varchar(100) DEFAULT NULL COMMENT '实例,host:port', `parent_task_id` bigint(20) DEFAULT NULL COMMENT '父任务id', `diagnostic_condition` varchar(100) DEFAULT NULL COMMENT '诊断条件', `param1` varchar(100) DEFAULT NULL COMMENT '备用参数1', `param2` varchar(100) DEFAULT NULL COMMENT '备用参数2', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用诊断记录'; -- -- Table structure for table `instance_alert_configs` -- DROP TABLE IF EXISTS `instance_alert_configs`; CREATE TABLE `instance_alert_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `alert_config` varchar(255) NOT NULL COMMENT '报警配置', `alert_value` varchar(512) NOT NULL COMMENT '报警阀值', `config_info` varchar(255) NOT NULL COMMENT '配置说明', `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警', `instance_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0:全局配置,其他代表实例id', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `compare_type` tinyint(4) NOT NULL COMMENT '比较类型:1小于,2等于,3大于,4不等于', `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天', `update_time` datetime NOT NULL COMMENT '报警配置更新时间', `last_check_time` datetime NOT NULL COMMENT '上次检查时间', `important_level` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '重要程度(0:一般;1:重要;2:紧急)', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置'; -- ---------------------------- -- Records of `instance_alert_configs` -- ---------------------------- BEGIN; INSERT INTO `instance_alert_configs` VALUES ('9', 'aof_current_size', '6000', 'aof当前尺寸(单位:MB)', '1', '0', '1', '3', '3', '2017-06-19 09:43:22', '2020-09-17 10:52:00', 0), ('10', 'aof_delayed_fsync', '3', '分钟aof阻塞个数', '1', '0', '1', '3', '1', '2017-06-19 10:38:19', '2020-09-17 11:09:00', 1), ('11', 'client_biggest_input_buf', '10', '输入缓冲区最大buffer大小(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 10:47:03', '2020-09-17 11:09:00', 1), ('12', 'client_longest_output_list', '50000', '输出缓冲区最大队列长度', '1', '0', '1', '3', '1', '2017-06-19 10:55:45', '2020-09-17 11:09:00', 1), ('13', 'instantaneous_ops_per_sec', '60000', '实时ops', '1', '0', '1', '3', '1', '2017-06-19 11:02:38', '2020-09-17 11:09:00', 1),('14', 'latest_fork_usec', '400000', '上次fork所用时间(单位:微秒)', '1', '0', '1', '3', '5', '2017-06-19 11:21:35', '2020-09-16 16:51:00', 1), ('15', 'mem_fragmentation_ratio', '1.5', '内存碎片率(检测大于500MB)', '1', '0', '1', '3', '5', '2017-06-19 12:49:16', '2020-09-16 16:51:00', 0), ('16', 'rdb_last_bgsave_status', 'ok', '上一次bgsave状态', '1', '0', '1', '4', '4', '2017-06-19 14:15:21', '2020-09-17 10:19:00', 0), ('17', 'total_net_output_bytes', '5000', '分钟网络输出流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:39:44', '2020-09-17 11:09:00', 0), ('19', 'total_net_input_bytes', '1200', '分钟网络输入流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:45:44', '2020-09-17 11:09:00', 0), ('20', 'sync_partial_err', '0', '分钟部分复制失败次数', '1', '0', '1', '3', '1', '2017-06-19 18:34:41', '2020-09-17 11:09:00', 1), ('21', 'sync_partial_ok', '0', '分钟部分复制成功次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:01', '2020-09-17 11:09:00', 1), ('22', 'sync_full', '0', '分钟全量复制执行次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:17', '2020-09-17 11:09:00', 1), ('23', 'rejected_connections', '0', '分钟拒绝连接数', '1', '0', '1', '3', '1', '2017-06-19 18:35:36', '2020-09-17 11:09:00', 2), ('54', 'master_slave_offset_diff', '20000000', '主从节点偏移量差(单位:字节)', '1', '0', '1', '3', '2', '2017-06-20 18:58:56', '2020-09-17 11:06:00', 0), ('56', 'cluster_state', 'ok', '集群状态', '1', '0', '1', '4', '1', '2017-06-21 18:01:52', '2020-09-17 11:09:00', 2), ('57', 'cluster_slots_ok', '16384', '集群成功分配槽个数', '1', '0', '1', '4', '1', '2017-06-21 18:02:04', '2020-09-17 11:09:00', 2); COMMIT; -- -- Table structure for table `instance_big_key` -- DROP TABLE IF EXISTS `instance_big_key`; CREATE TABLE `instance_big_key` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `audit_id` bigint(20) NOT NULL COMMENT 'audit id', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从,详见InstanceRoleEnum', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `big_key` varchar(255) NOT NULL COMMENT '键', `type` varchar(16) NOT NULL COMMENT '类型:string,hash,list,set,zset', `length` int(11) NOT NULL COMMENT '长度', `create_time` datetime NOT NULL COMMENT '记录创建时间', PRIMARY KEY (`id`), KEY `idx_app_audit` (`app_id`,`audit_id`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例bigkey列表'; -- -- Table structure for table `instance_config` -- DROP TABLE IF EXISTS `instance_config`; CREATE TABLE `instance_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Redis版本表主键id', `refresh` mediumint(9) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例配置模板'; -- ---------------------------- -- Records of `instance_config` -- ---------------------------- BEGIN; INSERT INTO `instance_config` VALUES ('1', 'cluster-enabled', 'yes', '是否开启集群模式', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('2', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('3', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('4', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('5', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('6', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2016-07-05 15:08:31', '2', '1', '29', '0'), ('7', 'port', '%d', 'sentinel实例端口', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('8', 'dir', '%s', '工作目录', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('9', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('10', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('11', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('12', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('13', 'daemonize', 'no', '是否守护进程', '2016-07-14 14:00:05', '6', '1', '29', '0'), ('14', 'tcp-backlog', '511', 'TCP连接完成队列', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('15', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('16', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2016-12-06 11:40:46', '6', '1', '29', '0'), ('17', 'loglevel', 'notice', '日志级别', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('18', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('19', 'dir', '%s', 'redis工作目录', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('20', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('21', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('22', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('23', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('24', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('25', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('26', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('27', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('28', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('29', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('30', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('31', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('32', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('33', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('34', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('35', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('36', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('37', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('38', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('39', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('40', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('41', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2016-11-24 10:24:21', '6', '1', '29', '0'), ('42', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('43', 'hz', '10', '执行后台task数量,默认:10', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('44', 'port', '%d', '端口', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('45', 'maxmemory', '%dmb', '当前实例最大可用内存', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('46', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('47', 'appendonly', 'yes', '开启append only持久化模式', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('48', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('49', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('50', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('51', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('52', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('53', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('54', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('55', 'maxclients', '10000', '客户端最大连接数', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('126', 'cluster-enabled', 'yes', '是否开启集群模式', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('127', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('128', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('129', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('130', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('131', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('132', 'port', '%d', 'sentinel实例端口', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('133', 'dir', '%s', '工作目录', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('134', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('135', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('136', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('137', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('138', 'daemonize', 'no', '是否守护进程', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('139', 'tcp-backlog', '511', 'TCP连接完成队列', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('140', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('141', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('142', 'loglevel', 'notice', '日志级别', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('143', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('144', 'dir', '%s', 'redis工作目录', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('145', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('146', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('147', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('148', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('149', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('150', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('151', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('152', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('153', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('154', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('155', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('156', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('157', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('158', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('159', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2018-09-18 18:25:32', '6', '0', '31', '0'), ('160', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2018-09-18 18:25:40', '6', '0', '31', '0'), ('161', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('162', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('163', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('164', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('165', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('166', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('167', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('168', 'hz', '10', '执行后台task数量,默认:10', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('169', 'port', '%d', '端口', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('170', 'maxmemory', '%dmb', '当前实例最大可用内存', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('171', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('172', 'appendonly', 'yes', '开启append only持久化模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('173', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('174', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('175', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('176', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('177', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('178', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('179', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('180', 'maxclients', '10000', '客户端最大连接数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('181', 'protected-mode', 'yes', '开启保护模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('182', 'bind', '0.0.0.0', '默认客户端都可连接', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('185', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2018-09-18 18:26:32', '6', '1', '31', '0'), ('186', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2018-09-18 18:27:12', '6', '1', '31', '0'), ('253', 'protected-mode', 'no', '关闭保护模式', '2018-11-01 16:10:59', '5', '1', '31', '0'), ('354', 'cluster-enabled', 'yes', '是否开启集群模式', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('355', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('356', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('357', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('358', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('359', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('360', 'port', '%d', 'sentinel实例端口', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('361', 'dir', '%s', '工作目录', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('362', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('363', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('364', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('365', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('366', 'daemonize', 'no', '是否守护进程', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('367', 'tcp-backlog', '511', 'TCP连接完成队列', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('368', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('369', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('370', 'loglevel', 'notice', '日志级别', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('371', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('372', 'dir', '%s', 'redis工作目录', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('373', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('374', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('375', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('376', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('377', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('378', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('379', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('380', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('381', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('382', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('383', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('384', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('385', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('386', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('387', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('388', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('389', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('390', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('391', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('392', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('393', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('394', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('395', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('396', 'hz', '10', '执行后台task数量,默认:10', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('397', 'port', '%d', '端口', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('398', 'maxmemory', '%dmb', '当前实例最大可用内存', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('399', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('400', 'appendonly', 'yes', '开启append only持久化模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('401', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('402', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('403', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('404', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('405', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('406', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('407', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('408', 'maxclients', '10000', '客户端最大连接数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('409', 'protected-mode', 'yes', '开启保护模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('410', 'bind', '0.0.0.0', '默认客户端都可连接', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('411', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('412', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('413', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('414', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('415', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('416', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('417', 'slave-lazy-flush', 'yes', 'slave发起全量复制,是否采用flushall async清理老数据 默认值 no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('418', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2019-10-31 11:15:57', '6', '1', '12', '0'), ('419', 'protected-mode', 'no', '关闭sentinel保护模式', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('420', 'activedefrag', 'no', '碎片整理开启', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('421', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('422', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('423', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('424', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('425', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('506', 'cluster-enabled', 'yes', '是否开启集群模式', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('507', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('508', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('509', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('510', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('511', 'port', '%d', 'sentinel实例端口', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('512', 'dir', '%s', '工作目录', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('513', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('514', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('515', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('516', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('517', 'daemonize', 'no', '是否守护进程', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('518', 'tcp-backlog', '511', 'TCP连接完成队列', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('519', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('520', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('521', 'loglevel', 'notice', '日志级别', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('522', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('523', 'dir', '%s', 'redis工作目录', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('524', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('525', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('526', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('527', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('528', 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('529', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('530', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('531', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('532', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('533', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('534', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('535', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('536', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('537', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('538', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('539', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('540', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('541', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('542', 'hz', '10', '执行后台task数量,默认:10', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('543', 'port', '%d', '端口', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('544', 'maxmemory', '%dmb', '当前实例最大可用内存', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('545', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('546', 'appendonly', 'yes', '开启append only持久化模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('547', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('548', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('549', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('550', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('551', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('552', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('553', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('554', 'maxclients', '10000', '客户端最大连接数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('555', 'protected-mode', 'yes', '开启保护模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('556', 'bind', '0.0.0.0', '默认客户端都可连接', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('557', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('558', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('559', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('560', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('561', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('562', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('563', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('564', 'protected-mode', 'no', '关闭sentinel保护模式', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('565', 'activedefrag', 'yes', '碎片整理开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('566', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('567', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('568', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('569', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('570', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('571', 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('572', 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('573', 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('574', 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('575', 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('576', 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('577', 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('578', 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('579', 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('580', 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('581', 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('582', 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('583', 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('585', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:45:22', '6', '1', '37', '0'), ('587', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:18', '6', '1', '12', '0'), ('589', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:49', '6', '1', '31', '0'), ('590', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:49:47', '6', '1', '29', '0'); COMMIT; -- -- Table structure for table `instance_fault` -- DROP TABLE IF EXISTS `instance_fault`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `instance_fault` ( `id` int(11) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `inst_id` bigint(20) NOT NULL COMMENT '实例id', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `type` mediumint(4) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `reason` mediumtext NOT NULL COMMENT '故障原因描述', PRIMARY KEY (`id`), KEY `idx_ip_port` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `inst_id` (`inst_id`) ) ENGINE=InnoDB AUTO_INCREMENT=8927 DEFAULT CHARSET=utf8 COMMENT='实例故障表' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `instance_host` -- DROP TABLE IF EXISTS `instance_host`; CREATE TABLE `instance_host` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `ip` varchar(16) NOT NULL COMMENT '机器ip', `ssh_user` varchar(32) DEFAULT NULL COMMENT 'ssh用户', `ssh_pwd` varchar(32) DEFAULT NULL COMMENT 'ssh密码', `warn` int(5) DEFAULT '1' COMMENT '0不报警,1报警', PRIMARY KEY (`id`), UNIQUE KEY `uidx_host_ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_info` -- DROP TABLE IF EXISTS `instance_info`; CREATE TABLE `instance_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'memcached instance id', `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id', `app_id` bigint(20) NOT NULL COMMENT '应用id,与app_desc关联', `host_id` bigint(20) NOT NULL COMMENT '对应的主机id,与instance_host关联', `ip` varchar(16) NOT NULL COMMENT '实例的ip', `port` int(11) NOT NULL COMMENT '实例端口', `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线', `mem` int(11) NOT NULL COMMENT '内存大小', `conn` int(11) NOT NULL COMMENT '连接数', `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName', `type` mediumint(11) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`) USING BTREE, KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_latency_history` -- DROP TABLE IF EXISTS `instance_latency_history`; CREATE TABLE `instance_latency_history` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `event` varchar(255) NOT NULL COMMENT '事件名称', `execute_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `execution_cost` bigint(20) NOT NULL COMMENT '耗时(微妙)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `latencyistorykey` (`instance_id`,`event`,`execute_date`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executedate` (`app_id`,`execute_date`), KEY `idx_executedate` (`execute_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例延迟事件信息表'; -- -- Table structure for table `instance_minute_stats` -- DROP TABLE IF EXISTS `instance_minute_stats`; CREATE TABLE `instance_minute_stats` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `json` text NOT NULL COMMENT '统计json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例分钟统计表'; -- -- Table structure for table `instance_reshard_process` -- DROP TABLE IF EXISTS `instance_reshard_process`; CREATE TABLE `instance_reshard_process` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `audit_id` bigint(20) NOT NULL COMMENT '审核id', `source_instance_id` int(11) NOT NULL COMMENT '源实例id', `target_instance_id` int(11) NOT NULL COMMENT '目标实例id', `start_slot` int(11) NOT NULL COMMENT '开始slot', `end_slot` int(11) NOT NULL COMMENT '结束slot', `migrating_slot` int(11) NOT NULL COMMENT '正在迁移的slot', `is_pipeline` tinyint(4) NOT NULL COMMENT '是否为pipeline,0:否,1:是', `finish_slot_num` int(11) NOT NULL COMMENT '已经完成迁移的slot数量', `status` tinyint(4) NOT NULL COMMENT '0:运行中 1:完成 2:出错', `start_time` datetime NOT NULL COMMENT '迁移开始时间', `end_time` datetime NOT NULL COMMENT '迁移结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_audit` (`audit_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度'; -- -- Table structure for table `instance_slow_log` -- DROP TABLE IF EXISTS `instance_slow_log`; CREATE TABLE `instance_slow_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id', `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)', `command` varchar(255) NOT NULL COMMENT '执行命令', `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间', PRIMARY KEY (`id`), UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executetime` (`app_id`,`execute_time`), KEY `idx_executetime` (`execute_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表'; -- -- Table structure for table `instance_statistics` -- DROP TABLE IF EXISTS `instance_statistics`; CREATE TABLE `instance_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `inst_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `host_id` bigint(20) NOT NULL COMMENT '机器的id', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `port` int(255) NOT NULL COMMENT 'port', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从', `max_memory` bigint(255) NOT NULL COMMENT '预分配内存,单位byte', `used_memory` bigint(255) NOT NULL COMMENT '已使用内存,单位byte', `curr_items` bigint(255) NOT NULL COMMENT '当前item数量', `curr_connections` int(255) NOT NULL COMMENT '当前连接数', `misses` bigint(255) NOT NULL COMMENT 'miss数', `hits` bigint(255) NOT NULL COMMENT '命中数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mem_fragmentation_ratio` double DEFAULT '0' COMMENT '碎片率', `aof_delayed_fsync` int(11) DEFAULT '0' COMMENT 'aof阻塞次数', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `machine_id` (`host_id`), KEY `idx_inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_info` -- DROP TABLE IF EXISTS `machine_info`; CREATE TABLE `machine_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id', `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户', `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房', `mem` int(11) unsigned NOT NULL COMMENT '内存大小,单位G', `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量', `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟,0表示否,1表示是', `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip', `service_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上线时间', `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警,0不启用,1启用', `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用,1表示可用,0表示不可用;', `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组,默认为0,表示原生资源,非0表示外部提供的资源(可扩展)', `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他', `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))', `collect` int(11) DEFAULT '1' COMMENT 'switch of collect server status, 1:open, 0:close', `version_install` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '机器安装redis版本状态', `use_type` tinyint(4) DEFAULT '2' COMMENT '使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis-Sentinel机器(3)', `k8s_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否k8s容器:0:不是 1:是', `rack` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '机器所在机架信息', `is_allocating` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否在分配中,1是0否', `disk` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '磁盘空间:G', `dis_type` tinyint(4) DEFAULT 0 NOT NULL COMMENT '操作系统发行版本,0:centos;1:ubuntu', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='机器信息表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_relation` -- DROP TABLE IF EXISTS `machine_relation`; CREATE TABLE `machine_relation` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `ip` varchar(64) NOT NULL COMMENT '虚拟机ip', `real_ip` varchar(64) NOT NULL COMMENT '宿主机ip', `extra_desc` varchar(128) DEFAULT NULL COMMENT '实例描述信息', `status` int(255) NOT NULL COMMENT '实例变更状态 0:offline ,1:online', `is_sync` tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据同步状态 0: 未同步数据 -1:同步中 1:数据已同步 -2:同步失败 ', `sync_time` timestamp NULL DEFAULT NULL COMMENT '同步时间', `update_time` timestamp NULL DEFAULT NULL COMMENT 'pod最后更新时间', `taskid` bigint(11) DEFAULT NULL COMMENT '任务id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `machine_room` -- DROP TABLE IF EXISTS `machine_room`; CREATE TABLE `machine_room` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机房id', `name` varchar(255) NOT NULL COMMENT '机房名称', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `desc` varchar(255) DEFAULT NULL COMMENT '机房描述信息', `ip_network` varchar(32) NOT NULL DEFAULT '' COMMENT '机房网段信息', `operator` varchar(255) DEFAULT NULL COMMENT '运营商', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `machine_room` -- ---------------------------- BEGIN; INSERT INTO `machine_room` VALUES ('1', '阿里云杭州', '1', '阿里云-杭州机房', '172.27.*.*', '阿里云'); COMMIT; -- -- Table structure for table `machine_statistics` -- DROP TABLE IF EXISTS `machine_statistics`; CREATE TABLE `machine_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `host_id` bigint(20) NOT NULL COMMENT '机器id', `ip` varchar(16) NOT NULL COMMENT '机器ip', `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率', `load` varchar(120) NOT NULL COMMENT '机器负载', `traffic` varchar(120) NOT NULL COMMENT 'io网络流量', `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率', `memory_free` varchar(120) NOT NULL COMMENT '内存剩余', `memory_total` varchar(120) NOT NULL COMMENT '总内存量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `max_memory` int(11) DEFAULT '0' COMMENT '机器分配内存,单位MB', `instance_count` int(11) DEFAULT '0' COMMENT '机器实例数量', `machine_memory` int(11) DEFAULT '0' COMMENT '机器入库总内存,单位MB', PRIMARY KEY (`id`), UNIQUE KEY `uidx_ip` (`ip`), KEY `host_id` (`host_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_BLOB_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`; CREATE TABLE `QRTZ_BLOB_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_CALENDARS` -- DROP TABLE IF EXISTS `QRTZ_CALENDARS`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `QRTZ_CALENDARS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称', `CALENDAR` blob NOT NULL COMMENT 'calendar信息', PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `QRTZ_CRON_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`; CREATE TABLE `QRTZ_CRON_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_FIRED_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`; CREATE TABLE `QRTZ_FIRED_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(195) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(13) NOT NULL, `SCHED_TIME` bigint(13) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化', PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息,以及关联 Job 的执行信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_JOB_DETAILS` -- DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`; CREATE TABLE `QRTZ_JOB_DETAILS` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化,0不持久化,1持久化', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发,0非并发,1并发', `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复,0不恢复,1恢复', `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_LOCKS` -- DROP TABLE IF EXISTS `QRTZ_LOCKS`; CREATE TABLE `QRTZ_LOCKS` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_PAUSED_TRIGGER_GRPS` -- DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`; CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SCHEDULER_STATE` -- DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`; CREATE TABLE `QRTZ_SCHEDULER_STATE` ( `SCHED_NAME` varchar(120) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPLE_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`; CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPROP_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`; CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `STR_PROP_1` varchar(512) DEFAULT NULL, `STR_PROP_2` varchar(512) DEFAULT NULL, `STR_PROP_3` varchar(512) DEFAULT NULL, `INT_PROP_1` int(11) DEFAULT NULL, `INT_PROP_2` int(11) DEFAULT NULL, `LONG_PROP_1` bigint(20) DEFAULT NULL, `LONG_PROP_2` bigint(20) DEFAULT NULL, `DEC_PROP_1` decimal(13,4) DEFAULT NULL, `DEC_PROP_2` decimal(13,4) DEFAULT NULL, `BOOL_PROP_1` varchar(1) DEFAULT NULL, `BOOL_PROP_2` varchar(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_TRIGGERS`; CREATE TABLE `QRTZ_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(13) NOT NULL, `END_TIME` bigint(13) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(2) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `server` -- DROP TABLE IF EXISTS `server`; CREATE TABLE `server` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `host` varchar(255) DEFAULT NULL COMMENT 'host', `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version', `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num', `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号', `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息', `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息', `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u', `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `server_stat` -- DROP TABLE IF EXISTS `server_stat`; CREATE TABLE `server_stat` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `cdate` date NOT NULL COMMENT '数据收集天', `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟', `cuser` float DEFAULT NULL COMMENT '用户态占比', `csys` float DEFAULT NULL COMMENT '内核态占比', `cwio` float DEFAULT NULL COMMENT 'wio占比', `c_ext` text COMMENT '子cpu占比', `cload1` float DEFAULT NULL COMMENT '1分钟load', `cload5` float DEFAULT NULL COMMENT '5分钟load', `cload15` float DEFAULT NULL COMMENT '15分钟load', `mtotal` float DEFAULT NULL COMMENT '总内存,单位M', `mfree` float DEFAULT NULL COMMENT '空闲内存', `mcache` float DEFAULT NULL COMMENT 'cache', `mbuffer` float DEFAULT NULL COMMENT 'buffer', `mswap` float DEFAULT NULL COMMENT 'cache', `mswap_free` float DEFAULT NULL COMMENT 'cache', `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s', `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s', `nin_ext` text COMMENT '各网卡入流量详情', `nout_ext` text COMMENT '各网卡出流量详情', `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数', `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数', `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数', `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s', `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s', `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s', `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比', `d_ext` text COMMENT '磁盘各分区占比', `dspace` text COMMENT '磁盘各分区空间使用率', PRIMARY KEY (`ip`,`cdate`,`ctime`), KEY `idx_cdate` (`cdate`), KEY `idx_cdate_ctime` (`cdate`,`ctime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `system_config` -- DROP TABLE IF EXISTS `system_config`; CREATE TABLE `system_config` ( `config_key` varchar(255) NOT NULL COMMENT '配置key', `config_value` varchar(512) NOT NULL COMMENT '配置value', `info` varchar(255) NOT NULL COMMENT '配置说明', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `order_id` int(11) NOT NULL COMMENT '顺序', PRIMARY KEY (`config_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置'; -- ---------------------------- -- Records of `system_config` -- ---------------------------- BEGIN; INSERT INTO `system_config` VALUES ('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,11),('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,12),('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,33),('cachecloud.base.dir','/opt','cachecloud根目录,要和cachecloud-init.sh脚本中的目录一致',1,31),('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)
user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14),('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,22),('cachecloud.email.alert.interface','','邮件报警接口(参考报警接口规范)',1,24),('cachecloud.machine.ssh.name','cachecloud-open','机器ssh用户名',1,2),('cachecloud.machine.ssh.password','cachecloud-open','机器ssh密码',1,3),('cachecloud.machine.ssh.port','22','机器ssh端口',1,10),('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,35),('cachecloud.nmon.dir','/opt/cachecloud','nmon安装目录',1,32),('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,21),('cachecloud.owner.phone','xxx,yyy','手机号报警(逗号隔开)',1,21),('cachecloud.owner.weChat','xxx,yyy','微信号报警(逗号隔开)',1,21),('cachecloud.public.key.pem','/opt/ssh/id_rsa','密钥路径',1,5),('cachecloud.public.user.name','cachecloud-open','公钥用户名',1,4),('cachecloud.ssh.auth.type','1','ssh授权方式',1,1),('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,13),('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,22),('cachecloud.weChat.alert.interface','','微信报警接口(参考报警接口规范)',1,23),('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,34),('machine.load.alert.ratio','8.0','机器负载报警阀值',1,32); COMMIT; -- ---------------------------- -- Table structure for `system_resource` -- ---------------------------- DROP TABLE IF EXISTS `system_resource`; CREATE TABLE `system_resource` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '资源ID', `name` varchar(64) NOT NULL COMMENT '资源名称', `intro` varchar(255) DEFAULT NULL COMMENT '资源说明', `type` tinyint(4) NOT NULL COMMENT '1:仓库地址 2:脚本 3:资源包 4:公钥/私钥 6:目录管理 7:迁移工具管理', `lastmodify` datetime DEFAULT NULL COMMENT '最后更新时间', `dir` varchar(128) DEFAULT NULL COMMENT '资源路径', `url` varchar(128) DEFAULT NULL COMMENT '仓库地址', `ispush` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:未推送 1:已推送', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `username` varchar(255) DEFAULT NULL COMMENT '最后修改人', `task_id` bigint(11) DEFAULT NULL COMMENT '迁移任务id', `compile_info` varchar(255) DEFAULT NULL COMMENT '编译信息', `order_num` int(6) NOT NULL DEFAULT '0' COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `system_resource` -- ---------------------------- BEGIN; INSERT INTO `system_resource` VALUES (1,'cachecloud-init.sh','容器初始化脚本',2,'2020-07-15 18:35:41','/script','',0,1,NULL,NULL,NULL,0),(2,'x.x.x.x',NULL,1,'2020-08-10 10:31:51','/opt/download/software/cachecloud/resource','http://x.x.x.x/software/cachecloud/resource',0,1,'admin',0,NULL,0),(4,'cachecloud-env.sh','宿主环境脚本',2,'2020-07-15 18:36:28','/script','',0,1,NULL,NULL,NULL,0),(5,'id_rsa','私钥文件',4,'2020-07-07 10:45:39','/ssh','',0,1,NULL,NULL,NULL,0),(6,'id_rsa.pub','公钥文件',4,'2020-07-07 10:45:45','/ssh','',0,1,NULL,NULL,NULL,0),(12,'redis-4.0.14','redis 4.0.14资源包',3,'2020-08-10 09:52:41','/redis','http://download.redis.io/releases/redis-4.0.14.tar.gz',0,1,'admin',532,NULL,0),(21,'/script','脚本目录管理',6,'2020-08-10 10:51:34','',NULL,0,1,'admin',0,NULL,0),(28,'/ssh','ssh目录',6,'2020-07-20 17:55:03',NULL,NULL,0,1,'admin',0,NULL,0),(29,'redis-3.0.7','redis3.0.7 资源包',3,'2020-08-10 09:53:32','/redis','http://download.redis.io/releases/redis-3.0.7.tar.gz',0,1,'admin',529,NULL,0),(31,'redis-3.2.12','redis 3.2.12 资源包',3,'2020-08-10 15:08:21','/redis','http://download.redis.io/releases/redis-3.2.12.tar.gz',0,1,'admin',530,NULL,0),(32,'/redis','redis资源包管理',6,'2020-07-20 17:54:59',NULL,NULL,0,1,'admin',0,NULL,0),(33,'/tool','迁移工具资源包',6,'2020-07-20 17:54:53',NULL,NULL,0,1,'admin',0,NULL,0),(37,'redis-5.0.9','redis5.0.9 资源包',3,'2020-08-10 09:51:41','/redis','http://download.redis.io/releases/redis-5.0.9.tar.gz',0,1,'admin',533,NULL,0),(40,'redis-shake-2.0.3','redis 2.0.3\n修复fix 5.0迁移类型问题',7,'2020-08-11 10:53:26','/tool','https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz',0,1,'admin',518,NULL,0); COMMIT; -- -- Table structure for table `task_queue` -- DROP TABLE IF EXISTS `task_queue`; CREATE TABLE `task_queue` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `class_name` varchar(255) NOT NULL COMMENT '类名', `important_info` varchar(255) NOT NULL DEFAULT '' COMMENT '重要信息', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `param` longtext NOT NULL COMMENT '任务参数(json):随着任务变化', `init_param` longtext NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2中断,3失败', `parent_task_id` bigint(20) NOT NULL COMMENT '父任务id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `priority` int(11) NOT NULL COMMENT '优先级', `error_code` int(11) NOT NULL COMMENT '错误代码', `error_msg` varchar(255) NOT NULL COMMENT '错误消息', `task_note` varchar(255) NOT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务表'; -- -- Table structure for table `task_step_flow` -- DROP TABLE IF EXISTS `task_step_flow`; CREATE TABLE `task_step_flow` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `task_id` bigint(20) NOT NULL COMMENT '任务id', `child_task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '子任务id', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `order_no` int(11) NOT NULL COMMENT '序号', `status` tinyint(4) NOT NULL COMMENT '状态:0未开始、1成功、2中断、3跳过、4失败', `log` text COMMENT '日志', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_task_class_step` (`task_id`,`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤流表'; -- -- Table structure for table `task_step_meta` -- DROP TABLE IF EXISTS `task_step_meta`; CREATE TABLE `task_step_meta` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `step_desc` varchar(255) NOT NULL COMMENT '步骤描述', `ops_device` varchar(255) NOT NULL COMMENT '运维建议', `timeout` int(11) NOT NULL COMMENT '超时时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `order_no` int(11) NOT NULL COMMENT '序号', PRIMARY KEY (`id`), UNIQUE KEY `uk_class_step` (`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤元数据表'; /*!40101 SET character_set_client = @saved_cs_client */; -- ---------------------------- -- Table structure for `standard_statistics` -- ---------------------------- DROP TABLE IF EXISTS `standard_statistics`; CREATE TABLE `standard_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `info_json` text NOT NULL COMMENT '收集的json数据', `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `cluster_info_json` varchar(20480) NOT NULL DEFAULT '' COMMENT '收集的cluster info json数据', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_create_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_alert_record` -- DROP TABLE IF EXISTS `app_alert_record`; CREATE TABLE `app_alert_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `visible_type` int(1) NOT NULL COMMENT '可见类型(0:均可见;1:仅管理员可见;)', `important_level` int(1) NOT NULL COMMENT '重要类型(0:一般;1:重要;2:紧急)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `app_id` bigint(20) DEFAULT NULL COMMENT 'app id', `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id', `ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '机器ip', `port` int(10) DEFAULT NULL COMMENT '端口号', `title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '报警标题', `content` varchar(500) COLLATE utf8_bin NOT NULL COMMENT '报警内容', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `ip` (`ip`), KEY `idx_inst_id` (`instance_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报警记录表'; -- -- Table structure for table `config_restart_record` -- DROP TABLE IF EXISTS `config_restart_record`; CREATE TABLE `config_restart_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `app_name` varchar(36) NOT NULL COMMENT '应用名称', `operate_type` char(1) NOT NULL COMMENT '操作类型(0:滚动重启,1:修改配置强制重启;2:修改配置)', `param` varchar(2000) NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2成功,3失败,4配置修改待重启', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `log` longtext COMMENT '日志信息', `user_name` varchar(64) DEFAULT NULL COMMENT '操作人员姓名', `user_id` bigint(20) NOT NULL COMMENT '用户id', `instances` varchar(1000) DEFAULT NULL COMMENT '涉及实例id列表的json格式', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='重启记录表'; -- -- Table structure for table `module_info` -- DROP TABLE IF EXISTS `module_info`; CREATE TABLE `module_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `git_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'git resource', `info` varchar(128) DEFAULT NULL COMMENT '模块信息说明', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', PRIMARY KEY (`id`), UNIQUE KEY `NAMEKEY` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块信息表'; -- -- Table structure for table `module_version` -- DROP TABLE IF EXISTS `module_version`; CREATE TABLE `module_version` ( `id` int(11) NOT NULL AUTO_INCREMENT, `module_id` int(11) NOT NULL, `version_id` int(11) NOT NULL COMMENT '关联版本号', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `so_path` varchar(255) DEFAULT NULL COMMENT '编译后so库的地址', `tag` varchar(64) NOT NULL COMMENT '模块版本号', `status` int(255) NOT NULL DEFAULT '0' COMMENT '是否可用(关联so地址):0 不可用 1:可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块版本管理表'; -- -- Table structure for table `app_import` -- DROP TABLE IF EXISTS `app_import`; CREATE TABLE `app_import` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '目标应用id', `instance_info` text COMMENT '源redis实例信息', `redis_password` varchar(200) DEFAULT NULL COMMENT '源redis密码', `status` int(11) DEFAULT NULL COMMENT '迁移状态:PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功")', `step` int(11) DEFAULT NULL COMMENT '导入阶段', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `migrate_id` bigint(20) DEFAULT NULL COMMENT '数据迁移id', `mem_size` int(11) DEFAULT NULL COMMENT '目标应用内存大小,单位G', `redis_version_name` varchar(20) DEFAULT NULL COMMENT '目标应用redis版本,格式:redis-x.x.x', `app_build_task_id` bigint(20) DEFAULT NULL COMMENT '目标应用部署任务id', `source_type` int(11) DEFAULT NULL COMMENT '源redis类型:7:cluster, 6:sentinel, 5:standalone', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- redis_module_config definition CREATE TABLE `redis_module_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Module version版本表主键id', `refresh` tinyint(4) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', `module_id` int(11) NOT NULL DEFAULT '7' COMMENT 'Module 信息表id', `config_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '配置类型,0:加载和运行配置;1:加载时配置;2:运行时配置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='redis模块配置表'; -- app_to_module definition CREATE TABLE `app_to_module` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `app_id` bigint(20) NOT NULL COMMENT '应用id', `module_id` int(11) NOT NULL COMMENT '模块info id', `module_version_id` int(11) NOT NULL COMMENT '模块版本id', PRIMARY KEY (`id`), UNIQUE KEY `app_to_module_un` (`app_id`,`module_id`,`module_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='应用与模块关系表'; ================================================ FILE: cachecloud-web/sql/3.2.sql ================================================ -- MySQL dump 10.15 Distrib 10.0.16-MariaDB, for Linux (x86_64) -- -- Host: localhost Database: cachecloud_open -- ------------------------------------------------------ -- Server version 10.0.16-MariaDB-log SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for table `app_audit` -- DROP TABLE IF EXISTS `app_audit`; CREATE TABLE `app_audit` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '申请人的id', `user_name` varchar(64) NOT NULL COMMENT '用户名', `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置', `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1', `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2', `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3', `info` varchar(360) NOT NULL COMMENT '申请描述', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由', `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `operate_id` bigint(20) DEFAULT NULL COMMENT '工单处理人', PRIMARY KEY (`id`), KEY `idx_appid` (`app_id`), KEY `idx_create_time` (`create_time`), KEY `idx_status_create_time` (`status`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_audit_log` -- DROP TABLE IF EXISTS `app_audit_log`; CREATE TABLE `app_audit_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '审批操作人id', `info` longtext NOT NULL COMMENT 'app审批的详细信息', `type` tinyint(4) NOT NULL, `create_time` datetime NOT NULL, `app_audit_id` bigint(20) NOT NULL COMMENT '审批id', PRIMARY KEY (`id`), KEY `idx_audit_appid` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_client_command_minute_statistics` -- DROP TABLE IF EXISTS `app_client_command_minute_statistics`; CREATE TABLE `app_client_command_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `app_id` bigint(20) NOT NULL COMMENT '应用id', `command` varchar(20) NOT NULL COMMENT '命令明文', `cost` bigint(20) DEFAULT NULL COMMENT '命令累计毫秒耗时', `bytes_in` bigint(20) DEFAULT NULL COMMENT '输入流量', `bytes_out` bigint(20) DEFAULT NULL COMMENT '输出流量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx__appid_client_command_currentMin` (`app_id`,`client_ip`,`command`,`current_min`), KEY `idx_currentmin_appid_count_cost` (`current_min`,`app_id`,`count`,`cost`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟命令调用上报数据'; -- -- Table structure for table `app_client_exception_minute_statistics` -- DROP TABLE IF EXISTS `app_client_exception_minute_statistics`; CREATE TABLE `app_client_exception_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `type` tinyint(4) NOT NULL COMMENT '0:connect exception;1:command exception', `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `node` varchar(30) NOT NULL COMMENT '节点信息host:port', `count` bigint(20) DEFAULT NULL COMMENT '累计连接失败次数', `cost` bigint(20) DEFAULT NULL COMMENT '累计连接失败毫秒耗时', `latency_commands` varchar(255) DEFAULT NULL COMMENT '统计命令topN id,逗号分隔', `redis_pool_config` varchar(255) DEFAULT NULL COMMENT 'redis连接池配置信息', PRIMARY KEY (`id`), UNIQUE KEY `idx__client_node_type_currentMin` (`client_ip`,`node`,`type`,`current_min`), KEY `idx_appid_current_min` (`app_id`,`current_min`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据'; -- -- Table structure for table `app_client_latency_command` -- DROP TABLE IF EXISTS `app_client_latency_command`; CREATE TABLE `app_client_latency_command` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `command` varchar(255) NOT NULL COMMENT '命令明文', `size` bigint(20) DEFAULT NULL COMMENT '参数长度', `args` varchar(255) DEFAULT NULL COMMENT '裁剪后参数明文', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `invoke_time` bigint(20) DEFAULT NULL COMMENT '命令调用时间戳', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端异常命令调用详情'; -- -- Table structure for table `app_client_statistic_gather` -- DROP TABLE IF EXISTS `app_client_statistic_gather`; CREATE TABLE `app_client_statistic_gather` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gather_time` varchar(20) NOT NULL COMMENT '统计时间,格式yyyy-mm-dd', `app_id` bigint(20) NOT NULL COMMENT '应用id', `cmd_count` bigint(20) DEFAULT '0' COMMENT '命令调用次数', `conn_exp_count` bigint(20) DEFAULT '0' COMMENT '连接异常次数', `avg_cmd_cost` double DEFAULT '0' COMMENT '命令调用平均耗时,单位毫秒', `avg_cmd_exp_cost` double DEFAULT '0' COMMENT '命令超时平均耗时,单位毫秒', `avg_conn_exp_cost` double DEFAULT '0' COMMENT '连接异常平均耗时,单位毫秒', `cmd_exp_count` bigint(20) DEFAULT '0' COMMENT '命令超时次数', `instance_count` int(11) DEFAULT NULL COMMENT '应用实例数', `avg_mem_frag_ratio` double DEFAULT NULL COMMENT '平均碎片率', `mem_used_ratio` double DEFAULT NULL COMMENT '内存使用率', `exception_count` bigint(20) DEFAULT '0' COMMENT '异常数(旧,待下线)', `slow_log_count` bigint(20) DEFAULT '0' COMMENT '慢查询次数', `latency_count` bigint(20) DEFAULT '0' COMMENT '延迟事件次数', `object_size` bigint(20) DEFAULT '0' COMMENT '存储对象数', `used_memory` bigint(20) DEFAULT '0' COMMENT '内存占用 byte', `used_memory_rss` bigint(20) DEFAULT '0' COMMENT '物理内存占用 byte', `max_cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗(单位:秒)', `max_cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗(单位:秒)', `connected_clients` bigint(20) DEFAULT '0' COMMENT '应用客户端连接数', `topology_exam_result` tinyint(4) DEFAULT NULL COMMENT '拓扑诊断结果,0:正常,1:异常', PRIMARY KEY (`id`), UNIQUE KEY `idx_appid_gathertime` (`app_id`,`gather_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报数据全天统计'; -- -- Table structure for table `app_client_value_minute_stat` -- DROP TABLE IF EXISTS `app_client_value_minute_stat`; CREATE TABLE `app_client_value_minute_stat` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用appid', `collect_time` bigint(20) NOT NULL COMMENT '数据收集时间yyyyMMddHHmm00', `update_time` datetime NOT NULL COMMENT '更新时间', `command` varchar(20) NOT NULL COMMENT '执行命令', `distribute_type` tinyint(4) NOT NULL COMMENT '值分布', `count` int(11) NOT NULL COMMENT '命令执行次数', PRIMARY KEY (`id`), UNIQUE KEY `app_collect_command_dis` (`app_id`,`collect_time`,`command`,`distribute_type`), KEY `idx_collect_time` (`collect_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟值分布上报数据统计'; -- -- Table structure for table `app_client_version_statistic` -- DROP TABLE IF EXISTS `app_client_version_statistic`; CREATE TABLE `app_client_version_statistic` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址', `client_version` varchar(20) NOT NULL COMMENT '客户端版本', `report_time` datetime DEFAULT NULL COMMENT '上报时间', PRIMARY KEY (`id`), UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`), KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_daily` -- DROP TABLE IF EXISTS `app_daily`; CREATE TABLE `app_daily` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `date` date NOT NULL COMMENT '日期', `create_time` datetime NOT NULL, `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数', `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数', `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数', `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数', `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数', `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数', `avg_hit_ratio` double NOT NULL COMMENT '平均命中率', `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率', `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率', `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量', `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量', `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数', `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数', `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量', `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量', `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量', `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量', `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值', `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值', `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数', `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情', `client_cmd_count` bigint(20) NOT NULL COMMENT '累计命令调用次数', `client_avg_cmd_cost` double NOT NULL COMMENT '平均命令调用耗时', `client_conn_exp_count` bigint(20) NOT NULL COMMENT '累计连接异常事件次数', `client_avg_conn_exp_cost` double NOT NULL COMMENT '平均连接异常事件耗时', `client_cmd_exp_count` bigint(20) NOT NULL COMMENT '累计命令超时事件次数', `client_avg_cmd_exp_cost` double NOT NULL COMMENT '平均命令超时事件耗时', PRIMARY KEY (`id`), KEY `idx_appid_date` (`app_id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报'; -- -- Table structure for table `app_data_migrate_status` -- DROP TABLE IF EXISTS `app_data_migrate_status`; CREATE TABLE `app_data_migrate_status` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip', `migrate_machine_port` int(11) NOT NULL COMMENT '迁移工具所占port', `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表', `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表', `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id', `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id', `user_id` bigint(20) NOT NULL COMMENT '操作人', `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常', `start_time` datetime NOT NULL COMMENT '迁移开始执行时间', `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间', `log_path` varchar(255) NOT NULL COMMENT '日志文件路径', `config_path` varchar(255) NOT NULL COMMENT '配置文件路径', `migrate_id` varchar(50) DEFAULT NULL COMMENT 'migrate id', `migrate_tool` tinyint(4) DEFAULT NULL COMMENT 'migrate_tool, 0:redis-shake,1:redis-migrate-tool', `redis_source_version` varchar(20) DEFAULT NULL, `redis_target_version` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用迁移记录详情'; -- -- Table structure for table `app_desc` -- DROP TABLE IF EXISTS `app_desc`; CREATE TABLE `app_desc` ( `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id', `name` varchar(36) NOT NULL COMMENT '应用名', `user_id` bigint(20) NOT NULL COMMENT '申请人id', `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配,1申请未审批,2审批并发布 3:应用下线', `intro` varchar(255) NOT NULL COMMENT '应用描述', `create_time` datetime NOT NULL COMMENT '创建时间', `passed_time` datetime NOT NULL COMMENT '审批通过时间', `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型,1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud ,5. redis-sentinel ,6.redis-standalone ', `officer` varchar(32) NOT NULL COMMENT '负责人,中文', `ver_id` int(11) NOT NULL COMMENT '版本', `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试:1是0否', `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否', `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否', `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否', `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps', `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数', `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值', `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息', `client_conn_alert_value` int(11) DEFAULT '2000' COMMENT '客户端连接报警阀值', `app_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥', `important_level` tinyint(4) NOT NULL DEFAULT '2' COMMENT '应用级别,1:最重要,2:一般重要,3:一般', `password` varchar(255) DEFAULT '' COMMENT 'redis密码', `custom_password` varchar(255) DEFAULT NULL COMMENT '自定义密码', `hit_precent_alert_value` int(11) DEFAULT '0' COMMENT '命中率报警阀值 0:不报警 ', `is_access_monitor` int(11) DEFAULT '0' COMMENT '是否接入全局监控报警 默认0,0:不接入监控 1:接入监控', `app_fsync_value` int(11) DEFAULT '1' COMMENT '应用刷盘策略 1:主从节点appdendfsync=everysec 2:主从节点 appdendfsync=no', `version_id` int(11) NOT NULL DEFAULT '1' COMMENT 'Redis版本表主键id', `maxmemory_policy` tinyint(4) DEFAULT NULL COMMENT '淘汰策略(0:noeviction; 1:allkeys-lru;2:allkeys-lfu;3:volatile-lru;4:volatile-lfu;5:allkeys-random;6:volatile-random;7:volatile-ttl)', PRIMARY KEY (`app_id`), UNIQUE KEY `uidx_app_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app应用描述' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_command_statistics` -- DROP TABLE IF EXISTS `app_hour_command_statistics`; CREATE TABLE `app_hour_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_statistics` -- DROP TABLE IF EXISTS `app_hour_statistics`; CREATE TABLE `app_hour_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH', `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和', `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和', `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值', `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '每小时修改时间最大值', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_command_statistics` -- DROP TABLE IF EXISTS `app_minute_command_statistics`; CREATE TABLE `app_minute_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_statistics` -- DROP TABLE IF EXISTS `app_minute_statistics`; CREATE TABLE `app_minute_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `hits` bigint(20) NOT NULL COMMENT '命中数量', `misses` bigint(20) NOT NULL COMMENT '未命中数量', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '内存占用', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量', `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '客户端连接数', `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_to_user` -- DROP TABLE IF EXISTS `app_to_user`; CREATE TABLE `app_to_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '用户id', `app_id` bigint(20) NOT NULL COMMENT '应用id', PRIMARY KEY (`id`), KEY `app_id` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_user` -- DROP TABLE IF EXISTS `app_user`; CREATE TABLE `app_user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '用户名', `ch_name` varchar(255) NOT NULL COMMENT '中文名', `email` varchar(64) NOT NULL COMMENT '邮箱', `mobile` varchar(16) NOT NULL COMMENT '手机', `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员,1预留,2普通用户,-1无效', `weChat` varchar(32) DEFAULT NULL COMMENT '微信号', `isAlert` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户是否接收报警 0:不接收 1:接收', `password` varchar(64) DEFAULT NULL COMMENT '密码', `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间', `purpose` varchar(255) DEFAULT NULL COMMENT '使用目的', `company` varchar(255) DEFAULT NULL COMMENT '公司名称', PRIMARY KEY (`id`), UNIQUE KEY `uidx_user_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' /* `compression`='tokudb_zlib' */; -- ---------------------------- -- Records of `app_user` -- ---------------------------- BEGIN; INSERT INTO `app_user` VALUES ('1', 'admin', 'admin', 'admin@xxx.com', '13500000000', '0', null, '1', NULL, current_timestamp(), NULL, NULL); COMMIT; -- -- Table structure for table `brevity_schedule_resources` -- DROP TABLE IF EXISTS `brevity_schedule_resources`; CREATE TABLE `brevity_schedule_resources` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(4) NOT NULL COMMENT '类型,见:BrevityScheduleType', `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '时间版本', `host` varchar(16) NOT NULL COMMENT '资源ip', `port` int(11) NOT NULL DEFAULT '0' COMMENT '端口', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_type_host_port` (`type`,`host`,`port`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='短频任务表'; -- -- Table structure for table `diagnostic_task_record` -- DROP TABLE IF EXISTS `diagnostic_task_record`; CREATE TABLE `diagnostic_task_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `type` int(11) DEFAULT NULL COMMENT '诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam', `task_id` bigint(20) DEFAULT NULL COMMENT '任务流id', `audit_id` bigint(20) DEFAULT NULL COMMENT '审批id', `status` int(11) DEFAULT NULL COMMENT '诊断状态:0开始 1结束 2异常', `cost` bigint(20) DEFAULT NULL COMMENT '耗时,毫秒', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `redis_key` varchar(100) DEFAULT NULL COMMENT '结果的key', `node` varchar(100) DEFAULT NULL COMMENT '实例,host:port', `parent_task_id` bigint(20) DEFAULT NULL COMMENT '父任务id', `diagnostic_condition` varchar(100) DEFAULT NULL COMMENT '诊断条件', `param1` varchar(100) DEFAULT NULL COMMENT '备用参数1', `param2` varchar(100) DEFAULT NULL COMMENT '备用参数2', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用诊断记录'; -- -- Table structure for table `instance_alert_configs` -- DROP TABLE IF EXISTS `instance_alert_configs`; CREATE TABLE `instance_alert_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `alert_config` varchar(255) NOT NULL COMMENT '报警配置', `alert_value` varchar(512) NOT NULL COMMENT '报警阀值', `config_info` varchar(255) NOT NULL COMMENT '配置说明', `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警', `instance_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0:全局配置,其他代表实例id', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `compare_type` tinyint(4) NOT NULL COMMENT '比较类型:1小于,2等于,3大于,4不等于', `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天', `update_time` datetime NOT NULL COMMENT '报警配置更新时间', `last_check_time` datetime NOT NULL COMMENT '上次检查时间', `important_level` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '重要程度(0:一般;1:重要;2:紧急)', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置'; -- ---------------------------- -- Records of `instance_alert_configs` -- ---------------------------- BEGIN; INSERT INTO `instance_alert_configs` VALUES ('9', 'aof_current_size', '6000', 'aof当前尺寸(单位:MB)', '1', '0', '1', '3', '3', '2017-06-19 09:43:22', '2020-09-17 10:52:00', 0), ('10', 'aof_delayed_fsync', '3', '分钟aof阻塞个数', '1', '0', '1', '3', '1', '2017-06-19 10:38:19', '2020-09-17 11:09:00', 1), ('11', 'client_biggest_input_buf', '10', '输入缓冲区最大buffer大小(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 10:47:03', '2020-09-17 11:09:00', 1), ('12', 'client_longest_output_list', '50000', '输出缓冲区最大队列长度', '1', '0', '1', '3', '1', '2017-06-19 10:55:45', '2020-09-17 11:09:00', 1), ('13', 'instantaneous_ops_per_sec', '60000', '实时ops', '1', '0', '1', '3', '1', '2017-06-19 11:02:38', '2020-09-17 11:09:00', 1),('14', 'latest_fork_usec', '400000', '上次fork所用时间(单位:微秒)', '1', '0', '1', '3', '5', '2017-06-19 11:21:35', '2020-09-16 16:51:00', 1), ('15', 'mem_fragmentation_ratio', '1.5', '内存碎片率(检测大于500MB)', '1', '0', '1', '3', '5', '2017-06-19 12:49:16', '2020-09-16 16:51:00', 0), ('16', 'rdb_last_bgsave_status', 'ok', '上一次bgsave状态', '1', '0', '1', '4', '4', '2017-06-19 14:15:21', '2020-09-17 10:19:00', 0), ('17', 'total_net_output_bytes', '5000', '分钟网络输出流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:39:44', '2020-09-17 11:09:00', 0), ('19', 'total_net_input_bytes', '1200', '分钟网络输入流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:45:44', '2020-09-17 11:09:00', 0), ('20', 'sync_partial_err', '0', '分钟部分复制失败次数', '1', '0', '1', '3', '1', '2017-06-19 18:34:41', '2020-09-17 11:09:00', 1), ('21', 'sync_partial_ok', '0', '分钟部分复制成功次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:01', '2020-09-17 11:09:00', 1), ('22', 'sync_full', '0', '分钟全量复制执行次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:17', '2020-09-17 11:09:00', 1), ('23', 'rejected_connections', '0', '分钟拒绝连接数', '1', '0', '1', '3', '1', '2017-06-19 18:35:36', '2020-09-17 11:09:00', 2), ('54', 'master_slave_offset_diff', '20000000', '主从节点偏移量差(单位:字节)', '1', '0', '1', '3', '2', '2017-06-20 18:58:56', '2020-09-17 11:06:00', 0), ('56', 'cluster_state', 'ok', '集群状态', '1', '0', '1', '4', '1', '2017-06-21 18:01:52', '2020-09-17 11:09:00', 2), ('57', 'cluster_slots_ok', '16384', '集群成功分配槽个数', '1', '0', '1', '4', '1', '2017-06-21 18:02:04', '2020-09-17 11:09:00', 2); COMMIT; -- -- Table structure for table `instance_big_key` -- DROP TABLE IF EXISTS `instance_big_key`; CREATE TABLE `instance_big_key` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `audit_id` bigint(20) NOT NULL COMMENT 'audit id', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从,详见InstanceRoleEnum', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `big_key` varchar(255) NOT NULL COMMENT '键', `type` varchar(16) NOT NULL COMMENT '类型:string,hash,list,set,zset', `length` int(11) NOT NULL COMMENT '长度', `create_time` datetime NOT NULL COMMENT '记录创建时间', PRIMARY KEY (`id`), KEY `idx_app_audit` (`app_id`,`audit_id`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例bigkey列表'; -- -- Table structure for table `instance_config` -- DROP TABLE IF EXISTS `instance_config`; CREATE TABLE `instance_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Redis版本表主键id', `refresh` mediumint(9) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例配置模板'; -- ---------------------------- -- Records of `instance_config` -- ---------------------------- BEGIN; INSERT INTO `instance_config` VALUES ('1', 'cluster-enabled', 'yes', '是否开启集群模式', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('2', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('3', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('4', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('5', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2016-07-05 15:08:30', '2', '1', '29', '0'), ('6', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2016-07-05 15:08:31', '2', '1', '29', '0'), ('7', 'port', '%d', 'sentinel实例端口', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('8', 'dir', '%s', '工作目录', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('9', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('10', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('11', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('12', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2016-07-05 15:08:31', '5', '1', '29', '0'), ('13', 'daemonize', 'no', '是否守护进程', '2016-07-14 14:00:05', '6', '1', '29', '0'), ('14', 'tcp-backlog', '511', 'TCP连接完成队列', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('15', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('16', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2016-12-06 11:40:46', '6', '1', '29', '0'), ('17', 'loglevel', 'notice', '日志级别', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('18', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('19', 'dir', '%s', 'redis工作目录', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('20', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('21', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('22', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('23', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('24', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('25', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('26', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('27', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('28', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('29', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('30', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('31', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('32', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('33', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('34', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('35', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('36', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('37', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('38', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('39', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('40', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('41', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2016-11-24 10:24:21', '6', '1', '29', '0'), ('42', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('43', 'hz', '10', '执行后台task数量,默认:10', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('44', 'port', '%d', '端口', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('45', 'maxmemory', '%dmb', '当前实例最大可用内存', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('46', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2016-07-05 15:08:31', '6', '1', '29', '0'), ('47', 'appendonly', 'yes', '开启append only持久化模式', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('48', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('49', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('50', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('51', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('52', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('53', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('54', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('55', 'maxclients', '10000', '客户端最大连接数', '2016-07-05 15:08:32', '6', '1', '29', '0'), ('126', 'cluster-enabled', 'yes', '是否开启集群模式', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('127', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('128', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('129', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('130', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('131', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2018-09-18 18:23:03', '2', '1', '31', '0'), ('132', 'port', '%d', 'sentinel实例端口', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('133', 'dir', '%s', '工作目录', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('134', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('135', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('136', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('137', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2018-09-18 18:23:03', '5', '1', '31', '0'), ('138', 'daemonize', 'no', '是否守护进程', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('139', 'tcp-backlog', '511', 'TCP连接完成队列', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('140', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('141', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('142', 'loglevel', 'notice', '日志级别', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('143', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('144', 'dir', '%s', 'redis工作目录', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('145', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('146', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('147', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('148', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('149', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('150', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('151', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('152', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('153', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('154', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('155', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('156', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('157', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('158', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('159', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2018-09-18 18:25:32', '6', '0', '31', '0'), ('160', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2018-09-18 18:25:40', '6', '0', '31', '0'), ('161', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('162', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('163', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('164', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('165', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('166', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('167', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('168', 'hz', '10', '执行后台task数量,默认:10', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('169', 'port', '%d', '端口', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('170', 'maxmemory', '%dmb', '当前实例最大可用内存', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('171', 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('172', 'appendonly', 'yes', '开启append only持久化模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('173', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('174', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('175', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('176', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('177', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('178', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('179', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('180', 'maxclients', '10000', '客户端最大连接数', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('181', 'protected-mode', 'yes', '开启保护模式', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('182', 'bind', '0.0.0.0', '默认客户端都可连接', '2018-09-18 18:23:03', '6', '1', '31', '0'), ('185', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2018-09-18 18:26:32', '6', '1', '31', '0'), ('186', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2018-09-18 18:27:12', '6', '1', '31', '0'), ('253', 'protected-mode', 'no', '关闭保护模式', '2018-11-01 16:10:59', '5', '1', '31', '0'), ('354', 'cluster-enabled', 'yes', '是否开启集群模式', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('355', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('356', 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('357', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('358', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('359', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2019-10-24 17:33:26', '2', '1', '12', '0'), ('360', 'port', '%d', 'sentinel实例端口', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('361', 'dir', '%s', '工作目录', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('362', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('363', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('364', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('365', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('366', 'daemonize', 'no', '是否守护进程', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('367', 'tcp-backlog', '511', 'TCP连接完成队列', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('368', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('369', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('370', 'loglevel', 'notice', '日志级别', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('371', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('372', 'dir', '%s', 'redis工作目录', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('373', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('374', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('375', 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('376', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('377', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('378', 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('379', 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('380', 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('381', 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('382', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('383', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('384', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('385', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('386', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('387', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('388', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2019-10-24 17:33:26', '6', '0', '12', '0'), ('389', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('390', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('391', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('392', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('393', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('394', 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('395', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('396', 'hz', '10', '执行后台task数量,默认:10', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('397', 'port', '%d', '端口', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('398', 'maxmemory', '%dmb', '当前实例最大可用内存', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('399', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('400', 'appendonly', 'yes', '开启append only持久化模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('401', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('402', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('403', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('404', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('405', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('406', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('407', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('408', 'maxclients', '10000', '客户端最大连接数', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('409', 'protected-mode', 'yes', '开启保护模式', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('410', 'bind', '0.0.0.0', '默认客户端都可连接', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('411', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('412', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('413', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('414', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('415', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('416', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('417', 'slave-lazy-flush', 'yes', 'slave发起全量复制,是否采用flushall async清理老数据 默认值 no', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('418', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2019-10-31 11:15:57', '6', '1', '12', '0'), ('419', 'protected-mode', 'no', '关闭sentinel保护模式', '2019-10-24 17:33:26', '5', '1', '12', '0'), ('420', 'activedefrag', 'no', '碎片整理开启', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('421', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('422', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('423', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('424', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('425', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2019-10-24 17:33:26', '6', '1', '12', '0'), ('506', 'cluster-enabled', 'yes', '是否开启集群模式', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('507', 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('508', 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('509', 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('510', 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('511', 'port', '%d', 'sentinel实例端口', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('512', 'dir', '%s', '工作目录', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('513', 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('514', 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('515', 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('516', 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('517', 'daemonize', 'no', '是否守护进程', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('518', 'tcp-backlog', '511', 'TCP连接完成队列', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('519', 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('520', 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('521', 'loglevel', 'notice', '日志级别', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('522', 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('523', 'dir', '%s', 'redis工作目录', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('524', 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('525', 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('526', 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('527', 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('528', 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('529', 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('530', 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('531', 'slowlog-max-len', '128', '最多记录慢查询的条数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('532', 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('533', 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('534', 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('535', 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2020-04-26 18:12:55', '6', '0', '37', '0'), ('536', 'set-max-intset-entries', '512', 'set数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('537', 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('538', 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('539', 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('540', 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('541', 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('542', 'hz', '10', '执行后台task数量,默认:10', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('543', 'port', '%d', '端口', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('544', 'maxmemory', '%dmb', '当前实例最大可用内存', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('545', 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('546', 'appendonly', 'yes', '开启append only持久化模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('547', 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('548', 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('549', 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('550', 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('551', 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('552', 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('553', 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('554', 'maxclients', '10000', '客户端最大连接数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('555', 'protected-mode', 'yes', '开启保护模式', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('556', 'bind', '0.0.0.0', '默认客户端都可连接', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('557', 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('558', 'list-compress-depth', '0', '压缩方式,0:不压缩', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('559', 'always-show-logo', 'yes', 'redis启动是否显示logo', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('560', 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('561', 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('562', 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('563', 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('564', 'protected-mode', 'no', '关闭sentinel保护模式', '2020-04-26 18:12:55', '5', '1', '37', '0'), ('565', 'activedefrag', 'yes', '碎片整理开启', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('566', 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('567', 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('568', 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('569', 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('570', 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('571', 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('572', 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('573', 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2020-04-26 18:12:55', '2', '1', '37', '0'), ('574', 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('575', 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('576', 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('577', 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('578', 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('579', 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('580', 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('581', 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('582', 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('583', 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2020-04-26 18:12:55', '6', '1', '37', '0'), ('585', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:45:22', '6', '1', '37', '0'), ('587', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:18', '6', '1', '12', '0'), ('589', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:49', '6', '1', '31', '0'), ('590', 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:49:47', '6', '1', '29', '0'); COMMIT; -- -- Table structure for table `instance_fault` -- DROP TABLE IF EXISTS `instance_fault`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `instance_fault` ( `id` int(11) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `inst_id` bigint(20) NOT NULL COMMENT '实例id', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `type` mediumint(4) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `reason` mediumtext NOT NULL COMMENT '故障原因描述', PRIMARY KEY (`id`), KEY `idx_ip_port` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `inst_id` (`inst_id`) ) ENGINE=InnoDB AUTO_INCREMENT=8927 DEFAULT CHARSET=utf8 COMMENT='实例故障表' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `instance_host` -- DROP TABLE IF EXISTS `instance_host`; CREATE TABLE `instance_host` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `ip` varchar(16) NOT NULL COMMENT '机器ip', `ssh_user` varchar(32) DEFAULT NULL COMMENT 'ssh用户', `ssh_pwd` varchar(32) DEFAULT NULL COMMENT 'ssh密码', `warn` int(5) DEFAULT '1' COMMENT '0不报警,1报警', PRIMARY KEY (`id`), UNIQUE KEY `uidx_host_ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_info` -- DROP TABLE IF EXISTS `instance_info`; CREATE TABLE `instance_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'memcached instance id', `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id', `app_id` bigint(20) NOT NULL COMMENT '应用id,与app_desc关联', `host_id` bigint(20) NOT NULL COMMENT '对应的主机id,与instance_host关联', `ip` varchar(16) NOT NULL COMMENT '实例的ip', `port` int(11) NOT NULL COMMENT '实例端口', `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线', `mem` int(11) NOT NULL COMMENT '内存大小', `conn` int(11) NOT NULL COMMENT '连接数', `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName', `type` mediumint(11) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`) USING BTREE, KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_latency_history` -- DROP TABLE IF EXISTS `instance_latency_history`; CREATE TABLE `instance_latency_history` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `event` varchar(255) NOT NULL COMMENT '事件名称', `execute_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `execution_cost` bigint(20) NOT NULL COMMENT '耗时(微妙)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `latencyistorykey` (`instance_id`,`event`,`execute_date`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executedate` (`app_id`,`execute_date`), KEY `idx_executedate` (`execute_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例延迟事件信息表'; -- -- Table structure for table `instance_minute_stats` -- DROP TABLE IF EXISTS `instance_minute_stats`; CREATE TABLE `instance_minute_stats` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `json` text NOT NULL COMMENT '统计json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例分钟统计表'; -- -- Table structure for table `instance_reshard_process` -- DROP TABLE IF EXISTS `instance_reshard_process`; CREATE TABLE `instance_reshard_process` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `audit_id` bigint(20) NOT NULL COMMENT '审核id', `source_instance_id` int(11) NOT NULL COMMENT '源实例id', `target_instance_id` int(11) NOT NULL COMMENT '目标实例id', `start_slot` int(11) NOT NULL COMMENT '开始slot', `end_slot` int(11) NOT NULL COMMENT '结束slot', `migrating_slot` int(11) NOT NULL COMMENT '正在迁移的slot', `is_pipeline` tinyint(4) NOT NULL COMMENT '是否为pipeline,0:否,1:是', `finish_slot_num` int(11) NOT NULL COMMENT '已经完成迁移的slot数量', `status` tinyint(4) NOT NULL COMMENT '0:运行中 1:完成 2:出错', `start_time` datetime NOT NULL COMMENT '迁移开始时间', `end_time` datetime NOT NULL COMMENT '迁移结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_audit` (`audit_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度'; -- -- Table structure for table `instance_slow_log` -- DROP TABLE IF EXISTS `instance_slow_log`; CREATE TABLE `instance_slow_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id', `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)', `command` varchar(255) NOT NULL COMMENT '执行命令', `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间', PRIMARY KEY (`id`), UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executetime` (`app_id`,`execute_time`), KEY `idx_executetime` (`execute_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表'; -- -- Table structure for table `instance_statistics` -- DROP TABLE IF EXISTS `instance_statistics`; CREATE TABLE `instance_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `inst_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `host_id` bigint(20) NOT NULL COMMENT '机器的id', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `port` int(255) NOT NULL COMMENT 'port', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从', `max_memory` bigint(255) NOT NULL COMMENT '预分配内存,单位byte', `used_memory` bigint(255) NOT NULL COMMENT '已使用内存,单位byte', `curr_items` bigint(255) NOT NULL COMMENT '当前item数量', `curr_connections` int(255) NOT NULL COMMENT '当前连接数', `misses` bigint(255) NOT NULL COMMENT 'miss数', `hits` bigint(255) NOT NULL COMMENT '命中数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mem_fragmentation_ratio` double DEFAULT '0' COMMENT '碎片率', `aof_delayed_fsync` int(11) DEFAULT '0' COMMENT 'aof阻塞次数', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `machine_id` (`host_id`), KEY `idx_inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_info` -- DROP TABLE IF EXISTS `machine_info`; CREATE TABLE `machine_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id', `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户', `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房', `mem` int(11) unsigned NOT NULL COMMENT '内存大小,单位G', `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量', `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟,0表示否,1表示是', `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip', `service_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上线时间', `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警,0不启用,1启用', `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用,1表示可用,0表示不可用;', `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组,默认为0,表示原生资源,非0表示外部提供的资源(可扩展)', `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他', `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))', `collect` int(11) DEFAULT '1' COMMENT 'switch of collect server status, 1:open, 0:close', `version_install` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '机器安装redis版本状态', `use_type` tinyint(4) DEFAULT '2' COMMENT '使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis-Sentinel机器(3)', `k8s_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否k8s容器:0:不是 1:是', `rack` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '机器所在机架信息', `is_allocating` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否在分配中,1是0否', `disk` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '磁盘空间:G', `dis_type` tinyint(4) DEFAULT 0 NOT NULL COMMENT '操作系统发行版本,0:centos;1:ubuntu', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='机器信息表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_relation` -- DROP TABLE IF EXISTS `machine_relation`; CREATE TABLE `machine_relation` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `ip` varchar(64) NOT NULL COMMENT '虚拟机ip', `real_ip` varchar(64) NOT NULL COMMENT '宿主机ip', `extra_desc` varchar(128) DEFAULT NULL COMMENT '实例描述信息', `status` int(255) NOT NULL COMMENT '实例变更状态 0:offline ,1:online', `is_sync` tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据同步状态 0: 未同步数据 -1:同步中 1:数据已同步 -2:同步失败 ', `sync_time` timestamp NULL DEFAULT NULL COMMENT '同步时间', `update_time` timestamp NULL DEFAULT NULL COMMENT 'pod最后更新时间', `taskid` bigint(11) DEFAULT NULL COMMENT '任务id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `machine_room` -- DROP TABLE IF EXISTS `machine_room`; CREATE TABLE `machine_room` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机房id', `name` varchar(255) NOT NULL COMMENT '机房名称', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `desc` varchar(255) DEFAULT NULL COMMENT '机房描述信息', `ip_network` varchar(32) NOT NULL DEFAULT '' COMMENT '机房网段信息', `operator` varchar(255) DEFAULT NULL COMMENT '运营商', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `machine_room` -- ---------------------------- BEGIN; INSERT INTO `machine_room` VALUES ('1', '阿里云杭州', '1', '阿里云-杭州机房', '172.27.*.*', '阿里云'); COMMIT; -- -- Table structure for table `machine_statistics` -- DROP TABLE IF EXISTS `machine_statistics`; CREATE TABLE `machine_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `host_id` bigint(20) NOT NULL COMMENT '机器id', `ip` varchar(16) NOT NULL COMMENT '机器ip', `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率', `load` varchar(120) NOT NULL COMMENT '机器负载', `traffic` varchar(120) NOT NULL COMMENT 'io网络流量', `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率', `memory_free` varchar(120) NOT NULL COMMENT '内存剩余', `memory_total` varchar(120) NOT NULL COMMENT '总内存量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `max_memory` int(11) DEFAULT '0' COMMENT '机器分配内存,单位MB', `instance_count` int(11) DEFAULT '0' COMMENT '机器实例数量', `machine_memory` int(11) DEFAULT '0' COMMENT '机器入库总内存,单位MB', PRIMARY KEY (`id`), UNIQUE KEY `uidx_ip` (`ip`), KEY `host_id` (`host_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_BLOB_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`; CREATE TABLE `QRTZ_BLOB_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_CALENDARS` -- DROP TABLE IF EXISTS `QRTZ_CALENDARS`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `QRTZ_CALENDARS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称', `CALENDAR` blob NOT NULL COMMENT 'calendar信息', PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息' /* `compression`='tokudb_zlib' */; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Table structure for table `QRTZ_CRON_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`; CREATE TABLE `QRTZ_CRON_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_FIRED_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`; CREATE TABLE `QRTZ_FIRED_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(195) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(13) NOT NULL, `SCHED_TIME` bigint(13) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化', PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息,以及关联 Job 的执行信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_JOB_DETAILS` -- DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`; CREATE TABLE `QRTZ_JOB_DETAILS` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化,0不持久化,1持久化', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发,0非并发,1并发', `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复,0不恢复,1恢复', `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_LOCKS` -- DROP TABLE IF EXISTS `QRTZ_LOCKS`; CREATE TABLE `QRTZ_LOCKS` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_PAUSED_TRIGGER_GRPS` -- DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`; CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SCHEDULER_STATE` -- DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`; CREATE TABLE `QRTZ_SCHEDULER_STATE` ( `SCHED_NAME` varchar(120) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPLE_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`; CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPROP_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`; CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `STR_PROP_1` varchar(512) DEFAULT NULL, `STR_PROP_2` varchar(512) DEFAULT NULL, `STR_PROP_3` varchar(512) DEFAULT NULL, `INT_PROP_1` int(11) DEFAULT NULL, `INT_PROP_2` int(11) DEFAULT NULL, `LONG_PROP_1` bigint(20) DEFAULT NULL, `LONG_PROP_2` bigint(20) DEFAULT NULL, `DEC_PROP_1` decimal(13,4) DEFAULT NULL, `DEC_PROP_2` decimal(13,4) DEFAULT NULL, `BOOL_PROP_1` varchar(1) DEFAULT NULL, `BOOL_PROP_2` varchar(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_TRIGGERS`; CREATE TABLE `QRTZ_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(13) NOT NULL, `END_TIME` bigint(13) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(2) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `server` -- DROP TABLE IF EXISTS `server`; CREATE TABLE `server` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `host` varchar(255) DEFAULT NULL COMMENT 'host', `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version', `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num', `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号', `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息', `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息', `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u', `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `server_stat` -- DROP TABLE IF EXISTS `server_stat`; CREATE TABLE `server_stat` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `cdate` date NOT NULL COMMENT '数据收集天', `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟', `cuser` float DEFAULT NULL COMMENT '用户态占比', `csys` float DEFAULT NULL COMMENT '内核态占比', `cwio` float DEFAULT NULL COMMENT 'wio占比', `c_ext` text COMMENT '子cpu占比', `cload1` float DEFAULT NULL COMMENT '1分钟load', `cload5` float DEFAULT NULL COMMENT '5分钟load', `cload15` float DEFAULT NULL COMMENT '15分钟load', `mtotal` float DEFAULT NULL COMMENT '总内存,单位M', `mfree` float DEFAULT NULL COMMENT '空闲内存', `mcache` float DEFAULT NULL COMMENT 'cache', `mbuffer` float DEFAULT NULL COMMENT 'buffer', `mswap` float DEFAULT NULL COMMENT 'cache', `mswap_free` float DEFAULT NULL COMMENT 'cache', `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s', `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s', `nin_ext` text COMMENT '各网卡入流量详情', `nout_ext` text COMMENT '各网卡出流量详情', `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数', `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数', `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数', `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s', `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s', `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s', `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比', `d_ext` text COMMENT '磁盘各分区占比', `dspace` text COMMENT '磁盘各分区空间使用率', PRIMARY KEY (`ip`,`cdate`,`ctime`), KEY `idx_cdate` (`cdate`), KEY `idx_cdate_ctime` (`cdate`,`ctime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `system_config` -- DROP TABLE IF EXISTS `system_config`; CREATE TABLE `system_config` ( `config_key` varchar(255) NOT NULL COMMENT '配置key', `config_value` varchar(512) NOT NULL COMMENT '配置value', `info` varchar(255) NOT NULL COMMENT '配置说明', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `order_id` int(11) NOT NULL COMMENT '顺序', PRIMARY KEY (`config_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置'; -- ---------------------------- -- Records of `system_config` -- ---------------------------- BEGIN; INSERT INTO `system_config` VALUES ('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,11),('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,12),('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,33),('cachecloud.base.dir','/opt','cachecloud根目录,要和cachecloud-init.sh脚本中的目录一致',1,31),('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)
user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14),('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,22),('cachecloud.email.alert.interface','','邮件报警接口(参考报警接口规范)',1,24),('cachecloud.machine.ssh.name','cachecloud-open','机器ssh用户名',1,2),('cachecloud.machine.ssh.password','cachecloud-open','机器ssh密码',1,3),('cachecloud.machine.ssh.port','22','机器ssh端口',1,10),('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,35),('cachecloud.nmon.dir','/opt/cachecloud','nmon安装目录',1,32),('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,21),('cachecloud.owner.phone','xxx,yyy','手机号报警(逗号隔开)',1,21),('cachecloud.owner.weChat','xxx,yyy','微信号报警(逗号隔开)',1,21),('cachecloud.public.key.pem','/opt/ssh/id_rsa','密钥路径',1,5),('cachecloud.public.user.name','cachecloud-open','公钥用户名',1,4),('cachecloud.ssh.auth.type','1','ssh授权方式',1,1),('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,13),('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,22),('cachecloud.weChat.alert.interface','','微信报警接口(参考报警接口规范)',1,23),('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,34),('machine.load.alert.ratio','8.0','机器负载报警阀值',1,32); COMMIT; -- ---------------------------- -- Table structure for `system_resource` -- ---------------------------- DROP TABLE IF EXISTS `system_resource`; CREATE TABLE `system_resource` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '资源ID', `name` varchar(64) NOT NULL COMMENT '资源名称', `intro` varchar(255) DEFAULT NULL COMMENT '资源说明', `type` tinyint(4) NOT NULL COMMENT '1:仓库地址 2:脚本 3:资源包 4:公钥/私钥 6:目录管理 7:迁移工具管理', `lastmodify` datetime DEFAULT NULL COMMENT '最后更新时间', `dir` varchar(128) DEFAULT NULL COMMENT '资源路径', `url` varchar(128) DEFAULT NULL COMMENT '仓库地址', `ispush` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:未推送 1:已推送', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `username` varchar(255) DEFAULT NULL COMMENT '最后修改人', `task_id` bigint(11) DEFAULT NULL COMMENT '迁移任务id', `compile_info` varchar(255) DEFAULT NULL COMMENT '编译信息', `order_num` int(6) NOT NULL DEFAULT '0' COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `system_resource` -- ---------------------------- BEGIN; INSERT INTO `system_resource` VALUES (1,'cachecloud-init.sh','容器初始化脚本',2,'2020-07-15 18:35:41','/script','',0,1,NULL,NULL,NULL,0),(2,'x.x.x.x',NULL,1,'2020-08-10 10:31:51','/opt/download/software/cachecloud/resource','http://x.x.x.x/software/cachecloud/resource',0,1,'admin',0,NULL,0),(4,'cachecloud-env.sh','宿主环境脚本',2,'2020-07-15 18:36:28','/script','',0,1,NULL,NULL,NULL,0),(5,'id_rsa','私钥文件',4,'2020-07-07 10:45:39','/ssh','',0,1,NULL,NULL,NULL,0),(6,'id_rsa.pub','公钥文件',4,'2020-07-07 10:45:45','/ssh','',0,1,NULL,NULL,NULL,0),(12,'redis-4.0.14','redis 4.0.14资源包',3,'2020-08-10 09:52:41','/redis','http://download.redis.io/releases/redis-4.0.14.tar.gz',0,1,'admin',532,NULL,0),(21,'/script','脚本目录管理',6,'2020-08-10 10:51:34','',NULL,0,1,'admin',0,NULL,0),(28,'/ssh','ssh目录',6,'2020-07-20 17:55:03',NULL,NULL,0,1,'admin',0,NULL,0),(29,'redis-3.0.7','redis3.0.7 资源包',3,'2020-08-10 09:53:32','/redis','http://download.redis.io/releases/redis-3.0.7.tar.gz',0,1,'admin',529,NULL,0),(31,'redis-3.2.12','redis 3.2.12 资源包',3,'2020-08-10 15:08:21','/redis','http://download.redis.io/releases/redis-3.2.12.tar.gz',0,1,'admin',530,NULL,0),(32,'/redis','redis资源包管理',6,'2020-07-20 17:54:59',NULL,NULL,0,1,'admin',0,NULL,0),(33,'/tool','迁移工具资源包',6,'2020-07-20 17:54:53',NULL,NULL,0,1,'admin',0,NULL,0),(37,'redis-5.0.9','redis5.0.9 资源包',3,'2020-08-10 09:51:41','/redis','http://download.redis.io/releases/redis-5.0.9.tar.gz',0,1,'admin',533,NULL,0),(40,'redis-shake-2.0.3','redis 2.0.3\n修复fix 5.0迁移类型问题',7,'2020-08-11 10:53:26','/tool','https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz',0,1,'admin',518,NULL,0); COMMIT; -- -- Table structure for table `task_queue` -- DROP TABLE IF EXISTS `task_queue`; CREATE TABLE `task_queue` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `class_name` varchar(255) NOT NULL COMMENT '类名', `important_info` varchar(255) NOT NULL DEFAULT '' COMMENT '重要信息', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `param` longtext NOT NULL COMMENT '任务参数(json):随着任务变化', `init_param` longtext NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2中断,3失败', `parent_task_id` bigint(20) NOT NULL COMMENT '父任务id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `priority` int(11) NOT NULL COMMENT '优先级', `error_code` int(11) NOT NULL COMMENT '错误代码', `error_msg` varchar(255) NOT NULL COMMENT '错误消息', `task_note` varchar(255) NOT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务表'; -- -- Table structure for table `task_step_flow` -- DROP TABLE IF EXISTS `task_step_flow`; CREATE TABLE `task_step_flow` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `task_id` bigint(20) NOT NULL COMMENT '任务id', `child_task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '子任务id', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `order_no` int(11) NOT NULL COMMENT '序号', `status` tinyint(4) NOT NULL COMMENT '状态:0未开始、1成功、2中断、3跳过、4失败', `log` text COMMENT '日志', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_task_class_step` (`task_id`,`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤流表'; -- -- Table structure for table `task_step_meta` -- DROP TABLE IF EXISTS `task_step_meta`; CREATE TABLE `task_step_meta` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `step_desc` varchar(255) NOT NULL COMMENT '步骤描述', `ops_device` varchar(255) NOT NULL COMMENT '运维建议', `timeout` int(11) NOT NULL COMMENT '超时时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `order_no` int(11) NOT NULL COMMENT '序号', PRIMARY KEY (`id`), UNIQUE KEY `uk_class_step` (`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤元数据表'; /*!40101 SET character_set_client = @saved_cs_client */; -- ---------------------------- -- Table structure for `standard_statistics` -- ---------------------------- DROP TABLE IF EXISTS `standard_statistics`; CREATE TABLE `standard_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `info_json` text NOT NULL COMMENT '收集的json数据', `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `cluster_info_json` varchar(20480) NOT NULL DEFAULT '' COMMENT '收集的cluster info json数据', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_create_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_alert_record` -- DROP TABLE IF EXISTS `app_alert_record`; CREATE TABLE `app_alert_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `visible_type` int(1) NOT NULL COMMENT '可见类型(0:均可见;1:仅管理员可见;)', `important_level` int(1) NOT NULL COMMENT '重要类型(0:一般;1:重要;2:紧急)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `app_id` bigint(20) DEFAULT NULL COMMENT 'app id', `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id', `ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '机器ip', `port` int(10) DEFAULT NULL COMMENT '端口号', `title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '报警标题', `content` varchar(500) COLLATE utf8_bin NOT NULL COMMENT '报警内容', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `ip` (`ip`), KEY `idx_inst_id` (`instance_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报警记录表'; -- -- Table structure for table `config_restart_record` -- DROP TABLE IF EXISTS `config_restart_record`; CREATE TABLE `config_restart_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `app_name` varchar(36) NOT NULL COMMENT '应用名称', `operate_type` char(1) NOT NULL COMMENT '操作类型(0:滚动重启,1:修改配置强制重启;2:修改配置)', `param` varchar(2000) NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2成功,3失败,4配置修改待重启', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `log` longtext COMMENT '日志信息', `user_name` varchar(64) DEFAULT NULL COMMENT '操作人员姓名', `user_id` bigint(20) NOT NULL COMMENT '用户id', `instances` varchar(1000) DEFAULT NULL COMMENT '涉及实例id列表的json格式', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='重启记录表'; -- -- Table structure for table `module_info` -- DROP TABLE IF EXISTS `module_info`; CREATE TABLE `module_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `git_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'git resource', `info` varchar(128) DEFAULT NULL COMMENT '模块信息说明', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', PRIMARY KEY (`id`), UNIQUE KEY `NAMEKEY` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块信息表'; -- -- Table structure for table `module_version` -- DROP TABLE IF EXISTS `module_version`; CREATE TABLE `module_version` ( `id` int(11) NOT NULL AUTO_INCREMENT, `module_id` int(11) NOT NULL, `version_id` int(11) NOT NULL COMMENT '关联版本号', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `so_path` varchar(255) DEFAULT NULL COMMENT '编译后so库的地址', `tag` varchar(64) NOT NULL COMMENT '模块版本号', `status` int(255) NOT NULL DEFAULT '0' COMMENT '是否可用(关联so地址):0 不可用 1:可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redis模块版本管理表'; -- -- Table structure for table `app_import` -- DROP TABLE IF EXISTS `app_import`; CREATE TABLE `app_import` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '目标应用id', `instance_info` text COMMENT '源redis实例信息', `redis_password` varchar(200) DEFAULT NULL COMMENT '源redis密码', `status` int(11) DEFAULT NULL COMMENT '迁移状态:PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功")', `step` int(11) DEFAULT NULL COMMENT '导入阶段', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `migrate_id` bigint(20) DEFAULT NULL COMMENT '数据迁移id', `mem_size` int(11) DEFAULT NULL COMMENT '目标应用内存大小,单位G', `redis_version_name` varchar(20) DEFAULT NULL COMMENT '目标应用redis版本,格式:redis-x.x.x', `app_build_task_id` bigint(20) DEFAULT NULL COMMENT '目标应用部署任务id', `source_type` int(11) DEFAULT NULL COMMENT '源redis类型:7:cluster, 6:sentinel, 5:standalone', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- redis_module_config definition CREATE TABLE `redis_module_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Module version版本表主键id', `refresh` tinyint(4) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', `module_id` int(11) NOT NULL DEFAULT '7' COMMENT 'Module 信息表id', `config_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '配置类型,0:加载和运行配置;1:加载时配置;2:运行时配置', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='redis模块配置表'; -- app_to_module definition CREATE TABLE `app_to_module` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `app_id` bigint(20) NOT NULL COMMENT '应用id', `module_id` int(11) NOT NULL COMMENT '模块info id', `module_version_id` int(11) NOT NULL COMMENT '模块版本id', PRIMARY KEY (`id`), UNIQUE KEY `app_to_module_un` (`app_id`,`module_id`,`module_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='应用与模块关系表'; ================================================ FILE: cachecloud-web/sql/3.3.sql ================================================ -- MySQL dump 10.15 -- Database: cachecloud_open SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; -- -- Table structure for table `app_audit` -- DROP TABLE IF EXISTS `app_audit`; CREATE TABLE `app_audit` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '申请人的id', `user_name` varchar(64) NOT NULL COMMENT '用户名', `type` tinyint(4) NOT NULL COMMENT '申请类型:0:申请应用,1:应用扩容,2:修改配置', `param1` varchar(600) DEFAULT NULL COMMENT '预留参数1', `param2` varchar(600) DEFAULT NULL COMMENT '预留参数2', `param3` varchar(600) DEFAULT NULL COMMENT '预留参数3', `info` varchar(360) NOT NULL COMMENT '申请描述', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:等待审批; 1:审批通过; -1:驳回', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `refuse_reason` varchar(360) DEFAULT NULL COMMENT '驳回理由', `task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '任务id', `operate_id` bigint(20) DEFAULT NULL COMMENT '工单处理人', PRIMARY KEY (`id`), KEY `idx_appid` (`app_id`), KEY `idx_create_time` (`create_time`), KEY `idx_status_create_time` (`status`,`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用审核表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_audit_log` -- DROP TABLE IF EXISTS `app_audit_log`; CREATE TABLE `app_audit_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `user_id` bigint(20) NOT NULL COMMENT '审批操作人id', `info` longtext NOT NULL COMMENT 'app审批的详细信息', `type` tinyint(4) NOT NULL, `create_time` datetime NOT NULL, `app_audit_id` bigint(20) NOT NULL COMMENT '审批id', PRIMARY KEY (`id`), KEY `idx_audit_appid` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app审核日志表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_client_command_minute_statistics` -- DROP TABLE IF EXISTS `app_client_command_minute_statistics`; CREATE TABLE `app_client_command_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `app_id` bigint(20) NOT NULL COMMENT '应用id', `command` varchar(20) NOT NULL COMMENT '命令明文', `cost` bigint(20) DEFAULT NULL COMMENT '命令累计毫秒耗时', `bytes_in` bigint(20) DEFAULT NULL COMMENT '输入流量', `bytes_out` bigint(20) DEFAULT NULL COMMENT '输出流量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `count` int(11) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx__appid_client_command_currentMin` (`app_id`,`client_ip`,`command`,`current_min`), KEY `idx_currentmin_appid_count_cost` (`current_min`,`app_id`,`count`,`cost`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟命令调用上报数据'; -- -- Table structure for table `app_client_exception_minute_statistics` -- DROP TABLE IF EXISTS `app_client_exception_minute_statistics`; CREATE TABLE `app_client_exception_minute_statistics` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `current_min` bigint(20) NOT NULL COMMENT '统计时间', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip', `type` tinyint(4) NOT NULL COMMENT '0:connect exception;1:command exception', `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `node` varchar(30) NOT NULL COMMENT '节点信息host:port', `count` bigint(20) DEFAULT NULL COMMENT '累计连接失败次数', `cost` bigint(20) DEFAULT NULL COMMENT '累计连接失败毫秒耗时', `latency_commands` varchar(255) DEFAULT NULL COMMENT '统计命令topN id,逗号分隔', `redis_pool_config` varchar(255) DEFAULT NULL COMMENT 'redis连接池配置信息', PRIMARY KEY (`id`), UNIQUE KEY `idx__client_node_type_currentMin` (`client_ip`,`node`,`type`,`current_min`), KEY `idx_appid_current_min` (`app_id`,`current_min`), KEY `idx_current_min` (`current_min`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端每分钟异常上报数据'; -- -- Table structure for table `app_client_latency_command` -- DROP TABLE IF EXISTS `app_client_latency_command`; CREATE TABLE `app_client_latency_command` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `command` varchar(255) NOT NULL COMMENT '命令明文', `size` bigint(20) DEFAULT NULL COMMENT '参数长度', `args` varchar(255) DEFAULT NULL COMMENT '裁剪后参数明文', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `invoke_time` bigint(20) DEFAULT NULL COMMENT '命令调用时间戳', PRIMARY KEY (`id`), KEY `idx_createtime` (`create_time`), KEY `idx_command` (`command`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端异常命令调用详情'; -- -- Table structure for table `app_client_statistic_gather` -- DROP TABLE IF EXISTS `app_client_statistic_gather`; CREATE TABLE `app_client_statistic_gather` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gather_time` varchar(20) NOT NULL COMMENT '统计时间,格式yyyy-mm-dd', `app_id` bigint(20) NOT NULL COMMENT '应用id', `cmd_count` bigint(20) DEFAULT '0' COMMENT '命令调用次数', `conn_exp_count` bigint(20) DEFAULT '0' COMMENT '连接异常次数', `avg_cmd_cost` double DEFAULT '0' COMMENT '命令调用平均耗时,单位毫秒', `avg_cmd_exp_cost` double DEFAULT '0' COMMENT '命令超时平均耗时,单位毫秒', `avg_conn_exp_cost` double DEFAULT '0' COMMENT '连接异常平均耗时,单位毫秒', `cmd_exp_count` bigint(20) DEFAULT '0' COMMENT '命令超时次数', `instance_count` int(11) DEFAULT NULL COMMENT '应用实例数', `avg_mem_frag_ratio` double DEFAULT NULL COMMENT '平均碎片率', `mem_used_ratio` double DEFAULT NULL COMMENT '内存使用率', `exception_count` bigint(20) DEFAULT '0' COMMENT '异常数(旧,待下线)', `slow_log_count` bigint(20) DEFAULT '0' COMMENT '慢查询次数', `latency_count` bigint(20) DEFAULT '0' COMMENT '延迟事件次数', `object_size` bigint(20) DEFAULT '0' COMMENT '存储对象数', `used_memory` bigint(20) DEFAULT '0' COMMENT '内存占用 byte', `used_memory_rss` bigint(20) DEFAULT '0' COMMENT '物理内存占用 byte', `max_cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗(单位:秒)', `max_cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗(单位:秒)', `connected_clients` bigint(20) DEFAULT '0' COMMENT '应用客户端连接数', `topology_exam_result` tinyint(4) DEFAULT NULL COMMENT '拓扑诊断结果,0:正常,1:异常', `used_disk` bigint(20) DEFAULT '0' COMMENT '磁盘占用byte', `server_cmd_count` bigint(20) NOT NULL DEFAULT '0' COMMENT 'server端统计的命令调用次数', PRIMARY KEY (`id`), UNIQUE KEY `idx_appid_gathertime` (`app_id`,`gather_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报数据全天统计'; -- -- Table structure for table `app_client_version_statistic` -- DROP TABLE IF EXISTS `app_client_version_statistic`; CREATE TABLE `app_client_version_statistic` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `client_ip` varchar(20) NOT NULL COMMENT '客户端ip地址', `client_version` varchar(20) NOT NULL COMMENT '客户端版本', `report_time` datetime DEFAULT NULL COMMENT '上报时间', PRIMARY KEY (`id`), UNIQUE KEY `app_client_ip` (`app_id`,`client_ip`), KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端上报版本信息统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_daily` -- DROP TABLE IF EXISTS `app_daily`; CREATE TABLE `app_daily` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `date` date NOT NULL COMMENT '日期', `create_time` datetime NOT NULL, `slow_log_count` bigint(20) NOT NULL COMMENT '慢查询个数', `client_exception_count` bigint(20) NOT NULL COMMENT '客户端异常个数', `max_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟最大客户端连接数', `avg_minute_client_count` bigint(20) NOT NULL COMMENT '每分钟平均客户端连接数', `max_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟最大命令数', `avg_minute_command_count` bigint(20) NOT NULL COMMENT '每分钟平均命令数', `avg_hit_ratio` double NOT NULL COMMENT '平均命中率', `min_minute_hit_ratio` double NOT NULL COMMENT '每分钟最小命中率', `max_minute_hit_ratio` double NOT NULL COMMENT '每分钟最大命中率', `avg_used_memory` bigint(20) NOT NULL COMMENT '最大内存使用量', `max_used_memory` bigint(20) NOT NULL COMMENT '平均内存使用量', `expired_keys_count` bigint(20) NOT NULL COMMENT '过期键个数', `evicted_keys_count` bigint(20) NOT NULL COMMENT '剔除键个数', `avg_minute_net_input_byte` double NOT NULL COMMENT '每分钟平均网络input量', `max_minute_net_input_byte` double NOT NULL COMMENT '每分钟最大网络input量', `avg_minute_net_output_byte` double NOT NULL COMMENT '每分钟平均网络output量', `max_minute_net_output_byte` double NOT NULL COMMENT '每分钟最大网络output量', `avg_object_size` bigint(20) NOT NULL COMMENT '键个数平均值', `max_object_size` bigint(20) NOT NULL COMMENT '键个数最大值', `big_key_times` bigint(20) NOT NULL COMMENT 'bigkey次数', `big_key_info` varchar(512) COLLATE utf8_bin NOT NULL COMMENT 'bigkey详情', `client_cmd_count` bigint(20) NOT NULL COMMENT '累计命令调用次数', `client_avg_cmd_cost` double NOT NULL COMMENT '平均命令调用耗时', `client_conn_exp_count` bigint(20) NOT NULL COMMENT '累计连接异常事件次数', `client_avg_conn_exp_cost` double NOT NULL COMMENT '平均连接异常事件耗时', `client_cmd_exp_count` bigint(20) NOT NULL COMMENT '累计命令超时事件次数', `client_avg_cmd_exp_cost` double NOT NULL COMMENT '平均命令超时事件耗时', `avg_used_disk` bigint(20) NOT NULL COMMENT '平均磁盘使用量', `max_used_disk` bigint(20) NOT NULL COMMENT '最大磁盘使用量', PRIMARY KEY (`id`), KEY `idx_appid_date` (`app_id`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='app日报'; -- -- Table structure for table `app_data_migrate_status` -- DROP TABLE IF EXISTS `app_data_migrate_status`; CREATE TABLE `app_data_migrate_status` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `migrate_machine_ip` varchar(255) NOT NULL COMMENT '迁移工具所在机器ip', `migrate_machine_port` int(11) NOT NULL COMMENT '迁移工具所占port', `source_migrate_type` tinyint(4) NOT NULL COMMENT '源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `source_servers` varchar(2048) NOT NULL COMMENT '源实例列表', `target_migrate_type` tinyint(4) NOT NULL COMMENT '目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy', `target_servers` varchar(2048) NOT NULL COMMENT '目标实例列表', `source_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '源应用id', `target_app_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '目标应用id', `user_id` bigint(20) NOT NULL COMMENT '操作人', `status` tinyint(4) NOT NULL COMMENT '迁移执行状态,0:开始,1:结束,2:异常', `start_time` datetime NOT NULL COMMENT '迁移开始执行时间', `end_time` datetime DEFAULT NULL COMMENT '迁移结束执行时间', `log_path` varchar(255) NOT NULL COMMENT '日志文件路径', `config_path` varchar(255) NOT NULL COMMENT '配置文件路径', `migrate_id` varchar(50) DEFAULT NULL COMMENT 'migrate id', `migrate_tool` tinyint(4) DEFAULT NULL COMMENT 'migrate_tool, 0:redis-shake,1:redis-migrate-tool', `redis_source_version` varchar(20) DEFAULT NULL, `redis_target_version` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用迁移记录详情'; -- -- Table structure for table `app_desc` -- DROP TABLE IF EXISTS `app_desc`; CREATE TABLE `app_desc` ( `app_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '应用id', `name` varchar(36) NOT NULL COMMENT '应用名', `user_id` bigint(20) NOT NULL COMMENT '申请人id', `status` tinyint(4) NOT NULL COMMENT '应用状态, 0未分配,1申请未审批,2审批并发布 3:应用下线', `intro` varchar(255) NOT NULL COMMENT '应用描述', `create_time` datetime NOT NULL COMMENT '创建时间', `passed_time` datetime NOT NULL COMMENT '审批通过时间', `type` int(10) NOT NULL DEFAULT '0' COMMENT 'cache类型,1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud ,5. redis-sentinel ,6.redis-standalone ', `officer` varchar(32) NOT NULL COMMENT '负责人,中文', `ver_id` int(11) NOT NULL COMMENT '版本', `is_test` tinyint(4) DEFAULT '0' COMMENT '是否测试:1是0否', `need_persistence` tinyint(4) DEFAULT '1' COMMENT '是否需要持久化: 1是0否', `need_hot_back_up` tinyint(4) DEFAULT '1' COMMENT '是否需要热备: 1是0否', `has_back_store` tinyint(4) DEFAULT '1' COMMENT '是否有后端数据源: 1是0否', `forecase_qps` int(11) DEFAULT NULL COMMENT '预估qps', `forecast_obj_num` int(11) DEFAULT NULL COMMENT '预估条目数', `mem_alert_value` int(11) DEFAULT NULL COMMENT '内存报警阀值', `client_machine_room` varchar(36) DEFAULT NULL COMMENT '客户端机房信息', `client_conn_alert_value` int(11) DEFAULT '2000' COMMENT '客户端连接报警阀值', `app_key` varchar(255) DEFAULT NULL COMMENT '应用秘钥', `important_level` tinyint(4) NOT NULL DEFAULT '2' COMMENT '应用级别,1:最重要,2:一般重要,3:一般', `password` varchar(255) DEFAULT '' COMMENT 'redis密码', `custom_password` varchar(255) DEFAULT NULL COMMENT '自定义密码', `hit_precent_alert_value` int(11) DEFAULT '0' COMMENT '命中率报警阀值 0:不报警 ', `is_access_monitor` int(11) DEFAULT '0' COMMENT '是否接入全局监控报警 默认0,0:不接入监控 1:接入监控', `app_fsync_value` int(11) DEFAULT '1' COMMENT '应用刷盘策略 1:主从节点appdendfsync=everysec 2:主从节点 appdendfsync=no', `version_id` int(11) NOT NULL DEFAULT '1' COMMENT 'Redis版本表主键id', `maxmemory_policy` tinyint(4) DEFAULT NULL COMMENT '淘汰策略(0:noeviction; 1:allkeys-lru;2:allkeys-lfu;3:volatile-lru;4:volatile-lfu;5:allkeys-random;6:volatile-random;7:volatile-ttl)', `persistence_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '持久化类型(0:常规;1:主aof自动刷盘;从常规;2:主关闭aof,从常规)', PRIMARY KEY (`app_id`), UNIQUE KEY `uidx_app_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='app应用描述' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_command_statistics` -- DROP TABLE IF EXISTS `app_hour_command_statistics`; CREATE TABLE `app_hour_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHH', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`command_name`,`collect_time`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每小时命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_hour_statistics` -- DROP TABLE IF EXISTS `app_hour_statistics`; CREATE TABLE `app_hour_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHH', `hits` bigint(20) NOT NULL COMMENT '每小时命中数量和', `misses` bigint(20) NOT NULL COMMENT '每小时未命中数量和', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '每小时内存占用最大值', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '每小时过期key数量和', `evicted_keys` bigint(20) NOT NULL COMMENT '每小时驱逐key数量和', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '每小时客户端连接数最大值', `object_size` bigint(20) NOT NULL COMMENT '每小时存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '每小时参与累加实例数最小值', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '每小时修改时间最大值', `used_disk` bigint(20) NOT NULL DEFAULT '0' COMMENT '磁盘占用(字节)', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用统计数据每小时统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_command_statistics` -- DROP TABLE IF EXISTS `app_minute_command_statistics`; CREATE TABLE `app_minute_command_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '统计时间:格式yyyyMMddHHmm', `command_name` varchar(60) NOT NULL COMMENT '命令名称', `command_count` bigint(20) NOT NULL COMMENT '命令执行次数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`,`command_name`), KEY `idx_create_time` (`create_time`), KEY `idx_modify_time` (`modify_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用的每分钟命令统计' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_minute_statistics` -- DROP TABLE IF EXISTS `app_minute_statistics`; CREATE TABLE `app_minute_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `hits` bigint(20) NOT NULL COMMENT '命中数量', `misses` bigint(20) NOT NULL COMMENT '未命中数量', `command_count` bigint(20) DEFAULT '0' COMMENT '命令总数', `used_memory` bigint(20) NOT NULL COMMENT '内存占用', `used_memory_rss` bigint(20) NOT NULL DEFAULT '0' COMMENT '物理内存占用', `expired_keys` bigint(20) NOT NULL COMMENT '过期key数量', `evicted_keys` bigint(20) NOT NULL COMMENT '驱逐key数量', `net_input_byte` bigint(20) DEFAULT '0' COMMENT '网络输入字节', `net_output_byte` bigint(20) DEFAULT '0' COMMENT '网络输出字节', `connected_clients` int(10) NOT NULL COMMENT '客户端连接数', `object_size` bigint(20) NOT NULL COMMENT '每分钟存储对象数最大值', `cpu_sys` bigint(20) DEFAULT '0' COMMENT '进程系统态消耗', `cpu_user` bigint(20) DEFAULT '0' COMMENT '进程用户态消耗', `cpu_sys_children` bigint(20) DEFAULT '0' COMMENT '子进程系统态消耗', `cpu_user_children` bigint(20) DEFAULT '0' COMMENT '子进程用户态消耗', `accumulation` int(10) NOT NULL DEFAULT '0' COMMENT '参与累加实例数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `used_disk` bigint(20) NOT NULL DEFAULT '0' COMMENT '磁盘占用(字节)', PRIMARY KEY (`id`), UNIQUE KEY `app_id` (`app_id`,`collect_time`), KEY `idx_create_time` (`create_time`) USING BTREE, KEY `idx_modify_time` (`modify_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; -- -- Table structure for table `app_to_user` -- DROP TABLE IF EXISTS `app_to_user`; CREATE TABLE `app_to_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL COMMENT '用户id', `app_id` bigint(20) NOT NULL COMMENT '应用id', PRIMARY KEY (`id`), KEY `app_id` (`app_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /* `compression`='tokudb_zlib' */; -- -- Table structure for table `app_user` -- DROP TABLE IF EXISTS `app_user`; CREATE TABLE `app_user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '用户名', `ch_name` varchar(255) NOT NULL COMMENT '中文名', `email` varchar(64) NOT NULL COMMENT '邮箱', `mobile` varchar(16) NOT NULL COMMENT '手机', `type` int(4) NOT NULL DEFAULT '2' COMMENT '0管理员,1预留,2普通用户,-1无效', `weChat` varchar(32) DEFAULT NULL COMMENT '微信号', `isAlert` tinyint(4) NOT NULL DEFAULT '1' COMMENT '用户是否接收报警 0:不接收 1:接收', `password` varchar(64) DEFAULT NULL COMMENT '密码', `register_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间', `purpose` varchar(255) DEFAULT NULL COMMENT '使用目的', `company` varchar(255) DEFAULT NULL COMMENT '公司名称', `biz_id` bigint(20) DEFAULT NULL COMMENT '所属业务组id(app_biz)', PRIMARY KEY (`id`), UNIQUE KEY `uidx_user_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' /* `compression`='tokudb_zlib' */; -- ---------------------------- -- Records of `app_user` -- ---------------------------- BEGIN; INSERT INTO `app_user` VALUES ('1', 'admin', 'admin', 'admin@xxx.com', '13500000000', '0', null, '1', NULL, current_timestamp(), NULL, NULL, NULL); COMMIT; -- -- Table structure for table `brevity_schedule_resources` -- DROP TABLE IF EXISTS `brevity_schedule_resources`; CREATE TABLE `brevity_schedule_resources` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `type` tinyint(4) NOT NULL COMMENT '类型,见:BrevityScheduleType', `version` bigint(20) NOT NULL DEFAULT '0' COMMENT '时间版本', `host` varchar(16) NOT NULL COMMENT '资源ip', `port` int(11) NOT NULL DEFAULT '0' COMMENT '端口', `create_time` datetime NOT NULL COMMENT '创建时间', PRIMARY KEY (`id`), KEY `idx_type_host_port` (`type`,`host`,`port`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='短频任务表'; -- -- Table structure for table `diagnostic_task_record` -- DROP TABLE IF EXISTS `diagnostic_task_record`; CREATE TABLE `diagnostic_task_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '应用id', `type` int(11) DEFAULT NULL COMMENT '诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam', `task_id` bigint(20) DEFAULT NULL COMMENT '任务流id', `audit_id` bigint(20) DEFAULT NULL COMMENT '审批id', `status` int(11) DEFAULT NULL COMMENT '诊断状态:0开始 1结束 2异常', `cost` bigint(20) DEFAULT NULL COMMENT '耗时,毫秒', `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `redis_key` varchar(100) DEFAULT NULL COMMENT '结果的key', `node` varchar(100) DEFAULT NULL COMMENT '实例,host:port', `parent_task_id` bigint(20) DEFAULT NULL COMMENT '父任务id', `diagnostic_condition` varchar(1000) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '诊断条件', `param1` varchar(100) DEFAULT NULL COMMENT '备用参数1', `param2` varchar(100) DEFAULT NULL COMMENT '备用参数2', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='应用诊断记录'; -- -- Table structure for table `instance_alert_configs` -- DROP TABLE IF EXISTS `instance_alert_configs`; CREATE TABLE `instance_alert_configs` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `alert_config` varchar(255) NOT NULL COMMENT '报警配置', `alert_value` varchar(512) NOT NULL COMMENT '报警阀值', `config_info` varchar(255) NOT NULL COMMENT '配置说明', `type` tinyint(4) NOT NULL COMMENT '1:全局报警,2:实例报警', `instance_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0:全局配置,其他代表实例id', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `compare_type` tinyint(4) NOT NULL COMMENT '比较类型:1小于,2等于,3大于,4不等于', `check_cycle` tinyint(4) NOT NULL COMMENT '1:一分钟,2:五分钟,3:半小时4:一个小时,5:一天', `update_time` datetime NOT NULL COMMENT '报警配置更新时间', `last_check_time` datetime NOT NULL COMMENT '上次检查时间', `important_level` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '重要程度(0:一般;1:重要;2:紧急)', `app_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '应用类型(0:redis;)', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`type`,`instance_id`,`alert_config`,`compare_type`,`app_type`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例报警阀值配置'; -- ---------------------------- -- Records of `instance_alert_configs` -- ---------------------------- BEGIN; INSERT INTO `instance_alert_configs` VALUES ('9', 'aof_current_size', '6000', 'aof当前尺寸(单位:MB)', '1', '0', '1', '3', '3', '2017-06-19 09:43:22', '2020-09-17 10:52:00', 0, 0), ('10', 'aof_delayed_fsync', '3', '分钟aof阻塞个数', '1', '0', '1', '3', '1', '2017-06-19 10:38:19', '2020-09-17 11:09:00', 1, 0), ('11', 'client_biggest_input_buf', '10', '输入缓冲区最大buffer大小(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 10:47:03', '2020-09-17 11:09:00', 1, 0), ('12', 'client_longest_output_list', '50000', '输出缓冲区最大队列长度', '1', '0', '1', '3', '1', '2017-06-19 10:55:45', '2020-09-17 11:09:00', 1, 0), ('13', 'instantaneous_ops_per_sec', '60000', '实时ops', '1', '0', '1', '3', '1', '2017-06-19 11:02:38', '2020-09-17 11:09:00', 1, 0), ('14', 'latest_fork_usec', '400000', '上次fork所用时间(单位:微秒)', '1', '0', '1', '3', '5', '2017-06-19 11:21:35', '2020-09-16 16:51:00', 1, 0), ('15', 'mem_fragmentation_ratio', '1.5', '内存碎片率(检测大于500MB)', '1', '0', '1', '3', '5', '2017-06-19 12:49:16', '2020-09-16 16:51:00', 0, 0), ('16', 'rdb_last_bgsave_status', 'ok', '上一次bgsave状态', '1', '0', '1', '4', '4', '2017-06-19 14:15:21', '2020-09-17 10:19:00', 0, 0), ('17', 'total_net_output_bytes', '5000', '分钟网络输出流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:39:44', '2020-09-17 11:09:00', 0, 0), ('19', 'total_net_input_bytes', '1200', '分钟网络输入流量(单位:MB)', '1', '0', '1', '3', '1', '2017-06-19 16:45:44', '2020-09-17 11:09:00', 0, 0), ('20', 'sync_partial_err', '0', '分钟部分复制失败次数', '1', '0', '1', '3', '1', '2017-06-19 18:34:41', '2020-09-17 11:09:00', 1, 0), ('21', 'sync_partial_ok', '0', '分钟部分复制成功次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:01', '2020-09-17 11:09:00', 1, 0), ('22', 'sync_full', '0', '分钟全量复制执行次数', '1', '0', '1', '3', '1', '2017-06-19 18:35:17', '2020-09-17 11:09:00', 1, 0), ('23', 'rejected_connections', '0', '分钟拒绝连接数', '1', '0', '1', '3', '1', '2017-06-19 18:35:36', '2020-09-17 11:09:00', 2, 0), ('54', 'master_slave_offset_diff', '20000000', '主从节点偏移量差(单位:字节)', '1', '0', '1', '3', '2', '2017-06-20 18:58:56', '2020-09-17 11:06:00', 0, 0), ('56', 'cluster_state', 'ok', '集群状态', '1', '0', '1', '4', '1', '2017-06-21 18:01:52', '2020-09-17 11:09:00', 2, 0), ('57', 'cluster_slots_ok', '16384', '集群成功分配槽个数', '1', '0', '1', '4', '1', '2017-06-21 18:02:04', '2020-09-17 11:09:00', 2, 0); COMMIT; -- -- Table structure for table `instance_big_key` -- DROP TABLE IF EXISTS `instance_big_key`; CREATE TABLE `instance_big_key` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `audit_id` bigint(20) NOT NULL COMMENT 'audit id', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从,详见InstanceRoleEnum', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `big_key` varchar(255) NOT NULL COMMENT '键', `type` varchar(16) NOT NULL COMMENT '类型:string,hash,list,set,zset', `length` int(11) NOT NULL COMMENT '长度', `create_time` datetime NOT NULL COMMENT '记录创建时间', PRIMARY KEY (`id`), KEY `idx_app_audit` (`app_id`,`audit_id`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_create_time` (`create_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例bigkey列表'; -- -- Table structure for table `instance_config` -- DROP TABLE IF EXISTS `instance_config`; CREATE TABLE `instance_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '配置名', `config_value` varchar(512) NOT NULL COMMENT '配置值', `info` varchar(512) NOT NULL COMMENT '配置说明', `update_time` datetime NOT NULL COMMENT '更新时间', `type` mediumint(9) NOT NULL COMMENT '类型:2.cluster节点特殊配置, 5:sentinel节点配置, 6:redis普通节点', `status` tinyint(4) NOT NULL COMMENT '1有效,0无效', `version_id` int(11) NOT NULL COMMENT 'Redis版本表主键id', `refresh` mediumint(9) DEFAULT '0' COMMENT '是否可重置:0不可,1可重置', `value_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '取值类型(0:默认值 config_value;1:从主节点拷贝)', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例配置模板'; -- ---------------------------- -- Records of `instance_config` -- ---------------------------- BEGIN; INSERT INTO instance_config (id, config_key, config_value, info, update_time, `type`, status, version_id, refresh, value_type) VALUES (1, 'cluster-enabled', 'yes', '是否开启集群模式', '2016-07-05 15:08:30', 2, 1, 29, 0, 0) ,(2, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2016-07-05 15:08:30', 2, 1, 29, 0, 1) ,(3, 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2016-07-05 15:08:30', 2, 1, 29, 0, 0) ,(4, 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2016-07-05 15:08:30', 2, 1, 29, 0, 0) ,(5, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2016-07-05 15:08:30', 2, 1, 29, 0, 0) ,(6, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2016-07-05 15:08:31', 2, 1, 29, 0, 1) ,(7, 'port', '%d', 'sentinel实例端口', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(8, 'dir', '%s', '工作目录', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(9, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(10, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(11, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(12, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2016-07-05 15:08:31', 5, 1, 29, 0, 0) ,(13, 'daemonize', 'no', '是否守护进程', '2016-07-14 14:00:05', 6, 1, 29, 0, 0) ,(14, 'tcp-backlog', '511', 'TCP连接完成队列', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(15, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(16, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2016-12-06 11:40:46', 6, 1, 29, 0, 1) ,(17, 'loglevel', 'notice', '日志级别', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(18, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(19, 'dir', '%s', 'redis工作目录', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(20, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(21, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(22, 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(23, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(24, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(25, 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(26, 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(27, 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(28, 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(29, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(30, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(31, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(32, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(33, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(34, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(35, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(36, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(37, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(38, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(39, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(40, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(41, 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2016-11-24 10:24:21', 6, 1, 29, 0, 0) ,(42, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(43, 'hz', '10', '执行后台task数量,默认:10', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(44, 'port', '%d', '端口', '2016-07-05 15:08:31', 6, 1, 29, 0, 0) ,(45, 'maxmemory', '%dmb', '当前实例最大可用内存', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(46, 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2016-07-05 15:08:31', 6, 1, 29, 0, 1) ,(47, 'appendonly', 'yes', '开启append only持久化模式', '2016-07-05 15:08:32', 6, 1, 29, 0, 1) ,(48, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(49, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(50, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(51, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(52, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(53, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(54, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(55, 'maxclients', '10000', '客户端最大连接数', '2016-07-05 15:08:32', 6, 1, 29, 0, 0) ,(126, 'cluster-enabled', 'yes', '是否开启集群模式', '2018-09-18 18:23:03', 2, 1, 31, 0, 0) ,(127, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2018-09-18 18:23:03', 2, 1, 31, 0, 1) ,(128, 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2018-09-18 18:23:03', 2, 1, 31, 0, 0) ,(129, 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2018-09-18 18:23:03', 2, 1, 31, 0, 0) ,(130, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2018-09-18 18:23:03', 2, 1, 31, 0, 0) ,(131, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2018-09-18 18:23:03', 2, 1, 31, 0, 1) ,(132, 'port', '%d', 'sentinel实例端口', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(133, 'dir', '%s', '工作目录', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(134, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(135, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(136, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(137, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2018-09-18 18:23:03', 5, 1, 31, 0, 0) ,(138, 'daemonize', 'no', '是否守护进程', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(139, 'tcp-backlog', '511', 'TCP连接完成队列', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(140, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(141, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(142, 'loglevel', 'notice', '日志级别', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(143, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(144, 'dir', '%s', 'redis工作目录', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(145, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(146, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(147, 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(148, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(149, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(150, 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(151, 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(152, 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(153, 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(154, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(155, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(156, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(157, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(158, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(159, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2018-09-18 18:25:32', 6, 0, 31, 0, 1) ,(160, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2018-09-18 18:25:40', 6, 0, 31, 0, 1) ,(161, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(162, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(163, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(164, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(165, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(166, 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(167, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(168, 'hz', '10', '执行后台task数量,默认:10', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(169, 'port', '%d', '端口', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(170, 'maxmemory', '%dmb', '当前实例最大可用内存', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(171, 'maxmemory-policy', 'volatile-lru', '内存不够时,淘汰策略,默认:volatile-lru', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(172, 'appendonly', 'yes', '开启append only持久化模式', '2018-09-18 18:23:03', 6, 1, 31, 0, 1) ,(173, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(174, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(175, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(176, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(177, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(178, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(179, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(180, 'maxclients', '10000', '客户端最大连接数', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(181, 'protected-mode', 'yes', '开启保护模式', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(182, 'bind', '0.0.0.0', '默认客户端都可连接', '2018-09-18 18:23:03', 6, 1, 31, 0, 0) ,(185, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2018-09-18 18:26:32', 6, 1, 31, 0, 0) ,(186, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2018-09-18 18:27:12', 6, 1, 31, 0, 0) ,(253, 'protected-mode', 'no', '关闭保护模式', '2018-11-01 16:10:59', 5, 1, 31, 0, 0) ,(354, 'cluster-enabled', 'yes', '是否开启集群模式', '2019-10-24 17:33:26', 2, 1, 12, 0, 0) ,(355, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2019-10-24 17:33:26', 2, 1, 12, 0, 1) ,(356, 'cluster-slave-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2019-10-24 17:33:26', 2, 1, 12, 0, 0) ,(357, 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2019-10-24 17:33:26', 2, 1, 12, 0, 0) ,(358, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2019-10-24 17:33:26', 2, 1, 12, 0, 0) ,(359, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2019-10-24 17:33:26', 2, 1, 12, 0, 1) ,(360, 'port', '%d', 'sentinel实例端口', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(361, 'dir', '%s', '工作目录', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(362, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(363, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(364, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(365, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(366, 'daemonize', 'no', '是否守护进程', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(367, 'tcp-backlog', '511', 'TCP连接完成队列', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(368, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(369, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(370, 'loglevel', 'notice', '日志级别', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(371, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(372, 'dir', '%s', 'redis工作目录', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(373, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(374, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(375, 'repl-ping-slave-period', '10', '指定slave定期ping master的周期,默认:10秒', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(376, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(377, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(378, 'repl-backlog-ttl', '7200', 'master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(379, 'slave-serve-stale-data', 'yes', '当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(380, 'slave-read-only', 'yes', 'slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(381, 'slave-priority', '100', 'slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(382, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(383, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(384, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(385, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(386, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(387, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2019-10-24 17:33:26', 6, 0, 12, 0, 1) ,(388, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2019-10-24 17:33:26', 6, 0, 12, 0, 1) ,(389, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(390, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(391, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(392, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(393, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(394, 'client-output-buffer-limit slave', '512mb 256mb 60', '客户端输出缓冲区限制(复制)', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(395, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(396, 'hz', '10', '执行后台task数量,默认:10', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(397, 'port', '%d', '端口', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(398, 'maxmemory', '%dmb', '当前实例最大可用内存', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(399, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(400, 'appendonly', 'yes', '开启append only持久化模式', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(401, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(402, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(403, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(404, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(405, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(406, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(407, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(408, 'maxclients', '10000', '客户端最大连接数', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(409, 'protected-mode', 'yes', '开启保护模式', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(410, 'bind', '0.0.0.0', '默认客户端都可连接', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(411, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(412, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(413, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(414, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(415, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(416, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(417, 'slave-lazy-flush', 'yes', 'slave发起全量复制,是否采用flushall async清理老数据 默认值 no', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(418, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2019-10-31 11:15:57', 6, 1, 12, 0, 0) ,(419, 'protected-mode', 'no', '关闭sentinel保护模式', '2019-10-24 17:33:26', 5, 1, 12, 0, 0) ,(420, 'activedefrag', 'no', '碎片整理开启', '2019-10-24 17:33:26', 6, 1, 12, 0, 1) ,(421, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(422, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(423, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(424, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(425, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2019-10-24 17:33:26', 6, 1, 12, 0, 0) ,(506, 'cluster-enabled', 'yes', '是否开启集群模式', '2020-04-26 18:12:55', 2, 1, 37, 0, 0) ,(507, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2020-04-26 18:12:55', 2, 1, 37, 0, 1) ,(508, 'cluster-migration-barrier', '1', '主从迁移至少需要的从节点数,默认1个', '2020-04-26 18:12:55', 2, 1, 37, 0, 0) ,(509, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2020-04-26 18:12:55', 2, 1, 37, 0, 0) ,(510, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2020-04-26 18:12:55', 2, 1, 37, 0, 1) ,(511, 'port', '%d', 'sentinel实例端口', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(512, 'dir', '%s', '工作目录', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(513, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(514, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(515, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(516, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(517, 'daemonize', 'no', '是否守护进程', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(518, 'tcp-backlog', '511', 'TCP连接完成队列', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(519, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(520, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(521, 'loglevel', 'notice', '日志级别', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(522, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(523, 'dir', '%s', 'redis工作目录', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(524, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(525, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(526, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(527, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(528, 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(529, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(530, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(531, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(532, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(533, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(534, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2020-04-26 18:12:55', 6, 0, 37, 0, 1) ,(535, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2020-04-26 18:12:55', 6, 0, 37, 0, 1) ,(536, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(537, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(538, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(539, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(540, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(541, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(542, 'hz', '10', '执行后台task数量,默认:10', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(543, 'port', '%d', '端口', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(544, 'maxmemory', '%dmb', '当前实例最大可用内存', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(545, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(546, 'appendonly', 'yes', '开启append only持久化模式', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(547, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(548, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(549, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(550, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(551, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(552, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(553, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(554, 'maxclients', '10000', '客户端最大连接数', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(555, 'protected-mode', 'yes', '开启保护模式', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(556, 'bind', '0.0.0.0', '默认客户端都可连接', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(557, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(558, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(559, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(560, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(561, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(562, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(563, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(564, 'protected-mode', 'no', '关闭sentinel保护模式', '2020-04-26 18:12:55', 5, 1, 37, 0, 0) ,(565, 'activedefrag', 'yes', '碎片整理开启', '2020-04-26 18:12:55', 6, 1, 37, 0, 1) ,(566, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(567, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(568, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(569, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(570, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(571, 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(572, 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(573, 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2020-04-26 18:12:55', 2, 1, 37, 0, 0) ,(574, 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(575, 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(576, 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(577, 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(578, 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(579, 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(580, 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(581, 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(582, 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(583, 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2020-04-26 18:12:55', 6, 1, 37, 0, 0) ,(585, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:45:22', 6, 1, 37, 0, 0) ,(587, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:18', 6, 1, 12, 0, 0) ,(589, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:46:49', 6, 1, 31, 0, 0) ,(590, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2020-05-26 15:49:47', 6, 1, 29, 0, 0) ,(868, 'cluster-enabled', 'yes', '是否开启集群模式', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(869, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2021-06-09 10:12:50', 2, 1, 51, 0, 1) ,(870, 'cluster-migration-barrier', '3', '从节点自动迁移至少需要的可用节点数,默认1个', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(871, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(872, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2021-06-09 10:12:50', 2, 1, 51, 0, 1) ,(873, 'port', '%d', 'sentinel实例端口', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(874, 'dir', '%s', '工作目录', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(875, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(876, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(877, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(878, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(879, 'daemonize', 'no', '是否守护进程', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(880, 'tcp-backlog', '511', 'TCP连接完成队列', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(881, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(882, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(883, 'loglevel', 'notice', '日志级别', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(884, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(885, 'dir', '%s', 'redis工作目录', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(886, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(887, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(888, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(889, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(890, 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(891, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(892, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(893, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(894, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(895, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(896, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2021-06-09 10:12:50', 6, 0, 51, 0, 1) ,(897, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2021-06-09 10:12:50', 6, 0, 51, 0, 1) ,(898, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(899, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(900, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(901, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(902, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(903, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(904, 'hz', '10', '执行后台task数量,默认:10', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(905, 'port', '%d', '端口', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(906, 'maxmemory', '%dmb', '当前实例最大可用内存', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(907, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(908, 'appendonly', 'yes', '开启append only持久化模式', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(909, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(910, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(911, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(912, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(913, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(914, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(915, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(916, 'maxclients', '10000', '客户端最大连接数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(917, 'protected-mode', 'yes', '开启保护模式', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(918, 'bind', '0.0.0.0', '默认客户端都可连接', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(919, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(920, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(921, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(922, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(923, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(924, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(925, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(926, 'protected-mode', 'no', '关闭sentinel保护模式', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(927, 'activedefrag', 'no', '碎片整理开启', '2022-06-07 10:16:26', 6, 1, 51, 0, 1) ,(928, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(929, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(930, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(931, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(932, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(933, 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(934, 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(935, 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(936, 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(937, 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(938, 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(939, 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(940, 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(941, 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(942, 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(943, 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(944, 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(945, 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(946, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(947, 'repl-diskless-load', 'on-empty-db', '完全安全的情况下才使用无磁盘加载', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(948, 'tracking-table-max-keys', '1000000', '无效表键的最大填充数量', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(949, 'rdb-del-sync-files', 'yes', '默认:no 不删除rdb文件,删除实例中复制使用的不持久的RDB文件', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(950, 'lazyfree-lazy-user-del', 'yes', '默认值no,设置del操作命令同unlink一致', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(951, 'io-threads', '1', '读写io线程数量', '2021-06-09 15:22:48', 6, 1, 51, 0, 0) ,(952, 'io-threads-do-reads', 'no', '开启io读线程', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(953, 'jemalloc-bg-thread', 'yes', '启用Jemalloc后台线程清理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(954, 'server_cpulist', '0-7:2', '设置redis服务器/io线程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(955, 'bio_cpulist', '1,3', '设置bio线程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(956, 'aof_rewrite_cpulist', '8-11', '设置aof重写子进程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(957, 'bgsave_cpulist', '1,10-11', '设置bgsave子进程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(959, 'save', '', '关闭同步操作', '2021-07-01 10:31:11', 6, 1, 51, 0, 0) ,(1579, 'enable-module-command', 'yes', '是否支持module命令', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1582, 'save', '', '关闭同步操作', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1584, 'cluster-enabled', 'yes', '是否开启集群模式', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1585, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2024-01-17 10:23:00', 2, 1, 62, 0, 1) ,(1586, 'cluster-migration-barrier', '3', '从节点自动迁移至少需要的可用节点数,默认1个', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1587, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1588, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2024-01-17 10:23:00', 2, 1, 62, 0, 1) ,(1589, 'port', '%d', 'sentinel实例端口', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1590, 'dir', '%s', '工作目录', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1591, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1592, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1593, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1594, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1595, 'daemonize', 'no', '是否守护进程', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1596, 'tcp-backlog', '511', 'TCP连接完成队列', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1597, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1598, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1599, 'loglevel', 'notice', '日志级别', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1600, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1601, 'dir', '%s', 'redis工作目录', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1602, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1603, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1604, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1605, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1606, 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1607, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1608, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1609, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1610, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1611, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1612, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2024-01-17 10:23:00', 6, 0, 62, 0, 1) ,(1613, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2024-01-17 10:23:00', 6, 0, 62, 0, 1) ,(1614, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1615, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1616, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1617, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1618, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1619, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1620, 'hz', '10', '执行后台task数量,默认:10', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1621, 'port', '%d', '端口', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1622, 'maxmemory', '%dmb', '当前实例最大可用内存', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1623, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1624, 'appendonly', 'yes', '开启append only持久化模式', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1625, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1626, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1627, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1628, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1629, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1630, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1631, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1632, 'maxclients', '10000', '客户端最大连接数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1633, 'protected-mode', 'no', '开启保护模式', '2024-06-05 11:55:57', 6, 1, 62, 0, 0) ,(1634, 'bind', '0.0.0.0 -::*', '默认客户端都可连接', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1635, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1636, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1637, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1638, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1639, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1640, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1641, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1642, 'protected-mode', 'no', '关闭sentinel保护模式', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1643, 'activedefrag', 'no', '碎片整理开启', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1644, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1645, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1646, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1647, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1648, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1649, 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1650, 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1651, 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1652, 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1653, 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1654, 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1655, 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1656, 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1657, 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1658, 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1659, 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1660, 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1661, 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1662, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1663, 'repl-diskless-load', 'on-empty-db', '完全安全的情况下才使用无磁盘加载', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1664, 'tracking-table-max-keys', '1000000', '无效表键的最大填充数量', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1665, 'rdb-del-sync-files', 'yes', '默认:no 不删除rdb文件,删除实例中复制使用的不持久的RDB文件', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1666, 'lazyfree-lazy-user-del', 'yes', '默认值no,设置del操作命令同unlink一致', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1667, 'io-threads', '1', '读写io线程数量', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1668, 'io-threads-do-reads', 'no', '开启io读线程', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1669, 'jemalloc-bg-thread', 'yes', '启用Jemalloc后台线程清理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1670, 'server_cpulist', '0-7:2', '设置redis服务器/io线程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1671, 'bio_cpulist', '1,3', '设置bio线程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1672, 'aof_rewrite_cpulist', '8-11', '设置aof重写子进程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1673, 'bgsave_cpulist', '1,10-11', '设置bgsave子进程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0); COMMIT; -- -- Table structure for table `instance_fault` -- DROP TABLE IF EXISTS `instance_fault`; CREATE TABLE `instance_fault` ( `id` int(11) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `inst_id` bigint(20) NOT NULL COMMENT '实例id', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '状态:0:心跳停止,1:心跳恢复', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `type` mediumint(4) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `reason` mediumtext NOT NULL COMMENT '故障原因描述', PRIMARY KEY (`id`), KEY `idx_ip_port` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例故障表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_info` -- DROP TABLE IF EXISTS `instance_info`; CREATE TABLE `instance_info` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'memcached instance id', `parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '对等实例的id', `app_id` bigint(20) NOT NULL COMMENT '应用id,与app_desc关联', `host_id` bigint(20) NOT NULL COMMENT '对应的主机id,与instance_host关联', `ip` varchar(16) NOT NULL COMMENT '实例的ip', `port` int(11) NOT NULL COMMENT '实例端口', `status` tinyint(4) NOT NULL COMMENT '是否启用:0:节点异常,1:正常启用,2:节点下线', `mem` int(11) NOT NULL COMMENT '内存大小', `conn` int(11) NOT NULL COMMENT '连接数', `cmd` varchar(255) NOT NULL COMMENT '启动实例的命令/redis-sentinel的masterName', `type` mediumint(11) NOT NULL COMMENT '类型:1. memcached, 2. redis-cluster, 3. memcacheq, 4. 非cache-cloud 5. redis-sentinel 6.redis-standalone', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uidx_inst_ipport` (`ip`,`port`) USING BTREE, KEY `app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `instance_latency_history` -- DROP TABLE IF EXISTS `instance_latency_history`; CREATE TABLE `instance_latency_history` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `event` varchar(255) NOT NULL COMMENT '事件名称', `execute_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `execution_cost` bigint(20) NOT NULL COMMENT '耗时(微妙)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `latencyistorykey` (`instance_id`,`event`,`execute_date`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executedate` (`app_id`,`execute_date`), KEY `idx_executedate` (`execute_date`), KEY `idx_executedate_app` (`execute_date`,`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢延迟事件信息列表'; -- -- Table structure for table `instance_minute_stats` -- DROP TABLE IF EXISTS `instance_minute_stats`; CREATE TABLE `instance_minute_stats` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `json` text NOT NULL COMMENT '统计json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例分钟统计表'; -- -- Table structure for table `instance_reshard_process` -- DROP TABLE IF EXISTS `instance_reshard_process`; CREATE TABLE `instance_reshard_process` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id', `app_id` bigint(20) NOT NULL COMMENT '应用id', `audit_id` bigint(20) NOT NULL COMMENT '审核id', `source_instance_id` int(11) NOT NULL COMMENT '源实例id', `target_instance_id` int(11) NOT NULL COMMENT '目标实例id', `start_slot` int(11) NOT NULL COMMENT '开始slot', `end_slot` int(11) NOT NULL COMMENT '结束slot', `migrating_slot` int(11) NOT NULL COMMENT '正在迁移的slot', `is_pipeline` tinyint(4) NOT NULL COMMENT '是否为pipeline,0:否,1:是', `finish_slot_num` int(11) NOT NULL COMMENT '已经完成迁移的slot数量', `status` tinyint(4) NOT NULL COMMENT '0:运行中 1:完成 2:出错', `start_time` datetime NOT NULL COMMENT '迁移开始时间', `end_time` datetime NOT NULL COMMENT '迁移结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '更新时间', PRIMARY KEY (`id`), KEY `idx_audit` (`audit_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例Reshard进度'; -- -- Table structure for table `instance_slow_log` -- DROP TABLE IF EXISTS `instance_slow_log`; CREATE TABLE `instance_slow_log` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `instance_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `ip` varchar(32) NOT NULL COMMENT 'ip', `port` int(11) NOT NULL COMMENT 'port', `slow_log_id` bigint(20) NOT NULL COMMENT '慢查询id', `cost_time` int(11) NOT NULL COMMENT '耗时(微妙)', `command` varchar(255) NOT NULL COMMENT '执行命令', `execute_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '执行时间点', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间', PRIMARY KEY (`id`), UNIQUE KEY `slowlogkey` (`instance_id`,`slow_log_id`,`execute_time`), KEY `idx_app_create_time` (`app_id`,`create_time`), KEY `idx_app_executetime` (`app_id`,`execute_time`), KEY `idx_executetime` (`execute_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='实例慢查询列表'; -- -- Table structure for table `instance_statistics` -- DROP TABLE IF EXISTS `instance_statistics`; CREATE TABLE `instance_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `inst_id` bigint(20) NOT NULL COMMENT '实例的id', `app_id` bigint(20) NOT NULL COMMENT 'app id', `host_id` bigint(20) NOT NULL COMMENT '机器的id', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `port` int(255) NOT NULL COMMENT 'port', `role` tinyint(255) NOT NULL COMMENT '主从,1主2从', `max_memory` bigint(255) NOT NULL COMMENT '预分配内存,单位byte', `used_memory` bigint(255) NOT NULL COMMENT '已使用内存,单位byte', `curr_items` bigint(255) NOT NULL COMMENT '当前item数量', `curr_connections` int(255) NOT NULL COMMENT '当前连接数', `misses` bigint(255) NOT NULL COMMENT 'miss数', `hits` bigint(255) NOT NULL COMMENT '命中数', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mem_fragmentation_ratio` double DEFAULT '0' COMMENT '碎片率', `aof_delayed_fsync` int(11) DEFAULT '0' COMMENT 'aof阻塞次数', `used_disk` bigint(255) NOT NULL DEFAULT '0' COMMENT '已使用磁盘,单位byte', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`,`port`), KEY `app_id` (`app_id`), KEY `machine_id` (`host_id`), KEY `idx_inst_id` (`inst_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='实例的最新统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_info` -- DROP TABLE IF EXISTS `machine_info`; CREATE TABLE `machine_info` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '机器的id', `ssh_user` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh用户', `ssh_passwd` varchar(20) COLLATE utf8_bin NOT NULL DEFAULT 'cachecloud' COMMENT 'ssh密码', `ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT 'ip', `room` varchar(20) COLLATE utf8_bin NOT NULL COMMENT '所属机房', `mem` int(11) unsigned NOT NULL COMMENT '内存大小,单位G', `cpu` mediumint(24) unsigned NOT NULL COMMENT 'cpu数量', `virtual` tinyint(8) unsigned NOT NULL DEFAULT '1' COMMENT '是否虚拟,0表示否,1表示是', `real_ip` varchar(16) COLLATE utf8_bin NOT NULL COMMENT '宿主机ip', `service_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上线时间', `fault_count` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '故障次数', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `warn` tinyint(255) unsigned NOT NULL DEFAULT '1' COMMENT '是否启用报警,0不启用,1启用', `available` tinyint(255) NOT NULL COMMENT '表示机器是否可用,1表示可用,0表示不可用;', `groupId` int(11) NOT NULL DEFAULT '0' COMMENT '机器分组,默认为0,表示原生资源,非0表示外部提供的资源(可扩展)', `type` int(11) NOT NULL DEFAULT '0' COMMENT '0原生 1 其他', `extra_desc` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '对于机器的额外说明(例如机器安装的其他服务(web,mysql,queue等等))', `collect` int(11) DEFAULT '1' COMMENT 'switch of collect server status, 1:open, 0:close', `version_install` varchar(512) COLLATE utf8_bin DEFAULT NULL COMMENT '机器安装redis版本状态', `use_type` tinyint(4) DEFAULT '2' COMMENT '使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis-Sentinel机器(3)', `k8s_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否k8s容器:0:不是 1:是', `rack` varchar(128) COLLATE utf8_bin DEFAULT '' COMMENT '机器所在机架信息', `is_allocating` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否在分配中,1是0否', `disk` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '磁盘空间:G', `dis_type` tinyint(4) DEFAULT 0 NOT NULL COMMENT '操作系统发行版本,0:centos;1:ubuntu', PRIMARY KEY (`id`), UNIQUE KEY `ip` (`ip`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='机器信息表' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `machine_relation` -- DROP TABLE IF EXISTS `machine_relation`; CREATE TABLE `machine_relation` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id', `ip` varchar(64) NOT NULL COMMENT '虚拟机ip', `real_ip` varchar(64) NOT NULL COMMENT '宿主机ip', `extra_desc` varchar(128) DEFAULT NULL COMMENT '实例描述信息', `status` int(255) NOT NULL COMMENT '实例变更状态 0:offline ,1:online', `is_sync` tinyint(4) NOT NULL DEFAULT '0' COMMENT '数据同步状态 0: 未同步数据 -1:同步中 1:数据已同步 -2:同步失败 ', `sync_time` timestamp NULL DEFAULT NULL COMMENT '同步时间', `update_time` timestamp NULL DEFAULT NULL COMMENT 'pod最后更新时间', `taskid` bigint(11) DEFAULT NULL COMMENT '任务id', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `machine_room` -- DROP TABLE IF EXISTS `machine_room`; CREATE TABLE `machine_room` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '机房id', `name` varchar(255) NOT NULL COMMENT '机房名称', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `desc` varchar(255) DEFAULT NULL COMMENT '机房描述信息', `ip_network` varchar(32) NOT NULL DEFAULT '' COMMENT '机房网段信息', `operator` varchar(255) DEFAULT NULL COMMENT '运营商', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `machine_room` -- ---------------------------- BEGIN; INSERT INTO `machine_room` VALUES ('1', '阿里云杭州', '1', '阿里云-杭州机房', '172.27.*.*', '阿里云'); COMMIT; -- -- Table structure for table `machine_statistics` -- DROP TABLE IF EXISTS `machine_statistics`; CREATE TABLE `machine_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `host_id` bigint(20) NOT NULL COMMENT '机器id', `ip` varchar(16) NOT NULL COMMENT '机器ip', `cpu_usage` varchar(120) NOT NULL COMMENT 'cpu使用率', `load` varchar(120) NOT NULL COMMENT '机器负载', `traffic` varchar(120) NOT NULL COMMENT 'io网络流量', `memory_usage_ratio` varchar(120) NOT NULL COMMENT '内存使用率', `memory_free` varchar(120) NOT NULL COMMENT '内存剩余', `memory_total` varchar(120) NOT NULL COMMENT '总内存量', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', `max_memory` int(11) DEFAULT '0' COMMENT '机器分配内存,单位MB', `instance_count` int(11) DEFAULT '0' COMMENT '机器实例数量', `machine_memory` int(11) DEFAULT '0' COMMENT '机器入库总内存,单位MB', `disk_total` varchar(120) DEFAULT NULL COMMENT '机器分配磁盘,单位MB', `disk_available` varchar(120) DEFAULT NULL COMMENT '机器空闲磁盘,单位MB', `disk_usage_ratio` varchar(15) DEFAULT NULL COMMENT '机器磁盘使用率,百分比(无需乘100)', PRIMARY KEY (`id`), UNIQUE KEY `uidx_ip` (`ip`), KEY `host_id` (`host_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='机器状态统计信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_BLOB_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`; CREATE TABLE `QRTZ_BLOB_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `BLOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `SCHED_NAME` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Trigger 作为 Blob 类型存储(用于 Quartz 用户用 JDBC 创建他们自己定制的 Trigger 类型' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_CALENDARS` -- DROP TABLE IF EXISTS `QRTZ_CALENDARS`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `QRTZ_CALENDARS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `CALENDAR_NAME` varchar(200) NOT NULL COMMENT 'calendar名称', `CALENDAR` blob NOT NULL COMMENT 'calendar信息', PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='以 Blob 类型存储 Quartz 的 Calendar 信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_CRON_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`; CREATE TABLE `QRTZ_CRON_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL COMMENT 'scheduler名称', `TRIGGER_NAME` varchar(200) NOT NULL COMMENT 'trigger名', `TRIGGER_GROUP` varchar(200) NOT NULL COMMENT 'trigger组', `CRON_EXPRESSION` varchar(120) NOT NULL COMMENT 'cron表达式', `TIME_ZONE_ID` varchar(80) DEFAULT NULL COMMENT '时区', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储 Cron Trigger,包括 Cron 表达式和时区信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_FIRED_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`; CREATE TABLE `QRTZ_FIRED_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `ENTRY_ID` varchar(195) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL, `FIRED_TIME` bigint(13) NOT NULL, `SCHED_TIME` bigint(13) NOT NULL, `PRIORITY` int(11) NOT NULL, `STATE` varchar(16) NOT NULL, `JOB_NAME` varchar(200) DEFAULT NULL, `JOB_GROUP` varchar(200) DEFAULT NULL, `IS_NONCONCURRENT` varchar(1) DEFAULT NULL COMMENT '是否非并行执行', `REQUESTS_RECOVERY` varchar(1) DEFAULT NULL COMMENT '是否持久化', PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`), KEY `IDX_QRTZ_FT_TRIG_INST_NAME` (`SCHED_NAME`,`INSTANCE_NAME`), KEY `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY` (`SCHED_NAME`,`INSTANCE_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_FT_J_G` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_FT_T_G` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_FT_TG` (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已触发的 Trigger相关的状态信息,以及关联 Job 的执行信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_JOB_DETAILS` -- DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`; CREATE TABLE `QRTZ_JOB_DETAILS` ( `SCHED_NAME` varchar(120) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `JOB_CLASS_NAME` varchar(250) NOT NULL, `IS_DURABLE` varchar(1) NOT NULL COMMENT '是否持久化,0不持久化,1持久化', `IS_NONCONCURRENT` varchar(1) NOT NULL COMMENT '是否非并发,0非并发,1并发', `IS_UPDATE_DATA` varchar(1) NOT NULL, `REQUESTS_RECOVERY` varchar(1) NOT NULL COMMENT '是否可恢复,0不恢复,1恢复', `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_J_REQ_RECOVERY` (`SCHED_NAME`,`REQUESTS_RECOVERY`), KEY `IDX_QRTZ_J_GRP` (`SCHED_NAME`,`JOB_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储每一个已配置的 Job 的详细信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_LOCKS` -- DROP TABLE IF EXISTS `QRTZ_LOCKS`; CREATE TABLE `QRTZ_LOCKS` ( `SCHED_NAME` varchar(120) NOT NULL, `LOCK_NAME` varchar(40) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储程序的悲观锁的信息(假如使用了悲观锁)' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_PAUSED_TRIGGER_GRPS` -- DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`; CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已暂停的 Trigger 组的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SCHEDULER_STATE` -- DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`; CREATE TABLE `QRTZ_SCHEDULER_STATE` ( `SCHED_NAME` varchar(120) NOT NULL, `INSTANCE_NAME` varchar(200) NOT NULL COMMENT '执行quartz实例的主机名', `LAST_CHECKIN_TIME` bigint(13) NOT NULL COMMENT '实例将状态报告给集群中的其它实例的上一次时间', `CHECKIN_INTERVAL` bigint(13) NOT NULL COMMENT '实例间状态报告的时间频率', PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储少量的有关 Scheduler 的状态信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPLE_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`; CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `REPEAT_COUNT` bigint(7) NOT NULL COMMENT '重复次数', `REPEAT_INTERVAL` bigint(12) NOT NULL COMMENT '重复间隔', `TIMES_TRIGGERED` bigint(10) NOT NULL COMMENT '已出发次数', PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储简单的 Trigger,包括重复次数,间隔,以及已触的次数' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_SIMPROP_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`; CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `STR_PROP_1` varchar(512) DEFAULT NULL, `STR_PROP_2` varchar(512) DEFAULT NULL, `STR_PROP_3` varchar(512) DEFAULT NULL, `INT_PROP_1` int(11) DEFAULT NULL, `INT_PROP_2` int(11) DEFAULT NULL, `LONG_PROP_1` bigint(20) DEFAULT NULL, `LONG_PROP_2` bigint(20) DEFAULT NULL, `DEC_PROP_1` decimal(13,4) DEFAULT NULL, `DEC_PROP_2` decimal(13,4) DEFAULT NULL, `BOOL_PROP_1` varchar(1) DEFAULT NULL, `BOOL_PROP_2` varchar(1) DEFAULT NULL, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `QRTZ_TRIGGERS` -- DROP TABLE IF EXISTS `QRTZ_TRIGGERS`; CREATE TABLE `QRTZ_TRIGGERS` ( `SCHED_NAME` varchar(120) NOT NULL, `TRIGGER_NAME` varchar(200) NOT NULL, `TRIGGER_GROUP` varchar(200) NOT NULL, `JOB_NAME` varchar(200) NOT NULL, `JOB_GROUP` varchar(200) NOT NULL, `DESCRIPTION` varchar(250) DEFAULT NULL, `NEXT_FIRE_TIME` bigint(13) DEFAULT NULL, `PREV_FIRE_TIME` bigint(13) DEFAULT NULL, `PRIORITY` int(11) DEFAULT NULL, `TRIGGER_STATE` varchar(16) NOT NULL, `TRIGGER_TYPE` varchar(8) NOT NULL, `START_TIME` bigint(13) NOT NULL, `END_TIME` bigint(13) DEFAULT NULL, `CALENDAR_NAME` varchar(200) DEFAULT NULL, `MISFIRE_INSTR` smallint(2) DEFAULT NULL, `JOB_DATA` blob, PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_J` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_JG` (`SCHED_NAME`,`JOB_GROUP`), KEY `IDX_QRTZ_T_C` (`SCHED_NAME`,`CALENDAR_NAME`), KEY `IDX_QRTZ_T_G` (`SCHED_NAME`,`TRIGGER_GROUP`), KEY `IDX_QRTZ_T_STATE` (`SCHED_NAME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_STATE` (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_N_G_STATE` (`SCHED_NAME`,`TRIGGER_GROUP`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NEXT_FIRE_TIME` (`SCHED_NAME`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST` (`SCHED_NAME`,`TRIGGER_STATE`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_STATE`), KEY `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP` (`SCHED_NAME`,`MISFIRE_INSTR`,`NEXT_FIRE_TIME`,`TRIGGER_GROUP`,`TRIGGER_STATE`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储已配置的 Trigger 的信息' /* `compression`='tokudb_zlib' */; -- -- Table structure for table `server` -- DROP TABLE IF EXISTS `server`; CREATE TABLE `server` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `host` varchar(255) DEFAULT NULL COMMENT 'host', `nmon` varchar(255) DEFAULT NULL COMMENT 'nmon version', `cpus` tinyint(4) DEFAULT NULL COMMENT 'logic cpu num', `cpu_model` varchar(255) DEFAULT NULL COMMENT 'cpu 型号', `dist` varchar(255) DEFAULT NULL COMMENT '发行版信息', `kernel` varchar(255) DEFAULT NULL COMMENT '内核信息', `ulimit` varchar(255) DEFAULT NULL COMMENT 'ulimit -n,ulimit -u', `updatetime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`ip`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `server_stat` -- DROP TABLE IF EXISTS `server_stat`; CREATE TABLE `server_stat` ( `ip` varchar(16) NOT NULL COMMENT 'ip', `cdate` date NOT NULL COMMENT '数据收集天', `ctime` char(4) NOT NULL COMMENT '数据收集小时分钟', `cuser` float DEFAULT NULL COMMENT '用户态占比', `csys` float DEFAULT NULL COMMENT '内核态占比', `cwio` float DEFAULT NULL COMMENT 'wio占比', `c_ext` text COMMENT '子cpu占比', `cload1` float DEFAULT NULL COMMENT '1分钟load', `cload5` float DEFAULT NULL COMMENT '5分钟load', `cload15` float DEFAULT NULL COMMENT '15分钟load', `mtotal` float DEFAULT NULL COMMENT '总内存,单位M', `mfree` float DEFAULT NULL COMMENT '空闲内存', `mcache` float DEFAULT NULL COMMENT 'cache', `mbuffer` float DEFAULT NULL COMMENT 'buffer', `mswap` float DEFAULT NULL COMMENT 'cache', `mswap_free` float DEFAULT NULL COMMENT 'cache', `nin` float DEFAULT NULL COMMENT '网络入流量 单位K/s', `nout` float DEFAULT NULL COMMENT '网络出流量 单位k/s', `nin_ext` text COMMENT '各网卡入流量详情', `nout_ext` text COMMENT '各网卡出流量详情', `tuse` int(11) DEFAULT NULL COMMENT 'tcp estab连接数', `torphan` int(11) DEFAULT NULL COMMENT 'tcp orphan连接数', `twait` int(11) DEFAULT NULL COMMENT 'tcp time wait连接数', `dread` float DEFAULT NULL COMMENT '磁盘读速率 单位K/s', `dwrite` float DEFAULT NULL COMMENT '磁盘写速率 单位K/s', `diops` float DEFAULT NULL COMMENT '磁盘io速率 交互次数/s', `dbusy` float DEFAULT NULL COMMENT '磁盘io带宽使用百分比', `d_ext` text COMMENT '磁盘各分区占比', `dspace` text COMMENT '磁盘各分区空间使用率', PRIMARY KEY (`ip`,`cdate`,`ctime`), KEY `idx_cdate` (`cdate`), KEY `idx_cdate_ctime` (`cdate`,`ctime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Table structure for table `standard_statistics` -- CREATE TABLE `standard_statistics` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `collect_time` bigint(20) NOT NULL COMMENT '收集时间:格式yyyyMMddHHmm', `ip` varchar(16) NOT NULL COMMENT 'ip地址', `port` int(11) NOT NULL COMMENT '端口/hostId', `db_type` varchar(16) NOT NULL COMMENT '收集的数据类型', `info_json` text NOT NULL COMMENT '收集的json数据', `diff_json` text NOT NULL COMMENT '上一次收集差异的json数据', `cluster_info_json` varchar(20480) NOT NULL DEFAULT '' COMMENT '收集的cluster info json数据', `created_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uniq_index` (`ip`,`port`,`db_type`,`collect_time`), KEY `idx_collect_time` (`collect_time`), KEY `idx_created_time` (`created_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 /* `compression`='tokudb_zlib' */; -- -- Table structure for table `system_config` -- DROP TABLE IF EXISTS `system_config`; CREATE TABLE `system_config` ( `config_key` varchar(255) NOT NULL COMMENT '配置key', `config_value` varchar(512) NOT NULL COMMENT '配置value', `info` varchar(255) NOT NULL COMMENT '配置说明', `status` tinyint(4) NOT NULL COMMENT '1:可用,0:不可用', `order_id` int(11) NOT NULL COMMENT '顺序', PRIMARY KEY (`config_key`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统配置'; -- ---------------------------- -- Records of `system_config` -- ---------------------------- BEGIN; INSERT INTO `system_config` VALUES ('cachecloud.admin.user.name','admin','cachecloud-admin用户名',1,11),('cachecloud.admin.user.password','admin','cachelcoud-admin密码',1,12),('cachecloud.app.client.conn.threshold','2000','应用连接数报警阀值',1,33),('cachecloud.base.dir','/opt','cachecloud根目录,要和cachecloud-init.sh脚本中的目录一致',1,31),('cachecloud.contact','user1:(xx@zz.com, user1:135xxxxxxxx)
user2: (user2@zz.com, user2:138xxxxxxxx)','值班联系人信息',1,14),('cachecloud.cookie.domain','','cookie登录方式所需要的域名',1,22),('cachecloud.email.alert.interface','','邮件报警接口(参考报警接口规范)',1,24),('cachecloud.machine.ssh.name','cachecloud-open','机器ssh用户名',1,2),('cachecloud.machine.ssh.password','cachecloud-open','机器ssh密码',1,3),('cachecloud.machine.ssh.port','22','机器ssh端口',1,10),('cachecloud.machine.stats.cron.minute','1','机器性能统计周期(分钟)',1,35),('cachecloud.nmon.dir','/opt/cachecloud','nmon安装目录',1,32),('cachecloud.owner.email','xx@sohu.com,yy@qq.com','邮件报警(逗号隔开)',1,21),('cachecloud.owner.phone','xxx,yyy','手机号报警(逗号隔开)',1,21),('cachecloud.owner.weChat','xxx,yyy','微信号报警(逗号隔开)',1,21),('cachecloud.public.key.pem','/opt/ssh/id_rsa','密钥路径',1,5),('cachecloud.public.user.name','cachecloud-open','公钥用户名',1,4),('cachecloud.ssh.auth.type','1','ssh授权方式',1,1),('cachecloud.superAdmin','admin,xx,yy','超级管理员组',1,13),('cachecloud.user.login.type','1','用户登录状态保存方式(session或cookie)',1,22),('cachecloud.weChat.alert.interface','','微信报警接口(参考报警接口规范)',1,23),('cachecloud.whether.schedule.clean.data','false','是否定期清理统计数据',1,34),('machine.load.alert.ratio','8.0','机器负载报警阀值',1,32); COMMIT; -- ---------------------------- -- Table structure for `system_resource` -- ---------------------------- DROP TABLE IF EXISTS `system_resource`; CREATE TABLE `system_resource` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '资源ID', `name` varchar(64) NOT NULL COMMENT '资源名称', `intro` varchar(255) DEFAULT NULL COMMENT '资源说明', `type` tinyint(4) NOT NULL COMMENT '1:仓库地址 2:脚本 3:资源包 4:公钥/私钥 6:目录管理 7:迁移工具管理', `lastmodify` datetime DEFAULT NULL COMMENT '最后更新时间', `dir` varchar(128) DEFAULT NULL COMMENT '资源路径', `url` varchar(128) DEFAULT NULL COMMENT '仓库地址', `ispush` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0:未推送 1:已推送', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:无效 1:有效', `username` varchar(255) DEFAULT NULL COMMENT '最后修改人', `task_id` bigint(11) DEFAULT NULL COMMENT '迁移任务id', `compile_info` varchar(255) DEFAULT NULL COMMENT '编译信息', `order_num` int(6) NOT NULL DEFAULT '0' COMMENT '排序', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of `system_resource` -- ---------------------------- BEGIN; INSERT INTO `system_resource` VALUES (1,'cachecloud-init.sh','容器初始化脚本',2,'2020-07-15 18:35:41','/script','',0,1,NULL,NULL,NULL,0), (2,'x.x.x.x',NULL,1,'2020-08-10 10:31:51','/opt/download/software/cachecloud/resource','http://x.x.x.x/software/cachecloud/resource',0,1,'admin',0,NULL,0), (4,'cachecloud-env.sh','宿主环境脚本',2,'2020-07-15 18:36:28','/script','',0,1,NULL,NULL,NULL,0), (5,'id_rsa','私钥文件',4,'2020-07-07 10:45:39','/ssh','',0,1,NULL,NULL,NULL,0), (6,'id_rsa.pub','公钥文件',4,'2020-07-07 10:45:45','/ssh','',0,1,NULL,NULL,NULL,0), (12,'redis-4.0.14','redis 4.0.14资源包',3,'2020-08-10 09:52:41','/redis','http://download.redis.io/releases/redis-4.0.14.tar.gz',0,1,'admin',532,NULL,0), (21,'/script','脚本目录管理',6,'2020-08-10 10:51:34','',NULL,0,1,'admin',0,NULL,0), (28,'/ssh','ssh目录',6,'2020-07-20 17:55:03',NULL,NULL,0,1,'admin',0,NULL,0), (29,'redis-3.0.7','redis3.0.7 资源包',3,'2020-08-10 09:53:32','/redis','http://download.redis.io/releases/redis-3.0.7.tar.gz',0,1,'admin',529,NULL,0), (31,'redis-3.2.12','redis 3.2.12 资源包',3,'2020-08-10 15:08:21','/redis','http://download.redis.io/releases/redis-3.2.12.tar.gz',0,1,'admin',530,NULL,0), (32,'/redis','redis资源包管理',6,'2020-07-20 17:54:59',NULL,NULL,0,1,'admin',0,NULL,0), (33,'/tool','迁移工具资源包',6,'2020-07-20 17:54:53',NULL,NULL,0,1,'admin',0,NULL,0), (37,'redis-5.0.9','redis5.0.9 资源包',3,'2020-08-10 09:51:41','/redis','http://download.redis.io/releases/redis-5.0.9.tar.gz',0,1,'admin',533,NULL,0), (40,'redis-shake-2.0.3','redis 2.0.3\n修复fix 5.0迁移类型问题',7,'2020-08-11 10:53:26','/tool','https://github.com/alibaba/RedisShake/releases/download/release-v2.0.3-20200724/redis-shake-v2.0.3.tar.gz',0,1,'admin',518,NULL,0), (51, 'redis-6.2.4', 'redis-6.2.4 资源包', 3, '2023-02-09 10:24:16', '/redis', 'http://download.redis.io/releases/redis-6.2.4.tar.gz', 1, 1, 'admin', 3507, NULL, 0), (62, 'redis-7.2.4', 'redis 7.2.4 资源包', 3, '2024-01-18 15:26:02', '/redis', 'http://download.redis.io/releases/redis-7.2.4.tar.gz', 1, 1, 'admin', 11687, NULL, 700); COMMIT; -- -- Table structure for table `task_queue` -- DROP TABLE IF EXISTS `task_queue`; CREATE TABLE `task_queue` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `class_name` varchar(255) NOT NULL COMMENT '类名', `important_info` varchar(255) NOT NULL DEFAULT '' COMMENT '重要信息', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `param` longtext NOT NULL COMMENT '任务参数(json):随着任务变化', `init_param` longtext NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2中断,3失败', `parent_task_id` bigint(20) NOT NULL COMMENT '父任务id', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `priority` int(11) NOT NULL COMMENT '优先级', `error_code` int(11) NOT NULL COMMENT '错误代码', `error_msg` varchar(255) NOT NULL COMMENT '错误消息', `task_note` varchar(255) NOT NULL COMMENT '备注', PRIMARY KEY (`id`), KEY `idx_app_id` (`app_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务表'; -- -- Table structure for table `task_step_flow` -- DROP TABLE IF EXISTS `task_step_flow`; CREATE TABLE `task_step_flow` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `task_id` bigint(20) NOT NULL COMMENT '任务id', `child_task_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '子任务id', `execute_ip_port` varchar(255) DEFAULT '' COMMENT '执行任务的ip:port', `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `order_no` int(11) NOT NULL COMMENT '序号', `status` tinyint(4) NOT NULL COMMENT '状态:0未开始、1成功、2中断、3跳过、4失败', `log` text COMMENT '日志', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_task_class_step` (`task_id`,`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤流表'; -- -- Table structure for table `task_step_meta` -- DROP TABLE IF EXISTS `task_step_meta`; CREATE TABLE `task_step_meta` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `class_name` varchar(255) NOT NULL COMMENT '类名', `step_name` varchar(255) NOT NULL COMMENT '步骤名', `step_desc` varchar(255) NOT NULL COMMENT '步骤描述', `ops_device` varchar(255) NOT NULL COMMENT '运维建议', `timeout` int(11) NOT NULL COMMENT '超时时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `order_no` int(11) NOT NULL COMMENT '序号', PRIMARY KEY (`id`), UNIQUE KEY `uk_class_step` (`class_name`,`step_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='任务步骤元数据表'; -- -- Table structure for table `app_alert_record` -- DROP TABLE IF EXISTS `app_alert_record`; CREATE TABLE `app_alert_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增id', `visible_type` int(1) NOT NULL COMMENT '可见类型(0:均可见;1:仅管理员可见;)', `important_level` int(1) NOT NULL COMMENT '重要类型(0:一般;1:重要;2:紧急)', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `app_id` bigint(20) DEFAULT NULL COMMENT 'app id', `instance_id` bigint(20) DEFAULT NULL COMMENT '实例id', `ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT '机器ip', `port` int(10) DEFAULT NULL COMMENT '端口号', `title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '报警标题', `content` varchar(500) COLLATE utf8_bin NOT NULL COMMENT '报警内容', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `ip` (`ip`), KEY `idx_inst_id` (`instance_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报警记录表'; -- -- Table structure for table `config_restart_record` -- DROP TABLE IF EXISTS `config_restart_record`; CREATE TABLE `config_restart_record` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `app_name` varchar(36) NOT NULL COMMENT '应用名称', `operate_type` char(1) NOT NULL COMMENT '操作类型(0:滚动重启,1:修改配置强制重启;2:修改配置)', `param` varchar(2000) NOT NULL COMMENT '初始化任务参数(json):不变', `status` tinyint(4) NOT NULL COMMENT '状态:0等待,1运行,2成功,3失败,4配置修改待重启,5修改配置后重启,6被停止', `start_time` datetime NOT NULL COMMENT '开始时间', `end_time` datetime NOT NULL COMMENT '结束时间', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', `log` longtext COMMENT '日志信息', `user_name` varchar(64) DEFAULT NULL COMMENT '操作人员姓名', `user_id` bigint(20) NOT NULL COMMENT '用户id', `instances` varchar(1000) DEFAULT NULL COMMENT '涉及实例id列表的json格式', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='重启记录表'; -- -- Table structure for table `app_import` -- DROP TABLE IF EXISTS `app_import`; CREATE TABLE `app_import` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT '目标应用id', `instance_info` text COMMENT '源redis实例信息', `redis_password` varchar(200) DEFAULT NULL COMMENT '源redis密码', `status` int(11) DEFAULT NULL COMMENT '迁移状态:PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功")', `step` int(11) DEFAULT NULL COMMENT '导入阶段', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `migrate_id` bigint(20) DEFAULT NULL COMMENT '数据迁移id', `mem_size` int(11) DEFAULT NULL COMMENT '目标应用内存大小,单位G', `redis_version_name` varchar(20) DEFAULT NULL COMMENT '目标应用redis版本,格式:redis-x.x.x', `app_build_task_id` bigint(20) DEFAULT NULL COMMENT '目标应用部署任务id', `source_type` int(11) DEFAULT NULL COMMENT '源redis类型:7:cluster, 6:sentinel, 5:standalone', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------新增加的表--------------------------- -- -- Table structure for table `app_biz` -- CREATE TABLE `app_biz` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '业务组名称', `biz_desc` varchar(255) NOT NULL COMMENT '业务组描述', PRIMARY KEY (`id`), UNIQUE KEY `bidx_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='业务组表'; -- -- Table structure for table `app_capacity_monitor` -- CREATE TABLE `app_capacity_monitor` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `sharding_master_num` int(10) NOT NULL DEFAULT '0' COMMENT '主分片数', `mem` bigint(20) NOT NULL COMMENT '应用初始内存(字节)', `cur_mem` bigint(20) NOT NULL COMMENT '应用当前内存(字节)', `mem_used` bigint(20) NOT NULL DEFAULT '0' COMMENT '应用已使用内存(字节)', `mem_used_history` bigint(20) DEFAULT '0' COMMENT '应用已使用内存(历史最大值)', `sharding_mem` bigint(20) NOT NULL COMMENT '应用分片初始内存(字节)', `cur_sharding_mem` bigint(20) NOT NULL COMMENT '应用分片当前内存(字节)', `sharding_mem_used` bigint(20) NOT NULL DEFAULT '0' COMMENT '分片已使用内存(最大值)', `expand_mem_percent` tinyint(4) NOT NULL COMMENT '应用扩容内存使用百分比', `expand_ratio` tinyint(4) NOT NULL COMMENT '扩容比率', `expand_ratio_total` int(10) NOT NULL COMMENT '当日最大扩容比率(超出不可扩容)', `is_expand` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可扩容:0否;1是', `is_reduce` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可缩容: 0否,1是', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `expand_time` datetime DEFAULT NULL COMMENT '上次扩容时间', `schedule_status` tinyint(4) DEFAULT '0' COMMENT '计划状态:0:无意义;1:待缩容;2:待扩容', `schedule_time` date DEFAULT NULL COMMENT '计划处理时间', `reduce_ratio_min` tinyint(4) NOT NULL DEFAULT '40' COMMENT '缩容内存使用率最小值', `reduce_ratio_max` tinyint(4) NOT NULL DEFAULT '60' COMMENT '缩容内存使用率最大值', `expand_count` int(10) NOT NULL DEFAULT '0' COMMENT '当日自动扩容次数', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=596 DEFAULT CHARSET=utf8 COMMENT='app应用容量监控'; ================================================ FILE: cachecloud-web/sql/function-support_custom_password.sql ================================================ -- app_desc change ALTER TABLE app_desc ADD custom_password varchar(255) DEFAULT NULL COMMENT '自定义密码'; ================================================ FILE: cachecloud-web/sql/update 2.0 to 3.0.sql ================================================ CREATE TABLE `app_alert_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `visible_type` int(1) NOT NULL COMMENT 'ɼͣ0ɼ1Աɼ', `important_level` int(1) NOT NULL COMMENT 'Ҫͣ0һ㣻1Ҫ2', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `app_id` bigint(20) DEFAULT NULL COMMENT 'app id', `instance_id` bigint(20) DEFAULT NULL COMMENT 'ʵid', `ip` varchar(16) COLLATE utf8_bin DEFAULT NULL COMMENT 'ip', `port` int(10) DEFAULT NULL COMMENT '˿ں', `title` varchar(255) COLLATE utf8_bin NOT NULL COMMENT '', `content` varchar(500) COLLATE utf8_bin NOT NULL COMMENT '', PRIMARY KEY (`id`), KEY `app_id` (`app_id`), KEY `ip` (`ip`), KEY `idx_inst_id` (`instance_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='¼'; CREATE TABLE `config_restart_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT 'Ӧid', `app_name` varchar(36) NOT NULL COMMENT 'Ӧ', `operate_type` char(1) NOT NULL COMMENT 'ͣ0:1:޸ǿ2޸ã', `param` varchar(2000) NOT NULL COMMENT 'ʼ(json):', `status` tinyint(4) NOT NULL COMMENT '״̬0ȴ1У2ɹ3ʧܣ4޸Ĵ', `start_time` datetime NOT NULL COMMENT 'ʼʱ', `end_time` datetime NOT NULL COMMENT 'ʱ', `create_time` datetime NOT NULL COMMENT 'ʱ', `update_time` datetime NOT NULL COMMENT '޸ʱ', `log` longtext COMMENT '־Ϣ', `user_name` varchar(64) DEFAULT NULL COMMENT 'Ա', `user_id` bigint(20) NOT NULL COMMENT 'ûid', `instances` varchar(1000) DEFAULT NULL COMMENT '漰ʵidбjsonʽ', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='¼'; CREATE TABLE `module_info` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL, `git_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'git resource', `info` varchar(128) DEFAULT NULL COMMENT 'ģϢ˵', `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0:Ч 1:Ч', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='RedisģϢ'; CREATE TABLE `module_version` ( `id` int(11) NOT NULL AUTO_INCREMENT, `module_id` int(11) NOT NULL, `version_id` int(11) NOT NULL COMMENT '汾', `create_time` datetime DEFAULT NULL COMMENT 'ʱ', `so_path` varchar(255) DEFAULT NULL COMMENT 'soĵַ', `tag` varchar(64) NOT NULL COMMENT 'ģ汾', `status` int(255) NOT NULL DEFAULT '0' COMMENT 'Ƿ(soַ)0 1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Redisģ汾'; CREATE TABLE `app_import` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) DEFAULT NULL COMMENT 'ĿӦid', `instance_info` text COMMENT 'ԴredisʵϢ', `redis_password` varchar(200) DEFAULT NULL COMMENT 'Դredis', `status` int(11) DEFAULT NULL COMMENT 'Ǩ״̬PREPARE(0, "׼", "Ӧõ-δʼ"), START(1, "...", "Ӧõ-ʼ"), ERROR(2, "error", "Ӧõ-"), VERSION_BUILD_START(11, "...", "½redis汾-"), VERSION_BUILD_ERROR(12, "error", "½redis汾-"), VERSION_BUILD_END(20, "ɹ", "½redis汾-"), APP_BUILD_INIT(21, "׼", "½redisӦ-׼"), APP_BUILD_START(22, "...", "½redisӦ-"), APP_BUILD_ERROR(23, "error", "½redisӦ-"), APP_BUILD_END(30, "ɹ", "½redisӦ-"), MIGRATE_INIT(31, "׼", "Ǩ-׼"), MIGRATE_START(32, "...", "Ǩ-"), MIGRATE_ERROR(33, "error", "Ǩ-"), MIGRATE_END(3, "ɹ", "Ӧõ-ɹ")', `step` int(11) DEFAULT NULL COMMENT '׶', `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, `migrate_id` bigint(20) DEFAULT NULL COMMENT 'Ǩid', `mem_size` int(11) DEFAULT NULL COMMENT 'ĿӦڴСλG', `redis_version_name` varchar(20) DEFAULT NULL COMMENT 'ĿӦredis汾ʽredis-x.x.x', `app_build_task_id` bigint(20) DEFAULT NULL COMMENT 'ĿӦòid', `source_type` int(11) DEFAULT NULL COMMENT 'Դredisͣ7:cluster, 6:sentinel, 5:standalone', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- instance_alert_configs change ALTER TABLE instance_alert_configs ADD important_level TINYINT(4) DEFAULT 0 NOT NULL COMMENT 'Ҫ̶ȣ0һ㣻1Ҫ2'; -- app_user change ALTER TABLE app_user ADD password varchar(64) NULL COMMENT ''; ALTER TABLE app_user ADD register_time DATETIME DEFAULT CURRENT_TIMESTAMP NULL COMMENT 'עʱ'; ALTER TABLE app_user ADD purpose varchar(255) NULL COMMENT 'ʹĿ'; ALTER TABLE app_user ADD company varchar(255) NULL COMMENT '˾'; -- module_info change ALTER TABLE module_info ADD CONSTRAINT `NAMEKEY` UNIQUE KEY (name); -- app_desc change ALTER TABLE app_desc ADD custom_password varchar(255) DEFAULT NULL COMMENT 'Զ'; -- redis_module_config definition CREATE TABLE `redis_module_config` ( `id` int(11) NOT NULL AUTO_INCREMENT, `config_key` varchar(128) NOT NULL COMMENT '', `config_value` varchar(512) NOT NULL COMMENT 'ֵ', `info` varchar(512) NOT NULL COMMENT '˵', `update_time` datetime NOT NULL COMMENT 'ʱ', `type` mediumint(9) NOT NULL COMMENT 'ͣ2.clusterڵ, 5:sentinelڵ, 6:redisͨڵ', `status` tinyint(4) NOT NULL COMMENT '1Ч,0Ч', `version_id` int(11) NOT NULL COMMENT 'Module version汾id', `refresh` tinyint(4) DEFAULT '0' COMMENT 'Ƿã0ɣ1', `module_id` int(11) NOT NULL DEFAULT '7' COMMENT 'Module Ϣid', `config_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'ͣ0غã1ʱã2ʱ', PRIMARY KEY (`id`), UNIQUE KEY `uniq_configkey_type_version_id` (`config_key`,`type`,`version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='redisģñ'; -- app_to_module definition CREATE TABLE `app_to_module` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '', `app_id` bigint(20) NOT NULL COMMENT 'Ӧid', `module_id` int(11) NOT NULL COMMENT 'ģinfo id', `module_version_id` int(11) NOT NULL COMMENT 'ģ汾id', PRIMARY KEY (`id`), UNIQUE KEY `app_to_module_un` (`app_id`,`module_id`,`module_version_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Ӧģϵ'; ALTER TABLE machine_info ADD dis_type tinyint(4) DEFAULT 0 NOT NULL COMMENT 'ϵͳа汾0:centos;1:ubuntu'; ================================================ FILE: cachecloud-web/sql/update 3.0 to 3.1.sql ================================================ -- system_resource change ALTER TABLE system_resource ADD order_num int(6) NOT NULL DEFAULT '0' COMMENT '排序'; ================================================ FILE: cachecloud-web/sql/update 3.1 to 3.2.sql ================================================ -- app_desc change ALTER TABLE app_desc ADD maxmemory_policy tinyint(4) DEFAULT NULL COMMENT '淘汰策略(0:noeviction; 1:allkeys-lru;2:allkeys-lfu;3:volatile-lru;4:volatile-lfu;5:allkeys-random;6:volatile-random;7:volatile-ttl)'; ================================================ FILE: cachecloud-web/sql/update 3.2 to 3.3.sql ================================================ ALTER TABLE instance_config ADD value_type TINYINT(4) DEFAULT 0 NOT NULL COMMENT '取值类型(0:默认值 config_value;1:从主节点拷贝)'; ALTER TABLE app_client_statistic_gather ADD used_disk BIGINT(20) DEFAULT 0 NULL COMMENT '磁盘占用byte'; ALTER TABLE app_client_statistic_gather ADD server_cmd_count bigint(20) DEFAULT 0 NOT NULL COMMENT 'server端统计的命令调用次数'; ALTER TABLE instance_statistics ADD used_disk bigint(255) DEFAULT 0 NOT NULL COMMENT '已使用磁盘,单位byte'; ALTER TABLE app_minute_statistics ADD used_disk bigint(20) DEFAULT 0 NOT NULL COMMENT '磁盘占用(字节)'; ALTER TABLE app_hour_statistics ADD used_disk bigint(20) DEFAULT 0 NOT NULL COMMENT '磁盘占用(字节)'; ALTER TABLE machine_statistics ADD disk_total varchar(120) NULL COMMENT '机器分配磁盘,单位MB'; ALTER TABLE machine_statistics ADD disk_available varchar(120) NULL COMMENT '机器空闲磁盘,单位MB'; ALTER TABLE machine_statistics ADD disk_usage_ratio varchar(15) NULL COMMENT '机器磁盘使用率,百分比(无需乘100)'; ALTER TABLE app_daily ADD avg_used_disk BIGINT(20) NOT NULL COMMENT '平均磁盘使用量'; ALTER TABLE app_daily ADD max_used_disk BIGINT(20) NOT NULL COMMENT '最大磁盘使用量'; ALTER TABLE app_desc ADD persistence_type TINYINT(4) DEFAULT 0 NOT NULL COMMENT '持久化类型(0:常规;1:主aof自动刷盘;从常规;2:主关闭aof,从常规)'; ALTER TABLE app_user ADD biz_id BIGINT(20) DEFAULT NULL COMMENT '所属业务组id(app_biz)'; ALTER TABLE instance_alert_configs ADD app_type TINYINT(4) DEFAULT 0 NOT NULL COMMENT '应用类型(0:redis;)'; ALTER TABLE instance_alert_configs DROP KEY uniq_index; ALTER TABLE instance_alert_configs ADD CONSTRAINT uniq_index UNIQUE KEY (`type`,instance_id,alert_config,compare_type,app_type); -- -- Table structure for table `app_biz` -- CREATE TABLE `app_biz` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) NOT NULL COMMENT '业务组名称', `biz_desc` varchar(255) NOT NULL COMMENT '业务组描述', PRIMARY KEY (`id`), UNIQUE KEY `bidx_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='业务组表'; -- -- Table structure for table `app_capacity_monitor` -- CREATE TABLE `app_capacity_monitor` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `app_id` bigint(20) NOT NULL COMMENT '应用id', `sharding_master_num` int(10) NOT NULL DEFAULT '0' COMMENT '主分片数', `mem` bigint(20) NOT NULL COMMENT '应用初始内存(字节)', `cur_mem` bigint(20) NOT NULL COMMENT '应用当前内存(字节)', `mem_used` bigint(20) NOT NULL DEFAULT '0' COMMENT '应用已使用内存(字节)', `mem_used_history` bigint(20) DEFAULT '0' COMMENT '应用已使用内存(历史最大值)', `sharding_mem` bigint(20) NOT NULL COMMENT '应用分片初始内存(字节)', `cur_sharding_mem` bigint(20) NOT NULL COMMENT '应用分片当前内存(字节)', `sharding_mem_used` bigint(20) NOT NULL DEFAULT '0' COMMENT '分片已使用内存(最大值)', `expand_mem_percent` tinyint(4) NOT NULL COMMENT '应用扩容内存使用百分比', `expand_ratio` tinyint(4) NOT NULL COMMENT '扩容比率', `expand_ratio_total` int(10) NOT NULL COMMENT '当日最大扩容比率(超出不可扩容)', `is_expand` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可扩容:0否;1是', `is_reduce` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否可缩容: 0否,1是', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `expand_time` datetime DEFAULT NULL COMMENT '上次扩容时间', `schedule_status` tinyint(4) DEFAULT '0' COMMENT '计划状态:0:无意义;1:待缩容;2:待扩容', `schedule_time` date DEFAULT NULL COMMENT '计划处理时间', `reduce_ratio_min` tinyint(4) NOT NULL DEFAULT '40' COMMENT '缩容内存使用率最小值', `reduce_ratio_max` tinyint(4) NOT NULL DEFAULT '60' COMMENT '缩容内存使用率最大值', `expand_count` int(10) NOT NULL DEFAULT '0' COMMENT '当日自动扩容次数', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=596 DEFAULT CHARSET=utf8 COMMENT='app应用容量监控'; ------------------------------- add for redis 6.2 and 7.2---------------------------------------------------------- # below two insert sql are related, note the ids related, system_resource.id and instance_config.version_id # 注意两个表之间的id相关联,system_resource表id字段 和 instance_config表version_id字段 BEGIN; INSERT INTO `system_resource` VALUES (51, 'redis-6.2.4', 'redis-6.2.4 资源包', 3, '2023-02-09 10:24:16', '/redis', 'http://download.redis.io/releases/redis-6.2.4.tar.gz', 1, 1, 'admin', 3507, NULL, 0), (62, 'redis-7.2.4', 'redis 7.2.4 资源包', 3, '2024-01-18 15:26:02', '/redis', 'http://download.redis.io/releases/redis-7.2.4.tar.gz', 1, 1, 'admin', 11687, NULL, 700); COMMIT; BEGIN; INSERT INTO instance_config (id, config_key, config_value, info, update_time, `type`, status, version_id, refresh, value_type) VALUES (868, 'cluster-enabled', 'yes', '是否开启集群模式', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(869, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2021-06-09 10:12:50', 2, 1, 51, 0, 1) ,(870, 'cluster-migration-barrier', '3', '从节点自动迁移至少需要的可用节点数,默认1个', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(871, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(872, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2021-06-09 10:12:50', 2, 1, 51, 0, 1) ,(873, 'port', '%d', 'sentinel实例端口', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(874, 'dir', '%s', '工作目录', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(875, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(876, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(877, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(878, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(879, 'daemonize', 'no', '是否守护进程', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(880, 'tcp-backlog', '511', 'TCP连接完成队列', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(881, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(882, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(883, 'loglevel', 'notice', '日志级别', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(884, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(885, 'dir', '%s', 'redis工作目录', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(886, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(887, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(888, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(889, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(890, 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(891, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(892, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(893, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(894, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(895, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(896, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2021-06-09 10:12:50', 6, 0, 51, 0, 1) ,(897, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2021-06-09 10:12:50', 6, 0, 51, 0, 1) ,(898, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(899, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(900, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(901, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(902, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(903, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(904, 'hz', '10', '执行后台task数量,默认:10', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(905, 'port', '%d', '端口', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(906, 'maxmemory', '%dmb', '当前实例最大可用内存', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(907, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(908, 'appendonly', 'yes', '开启append only持久化模式', '2021-06-09 10:12:50', 6, 1, 51, 0, 1) ,(909, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(910, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(911, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(912, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(913, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(914, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(915, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(916, 'maxclients', '10000', '客户端最大连接数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(917, 'protected-mode', 'yes', '开启保护模式', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(918, 'bind', '0.0.0.0', '默认客户端都可连接', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(919, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(920, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(921, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(922, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(923, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(924, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(925, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(926, 'protected-mode', 'no', '关闭sentinel保护模式', '2021-06-09 10:12:50', 5, 1, 51, 0, 0) ,(927, 'activedefrag', 'no', '碎片整理开启', '2022-06-07 10:16:26', 6, 1, 51, 0, 1) ,(928, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(929, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(930, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(931, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(932, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(933, 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(934, 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(935, 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2021-06-09 10:12:50', 2, 1, 51, 0, 0) ,(936, 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(937, 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(938, 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(939, 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(940, 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(941, 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(942, 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(943, 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(944, 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(945, 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(946, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(947, 'repl-diskless-load', 'on-empty-db', '完全安全的情况下才使用无磁盘加载', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(948, 'tracking-table-max-keys', '1000000', '无效表键的最大填充数量', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(949, 'rdb-del-sync-files', 'yes', '默认:no 不删除rdb文件,删除实例中复制使用的不持久的RDB文件', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(950, 'lazyfree-lazy-user-del', 'yes', '默认值no,设置del操作命令同unlink一致', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(951, 'io-threads', '1', '读写io线程数量', '2021-06-09 15:22:48', 6, 1, 51, 0, 0) ,(952, 'io-threads-do-reads', 'no', '开启io读线程', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(953, 'jemalloc-bg-thread', 'yes', '启用Jemalloc后台线程清理', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(954, 'server_cpulist', '0-7:2', '设置redis服务器/io线程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(955, 'bio_cpulist', '1,3', '设置bio线程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(956, 'aof_rewrite_cpulist', '8-11', '设置aof重写子进程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(957, 'bgsave_cpulist', '1,10-11', '设置bgsave子进程的cpu使用权重', '2021-06-09 10:12:50', 6, 1, 51, 0, 0) ,(959, 'save', '', '关闭同步操作', '2021-07-01 10:31:11', 6, 1, 51, 0, 0) ,(1579, 'enable-module-command', 'yes', '是否支持module命令', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1582, 'save', '', '关闭同步操作', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1584, 'cluster-enabled', 'yes', '是否开启集群模式', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1585, 'cluster-node-timeout', '15000', '集群节点超时时间,默认15秒', '2024-01-17 10:23:00', 2, 1, 62, 0, 1) ,(1586, 'cluster-migration-barrier', '3', '从节点自动迁移至少需要的可用节点数,默认1个', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1587, 'cluster-config-file', 'nodes-%d.conf', '集群配置文件名称,格式:nodes-{port}.conf', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1588, 'cluster-require-full-coverage', 'no', '节点部分失败期间,其他节点是否继续工作', '2024-01-17 10:23:00', 2, 1, 62, 0, 1) ,(1589, 'port', '%d', 'sentinel实例端口', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1590, 'dir', '%s', '工作目录', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1591, 'sentinel monitor', '%s %s %d 1', 'master名称定义和最少参与监控的sentinel数,格式:masterName ip port num', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1592, 'sentinel down-after-milliseconds', '%s 20000', 'Sentinel判定服务器断线的毫秒数', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1593, 'sentinel failover-timeout', '%s 180000', '故障迁移超时时间,默认:3分钟', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1594, 'sentinel parallel-syncs', '%s 1', '在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1595, 'daemonize', 'no', '是否守护进程', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1596, 'tcp-backlog', '511', 'TCP连接完成队列', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1597, 'timeout', '0', '客户端闲置多少秒后关闭连接,默认为0,永不关闭', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1598, 'tcp-keepalive', '60', '检测客户端是否健康周期,默认关闭', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1599, 'loglevel', 'notice', '日志级别', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1600, 'databases', '16', '可用的数据库数,默认值为16个,默认数据库为0', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1601, 'dir', '%s', 'redis工作目录', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1602, 'stop-writes-on-bgsave-error', 'no', 'bgsave出错了不停写', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1603, 'repl-timeout', '60', 'master批量数据传输时间或者ping回复时间间隔,默认:60秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1604, 'repl-disable-tcp-nodelay', 'no', '是否禁用socket的NO_DELAY,默认关闭,影响主从延迟', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1605, 'repl-backlog-size', '10M', '复制缓存区,默认:1mb,配置为:10Mb', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1606, 'repl-backlog-ttl', '7200', 'master在没有从节点的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1607, 'lua-time-limit', '5000', 'Lua脚本最长的执行时间,单位为毫秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1608, 'slowlog-log-slower-than', '10000', '慢查询被记录的阀值,默认10毫秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1609, 'slowlog-max-len', '128', '最多记录慢查询的条数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1610, 'hash-max-ziplist-entries', '512', 'hash数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1611, 'hash-max-ziplist-value', '64', 'hash数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1612, 'list-max-ziplist-entries', '512', 'list数据结构优化参数', '2024-01-17 10:23:00', 6, 0, 62, 0, 1) ,(1613, 'list-max-ziplist-value', '64', 'list数据结构优化参数', '2024-01-17 10:23:00', 6, 0, 62, 0, 1) ,(1614, 'set-max-intset-entries', '512', 'set数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1615, 'zset-max-ziplist-entries', '128', 'zset数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1616, 'zset-max-ziplist-value', '64', 'zset数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1617, 'activerehashing', 'yes', '是否激活重置哈希,默认:yes', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1618, 'client-output-buffer-limit normal', '0 0 0', '客户端输出缓冲区限制(客户端)', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1619, 'client-output-buffer-limit pubsub', '32mb 8mb 60', '客户端输出缓冲区限制(发布订阅)', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1620, 'hz', '10', '执行后台task数量,默认:10', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1621, 'port', '%d', '端口', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1622, 'maxmemory', '%dmb', '当前实例最大可用内存', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1623, 'maxmemory-policy', 'volatile-lfu', '内存不够时,淘汰策略,默认:volatile-lfu', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1624, 'appendonly', 'yes', '开启append only持久化模式', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1625, 'appendfsync', 'everysec', '默认:aof每秒同步一次', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1626, 'appendfilename', 'appendonly-%d.aof', 'aof文件名称,默认:appendonly-{port}.aof', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1627, 'dbfilename', 'dump-%d.rdb', 'RDB文件默认名称,默认dump-{port}.rdb', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1628, 'aof-rewrite-incremental-fsync', 'yes', 'aof rewrite过程中,是否采取增量文件同步策略,默认:yes', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1629, 'no-appendfsync-on-rewrite', 'yes', '是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1630, 'auto-aof-rewrite-min-size', '64m', '触发rewrite的aof文件最小阀值,默认64m', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1631, 'auto-aof-rewrite-percentage', '%d', 'Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1632, 'maxclients', '10000', '客户端最大连接数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1633, 'protected-mode', 'no', '开启保护模式', '2024-06-05 11:55:57', 6, 1, 62, 0, 0) ,(1634, 'bind', '0.0.0.0 -::*', '默认客户端都可连接', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1635, 'list-max-ziplist-size', '-2', '8Kb对象以内采用ziplist', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1636, 'list-compress-depth', '0', '压缩方式,0:不压缩', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1637, 'always-show-logo', 'yes', 'redis启动是否显示logo', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1638, 'lazyfree-lazy-eviction', 'yes', '在被动淘汰键时,是否采用lazy free机制,默认:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1639, 'lazyfree-lazy-expire', 'yes', 'TTL的键过期是否采用lazyfree机制 默认值:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1640, 'lazyfree-lazy-server-del', 'yes', '隐式的DEL键(rename)是否采用lazyfree机制 默认值:no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1641, 'aof-use-rdb-preamble', 'yes', '是否开启混合持久化,默认值 no 不开启', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1642, 'protected-mode', 'no', '关闭sentinel保护模式', '2024-01-17 10:23:00', 5, 1, 62, 0, 0) ,(1643, 'activedefrag', 'no', '碎片整理开启', '2024-01-17 10:23:00', 6, 1, 62, 0, 1) ,(1644, 'active-defrag-threshold-lower', '10', '碎片率达到百分之多少开启整理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1645, 'active-defrag-threshold-upper', '100', '碎片率小余多少百分比开启整理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1646, 'active-defrag-ignore-bytes', '300mb', '内存碎片达到多少兆开启碎片', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1647, 'active-defrag-cycle-min', '10', '碎片整理最小cpu百分比', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1648, 'active-defrag-cycle-max', '30', '碎片整理最大cpu百分比', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1649, 'active-defrag-max-scan-fields', '1000', '内存碎片处理set/hash/zset/list 中的最大数量的项', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1650, 'replica-serve-stale-data', 'yes', '从节点与master断连或复制命令响应:yes 继续响应 no:相关命令返回异常信息', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1651, 'cluster-replica-validity-factor', '10', '从节点延迟有效性判断因子,默认10秒', '2024-01-17 10:23:00', 2, 1, 62, 0, 0) ,(1652, 'replica-priority', '100', '从节点的优先级,影响sentinel/cluster晋升master操作,0永远不晋升', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1653, 'replica-read-only', 'yes', '从节点是否只读: yes 只读', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1654, 'replica-lazy-flush', 'yes', '从节点发起全量复制,是否采用flushall async清理老数据 默认值 no', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1655, 'client-output-buffer-limit replica', '512mb 256mb 60', '客户端输出缓冲区限制', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1656, 'replica-ignore-maxmemory', 'yes', '从节点是否开启最大内存,避免一些过大缓冲区导致oom', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1657, 'stream-node-max-bytes', '4096', 'stream数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1658, 'stream-node-max-entries', '100', 'stream数据结构优化参数', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1659, 'dynamic-hz', 'yes', '自适应平衡空闲CPU的使用率和响应', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1660, 'rdb-save-incremental-fsync', 'yes', 'rdb同步刷盘是否采用增量fsync,每32MB执行一次fsync', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1661, 'repl-ping-replica-period', '10', '指定从节点定期ping master的周期,默认:10秒', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1662, 'latency-monitor-threshold', '30', '延迟事件阀值,单位ms', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1663, 'repl-diskless-load', 'on-empty-db', '完全安全的情况下才使用无磁盘加载', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1664, 'tracking-table-max-keys', '1000000', '无效表键的最大填充数量', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1665, 'rdb-del-sync-files', 'yes', '默认:no 不删除rdb文件,删除实例中复制使用的不持久的RDB文件', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1666, 'lazyfree-lazy-user-del', 'yes', '默认值no,设置del操作命令同unlink一致', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1667, 'io-threads', '1', '读写io线程数量', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1668, 'io-threads-do-reads', 'no', '开启io读线程', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1669, 'jemalloc-bg-thread', 'yes', '启用Jemalloc后台线程清理', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1670, 'server_cpulist', '0-7:2', '设置redis服务器/io线程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1671, 'bio_cpulist', '1,3', '设置bio线程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1672, 'aof_rewrite_cpulist', '8-11', '设置aof重写子进程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0) ,(1673, 'bgsave_cpulist', '1,10-11', '设置bgsave子进程的cpu使用权重', '2024-01-17 10:23:00', 6, 1, 62, 0, 0); ================================================ FILE: cachecloud-web/sql/update-system_resource.sql ================================================ -- system_resource change ALTER TABLE system_resource ADD order_num int(6) NOT NULL DEFAULT '0' COMMENT '排序'; ================================================ FILE: cachecloud-web/sql/update2.0-2.1.sql ================================================ create or replace table app_import( id bigint auto_increment primary key, app_id bigint null comment '目标应用id', instance_info text null comment '源redis实例信息', redis_password varchar (200) null comment '源redis密码', status int null comment '迁移状态:PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功")', step int null comment '导入阶段', create_time timestamp default CURRENT_TIMESTAMP not null, update_time timestamp default CURRENT_TIMESTAMP null, migrate_id bigint null comment '数据迁移id', mem_size int null comment '目标应用内存大小,单位G', redis_version_name varchar (20) null comment '目标应用redis版本,格式:redis-x.x.x', app_build_task_id bigint null comment '目标应用部署任务id', source_type int null comment '源redis类型:7:cluster, 6:sentinel, 5:standalone' ); ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ApplicationStarter.java ================================================ package com.sohu.cache; import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.ImportResource; import org.springframework.scheduling.annotation.EnableAsync; /** * Created by zhangyijun */ @SpringBootApplication @EnableAutoConfiguration(exclude = {MybatisAutoConfiguration.class}) @ImportResource("${spring.application.import}") @EnableAsync public class ApplicationStarter { public static void main(String[] args) { SpringApplication app = new SpringApplication(ApplicationStarter.class); app.setAdditionalProfiles(); app.setBannerMode(Banner.Mode.LOG); app.run(args); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/InstanceAlertService.java ================================================ package com.sohu.cache.alert; import com.sohu.cache.entity.InstanceFault; import java.util.List; /** * 实例报警检测 * @author leifu * @Date 2014年12月16日 * @Time 下午1:56:35 */ public interface InstanceAlertService { /** * 实例故障列表 * * @param instId * @return */ List getListByInstId(int instId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/bean/AlertConfigBaseData.java ================================================ package com.sohu.cache.alert.bean; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.StandardStats; /** * 报警基础数据 * @author leifu * @Date 2017年6月16日 * @Time 下午2:19:10 */ public class AlertConfigBaseData { /** * 基准数据 */ private StandardStats standardStats; /** * 实例信息 */ private InstanceInfo instanceInfo; public StandardStats getStandardStats() { return standardStats; } public void setStandardStats(StandardStats standardStats) { this.standardStats = standardStats; } public InstanceInfo getInstanceInfo() { return instanceInfo; } public void setInstanceInfo(InstanceInfo instanceInfo) { this.instanceInfo = instanceInfo; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/impl/BaseAlertService.java ================================================ package com.sohu.cache.alert.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.alert.WeChatComponent; import com.sohu.cache.web.service.AppAlertRecordService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; /** * 报警基类 * * @author leifu * @Date 2014年12月16日 * @Time 下午4:15:11 */ public class BaseAlertService { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 邮箱报警 */ @Autowired(required = false) protected EmailComponent emailComponent; /** * 报警记录 */ @Autowired(required = false) protected AppAlertRecordService appAlertRecordService; /** * 微信报警 */ @Autowired(required = false) protected WeChatComponent weChatComponent; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/impl/InstanceAlertServiceImpl.java ================================================ package com.sohu.cache.alert.impl; import com.sohu.cache.alert.InstanceAlertService; import com.sohu.cache.dao.InstanceFaultDao; import com.sohu.cache.entity.InstanceFault; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 实例报警 * * @author leifu */ @Service public class InstanceAlertServiceImpl implements InstanceAlertService { @Autowired private InstanceFaultDao instanceFaultDao; @Override public List getListByInstId(int instId) { return instanceFaultDao.getListByInstId(instId); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/AlertConfigStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.StandardStats; import com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum; import com.sohu.cache.util.JsonUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.math.NumberUtils; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * @author leifu * @Date 2017年6月2日 * @Time 下午3:24:53 */ public abstract class AlertConfigStrategy { protected final static String MB_STRING = "MB"; protected final static String EMPTY = ""; /** * 检查配置 * * @param instanceAlertConfig * @param alertConfigBaseData */ public abstract List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData); /** * 比较long类型 * * @param instanceAlertConfig 报警配置 * @param currentValue 当前值 * @return */ protected boolean isCompareLongRight(InstanceAlertConfig instanceAlertConfig, long currentValue) { long alertValue = NumberUtils.toLong(instanceAlertConfig.getAlertValue()); int compareType = instanceAlertConfig.getCompareType(); if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) { return false; } return true; } /** * 比较int类型 * * @param instanceAlertConfig 报警配置 * @param currentValue 当前值 * @return */ protected boolean isCompareIntRight(InstanceAlertConfig instanceAlertConfig, int currentValue) { int alertValue = NumberUtils.toInt(instanceAlertConfig.getAlertValue()); int compareType = instanceAlertConfig.getCompareType(); if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) { return false; } return true; } /** * 比较double类型 * * @param instanceAlertConfig 报警配置 * @param currentValue 当前值 * @return */ protected boolean isCompareDoubleRight(InstanceAlertConfig instanceAlertConfig, double currentValue) { double alertValue = NumberUtils.toDouble(instanceAlertConfig.getAlertValue()); int compareType = instanceAlertConfig.getCompareType(); if (compareType == InstanceAlertCompareTypeEnum.LESS_THAN.getValue() && currentValue < alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.MORE_THAN.getValue() && currentValue > alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue == alertValue) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && currentValue != alertValue) { return false; } return true; } /** * 比较字符串类型 * * @param instanceAlertConfig 报警配置 * @param currentValue 当期值 * @return */ protected boolean isCompareStringRight(InstanceAlertConfig instanceAlertConfig, String currentValue) { String alertValue = instanceAlertConfig.getAlertValue(); int compareType = instanceAlertConfig.getCompareType(); if (compareType == InstanceAlertCompareTypeEnum.EQUAL.getValue() && currentValue.equals(alertValue)) { return false; } else if (compareType == InstanceAlertCompareTypeEnum.NOT_EQUAL.getValue() && !currentValue.equals(alertValue)) { return false; } return true; } /** * 获取全量统计项中的内容 */ protected static Object getValueFromRedisInfo(StandardStats standardStats, String attribute) { if (standardStats == null) { return null; } // 转换成Map Map infoMap = JsonUtil.fromJson(standardStats.getInfoJson(), Map.class); if (MapUtils.isEmpty(infoMap)) { return null; } for (Entry entry : infoMap.entrySet()) { Object object = entry.getValue(); // 转换成Map> if (!(object instanceof Map)) { continue; } Map sectionInfoMap = (Map) object; if (sectionInfoMap.containsKey(attribute)) { return MapUtils.getObject(sectionInfoMap, attribute); } } return null; } /** * 获取差值统计项中的内容 * @param redisInfo * @param attribute * @return */ protected static Object getValueFromDiffInfo(StandardStats standardStats, String attribute) { if (standardStats == null) { return null; } Map diffInfoMap = JsonUtil.fromJson(standardStats.getDiffJson(), Map.class); if (MapUtils.isEmpty(diffInfoMap)) { return null; } return MapUtils.getObject(diffInfoMap, attribute); } /** * 获取cluster info统计项中的内容 * @param redisInfo * @param attribute * @return */ protected static Object getValueFromClusterInfo(StandardStats standardStats, String attribute) { if (standardStats == null) { return null; } Map clusterInfoMap = JsonUtil.fromJson(standardStats.getClusterInfoJson(), Map.class); if (MapUtils.isEmpty(clusterInfoMap)) { return null; } return MapUtils.getObject(clusterInfoMap, attribute); } /** * 把字节变为兆 * @param value * @return */ protected long changeByteToMB(long value) { return value / 1024 / 1024; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/AofCurrentSizeAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * aof当前尺寸检测 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class AofCurrentSizeAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.aof_current_size.getValue()); // 没有配置Aof if (object == null) { return null; } long aofCurrentSize = NumberUtils.toLong(object.toString()); aofCurrentSize = changeByteToMB(aofCurrentSize); boolean compareRight = isCompareLongRight(instanceAlertConfig, aofCurrentSize); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(aofCurrentSize), instanceInfo.getAppId(), MB_STRING)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/ClientBiggestInputBufAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 客户端输入缓冲区最大buffer * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class ClientBiggestInputBufAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.client_biggest_input_buf.getValue()); if (object == null) { return null; } // 关系比对 long clientBiggestInputBuf = NumberUtils.toLong(object.toString()) ; clientBiggestInputBuf = changeByteToMB(clientBiggestInputBuf); boolean compareRight = isCompareLongRight(instanceAlertConfig, clientBiggestInputBuf); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clientBiggestInputBuf), instanceInfo.getAppId(), MB_STRING)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/ClientLongestOutputListAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 客户端输出缓冲区最大队列长度 * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class ClientLongestOutputListAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.client_longest_output_list.getValue()); if (object == null) { return null; } // 关系比对 long clientLongestOutputList = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, clientLongestOutputList); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clientLongestOutputList), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/ClusterSlotsOkAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisClusterInfoEnum; /** * 集群成功分配槽个数监控 * @author leifu * @Date 2017年6月21日 * @Time 下午3:01:21 */ public class ClusterSlotsOkAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromClusterInfo(alertConfigBaseData.getStandardStats(), RedisClusterInfoEnum.cluster_slots_ok.getValue()); if (object == null) { return null; } // 关系比对 int clusterSlotsOk = NumberUtils.toInt(object.toString()); boolean compareRight = isCompareIntRight(instanceAlertConfig, clusterSlotsOk); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clusterSlotsOk), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/ClusterStateAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisClusterInfoEnum; /** * 集群状态监控 * @author leifu * @Date 2017年6月21日 * @Time 下午3:01:21 */ public class ClusterStateAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromClusterInfo(alertConfigBaseData.getStandardStats(), RedisClusterInfoEnum.cluster_state.getValue()); if (object == null) { return null; } // 关系比对 String clusterState = object.toString(); boolean compareRight = isCompareStringRight(instanceAlertConfig, clusterState); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(clusterState), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/DefaultCommonAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import org.apache.commons.lang.math.NumberUtils; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * aof当前尺寸检测 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class DefaultCommonAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), instanceAlertConfig.getAlertConfig()); if (object == null) { return null; } if(judgeNumber(object)){ if(judegNumberIsDouble(object)){ double currentValue= NumberUtils.toDouble(object.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, currentValue); if (compareRight) { return null; } }else{ long currentValue = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, currentValue); if (compareRight) { return null; } } }else{ String currentValue = object.toString(); boolean compareRight = isCompareStringRight(instanceAlertConfig, currentValue); if (compareRight) { return null; } } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, object.toString(), instanceInfo.getAppId(), EMPTY)); } private boolean judgeNumber(Object object){ Pattern numberPattern = Pattern.compile("^-?(([0-9]|([1-9][0-9]*))(\\.[0-9]+)?)$"); Matcher matcher = numberPattern.matcher(object.toString()); return matcher.matches(); } private boolean judegNumberIsDouble(Object object){ return object.toString().contains("."); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/InstantaneousOpsPerSecAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 实时ops * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class InstantaneousOpsPerSecAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.instantaneous_ops_per_sec.getValue()); if (object == null) { return null; } // 关系比对 long instantaneousOpsPerSec = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, instantaneousOpsPerSec); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(instantaneousOpsPerSec), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/LatestForkUsecAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 上一次fork的微秒 * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class LatestForkUsecAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.latest_fork_usec.getValue()); if (object == null) { return null; } // 关系比对 long latestForkUsec = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, latestForkUsec); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(latestForkUsec), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MasterSlaveOffsetAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 主从偏移量监控 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MasterSlaveOffsetAlertStrategy extends AlertConfigStrategy { /** * 格式: * connected_slaves:2 * slave0:ip=x.x.x.x,port=6380,state=online,offset=33119690469561,lag=1 * slave1:ip=x.x.x.x,port=6380,state=online,offset=33119690513578,lag=0 * master_repl_offset:33119653194425 */ @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object connectedSlavesObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.connected_slaves.getValue()); if (connectedSlavesObject == null) { return null; } int connectedSlaves = NumberUtils.toInt(connectedSlavesObject.toString()); if (connectedSlaves == 0) { return null; } Object masterReplOffsetObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.master_repl_offset.getValue()); if (masterReplOffsetObject == null) { return null; } List instanceAlertValueResultList = new ArrayList(); for (int i = 0; i < connectedSlaves; i++) { Object slaveInfo = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), "slave" + i); if (slaveInfo == null) { continue; } String[] arr = slaveInfo.toString().split(","); if (arr.length < 5) { continue; } String state = arr[2]; if (!"state=online".equals(state)) { continue; } String slaveHostPort = arr[0] + "," + arr[1]; String slaveOffsetStr = arr[3]; String[] slaveOffsetArr = slaveOffsetStr.split("="); if (slaveOffsetArr.length != 2) { continue; } String slaveOffset = slaveOffsetArr[1]; long diffOffset = Math.abs(NumberUtils.toLong(masterReplOffsetObject.toString()) - NumberUtils.toLong(slaveOffset)); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, diffOffset); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); InstanceAlertValueResult instanceAlertValueResult = new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(diffOffset), instanceInfo.getAppId(), EMPTY); String otherInfo = String.format("masterOffset is %s
slaveOffset is %s
%s", masterReplOffsetObject.toString(), slaveOffset, slaveHostPort); instanceAlertValueResult.setOtherInfo(otherInfo); instanceAlertValueResultList.add(instanceAlertValueResult); } return instanceAlertValueResultList; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MemFragmentationRatioAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 内存碎片率 * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MemFragmentationRatioAlertStrategy extends AlertConfigStrategy { /** * 实例最小500MB才进行内存碎片率检查,否则价值不是很大 */ private final static long MIN_CHECK_MEMORY = 500L * 1024 * 1024; @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { // 检查内存 Object usedMemoryObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_memory.getValue()); long usedMemory = NumberUtils.toLong(usedMemoryObject.toString()); if (usedMemory < MIN_CHECK_MEMORY) { return null; } // 内存碎片率 Object memFragmentationRatioObject = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.mem_fragmentation_ratio.getValue()); if (memFragmentationRatioObject == null) { return null; } // 关系比对 double memFragmentationRatio = NumberUtils.toDouble(memFragmentationRatioObject.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, memFragmentationRatio); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); InstanceAlertValueResult instanceAlertValueResult = new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(memFragmentationRatio), instanceInfo.getAppId(), EMPTY); instanceAlertValueResult.setOtherInfo(String.format("内存使用为%s MB", String.valueOf(changeByteToMB(usedMemory)))); return Arrays.asList(instanceAlertValueResult); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteAofDelayedFsyncAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟aof delay fsync检测 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteAofDelayedFsyncAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.aof_delayed_fsync.getValue()); if (object == null) { return null; } long aofDelayedFsync = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, aofDelayedFsync); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(aofDelayedFsync), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteRejectedConnectionsAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟拒绝客户端连接数 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteRejectedConnectionsAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.rejected_connections.getValue()); if (object == null) { return null; } long minuteRejectedConnections = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteRejectedConnections); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteRejectedConnections), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncFullAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟全量复制次数 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteSyncFullAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_full.getValue()); if (object == null) { return null; } long minuteSyncFull = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncFull); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncFull), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncPartialErrAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟部分复制失败次数 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteSyncPartialErrAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_partial_err.getValue()); if (object == null) { return null; } long minuteSyncPartialErr = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncPartialErr); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncPartialErr), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteSyncPartialOkAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟部分复制成功次数 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteSyncPartialOkAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.sync_partial_ok.getValue()); if (object == null) { return null; } long minuteSyncPartialOk = NumberUtils.toLong(object.toString()); boolean compareRight = isCompareLongRight(instanceAlertConfig, minuteSyncPartialOk); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(minuteSyncPartialOk), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteTotalNetInputMBytesAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟输入网络流量 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteTotalNetInputMBytesAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object totalNetInputBytesObject = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.total_net_input_bytes.getValue()); if (totalNetInputBytesObject == null) { return null; } // 关系比对 long totalNetInputBytes = NumberUtils.toLong(totalNetInputBytesObject.toString()) ; totalNetInputBytes = changeByteToMB(totalNetInputBytes); boolean compareRight = isCompareLongRight(instanceAlertConfig, totalNetInputBytes); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(totalNetInputBytes), instanceInfo.getAppId(), MB_STRING)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteTotalNetOutputMBytesAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import org.apache.commons.lang.math.NumberUtils; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * 分钟输出网络流量 * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class MinuteTotalNetOutputMBytesAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object totalNetOutputBytesObject = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.total_net_output_bytes.getValue()); if (totalNetOutputBytesObject == null) { return null; } // 关系比对 long totalNetOutputBytes = NumberUtils.toLong(totalNetOutputBytesObject.toString()); totalNetOutputBytes = changeByteToMB(totalNetOutputBytes); boolean compareRight = isCompareLongRight(instanceAlertConfig, totalNetOutputBytes); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(totalNetOutputBytes), instanceInfo.getAppId(), MB_STRING)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteUsedCpuSysChStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; import org.apache.commons.lang.math.NumberUtils; import java.util.Arrays; import java.util.List; /** * @Author: rucao * @Date: 2021/6/9 上午11:03 */ public class MinuteUsedCpuSysChStrategy extends AlertConfigStrategy{ @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_cpu_sys_children.getValue()); if (object == null) { return null; } double min_used_cpu_sys_children_err= NumberUtils.toDouble(object.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, min_used_cpu_sys_children_err); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(min_used_cpu_sys_children_err), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteUsedCpuSysStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; import org.apache.commons.lang.math.NumberUtils; import java.util.Arrays; import java.util.List; /** * @Author: rucao * @Date: 2021/6/9 上午11:03 */ public class MinuteUsedCpuSysStrategy extends AlertConfigStrategy{ @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_cpu_sys.getValue()); if (object == null) { return null; } double min_used_cpu_sys_err= NumberUtils.toDouble(object.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, min_used_cpu_sys_err); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(min_used_cpu_sys_err), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteUsedCpuUserChStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; import org.apache.commons.lang.math.NumberUtils; import java.util.Arrays; import java.util.List; /** * @Author: rucao * @Date: 2021/6/9 上午11:03 */ public class MinuteUsedCpuUserChStrategy extends AlertConfigStrategy{ @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_cpu_user_children.getValue()); if (object == null) { return null; } double min_used_cpu_user_children_err= NumberUtils.toDouble(object.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, min_used_cpu_user_children_err); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(min_used_cpu_user_children_err), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/MinuteUsedCpuUserStrategy.java ================================================ package com.sohu.cache.alert.strategy; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; import org.apache.commons.lang.math.NumberUtils; import java.util.Arrays; import java.util.List; /** * @Author: rucao * @Date: 2021/6/9 上午11:03 */ public class MinuteUsedCpuUserStrategy extends AlertConfigStrategy{ @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromDiffInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.used_cpu_user.getValue()); if (object == null) { return null; } double min_used_cpu_user_err= NumberUtils.toDouble(object.toString()); boolean compareRight = isCompareDoubleRight(instanceAlertConfig, min_used_cpu_user_err); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(min_used_cpu_user_err), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/alert/strategy/RdbLastBgsaveStatusAlertStrategy.java ================================================ package com.sohu.cache.alert.strategy; import java.util.Arrays; import java.util.List; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.RedisInfoEnum; /** * RDB最近一次bgsave的执行状态 * * @author leifu * @Date 2017年6月16日 * @Time 下午2:34:10 */ public class RdbLastBgsaveStatusAlertStrategy extends AlertConfigStrategy { @Override public List checkConfig(InstanceAlertConfig instanceAlertConfig, AlertConfigBaseData alertConfigBaseData) { Object object = getValueFromRedisInfo(alertConfigBaseData.getStandardStats(), RedisInfoEnum.rdb_last_bgsave_status.getValue()); if (object == null) { return null; } // 关系比对 String rdbLastBgsaveStatus = object.toString(); boolean compareRight = isCompareStringRight(instanceAlertConfig, rdbLastBgsaveStatus); if (compareRight) { return null; } InstanceInfo instanceInfo = alertConfigBaseData.getInstanceInfo(); return Arrays.asList(new InstanceAlertValueResult(instanceAlertConfig, instanceInfo, String.valueOf(rdbLastBgsaveStatus), instanceInfo.getAppId(), EMPTY)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/AsyncService.java ================================================ package com.sohu.cache.async; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; /** * 异步服务类 * Created by yijunzhang on 14-6-18. */ public interface AsyncService { /** * 提交任务 * * @param callable * @return 返回是否提交成功 */ public boolean submitFuture(KeyCallable callable); /** * 提交任务并可拿到返回结果 * @param callable * @return */ public Future submitFutureWithRst(KeyCallable callable); /** * 提交任务 * * @param threadPoolKey * @param callable * @return 返回是否提交成功 */ public boolean submitFuture(String threadPoolKey, KeyCallable callable); /** * 提交任务 * * @param threadPoolKey * @param callable * @return 返回任务结果 */ public Future submitFutureWithRst(String threadPoolKey, KeyCallable callable); /** * 提交任务 * * @param callable * @return 返回成功结果 */ public Future submitFuture(Callable callable); /** * 装配key对应的线程池 * * @param threadPoolKey * @param threadPool */ public void assemblePool(String threadPoolKey, ThreadPoolExecutor threadPool); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/AsyncThreadPoolFactory.java ================================================ package com.sohu.cache.async; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 异步线程池 Created by yijunzhang on 14-7-10. */ public class AsyncThreadPoolFactory { public static final String DEFAULT_ASYNC_POOL = "async-pool"; public static final ThreadPoolExecutor DEFAULT_ASYNC_THREAD_POOL = new ThreadPoolExecutor(256, 256, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(1024), new NamedThreadFactory(DEFAULT_ASYNC_POOL, true),new CounterRejectedExecutionHandler()); public static final String TASK_EXECUTE_POOL = "task-execute-pool"; public static final ThreadPoolExecutor TASK_EXECUTE_THREAD_POOL = new ThreadPoolExecutor(200, 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(500), new NamedThreadFactory(TASK_EXECUTE_POOL, true), new CounterRejectedExecutionHandler()); public static final String CLIENT_REPORT_POOL ="client-report-pool"; public static final ThreadPoolExecutor CLIENT_REPORT_THREAD_POOL = new ThreadPoolExecutor(100, 100, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue(), new NamedThreadFactory(CLIENT_REPORT_POOL, true),new CounterRejectedExecutionHandler()); public static final String REDIS_SLOWLOG_POOL = "redis-slowlog-pool"; public static final ThreadPoolExecutor REDIS_SLOWLOG_THREAD_POOL = new ThreadPoolExecutor(30, 30, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(256), new NamedThreadFactory(REDIS_SLOWLOG_POOL, true),new CounterRejectedExecutionHandler()); public static final String MACHINE_POOL = "machine-ssh-pool"; public static final ThreadPoolExecutor MACHINE_THREAD_POOL = new ThreadPoolExecutor(256, 512, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(2048), new NamedThreadFactory(MACHINE_POOL, true)); public static final String APP_POOL = "app-pool"; public static final ThreadPoolExecutor APP_THREAD_POOL = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(256), new NamedThreadFactory(APP_POOL, true)); public static final String BREVITY_SCHEDULER_POOL = "brevity-scheduler-pool"; public static final ThreadPoolExecutor BREVITY_SCHEDULER_ASYNC_THREAD_POOL = new ThreadPoolExecutor(10, 50, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(2048), new NamedThreadFactory(BREVITY_SCHEDULER_POOL, true),new CounterRejectedExecutionHandler()); public static final String RESHARD_PROCESS_POOL = "redis-cluster-reshard"; public static final ThreadPoolExecutor RESHARD_PROCESS_THREAD_POOL = new ThreadPoolExecutor(10, 100, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(256), new NamedThreadFactory(RESHARD_PROCESS_POOL, false),new CounterRejectedExecutionHandler()); public static final String ALERT_RECORD_POOL = "alert-record-pool"; public static final ThreadPoolExecutor ALERT_RECORD_THREAD_POOL = new ThreadPoolExecutor(3, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(1024), new NamedThreadFactory(ALERT_RECORD_POOL, false)); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/CounterRejectedExecutionHandler.java ================================================ package com.sohu.cache.async; import com.google.common.util.concurrent.AtomicLongMap; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; /** * @author fulei * @date 2018年8月18日 * @time 上午10:29:59 */ public class CounterRejectedExecutionHandler implements RejectedExecutionHandler { private Logger logger = LoggerFactory.getLogger(CounterRejectedExecutionHandler.class); public static final AtomicLongMap THREAD_POOL_REJECT_MAP = AtomicLongMap.create(); @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { NamedThreadFactory namedThreadFactory = (NamedThreadFactory) executor.getThreadFactory(); String threadPoolName = namedThreadFactory.getThreadPoolName(); if (StringUtils.isBlank(threadPoolName)) { logger.warn("threadPoolName is null"); return; } THREAD_POOL_REJECT_MAP.getAndIncrement(threadPoolName); throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + executor.toString()); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/KeyCallable.java ================================================ package com.sohu.cache.async; import java.util.concurrent.Callable; /** * Created by yijunzhang on 14-6-18. */ public abstract class KeyCallable implements Callable { private final String key; private volatile boolean cancelled = false; public KeyCallable(String key) { this.key = key; } public abstract V execute(); @Override public V call() throws Exception { if (!cancelled) { V v = execute(); return v; } return null; } public void cancel() { this.cancelled = true; } public String getKey() { return key; } public boolean isCancelled() { return cancelled; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/KeyFuture.java ================================================ package com.sohu.cache.async; import java.util.concurrent.Future; /** * Created by yijunzhang on 15-1-20. */ public class KeyFuture { private final String key; private final Future future; public KeyFuture(String key, Future future) { this.key = key; this.future = future; } public String getKey() { return key; } public Future getFuture() { return future; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/NamedThreadFactory.java ================================================ package com.sohu.cache.async; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * Created by yijunzhang on 14-6-18. */ public class NamedThreadFactory implements ThreadFactory { private static final AtomicInteger POOL_SEQ = new AtomicInteger(1); private final AtomicInteger mThreadNum = new AtomicInteger(1); private final String mPrefix; private final boolean mDaemo; private final ThreadGroup mGroup; public NamedThreadFactory() { this("pool-" + POOL_SEQ.getAndIncrement(), false); } public NamedThreadFactory(String prefix) { this(prefix, false); } public NamedThreadFactory(String prefix, boolean daemo) { mPrefix = prefix + "-thread-"; mDaemo = daemo; SecurityManager s = System.getSecurityManager(); mGroup = (s == null) ? Thread.currentThread().getThreadGroup() : s.getThreadGroup(); } public Thread newThread(Runnable runnable) { String name = mPrefix + mThreadNum.getAndIncrement(); Thread ret = new Thread(mGroup, runnable, name, 0); ret.setDaemon(mDaemo); return ret; } public ThreadGroup getThreadGroup() { return mGroup; } public String getThreadPoolName() { return mPrefix; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/async/impl/AsyncServiceImpl.java ================================================ package com.sohu.cache.async.impl; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.PreDestroy; import java.util.concurrent.*; /** * Created by yijunzhang on 14-6-18. */ @Service public class AsyncServiceImpl implements AsyncService { private final static String DEFAULT_THREAD_POOL = "default_thread_pool"; public final ConcurrentMap threadPoolMap = new ConcurrentSkipListMap(); private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final ExecutorService defaultThreadPool = AsyncThreadPoolFactory.DEFAULT_ASYNC_THREAD_POOL; public AsyncServiceImpl() { threadPoolMap.put(DEFAULT_THREAD_POOL, defaultThreadPool); } @Override public boolean submitFuture(KeyCallable callable) { return submitFuture(DEFAULT_THREAD_POOL, callable); } @Override public Future submitFutureWithRst(KeyCallable callable) { return submitFuture((Callable)callable); } @Override public boolean submitFuture(String threadPoolKey, KeyCallable callable) { try { ExecutorService executorService = threadPoolMap.get(threadPoolKey); if (executorService == null) { logger.warn("threadPoolKey={} not found , used defaultThreadPool", threadPoolKey); executorService = defaultThreadPool; } Future future = executorService.submit(callable); return true; } catch (Exception e) { logger.error(callable.getKey(), e); return false; } } @Override public Future submitFutureWithRst(String threadPoolKey, KeyCallable callable) { try { ExecutorService executorService = threadPoolMap.get(threadPoolKey); if (executorService == null) { logger.warn("threadPoolKey={} not found , used defaultThreadPool", threadPoolKey); executorService = defaultThreadPool; } Future future = executorService.submit(callable); return future; } catch (Exception e) { logger.error(callable.getKey(), e); return null; } } @Override public Future submitFuture(Callable callable) { try { Future future = defaultThreadPool.submit(callable); return future; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public void assemblePool(String threadPoolKey, ThreadPoolExecutor threadPool) { ExecutorService executorService = threadPoolMap.putIfAbsent(threadPoolKey, threadPool); if (executorService != null) { logger.warn("{} is assembled", threadPoolKey); } } @PreDestroy public void destory() { for (ExecutorService executorService : threadPoolMap.values()) { if (!executorService.isShutdown()) { executorService.shutdown(); } } threadPoolMap.clear(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/AppClientReportConstant.java ================================================ package com.sohu.cache.client; import java.util.Arrays; import java.util.List; /** * Created by rucao on 2019/12/18 */ public class AppClientReportConstant { public final static List ClientReportCommandBlacklist = Arrays.asList("info", "ping"); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/AppClientReportModel.java ================================================ package com.sohu.cache.client; import lombok.Data; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/16 */ @Data public class AppClientReportModel { /** * appId */ private long appId; /** * 客户端版本 */ private String clientVersion; /** * 客户端ip */ private String clientIp; /** * 客户端连接池配置信息 */ private Map config; /** * 上报数据时间 */ private long currentMin; /** * 统计耗时 */ private long cost; /** * 上报异常数据 */ private List> exceptionModels; /** * 上报命令数据 */ private List> commandStatsModels; /** * 其他信息 */ private Map otherInfo; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/command/AppClientCommand.java ================================================ package com.sohu.cache.client.command; import com.google.common.collect.Maps; import com.netflix.hystrix.*; import com.sohu.cache.client.service.ClientVersionService; import com.sohu.cache.constant.ClientStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.ObjectConvert; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; /** * Created by zhangyijun on 2017/8/7. */ public class AppClientCommand extends HystrixCommand> { private final Logger logger = LoggerFactory.getLogger(this.getClass()); public final static int DEFAULT_TIMEOUT = 4000; public final static int DEFAULT_POOL_SIZE = 30; private static final String commandKey = "cacheClient"; private static final String groupKey = "appClientService"; private static final String poolKey = "appClientPool"; private final AppClientParams appClientParams; private final InstanceDao instanceDao; private final AppDao appDao; private final ClientVersionService clientVersionService; private final ConcurrentMap> appClientMap; public AppClientCommand(AppClientParams appClientParams, AppDao appDao, InstanceDao instanceDao, ClientVersionService clientVersionService, ConcurrentMap> appClientMap) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey)) .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey)) .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(poolKey)) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withFallbackIsolationSemaphoreMaxConcurrentRequests(100) .withExecutionTimeoutInMilliseconds(DEFAULT_TIMEOUT)) .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(DEFAULT_POOL_SIZE))); this.appClientParams = appClientParams; this.instanceDao = instanceDao; this.appDao = appDao; this.clientVersionService = clientVersionService; this.appClientMap = appClientMap; } @Override protected Map run() throws Exception { Map model = Maps.newHashMap(); Integer type = appClientParams.getType(); long appId = appClientParams.getAppId(); boolean isCheck = checkRedisApp(model); if (!isCheck) { return model; } if(type == null){ type = appClientParams.getCacheAppDesc().getType(); } if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { model.putAll(getRedisClusterInfo(true)); } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) { model.putAll(getRedisSentinelInfo(true)); } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { model.putAll(getRedisStandaloneInfo(true)); } model.put("type", type); //每次数据库操作成功,更新缓存 addAppClient(appId, model); return model; } public void addAppClient(long appId, Map model) { int status = MapUtils.getIntValue(model, "status", ClientStatusEnum.ERROR.getStatus()); if (status != ClientStatusEnum.ERROR.getStatus()) { appClientMap.put(appId, model); } } @Override protected Map getFallback() { //抛出异常 if (this.isFailedExecution()) { Throwable throwable = this.getFailedExecutionException(); logger.error(throwable.getMessage(), throwable); } //判断是否为调用超时 if (this.isResponseTimedOut()) { long time = this.getExecutionTimeInMilliseconds(); logger.warn("commandKey={} groupKey={} poolKey={} timeout cost={} ms", commandKey, groupKey, poolKey, time); } Map model = appClientMap.get(appClientParams.getAppId()); int status = MapUtils.getIntValue(model, "status", ClientStatusEnum.ERROR.getStatus()); if (status == ClientStatusEnum.ERROR.getStatus()) { logger.error("app-fallback-error: appId={} ,clientIp={},stat={}", appClientParams.getAppId(), appClientParams.getAppClientIp(), model); } return model; } private boolean checkRedisApp(Map model) { long appId = appClientParams.getAppId(); Integer type = appClientParams.getType(); AppDesc appDesc = appDao.getAppDescById(appId); if (type == null && appDesc != null) { if (appDesc.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { type = appDesc.getType(); } } if (appDesc == null) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", String.format("appId:%s 不存在", appId)); return false; } else if (type == null || appDesc.getType() != type) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", String.format("appId:%s 类型不符,期望类型:%s,实际类型%s,请联系管理员!", appId, type, appDesc.getType())); return false; } appClientParams.setCacheAppDesc(appDesc); return true; } public Map getRedisStandaloneInfo(boolean clientRequest) { long appId = appClientParams.getAppId(); Map model = Maps.newHashMap(); boolean isPass = beforeProcess(clientRequest, model); if (!isPass) { return model; } List instanceList = appClientParams.getCacheInstanceInfos(); if (CollectionUtils.isEmpty(instanceList)) { instanceList = instanceDao.getInstListByAppId(appId); } String shardsInfo = ObjectConvert.assembleInstance(instanceList); if (StringUtils.isBlank(shardsInfo)) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", "ERROR: appId:" + appId + "shardsInfo为空 "); return model; } String standalone = null; for (InstanceInfo instanceInfo : instanceList) { if (instanceInfo.isOffline()) { continue; } standalone = instanceInfo.getIp() + ":" + instanceInfo.getPort(); } model.put("standalone", standalone); model.put("status", ClientStatusEnum.GOOD.getStatus()); return model; } public Map getRedisSentinelInfo(boolean clientRequest) { Map model = Maps.newHashMap(); boolean isPass = beforeProcess(clientRequest, model); if (!isPass) { return model; } long appId = appClientParams.getAppId(); List instanceList = appClientParams.getCacheInstanceInfos(); if (CollectionUtils.isEmpty(instanceList)) { instanceList = instanceDao.getInstListByAppId(appId); } if (instanceList == null || instanceList.isEmpty()) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", "appId: " + appId + " 实例集合为空 "); return model; } String shardsInfo = ObjectConvert.assembleInstance(instanceList); if (StringUtils.isBlank(shardsInfo)) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", "ERROR: appId:" + appId + "shardsInfo为空 "); return model; } String masterName = null; List sentinelList = new ArrayList(); for (InstanceInfo instance : instanceList) { if (instance.isOffline()) { continue; } if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL && masterName == null && StringUtils.isNotBlank(instance.getCmd())) { masterName = instance.getCmd(); } if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { sentinelList.add(instance.getIp() + ":" + instance.getPort()); } } String sentinels = StringUtils.join(sentinelList, " "); model.put("sentinels", sentinels); model.put("masterName", masterName); model.put("appId", appId); model.put("status", ClientStatusEnum.GOOD.getStatus()); return model; } public Map getRedisClusterInfo(boolean clientRequest) { long appId = appClientParams.getAppId(); Map model = Maps.newHashMap(); boolean isPass = beforeProcess(clientRequest, model); if (!isPass) { return model; } List instanceList = appClientParams.getCacheInstanceInfos(); if (CollectionUtils.isEmpty(instanceList)) { instanceList = instanceDao.getInstListByAppId(appId); } if (instanceList == null || instanceList.isEmpty()) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", "ERROR: appId:" + appId + "实例集合为空 "); return model; } String shardsInfo = ObjectConvert.assembleInstance(instanceList); if (StringUtils.isBlank(shardsInfo)) { model.put("status", ClientStatusEnum.ERROR.getStatus()); model.put("message", "ERROR: appId:" + appId + "shardsInfo为空 "); return model; } int shardNum = shardsInfo.split(" ").length; model.put("appId", appId); model.put("shardNum", shardNum); model.put("shardInfo", shardsInfo); model.put("status", ClientStatusEnum.GOOD.getStatus()); return model; } private boolean beforeProcess(boolean clientRequest, Map model) { long appId = appClientParams.getAppId(); String clientVersion = appClientParams.getClientVersion(); if (StringUtils.isBlank(clientVersion)) { clientVersion = appClientParams.getCacheMaxVersion(); if (StringUtils.isBlank(clientVersion)) { clientVersion = clientVersionService.getAppMaxClientVersion(appClientParams.getAppId()); } if (StringUtils.isBlank(clientVersion)) { clientVersion = "1.7-SNAPSHOT"; } } addPkey(clientVersion, model); if (clientRequest) { //保存版本信息 try { String appClientIp = appClientParams.getAppClientIp(); clientVersionService.saveOrUpdateClientVersion(appId, appClientIp, clientVersion); } catch (Exception e) { logger.error("redis heart error:" + e.getMessage(), e); } } return true; } // 处理pkey private void addPkey(String clientVersion, Map model) { Double partVersion = NumberUtils.toDouble(clientVersion.substring(0, 3), 1.7); if (partVersion >= 1.7) { AppDesc appDesc = appClientParams.getCacheAppDesc(); if (appDesc == null) { appDesc = appDao.getAppDescById(appClientParams.getAppId()); } String pkey = appDesc.getPkey(); if (StringUtils.isNotBlank(pkey)) { model.put("pkey", pkey); } else { model.put("pkey", ""); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/command/AppClientParams.java ================================================ package com.sohu.cache.client.command; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import java.util.List; /** * Created by zhangyijun on 2017/8/7. */ public class AppClientParams { private final long appId; // 调用级别cache,加速初始化. private AppDesc cacheAppDesc; private List cacheInstanceInfos; private String cacheMaxVersion; private final Integer type; private final String appClientIp; private final String clientVersion; public AppClientParams(long appId, Integer type, String appClientIp, String clientVersion) { this.appId = appId; this.type = type; this.appClientIp = appClientIp; this.clientVersion = clientVersion; } public long getAppId() { return appId; } public Integer getType() { return type; } public String getAppClientIp() { return appClientIp; } public String getClientVersion() { return clientVersion; } public AppDesc getCacheAppDesc() { return cacheAppDesc; } public void setCacheAppDesc(AppDesc cacheAppDesc) { this.cacheAppDesc = cacheAppDesc; } public List getCacheInstanceInfos() { return cacheInstanceInfos; } public void setCacheInstanceInfos(List cacheInstanceInfos) { this.cacheInstanceInfos = cacheInstanceInfos; } public String getCacheMaxVersion() { return cacheMaxVersion; } public void setCacheMaxVersion(String cacheMaxVersion) { this.cacheMaxVersion = cacheMaxVersion; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/heartbeat/RedisClientController.java ================================================ package com.sohu.cache.client.heartbeat; import com.sohu.cache.client.command.AppClientParams; import com.sohu.cache.client.service.AppClientService; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.util.IpUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.Map; /** * Created by zhangyijun on 2017/8/7. */ @RestController @RequestMapping(value = "/cache/client") public class RedisClientController { @Autowired private AppClientService appClientService; /** * 通过appId返回RedisCluster实例信息 * * @param appId */ @RequestMapping(value = "/redis/cluster/{appId}.json", method = RequestMethod.GET) public Map getClusterByAppIdAndKey(HttpServletRequest request, @PathVariable long appId) { AppClientParams clientParams = wrapClientParams(request, appId, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); return appClientService.getAppClientInfo(clientParams); } /** * 通过appId返回RedisSentinel实例信息 * * @param appId */ @RequestMapping(value = "/redis/sentinel/{appId}.json") public Map getSentinelAppById(HttpServletRequest request, @PathVariable long appId, Model model) { AppClientParams clientParams = wrapClientParams(request, appId, ConstUtils.CACHE_REDIS_SENTINEL); return appClientService.getAppClientInfo(clientParams); } /** * 通过appId返回RedisStandalone实例信息 * * @param appId */ @RequestMapping(value = "/redis/standalone/{appId}.json") public Map getStandaloneAppById(HttpServletRequest request, @PathVariable long appId, Model model) { AppClientParams clientParams = wrapClientParams(request, appId, ConstUtils.CACHE_REDIS_STANDALONE); return appClientService.getAppClientInfo(clientParams); } private AppClientParams wrapClientParams(HttpServletRequest request, long appId, int type) { String appClientIp = IpUtil.getIpAddr(request); String clientVersion = request.getParameter("clientVersion"); return new AppClientParams(appId, type, appClientIp, clientVersion); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/heartbeat/RedisClientOldController.java ================================================ package com.sohu.cache.client.heartbeat; import com.google.common.collect.Lists; import com.sohu.cache.client.service.ClientVersionService; import com.sohu.cache.constant.ClientStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.ObjectConvert; import com.sohu.cache.web.util.IpUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; /** * redis 客户端连接类 */ @Controller @RequestMapping(value = "/cache/client") public class RedisClientOldController { private final Logger logger = LoggerFactory.getLogger(RedisClientOldController.class); @Resource private AppDao appDao; @Resource private InstanceDao instanceDao; @Resource(name = "clientVersionService") private ClientVersionService clientVersionService; /** * 通过appId返回RedisCluster实例信息 * * @param appId */ @RequestMapping(value = "/redis/cluster/old/{appId}.json") public void getClusterByAppIdAndKey(HttpServletRequest request, @PathVariable long appId, Model model) { if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, false)) { return; } getRedisClusterInfo(request, appId, model); } private void getRedisClusterInfo(HttpServletRequest request, long appId, Model model) { String clientVersion = request.getParameter("clientVersion"); List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", "ERROR: appId:" + appId + "实例集合为空 "); return; } String shardsInfo = ObjectConvert.assembleInstance(instanceList); if (StringUtils.isBlank(shardsInfo)) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", "ERROR: appId:" + appId + "shardsInfo为空 "); return; } int shardNum = shardsInfo.split(" ").length; model.addAttribute("appId", appId); model.addAttribute("shardNum", shardNum); model.addAttribute("shardInfo", shardsInfo); addPkey(clientVersion, appId, model); //保存版本信息 try { clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion); } catch (Exception e) { logger.error("redisCluster heart error:" + e.getMessage(), e); } } private void addPkey(String clientVersion, long appId, Model model) { if (clientVersion.startsWith("1.7")) { AppDesc appDesc = appDao.getAppDescById(appId); String pkey = appDesc.getPkey(); if (StringUtils.isNotBlank(pkey)) { model.addAttribute("pkey", pkey); } else { model.addAttribute("pkey", ""); } } } /** * 通过appId返回RedisSentinel实例信息 * * @param appId */ @RequestMapping(value = "/redis/sentinel/old/{appId}.json") public void getSentinelAppById(HttpServletRequest request, @PathVariable long appId, Model model) { if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_SENTINEL, false)) { return; } getRedisSentinelInfo(request, appId, model); } private void getRedisSentinelInfo(HttpServletRequest request, long appId, Model model) { String clientVersion = request.getParameter("clientVersion"); List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", "appId: " + appId + " 实例集合为空 "); return; } String masterName = null; List sentinelList = new ArrayList(); for (InstanceInfo instance : instanceList) { if (instance.isOffline()) { continue; } if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL && masterName == null && StringUtils.isNotBlank(instance.getCmd())) { masterName = instance.getCmd(); } if (instance.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { sentinelList.add(instance.getIp() + ":" + instance.getPort()); } } String sentinels = StringUtils.join(sentinelList, " "); model.addAttribute("sentinels", sentinels); model.addAttribute("masterName", masterName); model.addAttribute("appId", appId); model.addAttribute("status", ClientStatusEnum.GOOD.getStatus()); addPkey(clientVersion, appId, model); //保存版本信息 try { clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion); } catch (Exception e) { logger.error("redisSentinel heart error:" + e.getMessage(), e); } } /** * 通过appId返回RedisStandalone实例信息 * * @param appId */ @RequestMapping(value = "/redis/standalone/old/{appId}.json") public void getStandaloneAppById(HttpServletRequest request, @PathVariable long appId, Model model) { if (!handleRedisApp(appId, request, model, ConstUtils.CACHE_REDIS_STANDALONE, false)) { return; } getRedisStandaloneInfo(request, appId, model); } private void getRedisStandaloneInfo(HttpServletRequest request, long appId, Model model) { String clientVersion = request.getParameter("clientVersion"); List instanceList = instanceDao.getInstListByAppId(appId); String standalone = null; for (InstanceInfo instanceInfo : instanceList) { if (instanceInfo.isOffline()) { continue; } standalone = instanceInfo.getIp() + ":" + instanceInfo.getPort(); } model.addAttribute("standalone", standalone); model.addAttribute("status", ClientStatusEnum.GOOD.getStatus()); addPkey(clientVersion, appId, model); //保存版本信息 try { clientVersionService.saveOrUpdateClientVersion(appId, IpUtil.getIpAddr(request), clientVersion); } catch (Exception e) { logger.error("redisStandalone heart error:" + e.getMessage(), e); } } /** * 检查客户端相关参数 * * @param appId 应用id * @param request * @param model * @param type 应用类型 * @param isCheckAppKey 是否检测appKey * @return */ private boolean handleRedisApp(long appId, HttpServletRequest request, Model model, int type, boolean isCheckAppKey) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", String.format("appId:%s 不存在", appId)); return false; } else if (appDesc.getType() != type) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", String.format("appId:%s 类型不符,期望类型:%s,实际类型%s,请联系管理员!", appId, type, appDesc.getType())); return false; } else if (isCheckAppKey) { String appKey = request.getParameter("appKey"); if (StringUtils.isBlank(appKey)) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", String.format("appId=%s,appKey参数为空", appId)); return false; } if (!appKey.equals(appDesc.getAppKey())) { model.addAttribute("status", ClientStatusEnum.ERROR.getStatus()); model.addAttribute("message", String.format("appId=%s,appKey:%s错误,与服务端不匹配", appId, appKey)); return false; } } return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/heartbeat/RedisClientReportDataController.java ================================================ package com.sohu.cache.client.heartbeat; import com.google.common.collect.Lists; import com.sohu.cache.client.AppClientReportModel; import com.sohu.cache.client.service.DealClientReportService; import com.sohu.cache.constant.ClientStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.JsonUtil; import com.sohu.cache.util.StringUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.regex.Pattern; /** * cachecloud客户端上报数据接口 * * @author leifu * @Date 2015年1月16日 * @Time 下午2:10:25 */ @Controller @RequestMapping(value = "/cachecloud/client") public class RedisClientReportDataController { private final Logger logger = LoggerFactory.getLogger(RedisClientReportDataController.class); @Autowired private DealClientReportService dealClientReportService; /** * 上报客户端上传数据 * * @param * @param model */ @RequestMapping(value = "/reportData.json", method = RequestMethod.POST) public void reportData(HttpServletRequest request, HttpServletResponse response, Model model) { return; } @RequestMapping(value = "/v1/reportData/exception", method = RequestMethod.POST) public ResponseEntity reportExceptionData(@RequestParam("clientVersion") String clientVersion, @RequestParam("stats") String json) { return dealAppClientReportData(clientVersion, json); } @RequestMapping(value = "/v1/reportData/command", method = RequestMethod.POST) public ResponseEntity reportCommandData(@RequestParam("clientVersion") String clientVersion, @RequestParam("stats") String json) { return dealAppClientReportData(clientVersion, json); } /** * 统一统一上报数据 * * @param clientVersion * @param json * @return */ private ResponseEntity dealAppClientReportData(String clientVersion, String json) { HttpStatus status = HttpStatus.CREATED; // 验证json的正确性 AppClientReportModel appClientReportModel = checkAppClientReportJson(json); if (appClientReportModel == null) { logger.error("reportWrong message: {}", json); status = HttpStatus.BAD_REQUEST; return ResponseEntity.status(status).body("reportWrong message"); } else if (clientIpFilter(appClientReportModel.getClientIp())) { logger.debug("discard report data, clientIp:{}", appClientReportModel.getClientIp()); return ResponseEntity.status(status).body("success"); } // 处理数据 boolean result = dealClientReportService.deal(appClientReportModel); if (!result) { logger.error("appClientReportCommandService deal fail, appClientReportModel is {}", appClientReportModel); status = HttpStatus.INTERNAL_SERVER_ERROR; return ResponseEntity.status(status).body("message deal fail"); } return ResponseEntity.status(status).body("success"); } private boolean clientIpFilter(String clientIp) { if (StringUtil.isBlank(clientIp)) { return true; } //todo 可自行实现客户端ip过滤逻辑 return false; } /** * 检验json正确性,返回AppClientReportModel * * @param json * @return */ private AppClientReportModel checkAppClientReportJson(String json) { if (StringUtils.isNotBlank(json)) { try { return JsonUtil.fromJson(json, AppClientReportModel.class); } catch (Exception e) { logger.error(e.getMessage(), e); } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/AppClientReportCommandService.java ================================================ package com.sohu.cache.client.service; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/16 */ public interface AppClientReportCommandService { /** * @param clientIp * @param currentMin * @param commandStatsModels */ void batchSave(long appId, String clientIp, long currentMin, List> commandStatsModels); /** * 获取一段时间内某个应用执行的命令列表 * * @param appId * @param startTime * @param endTime * @return */ List getAppDistinctCommand(Long appId, long startTime, long endTime); /** * 获取某个应用一段时间内某个命令的单个客户端统计信息, key-clientIp * * @param appId * @param command * @param startTime * @param endTime * @return */ Map>> getAppCommandClientStatistics(Long appId, String command, long startTime, long endTime, String clientIp); /** * 锁定命令,查看某个命令被哪些client调用, key-command * * @param appId * @param command * @param startTime * @param endTime * @return */ List> getAppClientStatisticsByCommand(Long appId, String command, long startTime, long endTime); /** * 取一段时间内某个应用的客户端ip列表 * * @param appId * @param startTime * @param endTime * @return */ List getAppDistinctClients(Long appId, long startTime, long endTime); /** * @param appId * @param startTime * @param endTime * @param command * @return */ List> getSumCmdStatByCmd(Long appId, long startTime, long endTime, String command); List> getSumCmdStatByClient(Long appId, long startTime, long endTime, String clientIp); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/AppClientReportExceptionService.java ================================================ package com.sohu.cache.client.service; import java.util.List; import java.util.Map; import java.util.Set; /** * Created by rucao on 2019/12/13 */ public interface AppClientReportExceptionService { /** * 处理上报数据 * * @param exceptionModels * @return */ void batchSave(long appId, String clientIp, String redisPoolConfig, long currentMin, List> exceptionModels); /** * 获取某个应用一段时间内的异常信息列表 * * @param appId * @param startTime * @param endTime * @param type * @return */ Map>> getAppExceptionStatisticsMap(Long appId, String clientIp, long startTime, long endTime, Integer type); /** * client_ip, node, sum(count) sum_count, sum(cost) sum_cost * * @param appId * @param startTime * @param endTime * @return */ List> getDistinctClientNodeStatistics(Long appId, String clientIp, long startTime, long endTime, Integer type); /** * client-redisPoolConfig 列表 * * @param appId * @param type * @param startTime * @param endTime * @return */ Map getAppDistinctClientConfig(Long appId, Integer type, long startTime, long endTime); Map> getAppClientConfigs(Long appId, Integer type, long startTime, long endTime); /** * @param clientIp * @param node * @param startTime * @param endTime * @return */ List> getLatencyCommandDetailByNode(String clientIp, String node, long startTime, long endTime); List> getLatencyCommandDetailByNodeV2(String node, long searchTime); /** * @param appId * @param searchTime * @return */ Map> getSumCmdExpStatGroupByNode(long appId, long searchTime); /** * @param nodeSet * @param searchTime * @return */ Map>> getLatencyCommandDetails(Set nodeSet, long searchTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/AppClientService.java ================================================ package com.sohu.cache.client.service; import com.sohu.cache.client.command.AppClientParams; import java.util.Map; /** * 应用级别客户端查询服务 * Created by zhangyijun on 2017/8/4. */ public interface AppClientService { /** * 根据appId查询客户端信息 * * @param appClientParams * @return */ Map getAppClientInfo(AppClientParams appClientParams); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/AppClientStatisticGatherService.java ================================================ package com.sohu.cache.client.service; /** * Created by rucao on 2019/12/29 */ public interface AppClientStatisticGatherService { void bathSave(long startTime, long endTime); void bathAdd(long startTime, long endTime); void bathAddServerCmdCount(long startTime, long endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/AppInstanceClientRelationService.java ================================================ package com.sohu.cache.client.service; import java.util.Date; import java.util.List; import com.sohu.cache.entity.AppClientCostTimeStat; import com.sohu.cache.entity.AppInstanceClientRelation; /** * 应用下节点和客户端关系服务 * * @author leifu * @Date 2016年5月3日 * @Time 下午6:48:40 */ public interface AppInstanceClientRelationService { void batchSave(List appClientCostTimeStatList); List getAppInstanceClientRelationList(Long appId, Date date); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/ClientReportExceptionService.java ================================================ package com.sohu.cache.client.service; import com.sohu.cache.entity.AppClientExceptionStat; import com.sohu.cache.entity.ClientInstanceException; import com.sohu.cache.web.util.Page; import java.util.List; /** * 客户端上报异常记录 * @author leifu * @Date 2015年1月19日 * @Time 上午10:02:32 */ public interface ClientReportExceptionService { /** * 获取客户端异常列表 * @param appId 应用id * @param startTime 开始收集时间 * @param endTime 结束收集时间 * @param type 异常类型(ClientExceptionType) * @param clientIp 客户端ip * @return */ List getAppExceptionList(Long appId, long startTime, long endTime, int type, String clientIp, Page page); /** * 获取客户端异常个数 * @param appId 应用id * @param startTime 开始收集时间 * @param endTime 结束收集时间 * @param type 异常类型(ClientExceptionType) * @param clientIp 客户端ip * @return */ int getAppExceptionCount(Long appId, long startTime, long endTime, int type, String clientIp); /** * 大于collectTime期间各个实例的异常统计 * @param ip * @param collectTime * @return */ List getInstanceExceptionStat(String ip, long collectTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/ClientReportInstanceService.java ================================================ package com.sohu.cache.client.service; import com.sohu.cache.entity.InstanceInfo; /** * * @author leifu * @Date 2015年1月19日 * @Time 上午10:02:28 */ public interface ClientReportInstanceService { /** * 根据host:port获取instance信息(缓存,不要求一致性) * @param host * @param port * @return */ InstanceInfo getInstanceInfoByHostPort(String host, int port); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/ClientVersionService.java ================================================ package com.sohu.cache.client.service; import com.sohu.cache.entity.AppClientVersion; import java.util.List; import java.util.Map; /** * 客户端版本信息 * * @author leifu * @Date 2015年2月2日 * @Time 上午10:19:59 */ public interface ClientVersionService { /** * 保存客户端版本信息 * * @param appId * @param appClientIp * @param clientVersion */ void saveOrUpdateClientVersion(long appId, String appClientIp, String clientVersion); /** * 获取应用的所有客户端版本信息 * * @param appId * @return */ List getAppAllClientVersion(long appId); /** * 获取应用客户端最大版本 * * @param appId * @return */ public String getAppMaxClientVersion(long appId); /** * 获取应用所有客户端最大版本 * * @return */ public List> getAllMaxClientVersion(); /** * 获取所有客户端版本 * * @return */ List getAll(long appId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/DealClientReportService.java ================================================ package com.sohu.cache.client.service; import com.sohu.cache.client.AppClientReportModel; /** * Created by rucao on 2019/12/13 */ public interface DealClientReportService { void init(); /** * 处理上报数据 * * @param * @return */ boolean deal(AppClientReportModel appClientReportModel); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/AppClientReportCommandServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.google.common.collect.Maps; import com.sohu.cache.client.service.AppClientReportCommandService; import com.sohu.cache.dao.AppClientCommandStatisticsDao; import com.sohu.cache.entity.AppClientCommandStatistics; import com.sohu.cache.report.ReportDataComponent; import com.sohu.cache.util.MapUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.assertj.core.util.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * Created by rucao on 2019/12/16 */ @Service @Slf4j public class AppClientReportCommandServiceImpl implements AppClientReportCommandService { @Autowired private AppClientCommandStatisticsDao appClientCommandStatisticsDao; @Autowired private ReportDataComponent reportDataComponent; @Override public void batchSave(long appId, String clientIp, long currentMin, List> commandStatsModels) { try { // 1.client上报 if (CollectionUtils.isEmpty(commandStatsModels)) { log.warn("commandStatsModels is empty:{},{}", clientIp, currentMin); return; } // 2.解析 List appClientCommandStatisticsList = commandStatsModels.stream() .filter(appClientCommandStatistics -> generate(appId, clientIp, currentMin, appClientCommandStatistics) != null) .map(appClientCommandStatistics -> generate(appId, clientIp, currentMin, appClientCommandStatistics)) .collect(Collectors.toList()); // 4.批量保存 if (CollectionUtils.isNotEmpty(appClientCommandStatisticsList)) { appClientCommandStatisticsDao.batchSave(appClientCommandStatisticsList); //上报数据 reportDataComponent.reportCommandData(appClientCommandStatisticsList); } } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public List getAppDistinctCommand(Long appId, long startTime, long endTime) { try { return appClientCommandStatisticsDao.getAppDistinctCommand(appId, startTime, endTime); } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public Map>> getAppCommandClientStatistics(Long appId, String command, long startTime, long endTime, String clientIp) { try { List> appClientCommandStatisticsList = appClientCommandStatisticsDao.getAppCommandStatistics(appId, startTime, endTime, command, clientIp); Map>> commandStatisticsMap = Maps.newHashMap(); appClientCommandStatisticsList.stream().forEach(commandStatistic -> { String client_ip = MapUtils.getString(commandStatistic, "client_ip"); ArrayList commandStatisticList = (ArrayList) MapUtils.getObject(commandStatisticsMap, client_ip); if (CollectionUtils.isEmpty(commandStatisticList)) { commandStatisticList = Lists.newArrayList(); commandStatisticsMap.put(client_ip, commandStatisticList); } commandStatisticList.add(commandStatistic); }); return commandStatisticsMap; } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public List> getAppClientStatisticsByCommand(Long appId, String command, long startTime, long endTime) { try { List> getAppClientStatisticsByCommand = appClientCommandStatisticsDao.getAppCommandStatistics(appId, startTime, endTime, command, null); return getAppClientStatisticsByCommand; } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getAppDistinctClients(Long appId, long startTime, long endTime) { try { return appClientCommandStatisticsDao.getAppDistinctClients(appId, startTime, endTime); } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List> getSumCmdStatByCmd(Long appId, long startTime, long endTime, String command) { try { return appClientCommandStatisticsDao.getSumCmdStatByCmd(appId, startTime, endTime, command); } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List> getSumCmdStatByClient(Long appId, long startTime, long endTime, String clientIp) { try { return appClientCommandStatisticsDao.getSumCmdStatByClient(appId, startTime, endTime, clientIp); } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } private AppClientCommandStatistics generate(long appId, String clientIp, long currentMin, Map commandStatsModel) { try { AppClientCommandStatistics appClientCommandStatistics = (AppClientCommandStatistics) MapUtil.mapToObject(commandStatsModel, AppClientCommandStatistics.class); if (appClientCommandStatistics != null) { appClientCommandStatistics.setAppId(appId); appClientCommandStatistics.setClientIp(clientIp); appClientCommandStatistics.setCurrentMin(currentMin); } return appClientCommandStatistics; } catch (Exception e) { log.error("generate appClientCommandStatistics error {}, {}", e.getMessage(), e); return null; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/AppClientReportExceptionServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.google.common.collect.Maps; import com.sohu.cache.client.service.AppClientReportExceptionService; import com.sohu.cache.dao.AppClientExceptionStatisticsDao; import com.sohu.cache.dao.AppClientLatencyCommandDao; import com.sohu.cache.entity.AppClientExceptionStatistics; import com.sohu.cache.entity.AppClientLatencyCommand; import com.sohu.cache.report.ReportDataComponent; import com.sohu.cache.util.MapUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.assertj.core.util.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; /** * Created by rucao on 2019/12/13 */ @Slf4j @Service("appClientReportExceptionService") public class AppClientReportExceptionServiceImpl implements AppClientReportExceptionService { private static int ARGS_MAX_LEN = 255; @Autowired private AppClientExceptionStatisticsDao appClientExceptionStatisticsDao; @Autowired private AppClientLatencyCommandDao appClientLatencyCommandDao; @Autowired private ReportDataComponent reportDataComponent; @Override public void batchSave(long appId, String clientIp, String redisPoolConfig, long currentMin, List> exceptionModels) { try { // 1.client上报 if (CollectionUtils.isEmpty(exceptionModels)) { log.warn("exceptionModels is empty:{},{}", clientIp, currentMin); return; } // 2.解析 List appClientExceptionStatisticsList = exceptionModels.stream() .map(exceptionModel -> generate(appId, clientIp, redisPoolConfig, currentMin, exceptionModel)) .filter(exceptionStatistics -> (exceptionStatistics != null)) .collect(Collectors.toList()); // 4.批量保存 if (CollectionUtils.isNotEmpty(appClientExceptionStatisticsList)) { appClientExceptionStatisticsDao.batchSave(appClientExceptionStatisticsList); //上报数据 reportDataComponent.reportExceptionData(appClientExceptionStatisticsList); } } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public Map>> getAppExceptionStatisticsMap(Long appId, String clientIp, long startTime, long endTime, Integer type) { try { List> appClientExceptionStatisticsList = appClientExceptionStatisticsDao.getAppExceptionStatistics(appId, clientIp, startTime, endTime, type); Map>> exceptionStatisticsMap = Maps.newHashMap(); appClientExceptionStatisticsList.stream().forEach(exceptionStatistic -> { String client_ip = MapUtils.getString(exceptionStatistic, "client_ip"); ArrayList commandStatisticList = (ArrayList) MapUtils.getObject(exceptionStatisticsMap, client_ip); if (CollectionUtils.isEmpty(commandStatisticList)) { commandStatisticList = Lists.newArrayList(); exceptionStatisticsMap.put(client_ip, commandStatisticList); } commandStatisticList.add(exceptionStatistic); }); return exceptionStatisticsMap; } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.emptyMap(); } @Override public List> getDistinctClientNodeStatistics(Long appId, String clientIp, long startTime, long endTime, Integer type) { try { return appClientExceptionStatisticsDao.getDistinctClientNodeStatistics(appId, clientIp, startTime, endTime, type); } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.EMPTY_LIST; } @Override public Map getAppDistinctClientConfig(Long appId, Integer type, long startTime, long endTime) { try { List> clientConfigList = appClientExceptionStatisticsDao.getAppDistinctClientConfig(appId, type, startTime, endTime); Map clientConfigMap = clientConfigList.stream().collect(Collectors.toMap (clientConfig -> MapUtils.getString(clientConfig, "client_ip"), clientConfig -> MapUtils.getString(clientConfig, "redis_pool_config"), (key1, key2) -> key2)); return clientConfigMap; } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public Map> getAppClientConfigs(Long appId, Integer type, long startTime, long endTime) { try { List> clientConfigList = appClientExceptionStatisticsDao.getAppClientConfigs(appId, type, startTime, endTime); Map> clientConfigMap = Maps.newHashMap(); clientConfigList.stream().forEach(clientConfig -> { String client_ip = MapUtils.getString(clientConfig, "client_ip"); String redis_pool_config = MapUtils.getString(clientConfig, "redis_pool_config"); String change_time = MapUtils.getString(clientConfig, "change_time"); String time_config = "变更时间:" + change_time + " 配置:" + redis_pool_config; List configTimeList; if (clientConfigMap.containsKey(client_ip)) { configTimeList = clientConfigMap.get(client_ip); } else { configTimeList = Lists.newArrayList(); clientConfigMap.put(client_ip, configTimeList); } configTimeList.add(time_config); } ); return clientConfigMap; } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public List> getLatencyCommandDetailByNode(String clientIp, String node, long startTime, long endTime) { try { List latencyCommandIdsList = appClientExceptionStatisticsDao.getLatencyCommandsByNode(clientIp, startTime, endTime, node); String latencyCommandIdsStr = StringUtils.join(latencyCommandIdsList, ","); List ids = Arrays.stream(latencyCommandIdsStr.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); return appClientLatencyCommandDao.getLatencyCommandByIds(ids); } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.EMPTY_LIST; } @Override public List> getLatencyCommandDetailByNodeV2(String node, long searchTime) { try { List latencyCommandIdsList = appClientExceptionStatisticsDao.getLatencyCommandsByNodeV2(node, searchTime); String latencyCommandIdsStr = StringUtils.join(latencyCommandIdsList, ","); List ids = Arrays.stream(latencyCommandIdsStr.split(",")).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); List> latencyCommandList = appClientLatencyCommandDao.getLatencyCommandByIds(ids); return latencyCommandList; } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.EMPTY_LIST; } @Override public Map> getSumCmdExpStatGroupByNode(long appId, long searchTime) { try { List> sumCmdExpStatList = appClientExceptionStatisticsDao.getSumCmdExpStatGroupByNode(appId, searchTime); return sumCmdExpStatList.stream().collect(Collectors.toMap(sumCmdExpStat -> MapUtils.getString(sumCmdExpStat, "node", ""), sumCmdExpStat -> sumCmdExpStat, (key1, key2) -> key2)); } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.EMPTY_MAP; } @Override public Map>> getLatencyCommandDetails(Set nodeSet, long searchTime) { try { return nodeSet.stream().collect(Collectors.toMap(node -> node, node -> getLatencyCommandDetailByNodeV2(node, searchTime))); } catch (Exception e) { log.error(e.getMessage(), e); } return Collections.EMPTY_MAP; } private AppClientExceptionStatistics generate(long appId, String clientIp, String redisPoolConfig, long currentMin, Map exceptionModel) { try { AppClientExceptionStatistics appClientExceptionStatistics = (AppClientExceptionStatistics) MapUtil.mapToObject(exceptionModel, AppClientExceptionStatistics.class); if (appClientExceptionStatistics != null) { appClientExceptionStatistics.setAppId(appId); appClientExceptionStatistics.setClientIp(clientIp); appClientExceptionStatistics.setRedisPoolConfig(redisPoolConfig); appClientExceptionStatistics.setCurrentMin(currentMin); List> commandFailedModels = (List) exceptionModel.get("commandFailedModels"); if (CollectionUtils.isNotEmpty(commandFailedModels)) { List appClientLatencyCommandList = commandFailedModels.stream() .map(commandFailedModel -> { try { String args = MapUtils.getString(commandFailedModel, "args", ""); if (StringUtils.isNotBlank(args) && args.length() > ARGS_MAX_LEN) { String args_new = args.substring(0, ARGS_MAX_LEN); commandFailedModel.put("args", args_new); } return (AppClientLatencyCommand) MapUtil.mapToObject(commandFailedModel, AppClientLatencyCommand.class); } catch (Exception e) { log.error(e.getMessage(), e); return null; } }) .filter(latencyCommand -> (latencyCommand != null)) .collect(Collectors.toList()); if(CollectionUtils.isNotEmpty(appClientLatencyCommandList)){ appClientLatencyCommandDao.batchSave(appClientLatencyCommandList); String latencyCommands = appClientLatencyCommandList.stream() .map(appClientLatencyCommand -> String.valueOf(appClientLatencyCommand.getId())) .collect(Collectors.joining(",")); appClientExceptionStatistics.setLatencyCommands(latencyCommands); } } } return appClientExceptionStatistics; } catch (Exception e) { log.error("generate appClientCommandStatistics exceptionModel: {}, error {}, {}", exceptionModel, e.getMessage(), e); return null; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/AppClientServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.sohu.cache.client.command.AppClientCommand; import com.sohu.cache.client.command.AppClientParams; import com.sohu.cache.client.service.AppClientService; import com.sohu.cache.client.service.ClientVersionService; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; /** * Created by zhangyijun on 2017/8/4. */ public class AppClientServiceImpl implements AppClientService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private InstanceDao instanceDao; @Autowired private AppDao appDao; @Autowired private ClientVersionService clientVersionService; private ConcurrentMap> appClientMap = Maps.newConcurrentMap(); @PostConstruct public void initApps() { long start = System.currentTimeMillis(); List onlineApps = appDao.getOnlineApps(); if (onlineApps == null) { return; } Map> cacheInstances = Maps.newHashMap(); List allInstances = instanceDao.getAllInsts(); for (InstanceInfo instanceInfo : allInstances) { long appId = instanceInfo.getAppId(); if (instanceInfo.isOnline()) { List instances = cacheInstances.get(appId); if (instances == null) { instances = Lists.newArrayList(); cacheInstances.put(appId, instances); } instances.add(instanceInfo); } } Map cacheMaxVersions = Maps.newHashMap(); List> appMaxVersions = clientVersionService.getAllMaxClientVersion(); for (Map map : appMaxVersions) { long appId = MapUtils.getLongValue(map, "appId"); String clientVersion = MapUtils.getString(map, "clientVersion"); cacheMaxVersions.put(appId, clientVersion); } for (AppDesc appDesc : onlineApps) { int type = appDesc.getType(); long appId = appDesc.getAppId(); AppClientParams appClientParams = new AppClientParams(appId, type, null, null); appClientParams.setCacheAppDesc(appDesc); appClientParams.setCacheInstanceInfos(cacheInstances.get(appId)); appClientParams.setCacheMaxVersion(cacheMaxVersions.get(appId)); AppClientCommand command = new AppClientCommand(appClientParams, appDao, instanceDao, clientVersionService, appClientMap); Map model; if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { model = command.getRedisClusterInfo(false); command.addAppClient(appId, model); } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) { model = command.getRedisSentinelInfo(false); command.addAppClient(appId, model); } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { model = command.getRedisStandaloneInfo(false); command.addAppClient(appId, model); } } long end = System.currentTimeMillis(); logger.warn("AppClientService: app-client-size={} cost={} ms", appClientMap.size(), (end - start)); } @Override public Map getAppClientInfo(AppClientParams appClientParams) { AppClientCommand command = new AppClientCommand(appClientParams, appDao, instanceDao, clientVersionService, appClientMap); return command.execute(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/AppClientStatisticGatherServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.sohu.cache.client.service.AppClientStatisticGatherService; import com.sohu.cache.dao.*; import com.sohu.cache.entity.AppClientStatisticGather; import com.sohu.cache.entity.AppStats; import com.sohu.cache.entity.TimeBetween; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.task.tasks.daily.TopologyExamTask; import com.sohu.cache.web.util.DateUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by rucao on 2019/12/29 */ @Slf4j @Service("appClientStatisticGatherService") public class AppClientStatisticGatherServiceImpl implements AppClientStatisticGatherService { @Autowired private AppClientExceptionStatisticsDao appClientExceptionStatisticsDao; @Autowired private AppClientCommandStatisticsDao appClientCommandStatisticsDao; @Resource private AppStatsDao appStatsDao; @Resource private InstanceSlowLogDao instanceSlowLogDao; @Autowired private InstanceLatencyHistoryDao instanceLatencyHistoryDao; @Autowired private AppClientStatisticGatherDao appClientStatisticGatherDao; @Autowired private AppStatsCenter appStatsCenter; @Autowired TopologyExamTask topologyExamTask; @Override public void bathSave(long startTime, long endTime) { try { List appClientConnExpStatList = appClientExceptionStatisticsDao.getAppClientConnExpStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientConnExpStatList)) { appClientStatisticGatherDao.batchSaveConnExpStats(appClientConnExpStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appClientCmdExpStatList = appClientExceptionStatisticsDao.getAppClientCmdExpStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientCmdExpStatList)) { appClientStatisticGatherDao.batchSaveCmdExpStats(appClientCmdExpStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appClientCmdStatList = appClientCommandStatisticsDao.getAppClientCmdStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientCmdStatList)) { appClientStatisticGatherDao.batchSaveCmdStats(appClientCmdStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } // try { // List appMemFragRatioList = appStatsDao.getMemFragRatios(startTime, endTime); // if (CollectionUtils.isNotEmpty(appMemFragRatioList)) { // appClientStatisticGatherDao.batchSaveMemFragRatio(appMemFragRatioList); // } // } catch (Exception e) { // log.error(e.getMessage(), e); // } try { List appSlowLogCountList = instanceSlowLogDao.getAppSlowLogCountStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appSlowLogCountList)) { appClientStatisticGatherDao.batchSaveSlowLogCount(appSlowLogCountList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appLatencyCountList = instanceLatencyHistoryDao.getAppLatencyCountStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appLatencyCountList)) { appClientStatisticGatherDao.batchSaveLatencyCount(appLatencyCountList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appStatsList = appStatsDao.gatherAppsStats(startTime, endTime); if (CollectionUtils.isNotEmpty(appStatsList)) { appClientStatisticGatherDao.batchSaveAppStats(appStatsList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List connClientList = appStatsCenter.getOnlineAppConnClients(); if (CollectionUtils.isNotEmpty(connClientList)) { appClientStatisticGatherDao.batchSaveConnClients(connClientList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List topologyExamList = topologyExamTask.checkAppsTopology(null); if (CollectionUtils.isNotEmpty(topologyExamList)) { appClientStatisticGatherDao.batchSaveTopologyExam(topologyExamList); } } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public void bathAdd(long startTime, long endTime) { try { List appClientConnExpStatList = appClientExceptionStatisticsDao.getAppClientConnExpStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientConnExpStatList)) { appClientStatisticGatherDao.batchAddConnExpStats(appClientConnExpStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appClientCmdExpStatList = appClientExceptionStatisticsDao.getAppClientCmdExpStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientCmdExpStatList)) { appClientStatisticGatherDao.batchAddCmdExpStats(appClientCmdExpStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appClientCmdStatList = appClientCommandStatisticsDao.getAppClientCmdStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appClientCmdStatList)) { appClientStatisticGatherDao.batchAddCmdStats(appClientCmdStatList); } } catch (Exception e) { log.error(e.getMessage(), e); } // try { // TimeBetween timeBetween = fillWithDateFormat(startTime); // long startTime_new = timeBetween.getStartTime(); // long endTime_new = timeBetween.getEndTime(); // List appMemFragRatioList = appStatsDao.getMemFragRatios(startTime_new, endTime_new); // if (CollectionUtils.isNotEmpty(appMemFragRatioList)) { // appClientStatisticGatherDao.batchSaveMemFragRatio(appMemFragRatioList); // } // } catch (Exception e) { // log.error(e.getMessage(), e); // } try { List appSlowLogCountList = instanceSlowLogDao.getAppSlowLogCountStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appSlowLogCountList)) { appClientStatisticGatherDao.batchAddSlowLogCount(appSlowLogCountList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appLatencyCountList = instanceLatencyHistoryDao.getAppLatencyCountStat(startTime, endTime); if (CollectionUtils.isNotEmpty(appLatencyCountList)) { appClientStatisticGatherDao.batchAddLatencyCount(appLatencyCountList); } } catch (Exception e) { log.error(e.getMessage(), e); } try { List appStatsList = appStatsDao.gatherAppsStats(startTime, endTime); if (CollectionUtils.isNotEmpty(appStatsList)) { appClientStatisticGatherDao.batchSaveAppStats(appStatsList); } } catch (Exception e) { log.error(e.getMessage(), e); } } @Override public void bathAddServerCmdCount(long startTime, long endTime) { //添加server端统计的命令调用次数 //每小时执行一次 try { String gatherTimePre = null; if(startTime == endTime){ gatherTimePre = DateUtil.formatYYYY_MM_dd(DateUtil.parseYYYYMMddHH(String.valueOf(startTime))); } String gatherTime = gatherTimePre; List appStatsList = appStatsDao.getAppHourStatsByTime(startTime, endTime); List gatherList = new ArrayList<>(appStatsList.size()); appStatsList.forEach(appStats -> { AppClientStatisticGather appClientStatisticGather = new AppClientStatisticGather(); appClientStatisticGather.setAppId(appStats.getAppId()); appClientStatisticGather.setServerCmdCount(appStats.getCommandCount()); if(gatherTime != null){ appClientStatisticGather.setGatherTime(gatherTime); } else { try { String gatherTimeOne = DateUtil.formatYYYY_MM_dd(DateUtil.parseYYYYMMddHH(String.valueOf(appStats.getCollectTime()))); appClientStatisticGather.setGatherTime(gatherTimeOne); } catch (Exception e) { log.error(e.getMessage(), e); return; } } gatherList.add(appClientStatisticGather); }); if (CollectionUtils.isNotEmpty(appStatsList)) { appClientStatisticGatherDao.batchAddAppServerCmdCount(gatherList); } } catch (Exception e) { log.error(e.getMessage(), e); } } private TimeBetween fillWithDateFormat(long startTime) throws Exception { String startTimeStr = Long.toString(startTime); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Date date = sdf.parse(startTimeStr); Date startDate_new = DateUtils.addMinutes(date, 5); Date endDate_new = DateUtils.addMinutes(startDate_new, 5); long startTime_new = NumberUtils.toLong(DateUtil.formatDate(startDate_new, "yyyyMMddHHmm00")); long endTime_new = NumberUtils.toLong(DateUtil.formatDate(endDate_new, "yyyyMMddHHmm00")); return new TimeBetween(startTime_new, endTime_new, startDate_new, endDate_new); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/AppInstanceClientRelationServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.client.service.AppInstanceClientRelationService; import com.sohu.cache.dao.AppInstanceClientRelationDao; import com.sohu.cache.entity.AppClientCostTimeStat; import com.sohu.cache.entity.AppInstanceClientRelation; /** * 应用下节点和客户端关系服务 * * @author leifu * @Date 2016年5月3日 * @Time 下午6:48:40 */ public class AppInstanceClientRelationServiceImpl implements AppInstanceClientRelationService { private Logger logger = LoggerFactory.getLogger(AppInstanceClientRelationServiceImpl.class); private AppInstanceClientRelationDao appInstanceClientRelationDao; @Override public void batchSave(List appClientCostTimeStatList) { if (CollectionUtils.isEmpty(appClientCostTimeStatList)) { return; } try { List appInstanceClientRelationList = new ArrayList(); for (AppClientCostTimeStat appClientCostTimeStat : appClientCostTimeStatList) { AppInstanceClientRelation appInstanceClientRelation = AppInstanceClientRelation.generateFromAppClientCostTimeStat(appClientCostTimeStat); if (appInstanceClientRelation != null) { appInstanceClientRelationList.add(appInstanceClientRelation); } } if (CollectionUtils.isNotEmpty(appInstanceClientRelationList)) { appInstanceClientRelationDao.batchSave(appInstanceClientRelationList); } } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override public List getAppInstanceClientRelationList(Long appId, Date date) { try { return appInstanceClientRelationDao.getAppInstanceClientRelationList(appId, date); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public void setAppInstanceClientRelationDao(AppInstanceClientRelationDao appInstanceClientRelationDao) { this.appInstanceClientRelationDao = appInstanceClientRelationDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportExceptionServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.sohu.cache.client.service.ClientReportExceptionService; import com.sohu.cache.client.service.ClientReportInstanceService; import com.sohu.cache.dao.AppClientExceptionStatDao; import com.sohu.cache.dao.AppClientVersionDao; import com.sohu.cache.entity.AppClientExceptionStat; import com.sohu.cache.entity.ClientInstanceException; import com.sohu.cache.web.util.Page; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; /** * 客户端上报异常service * * @author leifu * @Date 2015年1月19日 * @Time 上午10:02:32 */ public class ClientReportExceptionServiceImpl implements ClientReportExceptionService { private final Logger logger = LoggerFactory.getLogger(ClientReportExceptionServiceImpl.class); /** * 客户端异常操作 */ private AppClientExceptionStatDao appClientExceptionStatDao; /** * host:port与instanceInfo简单缓存 */ private ClientReportInstanceService clientReportInstanceService; /** * 客户端ip,版本查询 */ private AppClientVersionDao appClientVersionDao; @Override public List getAppExceptionList(Long appId, long startTime, long endTime, int type, String clientIp, Page page) { try { return appClientExceptionStatDao.getAppExceptionList(appId, startTime, endTime, type, clientIp, page); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public int getAppExceptionCount(Long appId, long startTime, long endTime, int type, String clientIp) { try { return appClientExceptionStatDao.getAppExceptionCount(appId, startTime, endTime, type, clientIp); } catch (Exception e) { logger.error(e.getMessage(), e); return 0; } } @Override public List getInstanceExceptionStat(String ip, long collectTime) { try { return appClientExceptionStatDao.getInstanceExceptionStat(ip, collectTime); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public void setAppClientExceptionStatDao(AppClientExceptionStatDao appClientExceptionStatDao) { this.appClientExceptionStatDao = appClientExceptionStatDao; } public void setAppClientVersionDao(AppClientVersionDao appClientVersionDao) { this.appClientVersionDao = appClientVersionDao; } public void setClientReportInstanceService(ClientReportInstanceService clientReportInstanceService) { this.clientReportInstanceService = clientReportInstanceService; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/ClientReportInstanceServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.client.service.ClientReportInstanceService; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.InstanceInfo; /** * @author leifu * @Date 2016年5月5日 * @Time 上午11:05:35 */ public class ClientReportInstanceServiceImpl implements ClientReportInstanceService { private Logger logger = LoggerFactory.getLogger(ClientReportInstanceServiceImpl.class); /** * 不要求一致性的本地缓存(hostport<=>instanceInfo) */ private final static ConcurrentHashMap hostPortInstanceMap = new ConcurrentHashMap(); private InstanceDao instanceDao; @Override public InstanceInfo getInstanceInfoByHostPort(String host, int port) { String hostPort = host + ":" + port; try { InstanceInfo instanceInfo = hostPortInstanceMap.get(hostPort); if (instanceInfo == null) { instanceInfo = instanceDao.getInstByIpAndPort(host, port); if (instanceInfo != null) { hostPortInstanceMap.putIfAbsent(hostPort, instanceInfo); } } return instanceInfo; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } public void setInstanceDao(InstanceDao instanceDao) { this.instanceDao = instanceDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/ClientVersionServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.sohu.cache.client.service.ClientVersionService; import com.sohu.cache.dao.AppClientVersionDao; import com.sohu.cache.entity.AppClientVersion; import com.sohu.cache.util.StringUtil; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import java.util.*; /** * 客户端版本信息 * * @author leifu * @Date 2015年2月2日 * @Time 上午10:19:59 */ public class ClientVersionServiceImpl implements ClientVersionService { private final Logger logger = LoggerFactory.getLogger(ClientVersionServiceImpl.class); private AppClientVersionDao appClientVersionDao; @Override public void saveOrUpdateClientVersion(long appId, String appClientIp, String clientVersion) { try { AppClientVersion appClientVersion = new AppClientVersion(); appClientVersion.setAppId(appId); appClientVersion.setClientIp(appClientIp); appClientVersion.setClientVersion(clientVersion); appClientVersion.setReportTime(new Date()); appClientVersionDao.saveOrUpdateClientVersion(appClientVersion); } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override public List getAppAllClientVersion(long appId) { try { return appClientVersionDao.getAppAllClientVersion(appId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public String getAppMaxClientVersion(long appId) { try { return appClientVersionDao.getAppMaxClientVersion(appId); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public List> getAllMaxClientVersion() { try { return appClientVersionDao.getAllMaxClientVersion(); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getAll(long appId) { try { return appClientVersionDao.getAll(appId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public void setAppClientVersionDao(AppClientVersionDao appClientVersionDao) { this.appClientVersionDao = appClientVersionDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/client/service/impl/DealClientReportServiceImpl.java ================================================ package com.sohu.cache.client.service.impl; import com.alibaba.fastjson.JSON; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.client.AppClientReportModel; import com.sohu.cache.client.service.AppClientReportCommandService; import com.sohu.cache.client.service.AppClientReportExceptionService; import com.sohu.cache.client.service.DealClientReportService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/13 */ @Slf4j public class DealClientReportServiceImpl implements DealClientReportService { @Autowired private AsyncService asyncService; @Autowired private AppClientReportCommandService appClientReportCommandService; @Autowired private AppClientReportExceptionService appClientReportExceptionService; @Override public void init() { asyncService.assemblePool(getThreadPoolKey(), AsyncThreadPoolFactory.CLIENT_REPORT_THREAD_POOL); } @Override public boolean deal(final AppClientReportModel appClientReportModel) { try { // 上报的数据 final long appId = appClientReportModel.getAppId(); final String clientIp = appClientReportModel.getClientIp(); final String redisPoolConfig = JSON.toJSONString(appClientReportModel.getConfig()); final long currentMin = appClientReportModel.getCurrentMin(); final List> commandStatsModels = appClientReportModel.getCommandStatsModels(); final List> exceptionModels = appClientReportModel.getExceptionModels(); String key = getThreadPoolKey() + "_" + clientIp; asyncService.submitFuture(getThreadPoolKey(), new KeyCallable(key) { @Override public Boolean execute() { try { if (CollectionUtils.isNotEmpty(commandStatsModels)) { appClientReportCommandService.batchSave(appId, clientIp, currentMin, commandStatsModels); } if (CollectionUtils.isNotEmpty(exceptionModels)) { appClientReportExceptionService.batchSave(appId, clientIp, redisPoolConfig, currentMin, exceptionModels); } return true; } catch (Exception e) { log.error(e.getMessage(), e); return false; } } }); return true; } catch (Exception e) { log.error(e.getMessage(), e); return false; } } private String getThreadPoolKey() { return AsyncThreadPoolFactory.CLIENT_REPORT_POOL; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/AppClientReportBean.java ================================================ package com.sohu.cache.configuration; import com.sohu.cache.client.service.DealClientReportService; import com.sohu.cache.client.service.impl.DealClientReportServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by rucao on 2019/12/16 */ @Configuration public class AppClientReportBean { @Bean(initMethod = "init") DealClientReportService dealClientReportService() { return new DealClientReportServiceImpl(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/AsynExecutorConfiguration.java ================================================ package com.sohu.cache.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; /** * @Author: zengyizhao * @DateTime: 2022/10/9 14:52 * @Description: */ @Configuration @EnableAsync public class AsynExecutorConfiguration { /** Set the ThreadPoolExecutor's core pool size. */ private int corePoolSize = 10; /** Set the ThreadPoolExecutor's maximum pool size. */ private int maxPoolSize = 50; /** Set the capacity for the ThreadPoolExecutor's BlockingQueue. */ private int queueCapacity = 500; @Bean public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix("AsyncExecutor-"); // rejection-policy:当pool已经达到max size的时候,如何处理新任务 // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/AsyncConfiguration.java ================================================ package com.sohu.cache.configuration; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.ForkJoinPool; @Configuration @Slf4j public class AsyncConfiguration { private int parallelism=256; @Bean public ForkJoinPool forkJoinPool() { log.info("availableProcessors:{}, parallelism:{}", Runtime.getRuntime().availableProcessors(), parallelism); ForkJoinPool forkJoinPool = new ForkJoinPool(parallelism); return forkJoinPool; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/DataSourceConfig.java ================================================ package com.sohu.cache.configuration; import com.zaxxer.hikari.HikariDataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * Created by zengyizhao on 2022/7/27. */ @Configuration public class DataSourceConfig { @Bean(name = "cacheCloudDB") @ConfigurationProperties(prefix = "cachecloud.primary") public HikariDataSource quartzDataSource() { return DataSourceBuilder.create() .type(HikariDataSource.class) .build(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/FreemakerCustomConfig.java ================================================ package com.sohu.cache.configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.TemplateExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @Author: zengyizhao * @CreateTime: 2023/4/10 15:23 * @Description: freemaker 定制配置 * @Version: 1.0 */ @Configuration public class FreemakerCustomConfig { @Bean public freemarker.template.Configuration configuration(freemarker.template.Configuration configuration) { configuration.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); DefaultObjectWrapper objectWrapper = (DefaultObjectWrapper) configuration.getObjectWrapper(); objectWrapper.setUseAdaptersForContainers(true); return configuration; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/SSHPoolConfig.java ================================================ package com.sohu.cache.configuration; import com.sohu.cache.ssh.SSHMachineInfo; import com.sohu.cache.ssh.SSHSessionPooledObjectFactory; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig; import org.apache.sshd.client.session.ClientSession; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.security.GeneralSecurityException; /** * @Author: zengyizhao * @CreateTime: 2024/2/22 15:20 * @Description: ssh session 连接池配置 * @Version: 1.0 */ @Configuration public class SSHPoolConfig { /** * ssh连接池配置 * @return */ @Bean public GenericKeyedObjectPool clientSessionPool() throws GeneralSecurityException, IOException { GenericKeyedObjectPoolConfig genericKeyedObjectPoolConfig = new GenericKeyedObjectPoolConfig(); genericKeyedObjectPoolConfig.setTestWhileIdle(true); genericKeyedObjectPoolConfig.setTestOnReturn(true); genericKeyedObjectPoolConfig.setMaxTotalPerKey(5); genericKeyedObjectPoolConfig.setMaxIdlePerKey(1); genericKeyedObjectPoolConfig.setMinIdlePerKey(1); genericKeyedObjectPoolConfig.setMaxWaitMillis(30000); genericKeyedObjectPoolConfig.setTimeBetweenEvictionRunsMillis(20000); genericKeyedObjectPoolConfig.setJmxEnabled(false); SSHSessionPooledObjectFactory factory = new SSHSessionPooledObjectFactory(); GenericKeyedObjectPool genericKeyedObjectPool = new GenericKeyedObjectPool<>( factory, genericKeyedObjectPoolConfig); return genericKeyedObjectPool; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/configuration/WebAntPathConfig.java ================================================ package com.sohu.cache.configuration; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebAntPathConfig implements WebMvcConfigurer { public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(true); } public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppAuditLogTypeEnum.java ================================================ package com.sohu.cache.constant; /** * 日志类型 * @author leifu */ public enum AppAuditLogTypeEnum { // 申请应用 APP_DESC_APPLY(1), // 扩容申请 APP_SCALE_APPLY(2), // 应用配置修改申请 APP_CONFIG_APPLY(3), // 审批 APP_CHECK(4), // 修改报警阀值 APP_CHANGE_ALERT(5), // 清理数据 APP_CLEAN_DATA(6), // 实例配置修改申请 INSTANCE_CONFIG_APPLY(7), // 键值分析 KEY_VALUE_ANALYSIS(8), // flush全部数据 FLUSHALL_DATA(9), // 应用诊断申请 APP_DIAGNOSTIC_APPLY(10); private int value; private AppAuditLogTypeEnum(int value) { this.value = value; } public int value() { return value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppAuditType.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * Created by yijunzhang on 14-10-20. */ public enum AppAuditType { APP_AUDIT(0, "申请集群"), APP_SCALE(1, "集群容量变更"), APP_MODIFY_CONFIG(2, "集群修改配置"), REGISTER_USER_APPLY(3, "用户注册"), INSTANCE_MODIFY_CONFIG(4, "实例修改配置"), APP_MONITOR_CONFIG(5, "全局报警配置修改"), KEY_ANALYSIS(6, "键值分析"), FLUSHALL_DATA(7, "清理数据"), APP_DIAGNOSTIC(8, "应用诊断"), APP_OFFLINE(10, "应用下线"), APP_MIGRATE(11, "应用数据迁移"), APP_IMPORT(12, "应用导入"), SCAN_CLEAN(13, "数据分析清理"); private final static Map MAP = new HashMap(); static { for (AppAuditType appAuditType : AppAuditType.values()) { MAP.put(appAuditType.getValue(), appAuditType); } } public static AppAuditType getAppAuditType(int value) { return MAP.get(value); } private int value; private String info; private AppAuditType(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppCheckEnum.java ================================================ package com.sohu.cache.constant; /** * 审批状态 * * @author leifu * @Time 2014年10月20日 */ public enum AppCheckEnum { // 通过审批 APP_PASS(1), // 驳回审批 APP_REJECT(-1), // 等待审批 APP_WATING_CHECK(0), //分配资源完毕 APP_ALLOCATE_RESOURCE(2); private Integer value; public Integer value() { return value; } private AppCheckEnum(Integer value) { this.value = value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppDataMigrateEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * Redis迁移类型枚举 * @author leifu * @Date 2016-6-8 * @Time 下午3:02:50 */ public enum AppDataMigrateEnum { //redis-migrate-tool REDIS_NODE(0, "single"), REDIS_CLUSTER_NODE(1, "redis cluster"), RDB_FILE(2, "rdb file"), TWEMPROXY(3, "twemproxy"), AOF_FILE(4, "aof file"), //redis-shake standalone(5, "standalone"), sentinel(6,"sentinel"), cluster(7,"cluster"); private int index; private String type; private static Map MAP = new HashMap(); static { for (AppDataMigrateEnum redisMigrateEnum : AppDataMigrateEnum.values()) { MAP.put(redisMigrateEnum.getIndex(), redisMigrateEnum); } } public static AppDataMigrateEnum getByIndex(int index) { return MAP.get(index); } private AppDataMigrateEnum(int index, String type) { this.index = index; this.type = type; } public static boolean isFileType(AppDataMigrateEnum appDataMigrateEnum) { if (RDB_FILE.equals(appDataMigrateEnum) || AOF_FILE.equals(appDataMigrateEnum)) { return true; } return false; } public int getIndex() { return index; } public String getType() { return type; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppDataMigrateResult.java ================================================ package com.sohu.cache.constant; /** * 迁移结果 * * @author leifu * @Date 2016-6-8 * @Time 下午3:15:08 */ public class AppDataMigrateResult { private int status; private String message; public AppDataMigrateResult(int status, String message) { this.status = status; this.message = message; } public boolean isSuccess() { if (status == 1) { return true; } return false; } public static AppDataMigrateResult success() { return new AppDataMigrateResult(1, "所有检查都成功,可以迁移啦!"); } public static AppDataMigrateResult success(String message) { return new AppDataMigrateResult(1, message); } public static AppDataMigrateResult fail(String message) { return new AppDataMigrateResult(0, message); } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "RedisMigrateResult [status=" + status + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppDataMigrateStatusEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * 迁移状态 * @author leifu * @Date 2016-6-9 * @Time 下午7:53:28 */ public enum AppDataMigrateStatusEnum { PREPARE(-1,"准备阶段"), START(0, "全量同步"), FULL_END(3,"增量同步"), END(1, "同步结束"), ERROR(2, "同步异常"); private int status; private String info; private static Map MAP = new HashMap(); static { for (AppDataMigrateStatusEnum rppDataMigrateStatusEnum : AppDataMigrateStatusEnum.values()) { MAP.put(rppDataMigrateStatusEnum.getStatus(), rppDataMigrateStatusEnum); } } public static AppDataMigrateStatusEnum getByStatus(int status) { return MAP.get(status); } private AppDataMigrateStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppDescEnum.java ================================================ package com.sohu.cache.constant; import java.util.Arrays; import java.util.List; import java.util.Optional; /** * app详情枚举(以后有关app详情的都往这里面迁) * * @author leifu * @Date 2015年1月26日 * @Time 上午11:34:22 */ public class AppDescEnum { /** * 应用类型:0 正式,1:测试 2:试用 */ public static enum AppTest { IS_TEST(1), NOT_TEST(0), IS_TRAIL(2); private int value; private AppTest(int value) { this.value = value; } public int getValue() { return value; } } /** * 应用重要度 */ public static enum AppImportantLevel { SUPER_IMPORTANT(1, "S"), VERY_IMPORTANT(2, "A"), IMPORTANT(3, "B"), COMMON(4, "C"); private int value; private String info; private AppImportantLevel(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } /** * 应用aof持久化刷盘策略 */ public static enum AppPersistenceType { GENERAL(0, "主从均aof每秒刷盘"), PERFORMANCE_DATASAFE_UNITY(1, "主aof系统自动刷盘,从每秒刷盘"), PERFORMANCE_BEST(2, "主aof关闭,从每秒刷盘"), NO_PERSISTENCE(3, "不持久化"); private int value; private String info; private AppPersistenceType(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } public static AppPersistenceType getByType(Integer persisType){ if(persisType == null){ return null; } AppPersistenceType[] values = AppPersistenceType.values(); Optional typeOptional = Arrays.asList(values).stream().filter(type -> type.getValue() == persisType).findFirst(); if(typeOptional.isPresent()){ return typeOptional.get(); } return null; } } /** * 应用内存淘汰策略 */ public static enum MaxmemoryPolicyType { NOEVICTION(0, "noeviction","不淘汰,占满写入失败"), ALLKEYSLRU(1, "allkeys-lru","所有键-最近最少使用"), ALLKEYSLFU(2, "allkeys-lfu","所有键-最少频率使用"), VOLATILELRU(3, "volatile-lru","有过期时间的键-最近最少使用"), VOLATILELFU(4, "volatile-lfu","有过期时间的键-最少频率使用"), ALLKEYSRANDOM(5, "allkeys-random","所有键-随机"), VOLATILERANDOM(6, "volatile-random","有过期时间的键-随机"), VOLATILETTL(7, "volatile-ttl","有过期时间的键-剩余时间最短"); private int type; private String name; private String desc; private MaxmemoryPolicyType(int type, String name, String desc) { this.type = type; this.name = name; this.desc = desc; } public int getType(){ return type; } public String getName(){ return name; } public String getDesc(){ return desc; } public static MaxmemoryPolicyType getByType(int type){ Optional policyTypeOptional = Arrays.asList(MaxmemoryPolicyType.values()).stream().filter(maxmemoryPolicyType -> maxmemoryPolicyType.type == type).findFirst(); if(policyTypeOptional.isPresent()){ return policyTypeOptional.get(); } return null; } public static MaxmemoryPolicyType getByName(String maxmemoryPolicyName){ Optional policyTypeOptional = Arrays.asList(MaxmemoryPolicyType.values()).stream().filter(maxmemoryPolicyType -> maxmemoryPolicyType.name.equals(maxmemoryPolicyName)).findFirst(); if(policyTypeOptional.isPresent()){ return policyTypeOptional.get(); } return null; } public static List getAll(){ MaxmemoryPolicyType[] values = MaxmemoryPolicyType.values(); return Arrays.asList(values); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppEnvNameEnum.java ================================================ package com.sohu.cache.constant; /** * @author fulei */ public enum AppEnvNameEnum { local("local"), test("test"), online_web("online_web"), online_stat("online_stat"), online_backup("online_backup"), afun("afun"), brazil("brazil"), ; private String name; private AppEnvNameEnum(String name) { this.name = name; } public String getName() { return name; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppStatusEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * 应用发布状态 * * @author leifu * @Time 2014年6月28日 */ public enum AppStatusEnum { STATUS_INITIALIZE(0, "未分配"), STATUS_ALLOCATED(1, "已申请未审批"), STATUS_PUBLISHED(2, "运行中"), STATUS_OFFLINE(3, "已下线"), STATUS_DENY(4, "驳回"); private int status; private String info; private static Map MAP = new HashMap(); static { for (AppStatusEnum appStatusEnum : AppStatusEnum.values()) { MAP.put(appStatusEnum.getStatus(), appStatusEnum); } } private AppStatusEnum(int status, String info) { this.status = status; this.info = info; } public static AppStatusEnum getByStatus(int status) { return MAP.get(status); } public int getStatus() { return status; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppTopology.java ================================================ package com.sohu.cache.constant; /** * 应用的配置、节点信息 * * Created by lingguo on 14-6-26. */ public enum AppTopology { TOTAL_MEMORY("total_memory"), /* 应用的总内存 */ MACHINE_COUNT("machine_count"), /* 应用的机器数量 */ MASTER_COUNT("master_count"), /* 主节点的数量 */ SLAVE_COUNT("slave_count"); /* 从节点的数量 */ private String value; AppTopology(String value) { this.value = value; } public String getValue() { return this.value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppUserAlertEnum.java ================================================ package com.sohu.cache.constant; /** * 用户类型 * @author leifu * @Time 2014年10月21日 */ public enum AppUserAlertEnum { //0:不报警 NO(0), //1:接收报警 YES(1); private Integer value; private AppUserAlertEnum(Integer value) { this.value = value; } public Integer value() { return value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/AppUserTypeEnum.java ================================================ package com.sohu.cache.constant; /** * 用户类型 * @author leifu * @Time 2014年10月21日 */ public enum AppUserTypeEnum { //管理员 ADMIN_USER(0), //普通用户 REGULAR_USER(2), //不存在用户 NO_USER(-1); private Integer value; private AppUserTypeEnum(Integer value) { this.value = value; } public Integer value() { return value; } @Override public String toString() { return String.valueOf(value); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/BaseConstant.java ================================================ package com.sohu.cache.constant; /** * @author leifu * @Date 2016-1-26 * @Time 下午9:26:58 */ public class BaseConstant { /** mill seconds of one day */ public static long MILLISECONDS_OF_ONE_SECOND = 1000; /** mill seconds of one day */ public static long MILLISECONDS_OF_ONE_MINUTE = 1000L * 60; /** mill seconds of one day */ public static long MILLISECONDS_OF_ONE_DAY = 1000L * 60 * 60 * 24; /** mill seconds of one hour */ public static long MILLISECONDS_OF_ONE_HOUR = 1000L * 60 * 60; public static String EMPTY_STRING = ""; public static String[] EMPTY_STRING_ARRAY = new String[0]; /** * WORD_SEPARATOR ( char )2 */ public static final String WORD_SEPARATOR = Character.toString((char) 2); public static final String SYSTEM_PROPERTY_CONFIG_FILE_PATH = "configFilePath"; public static final int ONE = 1; public static final int ZERO = 0; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ChmodEnum.java ================================================ package com.sohu.cache.constant; /** * * @author fulei */ public enum ChmodEnum { EXECUTE("x"), READ("r"), WRITE("w"); private String op; private ChmodEnum(String op) { this.op = op; } public String getOp() { return op; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ClientStatusEnum.java ================================================ package com.sohu.cache.constant; /** * 检查客户端的版本是否ok的枚举 * * @author: lingguo * @time: 2014/10/22 10:13 */ public enum ClientStatusEnum { GOOD(1), WARN(0), ERROR(-1); int status; ClientStatusEnum(int status) { this.status = status; } public int getStatus() { return status; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ClusterOperateResult.java ================================================ package com.sohu.cache.constant; /** * Cluster Operate Result * @author leifu * @Date 2017年6月27日 * @Time 上午8:43:10 */ public class ClusterOperateResult { private int status; private String message; public ClusterOperateResult(int status, String message) { this.status = status; this.message = message; } public static ClusterOperateResult success() { return new ClusterOperateResult(1, ""); } public static ClusterOperateResult fail(String message) { return new ClusterOperateResult(0, message); } public boolean isSuccess() { return status == 1; } public int getStatus() { return status; } public String getMessage() { return message; } @Override public String toString() { return "ClusterOperateResult [status=" + status + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/CommandResult.java ================================================ package com.sohu.cache.constant; import java.util.List; /** * ssh命令简单封装 * @author leifu * @Date 2016年7月27日 * @Time 下午3:06:42 */ public class CommandResult { private String command; private String result; private List resultLines; public CommandResult(String command, String result) { super(); this.command = command; this.result = result; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public List getResultLines() { return resultLines; } public void setResultLines(List resultLines) { this.resultLines = resultLines; } @Override public String toString() { return "CommandResult [command=" + command + ", result=" + result + ", resultLines=" + resultLines + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/DataFormatCheckResult.java ================================================ package com.sohu.cache.constant; /** * 数据格式检测 * @author leifu * @Date 2016年7月4日 * @Time 下午5:37:03 */ public class DataFormatCheckResult { private int status; private String message; private final static int SUCCESS = 1; private final static int FAIL = 0; public DataFormatCheckResult(int status, String message) { this.status = status; this.message = message; } public boolean isSuccess() { if (status == SUCCESS) { return true; } return false; } public static DataFormatCheckResult success(String message) { return new DataFormatCheckResult(SUCCESS, message); } public static DataFormatCheckResult fail(String message) { return new DataFormatCheckResult(FAIL, message); } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "DataFormatCheckResult [status=" + status + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/DiagnosticTypeEnum.java ================================================ package com.sohu.cache.constant; import com.sohu.cache.util.StringUtil; /** * @Author: rucao * @Date: 2020/6/9 17:11 */ public enum DiagnosticTypeEnum { SCAN_KEY(0, "scan", "扫描键"), BIG_KEY(1, "memoryUsed", "键内存诊断"), IDLE_KEY(2, "idlekey", "空闲键扫描"), HOT_KEY(3, "hotkey", "热点键诊断"), DEL_KEY(4, "deleteKey", "删除键"), SLOT_ANALYSIS(5, "slotAnalysis", "集群槽分析"), SCAN_CLEAN(6, "scanClean", "数据分析清理"); int type; String desc; String more; DiagnosticTypeEnum(int type, String desc, String more) { this.type = type; this.desc = desc; this.more = more; } public int getType() { return type; } public String getDesc() { return desc; } public String getMore() { return more; } public static int getDescKey(String desc) { for (DiagnosticTypeEnum diagnosticTypeEnum : DiagnosticTypeEnum.values()) { if (!StringUtil.isBlank(desc) && diagnosticTypeEnum.getDesc().equals(desc)) { return diagnosticTypeEnum.getType(); } } return -1; } public static String getKeyDesc(int type) { for (DiagnosticTypeEnum diagnosticTypeEnum : DiagnosticTypeEnum.values()) { if (type == diagnosticTypeEnum.getType()) { return diagnosticTypeEnum.getDesc(); } } return ""; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/EmptyObjectConstant.java ================================================ package com.sohu.cache.constant; /** * 空对象常量 * @author leifu * @Date 2016-1-26 * @Time 下午9:27:23 */ public class EmptyObjectConstant { public final static String EMPTY_STRING = ""; public static String[] EMPTY_STRING_ARRAY = new String[0]; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ErrorMessageEnum.java ================================================ package com.sohu.cache.constant; /** * 系统错误提示 * @author leifu * @Date 2016-6-25 * @Time 下午2:50:07 */ public enum ErrorMessageEnum { INNER_ERROR_MSG(1, "系统异常,请观察系统日志!"), PARAM_ERROR_MSG(2, "参数错误!"), REPEAT_INSERT_MSG(3, "重复插入!"), VERSION_NOT_EXIST(4, "版本不存在!"), ALERT_CONFIG_CONSTRAINT_ERROR_MSG(5, "该报警项已存在!") ; private int id; private String message; private ErrorMessageEnum(int id, String message) { this.id = id; this.message = message; } public int getId() { return id; } public String getMessage() { return message; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/HorizontalResult.java ================================================ package com.sohu.cache.constant; /** * 水平扩容结果标识 * @author leifu * @Date 2016年12月4日 * @Time 下午1:30:19 */ public class HorizontalResult { private int status; private String message; public HorizontalResult(int status, String message) { this.status = status; this.message = message; } public static HorizontalResult checkSuccess() { return new HorizontalResult(1, "所有检查都成功,可以开始水平扩容了!"); } public static HorizontalResult scaleSuccess() { return new HorizontalResult(1, "水平扩容已经成功开始!"); } public static HorizontalResult fail(String message) { return new HorizontalResult(0, message); } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "HorizontalResult [status=" + status + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ImportAppResult.java ================================================ package com.sohu.cache.constant; /** * 导入结果 * * @author leifu * @Date 2016-4-16 * @Time 下午3:41:37 */ public class ImportAppResult { private int status; private String message; public ImportAppResult(int status, String message) { this.status = status; this.message = message; } public static ImportAppResult success() { return new ImportAppResult(1, "所有检查都成功,可以添加啦!"); } public static ImportAppResult fail(String message) { return new ImportAppResult(0, message); } public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "ImportAppResult [status=" + status + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/InstanceStatusEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * 实例状态 * @author leifu * @Date 2014年11月26日 * @Time 下午5:05:35 */ public enum InstanceStatusEnum { ALLOCATE_STATUS(-1, "待分配"), ERROR_STATUS(0, "心跳停止"), GOOD_STATUS(1, "运行中"), OFFLINE_STATUS(2, "已下线"), FORGET_STATUS(3, "永久下线"); private int status; private String info; private static Map MAP = new HashMap(); static { for(InstanceStatusEnum instanceStatusEnum : InstanceStatusEnum.values()) { MAP.put(instanceStatusEnum.getStatus(), instanceStatusEnum); } } public static InstanceStatusEnum getByStatus(int status) { return MAP.get(status); } private InstanceStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/MachineConstant.java ================================================ package com.sohu.cache.constant; /** * User: lingguo * Date: 14-6-12 * Time: 上午11:42 */ public enum MachineConstant { Ip("ip"), Load("load"), Traffic("traffic"), CpuUsage("cpuUsage"), MemoryUsageRatio("memoryUsageRatio"), MemoryFree("memoryFree"), MemoryTotal("memoryTotal"), DiskUsage("diskUsageMap"); private String value; MachineConstant(String value) { this.value = value; } public String getValue() { return this.value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/MachineInfoEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * 机器信息枚举 * * @author leifu * @Date 2016年7月9日 * @Time 下午4:38:15 */ public class MachineInfoEnum { /** * 是否为可用 * * @author leifu * @Date 2016年7月9日 * @Time 下午4:43:49 */ public static enum AvailableEnum { YES(1), NO(0); private int value; private AvailableEnum(int value) { this.value = value; } public int getValue() { return value; } } /** * 机器类型 * * @author leifu * @Date 2016年7月9日 * @Time 下午4:42:58 */ public static enum TypeEnum { REDIS_NODE(0, "Redis类型"), REDIS_MIGRATE_TOOL(2, "Redis迁移工具类型"), SENTINEL_NODE(3, "Sentinel类型"), TWEMPROXY_NODE(4, "Twemproxy类型"), PIKA_NODE(5, "Pika类型"); private int type; private String info; private static Map MAP = new HashMap(); static { for (TypeEnum typeEnum : TypeEnum.values()) { MAP.put(typeEnum.getType(), typeEnum); } } public static TypeEnum getByType(int type) { return MAP.get(type); } private TypeEnum(int type, String info) { this.type = type; this.info = info; } public int getType() { return type; } public String getInfo() { return info; } } /** * 机器发现操作系统类型 * * @author zengyizhao * @Date 2022年9月5日 * @Time 下午4:26:58 */ public static enum DisTypeEnum { CENTOS(0, "centos"), UBUNTU(1, "ubuntu"); private int type; private String info; private static Map MAP = new HashMap<>(); static { for (DisTypeEnum typeEnum : DisTypeEnum.values()) { MAP.put(typeEnum.getType(), typeEnum); } } public static DisTypeEnum getByType(int type) { return MAP.get(type); } private DisTypeEnum(int type, String info) { this.type = type; this.info = info; } public int getType() { return type; } public String getInfo() { return info; } } public static enum MachineEnum { HOST("host"), CONTAINER("container"); private String value; MachineEnum(String value) { this.value = value; } public String getValue() { return value; } } public static enum MachineTypeEnum { HOST(1), CONTAINER(2), ALL(3); private int value; MachineTypeEnum(int value) { this.value = value; } public int getValue() { return value; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/OperateResult.java ================================================ package com.sohu.cache.constant; /** * Created by yijunzhang on 2018-12-26 */ public class OperateResult { private boolean isSuccess; private String message; private OperateResult(boolean isSuccess, String message) { this.isSuccess = isSuccess; this.message = message; } public static OperateResult success() { return new OperateResult(true, ""); } public static OperateResult fail(String message) { return new OperateResult(false, message); } public boolean isSuccess() { return isSuccess; } public void setSuccess(boolean isSuccess) { this.isSuccess = isSuccess; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "OperateResult [isSuccess=" + isSuccess + ", message=" + message + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/PipelineEnum.java ================================================ package com.sohu.cache.constant; /** * @author leifu * @Date 2017年7月13日 * @Time 下午3:26:03 */ public enum PipelineEnum { NO(0), YES(1); private int value; private PipelineEnum(int value) { this.value = value; } public static PipelineEnum getPipelineEnum(int pipelineInt) { for (PipelineEnum pipelineEnum : PipelineEnum.values()) { if (pipelineInt == pipelineEnum.value) { return pipelineEnum; } } return null; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/RedisConfigTemplateChangeEnum.java ================================================ package com.sohu.cache.constant; /** * 配置模板改变行为枚举 * * @author leifu * @Date 2016年7月27日 * @Time 下午3:51:13 */ public enum RedisConfigTemplateChangeEnum { UPDATE(1, "更新"), ADD(2, "添加"), DELETE(3, "删除"); private int index; private String info; private RedisConfigTemplateChangeEnum(int index, String info) { this.index = index; this.info = info; } public int getIndex() { return index; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/RedisConstant.java ================================================ package com.sohu.cache.constant; /** * redis 相关常量 * Created by yijunzhang on 14-6-10. */ public enum RedisConstant { Stats("Stats"), Keyspace("Keyspace"), Commandstats("Commandstats"), Replication("Replication"), Clients("Clients"), CPU("CPU"), Memory("Memory"), Server("Server"), Persistence("Persistence"), CollectTime("CollectTime"), DIFF("diff"); private String value; RedisConstant(String value) { this.value = value; } @Override public String toString() { return this.value; } public static RedisConstant value(String input) { RedisConstant[] constants = RedisConstant.values(); for (RedisConstant constant : constants) { if (constant.value.equals(input)) { return constant; } } return null; } public String getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/RedisExcludeCommand.java ================================================ package com.sohu.cache.constant; import java.util.HashSet; import java.util.Set; /** * Created by yijunzhang on 14-6-25. */ public class RedisExcludeCommand { private static Set excludeCommands = new HashSet(); static { //排除这些redis命令 excludeCommands.add("ping"); excludeCommands.add("cluster"); excludeCommands.add("config"); excludeCommands.add("ttl"); excludeCommands.add("client"); excludeCommands.add("bgrewriteaof"); excludeCommands.add("bgsave"); excludeCommands.add("dbsize"); excludeCommands.add("debug"); excludeCommands.add("flushall"); excludeCommands.add("flushdb"); excludeCommands.add("flush"); excludeCommands.add("info"); excludeCommands.add("lastsave"); excludeCommands.add("monitor"); excludeCommands.add("psync"); excludeCommands.add("save"); excludeCommands.add("shutdown"); excludeCommands.add("slaveof"); excludeCommands.add("slowlog"); excludeCommands.add("sync"); excludeCommands.add("time"); excludeCommands.add("replconf"); excludeCommands.add("asking"); excludeCommands.add("restore-asking"); excludeCommands.add("restore"); excludeCommands.add("select"); } public static boolean isExcludeCommand(String command) { return excludeCommands.contains(command); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/RedisMigrateToolConstant.java ================================================ package com.sohu.cache.constant; /** * Redis-Migrate-Tool常量 * @author leifu * @Date 2016-6-10 * @Time 上午9:23:30 */ public enum RedisMigrateToolConstant { Stats("Stats"), Keyspace("Group"), Clients("Clients"), Memory("Memory"), Server("Server"); private String value; RedisMigrateToolConstant(String value) { this.value = value; } @Override public String toString() { return this.value; } public static RedisMigrateToolConstant value(String input) { RedisMigrateToolConstant[] constants = RedisMigrateToolConstant.values(); for (RedisMigrateToolConstant constant : constants) { if (constant.value.equals(input)) { return constant; } } return null; } public String getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/RedisShakeEnum.java ================================================ package com.sohu.cache.constant; /** * Created by rucao on 2019/10/30 */ public enum RedisShakeEnum { LOG_WAITING_SOURCE_RDB("waiting source rdb", "等待源端save rdb完毕"), LOG_SYNCING("total", "全量同步阶段,显示百分比"), LOG_SYNC_RDB_DONE("sync rdb done", "全量同步完成"), LOG_FORWARD_COMMANDS("forwardCommands","当前dbSyncer进入增量同步"), LOG_ERROR("error","迁移任务发生异常,程序中断,详情请查看日志"); private String keyword; private String description; RedisShakeEnum(String keyword, String description) { this.keyword = keyword; this.description = description; } public String getKeyword() { return keyword; } public String getDescription() { return description; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ReshardStatusEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * Reshard状态 */ public enum ReshardStatusEnum { RUNNING(0, "运行中"), FINISH(1, "完成"), ERROR(2, "出错"); private int value; private String info; private final static Map MAP = new HashMap(); static { for (ReshardStatusEnum reshardStatusEnum : ReshardStatusEnum.values()) { MAP.put(reshardStatusEnum.getValue(), reshardStatusEnum); } } public static ReshardStatusEnum getReshardStatusEnum(int value) { return MAP.get(value); } private ReshardStatusEnum(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/SymbolConstant.java ================================================ package com.sohu.cache.constant; /** * 符号常量 * * @author leifu * @Date 2016-1-26 * @Time 下午9:25:32 */ public class SymbolConstant { /** , */ public final static String COMMA = ","; public final static String SLASH = "/"; public final static String BACK_SLASH = "\\"; /** : */ public final static String COLON = ":"; public final static String SPACE = " "; public final static String DOT = "."; public final static String ENTER = System.lineSeparator(); /** ; */ public final static String SEMICOLON = ";"; /** [ */ public final static String SQUARE_BRACKETS_LEFT = "["; /** ] */ public final static String SQUARE_BRACKETS_RIGHT = "]"; public final static String CURLY_BRACKETS_LEFT = "{"; public final static String CURLY_BRACKETS_RIGHT = "}"; /** ( */ public final static String PARENTHESES_BRACKETS_LEFT = "("; /** ) */ public final static String PARENTHESES_BRACKETS_RIGHT = ")"; public final static String QUESTION_SIGN = "?"; public final static String AND_SIGN = "&"; /** # */ public final static String POUND = "#"; /** * */ public final static String ASTERISK = "*"; /** $ */ public final static String DOLLAR_SIGN = "$"; public final static String ELLIPSIS_THREE = "..."; public final static String ELLIPSIS_SIX = "......"; /** = */ public final static String EQUAL_SIGN = "="; /** - */ public final static String MINUS_SIGN = "-"; public final static String PLUS_SIGN = "+"; public final static String MULTIPLICATION_SIGN = "*"; public final static String PERCENT = "%"; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/TimeDimensionalityEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.math.NumberUtils; /** * 时间维度枚举 * * @author leifu * @Date 2016年8月1日 * @Time 下午3:50:38 */ public enum TimeDimensionalityEnum { MINUTE(0, "以分钟为维度"), HOUR(1, "以小时为维度"); private int index; private String info; private static final Map MAP = new HashMap(); static { for (TimeDimensionalityEnum timeDimensionalityEnum : TimeDimensionalityEnum.values()) { MAP.put(timeDimensionalityEnum.getIndex(), timeDimensionalityEnum); } } private TimeDimensionalityEnum(int index, String info) { this.index = index; this.info = info; } public int getIndex() { return index; } public String getInfo() { return info; } public static TimeDimensionalityEnum getTimeDimensionalityEnumByIndex(String index) { return MAP.get(NumberUtils.toInt(index)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/UserLoginTypeEnum.java ================================================ package com.sohu.cache.constant; import java.util.HashMap; import java.util.Map; /** * 登录类型 * * @author leifu * @Date 2016年6月15日 * @Time 下午12:03:05 */ public enum UserLoginTypeEnum { SESSION(1, "session"), COOKIE(2, "cookie"); private int type; private String desc; private final static Map MAP = new HashMap(); static { for (UserLoginTypeEnum userLoginTypeEnum : UserLoginTypeEnum.values()) { MAP.put(userLoginTypeEnum.getType(), userLoginTypeEnum); } } public static UserLoginTypeEnum getLoginTypeEnum(int type) { return MAP.get(type); } private UserLoginTypeEnum(int type, String desc) { this.type = type; this.desc = desc; } public int getType() { return type; } public String getDesc() { return desc; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/constant/ValueSizeDistriEnum.java ================================================ package com.sohu.cache.constant; import com.sohu.cache.util.NumberUtil; import java.util.HashMap; import java.util.Map; /** * 值分布 * * @author leifu */ public enum ValueSizeDistriEnum { // 单位字节 BETWEEN_MIN_TO_0_BYTE("-2147483648_0", "wrong", 0), BETWEEN_0_TO_50_BYTE("0_50", "0-0.05k", 1), BETWEEN_50_TO_100_BYTE("50_100", "0.05k-0.1k", 2), BETWEEN_100_TO_200_BYTE("100_200", "0.1k-0.2k", 3), BETWEEN_200_TO_500_BYTE("200_500", "0.2k-0.5k", 4), BETWEEN_500_TO_1024_BYTE("500_1024", "0.5k-1k", 5), BETWEEN_1024_TO_2048_BYTE("1024_2048", "1-2k", 6), BETWEEN_2048_TO_5120_BYTE("2048_5120", "2-5k", 7), BETWEEN_5120_TO_10240_BYTE("5120_10240", "5-10k", 8), BETWEEN_10240_TO_20480_BYTE("10240_20480", "10-20k", 9), BETWEEN_20480_TO_51200_BYTE("20480_51200", "20-50k", 10), BETWEEN_51200_TO_102400_BYTE("51200_102400", "50-100k", 11), BETWEEN_102400_TO_204800_BYTE("102400_204800", "100-200k", 12), BETWEEN_204800_TO_512000_BYTE("204800_512000", "200-500k", 13), BETWEEN_512000_TO_1024000_BYTE("512000_1024000", "500k-1M", 15), BETWEEN_1024000_TO_2048000_BYTE("1024000_2048000", "1M-2M", 16), BETWEEN_2048000_TO_5120000_BYTE("2048000_5120000", "2M-5M", 17), BETWEEN_5120000_TO_10240000_BYTE("5120000_10240000", "5M-10M", 18), BETWEEN_10240000_TO_ABOVE_BYTE("10240000_2147483647", "above 10M", 19), //兼容老的 BETWEEN_512000_TO_ABOVE_BYTE("512000_2147483647", "above 500k", 14); private String value; private String info; private int type; private ValueSizeDistriEnum(String value, String info, int type) { this.value = value; this.info = info; this.type = type; } public int getType() { return type; } public String getValue() { return value; } public String getInfo() { return info; } public final static Map VALUE_MAP = new HashMap(); static { for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) { VALUE_MAP.put(enumObject.getValue(), enumObject); } } public static ValueSizeDistriEnum getByValue(String targetValue){ return VALUE_MAP.get(targetValue); } public final static Map TYPE_MAP = new HashMap(); static { for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) { TYPE_MAP.put(enumObject.getType(), enumObject); } } public static ValueSizeDistriEnum getByType(int targetType){ return TYPE_MAP.get(targetType); } /** * 查看length在哪个区间 * * @return */ public static ValueSizeDistriEnum getRightSizeBetween(int size) { ValueSizeDistriEnum[] enumArr = ValueSizeDistriEnum.values(); for (ValueSizeDistriEnum enumObject : enumArr) { if (isInSize(enumObject, size)) { return enumObject; } } return null; } /** * 确定length在指定区间 * * @param enumObject * @param size * @return */ private static boolean isInSize(ValueSizeDistriEnum enumObject, int size) { String value = enumObject.getValue(); int index = value.indexOf("_"); int start = NumberUtil.toInt(value.substring(0, index)); int end = NumberUtil.toInt(value.substring(index + 1)); if (size >= start && size < end) { return true; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppAlertRecordDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppAlertRecord; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/3 13:38 * @Description: 报警记录 */ public interface AppAlertRecordDao { /** * 保存报警信息 * * @param appAlertRecord * @return */ public int save(AppAlertRecord appAlertRecord); /** * 批量保存报警信息 * * @param appAlertRecordList * @return */ public int batchSave(List appAlertRecordList); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppAuditDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppAudit; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; import java.util.Map; /** * Created by yijunzhang on 14-10-20. */ public interface AppAuditDao { /** * 新增审核记录 * * @param appAudit */ public void insertAppAudit(AppAudit appAudit); /** * 查询所有等待审批的记录 */ public List selectWaitAppAudits(@Param("status") Integer status, @Param("type") Integer type, @Param("auditId") Long auditId, @Param("userId") Long userId, @Param("operateId") Long operateId); /** * 按id查询 * * @param id * @return */ public AppAudit getAppAudit(@Param("id") long id); /** * 更新审核状态 */ void updateAppAudit(@Param("id") long id, @Param("status") int status); void updateAppAuditUser(@Param("id") long id, @Param("status") int status, @Param("operateId") Long operateId); void updateAppAuditOperateUser(@Param("id") long id, @Param("operateId") Long operateId); /** * 更新驳回理由 */ public void updateRefuseReason(@Param("id") long id, @Param("refuseReason") String refuseReason); /** * 通过appId获取所有审批记录 */ public List getAppAuditByAppId(@Param("appId") Long appId); /** * 通过appId获取所有审批记录 */ public List getAppAuditByCondition(@Param("appId") Long appId, @Param("type") Integer type); /** * 通过appId,type, 和时间范围获取所有审批记录 */ public List getAppAuditByTypeAndTimeRange(@Param("appId") Long appId, @Param("type") Integer type, @Param("startTime") Date startTime, @Param("endTime") Date endTime); /** * @param id * @param taskId */ public void updateTaskId(@Param("id") long id, @Param("taskId") long taskId); List> getStatisticGroupByStatus(@Param("userId") Long userId, @Param("operateId") Long operateId, @Param("startTime") Date startTime, @Param("endTime") Date endTime); List> getStatisticGroupByType(@Param("userId") Long userId, @Param("operateId") Long operateId, @Param("startTime") Date startTime, @Param("endTime") Date endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppAuditLogDao.java ================================================ package com.sohu.cache.dao; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppAuditLog; import java.util.List; /** * 应用审批日志记录 * * @author leifu * @Time 2014年6月5日 */ public interface AppAuditLogDao { public int save(AppAuditLog appAuditLog); /** * 根据类型type(参考AppAuditLogTypeEnum)获取审批日志 * @param appAuditId * @param type * @return */ public List getAuditByType(@Param("appAuditId") Long appAuditId, @Param("type") int type); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppBizDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppBiz; import com.sohu.cache.entity.AppUser; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 业务组管理dao * @author zengyizhao * @Time 2023年1月16日 */ public interface AppBizDao { public AppBiz get(@Param("id") Long id); public int save(AppBiz appBiz); public int update(AppBiz appBiz); public int delete(@Param("id") Long id); public List getBizList(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppCapacityMonitorDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppCapacityMonitor; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2022/10/10 9:38 * @Description: 应用容量(自动扩容、缩容审计报表) */ public interface AppCapacityMonitorDao { /** * 保存应用容量监控信息 * * @param appCapacityMonitor * @return */ public int save(AppCapacityMonitor appCapacityMonitor); /** * 批量保存应用容量监控信息 * * @param appCapacityMonitorList * @return */ public int batchSave(List appCapacityMonitorList); /** * 更新应用容量监控信息 * * @param appCapacityMonitor * @return */ public int update(AppCapacityMonitor appCapacityMonitor); /** * 更新应用缩容计划 * * @param appCapacityMonitor * @return */ public int updateAppCapacityReduceSchedule(AppCapacityMonitor appCapacityMonitor); public int updateAppUsedMemHistory(@Param("appId") long appId, @Param("memUsedHistory") long memUsedHistory); /** * 根据appId查询应用容量监控信息 * @param appId * @return */ public AppCapacityMonitor getAppCapacityMonitorByAppId(long appId); /** * 根据appId查询所有在线应用容量监控信息 * @return */ public List getAppCapacityMonitorAll(); /** * 根据appId查询应用容量监控信息 * @param appCapacityMonitor * @return */ // public List getAppCapacityMonitorByCondition(AppCapacityMonitor appCapacityMonitor); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientCommandStatisticsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientCommandStatistics; import com.sohu.cache.entity.AppClientStatisticGather; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/16 */ @Repository public interface AppClientCommandStatisticsDao { /** * 批量保存 * * @param appClientCommandStatisticsList * @return */ int batchSave(List appClientCommandStatisticsList); /** * 获取应用指定时间内调用过的命令 * * @param appId * @param startTime * @param endTime * @return */ List getAppDistinctCommand(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * 获取应用指定时间内d的客户端ip * * @param appId * @param startTime * @param endTime * @return */ List getAppDistinctClients(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * 获取某个应用一段时间内某个命令的统计信息列表 * * @param appId * @param startTime * @param endTime * @param command * @return */ List> getAppCommandStatistics(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("command") String command, @Param("clientIp") String clientIp); /** * @param startTime * @param endTime * @return */ List getAppClientCmdStat(@Param("startTime") long startTime, @Param("endTime") long endTime); /** * @param appId * @param startTime * @param endTime * @param command * @return */ List> getSumCmdStatByCmd(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("command") String command); List> getSumCmdStatByClient(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("clientIp") String clientIp); int cleanCommandStatisticsBeforeCurrentMin(@Param("currentMin") long currentMin); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientCostTimeStatDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientCostTimeStat; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 客户端耗时dao * * @author leifu * @Date 2015年1月20日 * @Time 上午11:50:01 */ public interface AppClientCostTimeStatDao { /** * * @param appClientCostTimeStat */ void save(AppClientCostTimeStat appClientCostTimeStat); /** * 查询应用一段时间内某个命令、某对客户端和实例的耗时统计信息 * @param appId * @param command * @param instanceId * @param clientIp * @param startTime * @param endTime * @return */ List getAppCommandClientToInstanceStat(@Param("appId") Long appId, @Param("command") String command, @Param("instanceId") long instanceId, @Param("clientIp") String clientIp, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * 批量更新 * @param appClientCostTimeStatList * @return */ int batchSave(List appClientCostTimeStatList); /** * 获取最小id * @return */ long getTableMinimumId(); /** * 按照collectTime获取最小id * @param collectTime * @return */ long getMinimumIdByCollectTime(@Param("collectTime") long collectTime); /** * 按照id区间删除 * @param startId * @param endId */ long deleteByIds(@Param("startId") long startId, @Param("endId") long endId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientCostTimeTotalStatDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientCostTimeTotalStat; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 基于应用全局耗时统计(uniquekey: app_id, command, collect_time) * @author leifu * @Date 2015年6月26日 * @Time 下午4:24:24 */ public interface AppClientCostTimeTotalStatDao { /** * 保存基于应用的耗时统计 * @param appClientCostTimeTotalStat */ void save(AppClientCostTimeTotalStat appClientCostTimeTotalStat); /** * 获取应用指定时间内调用过的命令 * @param appId * @param startTime * @param endTime * @return */ List getAppDistinctCommand(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * 获取应用指定时间内某个命令的耗时统计 * @param appId * @param command * @param startTime * @param endTime * @return */ List getAppClientCommandStat(@Param("appId") Long appId, @Param("command") String command, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * 批量保存 * @param appClientCostTimeTotalStatList */ void batchSave(List appClientCostTimeTotalStatList); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientExceptionStatDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientExceptionStat; import com.sohu.cache.entity.ClientInstanceException; import com.sohu.cache.web.util.Page; import org.apache.ibatis.annotations.Param; import java.util.List; /** * 客户端异常dao * * @author leifu * @Date 2015年1月20日 * @Time 上午11:50:06 */ public interface AppClientExceptionStatDao { /** * 保存上报异常 * * @param appClientExceptionStat */ void save(AppClientExceptionStat appClientExceptionStat); /** * 获取客户端异常列表 * * @param appId 应用id * @param startTime 开始收集时间 * @param endTime 结束收集时间 * @param type 异常类型(ClientExceptionType) * @param clientIp 客户端ip * @return */ List getAppExceptionList(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("type") int type, @Param("clientIp") String clientIp, @Param("page") Page page); /** * 获取客户端异常个数 * * @param appId 应用id * @param startTime 开始收集时间 * @param endTime 结束收集时间 * @param type 异常类型(ClientExceptionType) * @param clientIp 客户端ip * @return */ int getAppExceptionCount(@Param("appId") Long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("type") int type, @Param("clientIp") String clientIp); /** * 大于collectTime后实例的异常统计 * @param ip * @param collectTime * @return */ List getInstanceExceptionStat(@Param("ip") String ip, @Param("collectTime") long collectTime); /** * 批量保存 * @param appClientExceptionStatList * @return */ int batchSave(List appClientExceptionStatList); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientExceptionStatisticsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientExceptionStatistics; import com.sohu.cache.entity.AppClientStatisticGather; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/16 */ @Repository public interface AppClientExceptionStatisticsDao { /** * 批量保存 * * @param appClientExceptionStatisticsList * @return */ int batchSave(List appClientExceptionStatisticsList); /** * 获取某个应用一段时间内的异常信息列表 * * @param appId * @param startTime * @param endTime * @param type * @return */ List> getAppExceptionStatistics(@Param("appId") Long appId, @Param("clientIp") String clientIp, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("type") Integer type); /** * @param appId * @param startTime * @param endTime * @return */ List> getDistinctClientNodeStatistics(@Param("appId") Long appId, @Param("clientIp") String clientIp, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("type") Integer type); /** * 获取应用指定时间内d的客户端ip * * @param appId * @param startTime * @param endTime * @return */ List> getAppDistinctClientConfig(@Param("appId") Long appId, @Param("type") Integer type, @Param("startTime") long startTime, @Param("endTime") long endTime); List> getAppClientConfigs(@Param("appId") Long appId, @Param("type") Integer type, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * @param clientIp * @param startTime * @param endTime * @param node * @return */ List getLatencyCommandsByNode(@Param("clientIp") String clientIp, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("node") String node); List getLatencyCommandsByNodeV2(@Param("node") String node, @Param("searchTime") long searchTime); /** * @param appId * @param searchTime * @return */ List> getSumCmdExpStatGroupByNode(@Param("appId") long appId, @Param("searchTime") long searchTime); /** * @param startTime * @param endTime * @return */ List getAppClientConnExpStat(@Param("startTime") long startTime, @Param("endTime") long endTime); /** * 获取指定日期连接异常个数 * @param appId * @param startTime * @param endTime * @return */ int getAppClientConnExpCount(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); /** * @param startTime * @param endTime * @return */ List getAppClientCmdExpStat(@Param("startTime") long startTime, @Param("endTime") long endTime); /** * 获取指定日期超时异常个数 * @param appId * @param startTime * @param endTime * @return */ int getAppClientCmdExpCount(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientLatencyCommandDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientLatencyCommand; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/16 */ @Repository public interface AppClientLatencyCommandDao { int batchSave(List appClientLatencyCommandList); List> getLatencyCommandByIds(@Param("ids") List ids); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientReportDataSizeDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientDataSizeStat; /** * 客户端内收集数据map的尺寸查询 * @author leifu * @Date 2015年7月13日 * @Time 下午3:26:48 */ public interface AppClientReportDataSizeDao { /** * 保存-客户端收集map的尺寸信息 * @param appClientDataSizeStat */ void save(AppClientDataSizeStat appClientDataSizeStat); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientStatisticGatherDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientStatisticGather; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/12/29 */ @Repository public interface AppClientStatisticGatherDao { @Deprecated int batchSave(); int batchSaveCmdStats(List list); int batchAddCmdStats(List list); int batchSaveConnExpStats(List list); int batchAddConnExpStats(List list); int batchSaveCmdExpStats(List list); int batchAddCmdExpStats(List list); int batchSaveMemFragRatio(List list); int batchSaveSlowLogCount(List list); int batchAddSlowLogCount(List list); int batchSaveLatencyCount(List list); int batchAddLatencyCount(List list); int batchSaveAppStats(List list); int batchAddAppServerCmdCount(List list); int batchSaveConnClients(List list); int batchSaveTopologyExam(List list); List> getAppClientStatisticByGatherTime(@Param("appId") long appId, @Param("gatherTime") String gatherTime); List getTopologyExamFailedByGatherTime(@Param("gatherTime") String gatherTime); List> getExpAppStatisticByGatherTime(@Param("gatherTime") String gatherTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppClientVersionDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppClientVersion; /** * 客户端版本dao * @author leifu * @Date 2015年2月2日 * @Time 上午10:36:20 */ public interface AppClientVersionDao { /** * 保存或者更新客户端版本信息 * @param appClientVersion */ void saveOrUpdateClientVersion(AppClientVersion appClientVersion); /** * 根据客户端ip获取所有的appId * @param clientIp * @return */ List getByClientIp(@Param("clientIp") String clientIp); /** * 获取应用的所有客户端版本信息 * @param appId * @return */ List getAppAllClientVersion(@Param("appId") long appId); /** * 获取应用的客户端最大版本信息 * @param appId * @return */ String getAppMaxClientVersion(@Param("appId") long appId); /** * 获取所有应用的最大客户端版本 * @return */ List> getAllMaxClientVersion(); /** * 获取所有版本,暂时不分页 * @return */ List getAll(@Param("appId") long appId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppDailyDao.java ================================================ package com.sohu.cache.dao; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppDailyData; import java.util.List; /** * 应用日报 * * @author leifu * @Date 2017年1月19日 * @Time 上午10:25:39 */ public interface AppDailyDao { void save(AppDailyData appDailyData); AppDailyData getAppDaily(@Param("appId") long appId, @Param("date") String date); List getAppDailyList(@Param("appId") long appId, @Param("startDate") long startDate, @Param("endDate") long endDate); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppCapacityStatisticsResult; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppMonitorStatisticsResult; import com.sohu.cache.entity.AppSearch; import com.sohu.cache.entity.AppStatisticsSearch; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import java.util.List; import java.util.Map; /** * 基于app的dao操作 * * @author leifu * @Date 2014年5月15日 * @Time 下午1:58:22 */ public interface AppDao { /** * 通过appId获取对应的app * * @param appId * @return */ public AppDesc getAppDescById(@Param("appId") long appId); AppDesc getOnlineAppDescById(@Param("appId") long appId); /** * 通过所有在线的应用 * * @return */ public List getOnlineApps(); List getOnlineAppsNonTest(); /** * 通过所有在线的应用 * * @return */ public List getAllApps(); /** * 通过应用名获取对应app * * @param appName * @return */ public AppDesc getByAppName(@Param("appName") String appName); /** * 保存app * * @param appDesc * @return */ public int save(AppDesc appDesc); /** * 更新app * * @param appDesc * @return */ public int update(AppDesc appDesc); /** * 更新appPwd * @param appId * @param appPwd * @return */ int updateAppPwd(@Param("appId") long appId, @Param("pkey") String appPwd); /** * 更新app,包含自定义密码 * * @param appDesc * @return */ public int updateWithCustomPwd(AppDesc appDesc); /** * 删除app * * @param id * @return */ public int delete(@Param("id") Long id); /** * 获取用户拥有的应用 * * @param userId * @return */ public List getAppDescList(@Param("userId") long userId); /** * 获取应用拥有的应用个数 * * @param userId * @return */ public int getUserAppCount(@Param("userId") long userId); /** * 获取所有应用 * * @param appSearch * @return */ public List getAllAppDescList(AppSearch appSearch); /** * 获取应用个数(有效状态) * * @param appSearch * @return */ public int getAllAppCount(AppSearch appSearch); /** *

* Description:获取应用个数 *

* @param * @return */ public int getTotalAppCount(); /** * 更新appKey * * @param appId * @param appKey */ public void updateAppKey(@Param("appId") long appId, @Param("appKey") String appKey); /** * 更新持久化类型 * * @param appId * @param persistenceType */ public int updateAppPersistenceType(@Param("appId") long appId, @Param("persistenceType") int persistenceType); /** * 更新内存策略 * * @param appId * @param maxmemoryPolicy */ public int updateAppMaxmemoryPolicy(@Param("appId") long appId, @Param("maxmemoryPolicy") int maxmemoryPolicy); /** * 获取app安装不同版本的数量 */ @Select("SELECT version_id,count(version_id) as num from app_desc where status=2 GROUP BY version_id") public List> getVersionStat(); public List getAppDescByIds(@Param("appIds") List appIds); public List getMonitorStatistics(AppStatisticsSearch search); public List getCapacityStatistics(AppStatisticsSearch search); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppDataMigrateStatusDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppDataMigrateSearch; import com.sohu.cache.entity.AppDataMigrateStatus; /** * 迁移状态Dao * * @author leifu * @Date 2016-6-9 * @Time 下午5:25:53 */ public interface AppDataMigrateStatusDao { int save(AppDataMigrateStatus appDataMigrateStatus); AppDataMigrateStatus get(@Param("id") long id); AppDataMigrateStatus getByMigrateId(@Param("migrateId") long migrateId); int updateStatus(@Param("id") long id, @Param("status") int status); int getMigrateTaskCount(@Param("appDataMigrateSearch") AppDataMigrateSearch appDataMigrateSearch); List search(@Param("appDataMigrateSearch") AppDataMigrateSearch appDataMigrateSearch); List getAllOnMigrateId(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppImportDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppImport; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @Author: rucao * @Date: 2021/1/7 下午6:03 */ public interface AppImportDao { AppImport get(@Param("id") Long id); int save(AppImport appImport); int update(AppImport appImport); List getAppImports(@Param("status") int status); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppInstanceClientRelationDao.java ================================================ package com.sohu.cache.dao; import java.util.Date; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppInstanceClientRelation; /** * 应用下节点和客户端关系Dao * * @author leifu * @Date 2016年5月4日 * @Time 上午9:19:44 */ public interface AppInstanceClientRelationDao { int save(AppInstanceClientRelation appInstanceClientRelation); int batchSave(List appInstanceClientRelationList); int isExist(AppInstanceClientRelation appInstanceClientRelation); List getAppInstanceClientRelationList(@Param("appId") Long appId, @Param("day") Date day); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppStatsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.*; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** * Created by yijunzhang on 14-6-9. */ public interface AppStatsDao { public static final int MINUTE_DIMENSIONALITY = 0; public static final int HOUR_DIMENSIONALITY = 1; /** * 插入或更新AppStats分钟统计 */ public void mergeMinuteAppStats(AppStats appStats); /** * 插入或更新AppCommandStats分钟统计 */ public void mergeMinuteCommandStatus(AppCommandStats commandStats); /** * 插入或更新AppStats小时统计 */ public void mergeHourAppStats(AppStats appStats); /** * 插入或更新AppCommandStats小时统计 */ public void mergeHourCommandStatus(AppCommandStats commandStats); /** * 按时间查询应用统计 * * @param appId 应用id * @param td 时间维度 * @return */ public List getAppStatsList(@Param("appId") long appId, @Param("td") TimeDimensionality td); /** * 按照分钟查询应用统计 * @param appId * @param beginTime * @param endTime * @return */ public List getAppStatsByMinute(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 按照分钟查询应用历史最大使用内存 * @param appId * @param beginTime * @param endTime * @return */ public Long getUsedMemoryMaxByTimeBetween(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 按照分钟查询应用统计 * @param appId * @param beginTime * @param endTime * @return */ public AppStats getOneAppStatsByMinute(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); List gatherAppsStats(@Param("startTime") long startTime, @Param("endTime") long endTime); /** * 按照小时查询应用统计 * @param appId * @param beginTime * @param endTime * @return */ public List getAppStatsByHour(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 按照小时查询应用统计 * @param beginTime * @param endTime * @return */ public List getAppHourStatsByTime(@Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 按时间查询应用命令统计 * * @param appId 应用id * @param commandName 命令名称 * @param td 时间维度 * @return */ public List getAppCommandStatsList(@Param("appId") long appId, @Param("commandName") String commandName, @Param("td") TimeDimensionality td); /** * 按应用命令统计 * * @param appId 应用id * @param td 时间维度 * @return */ public List getAppAllCommandStatsList(@Param("appId") long appId,@Param("td") TimeDimensionality td); /** * * @param appId * @param beginTime * @param endTime * @param commandName * @return */ public List getAppCommandStatsListByMinuteWithCommand(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime, @Param("commandName") String commandName); /** * * @param appId * @param beginTime * @param endTime * @param commandName * @return */ public List getAppCommandStatsListByHourWithCommand(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime, @Param("commandName") String commandName); /** * * @param appId * @param beginTime * @param endTime * @return */ public List getAppAllCommandStatsListByMinute(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * * @param appId * @param beginTime * @param endTime * @return */ public List getAppAllCommandStatsListByHour(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 查询一天中应用的命令执行次数的topN * * @param appId 应用id * @param td 时间维度 * @return */ public List getTopAppCommandStatsList(@Param("appId") long appId, @Param("td") TimeDimensionality td, @Param("top") int top); /** * 查询一段时间内,各个命令执行次数分布 * * @param appId 应用id * @param td 时间维度 * @return */ public List getTopAppCommandGroupSum(@Param("appId") long appId, @Param("td") TimeDimensionality td, @Param("top") int top); /** * 获取一定时间内命令峰值 * * @param appId * @param commandName * @param td 时间维度 * @return */ public AppCommandStats getCommandClimax(@Param("appId") long appId, @Param("commandName") String commandName, @Param("td") TimeDimensionality td); public AppCommandStats getCommandClimaxCount(@Param("appId") long appId, @Param("commandName") String commandName, @Param("td") TimeDimensionality td); public AppCommandStats getCommandClimaxCreateTime(@Param("appId") long appId, @Param("commandName") String commandName, @Param("commandCount") long commandCount, @Param("td") TimeDimensionality td); /** * 获取应用命令调用次数分布 * * @param appId * @param td 时间维度 * @return */ public List getAppCommandGroup(@Param("appId") long appId, @Param("td") TimeDimensionality td); public Long getAppCommandCount(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 应用分钟统计 * @param appId * @param beginTime * @param endTime * @return */ public Map getAppMinuteStat(@Param("appId") long appId, @Param("beginTime") long beginTime, @Param("endTime") long endTime); /** * 碎片率最高的应用 * @param startTime * @param endTime * @return */ public List getTopMemFragRatioApps(@Param("startTime") long startTime,@Param("endTime") long endTime); List getMemFragRatios(@Param("startTime") long startTime,@Param("endTime") long endTime); /** * todo 待下线 * @param startTime * @param endTime * @return */ List getExceptionCount(@Param("startTime") long startTime,@Param("endTime") long endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppToUserDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppToUser; /** * 用户-应用对应关系 * * @author leifu * @Time 2014年6月5日 */ public interface AppToUserDao { List getByUserId(@Param("userId") Long userId); Long save(AppToUser appToUser); void deleteByAppId(@Param("appId") Long appId); List getByAppId(@Param("appId") Long appId); void deleteAppToUser(@Param("appId") long appId, @Param("userId") long userId); void takeOverAppToUser(@Param("appId") long appId, @Param("originUserId") long originUserId, @Param("newUserId") long newUserId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/AppUserDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import com.sohu.cache.web.vo.AppUserVo; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.AppUser; /** * 用户管理dao * @author leifu * @Time 2014年6月5日 */ public interface AppUserDao { public AppUser get(@Param("id") Long id); public int save(AppUser user); public int update(AppUser user); public int delete(@Param("id") Long id); public int updatePwd(@Param("id") Long id, @Param("password") String password); public AppUser getByName(@Param("name") String name); AppUser getByEmail(@Param("email") String email); public List getUserList(@Param("chName") String chName); public List getUserWithBizList(@Param("chName") String chName, @Param("bizName") String bizName); List getAdminList(); public List getAllUser(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/ConfigDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.SystemConfig; /** * 配置修改dao * * @author leifu * @Date 2016年5月23日 * @Time 下午12:51:45 */ public interface ConfigDao { /** * 更新配置对key-value * * @param configKey * @param configValue */ public void update(@Param("configKey") String configKey, @Param("configValue") String configValue); /** * 获取配置列表 * * @param status * @return */ public List getConfigList(@Param("status") int status); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/ConfigRestartRecordDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.ConfigRestartRecord; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/10/14 15:58 * @Description: 重启记录 */ public interface ConfigRestartRecordDao { /** * @param configRestartRecord */ void save(ConfigRestartRecord configRestartRecord); /** * @param id * @return */ ConfigRestartRecord getById(@Param("id") long id); /** * 更新记录状态 * * @param id * @param status */ void updateStatus(@Param("id") long id, @Param("status") int status); /** * 根据条件更新 * * @param configRestartRecord */ void updateByCondition(ConfigRestartRecord configRestartRecord); /** * 获取重启记录列表 * @param configRestartRecord * @return */ List getListByCondition(ConfigRestartRecord configRestartRecord); /** * 获取重启记录条数 * @param configRestartRecord * @return */ int getCountByCondition(ConfigRestartRecord configRestartRecord); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/DiagnosticTaskRecordDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.DiagnosticTaskRecord; import org.apache.ibatis.annotations.Param; import java.util.List; /** * @Author: rucao * @Date: 2020/6/9 16:49 */ public interface DiagnosticTaskRecordDao { long insertDiagnosticTaskRecord(DiagnosticTaskRecord diagnosticTaskRecord); int updateDiagnosticStatus(@Param("id") long id, @Param("redisKey") String redisKey, @Param("status") int status, @Param("cost") long cost); List getDiagnosticTaskRecords(@Param("appId") Long appId, @Param("parentTaskId") Long parentTaskId, @Param("auditId") Long auditId, @Param("type") Integer type, @Param("status") Integer status); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceAlertConfigDao.java ================================================ package com.sohu.cache.dao; import java.util.Date; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.InstanceAlertConfig; /** * 实例报警配置Dao * @author leifu * @Date 2017年5月19日 * @Time 上午11:56:56 */ public interface InstanceAlertConfigDao { int save(InstanceAlertConfig instanceAlertConfig); int batchSave(List instanceAlertConfigList); List getAll(); List getByType(@Param("type") int type); List getByTypeAndAppType(@Param("type") int type, @Param("appType") int appType); List getByAlertConfig(@Param("alertConfig") String alertConfig); List getByAlertConfigAndType(@Param("alertConfig") String alertConfig, @Param("type") int type, @Param("appType") Integer appType); InstanceAlertConfig get(@Param("id") int id); int remove(@Param("id") int id); void update(@Param("id") long id, @Param("alertValue") String alertValue, @Param("checkCycle") int checkCycle, @Param("compareType") int compareType, @Param("importantLevel") int importantLevel); void updateImportantLevel(@Param("alertConfig") String alertConfig, @Param("compareType") int compareType, @Param("importantLevel") int importantLevel, @Param("appType") int appType); void updateLastCheckTime(@Param("id") long id, @Param("lastCheckTime") Date lastCheckTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceBigKeyDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.task.entity.InstanceBigKey; import com.sohu.cache.web.util.Page; import org.apache.ibatis.annotations.Param; import java.util.List; public interface InstanceBigKeyDao { /** * 批量保存bigkey * @param instanceBigKeyList * @return */ int batchSave(@Param("instanceBigKeyList") List instanceBigKeyList); /** * @param appId * @param auditId * @return */ int getAppBigKeyCount(@Param("appId") long appId, @Param("auditId") long auditId); /** * @param appId * @param auditId * @param page * @return */ List getAppBigKeyList(@Param("appId") long appId, @Param("auditId") long auditId, @Param("page") Page page); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceConfigDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.InstanceConfig; /** * 配置模板Dao * * @author leifu * @Date 2016年6月22日 * @Time 下午5:46:37 */ public interface InstanceConfigDao { /** * 获取所有配置模板 * @return */ List getAllInstanceConfig(); /** * 根据redis版本获取对应模板配置 * @param versionId redis版本主键id * @return redis版本所有配置项 */ List getConfigByRedisVersionId(@Param("versionId") int versionId); /** * 根据type获取配置模板列表 * * @param type * @return */ List getByType(@Param("type") int type); /** * 根据redis version 和 type获取配置模板列表 * @param type * @return */ List getByVersionAndType(@Param("type") int type,@Param("versionId") int versionId); /** * 根据redis version获取配置模板列表 * @param versionId * @return */ List getByVersion(@Param("versionId") int versionId); /** * 保存或者更新配置模板 * * @param instanceConfig * @return */ int saveOrUpdate(InstanceConfig instanceConfig); /** * 根据id获取配置模板 * * @param id * @return */ InstanceConfig getById(@Param("id") long id); /** * 根据configKey和type获取配置 * * @param configKey * @param type * @return */ InstanceConfig getByConfigKeyAndType(@Param("configKey") String configKey, @Param("type") int type); /** * 更改配置状态 * @param id * @param status * @return */ int updateStatus(@Param("id") long id, @Param("status") int status); /** * 删除配置 * @param id * @return */ int remove(@Param("id") long id); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.InstanceInfo; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** * 基于instance的dao操作 *

* User: lingguo * Date: 14-6-3 * Time: 下午3:58 */ public interface InstanceDao { /** * 通过type查询实例列表 * * @param type * @return */ public List getInstListByType(@Param("type") int type); /** * 查询appId下的所有instance * * @param appId * @return */ public List getInstListByAppId(@Param("appId") long appId); /** * 查询appId下的有效的instance * * @param appId * @return */ public List getEffectiveInstListByAppId(@Param("appId") long appId); /** * 通过host和port查询一个实例信息 * * @param ip * @param port * @return */ public InstanceInfo getInstByIpAndPort(@Param("ip") String ip, @Param("port") int port); /** * 通过host和port查询一个实例信息 * * @param ip * @param port * @return */ public InstanceInfo getAllInstByIpAndPort(@Param("ip") String ip, @Param("port") int port); /** * 通过所有实例列表(包括:0:节点异常,1:正常启用) */ public List getAllInsts(); /** * 检测当前机器心跳停止的实例 */ public List checkHeartStopInstance(@Param("ip") String ip); /** * 获取机器所有心跳停止的实例 */ public List getAllHeartStopInstance(); /** * 通过host和port查询一个实例信息 * * @param ip * @param port * @return */ public int getCountByIpAndPort(@Param("ip") String ip, @Param("port") int port); /** * 保存一个实例 * * @param instanceInfo */ public void saveInstance(InstanceInfo instanceInfo); /** * 根据ip和type查询实例数量 * * @param ip * @param type * @return */ public int getInstanceTypeCount(@Param("ip") String ip, @Param("type") int type); public List getInstancesByType(@Param("app_id") long app_id, @Param("type") int type); public InstanceInfo getInstanceInfoById(@Param("id") long id); public int getMemoryByHost(String host); public int getInstanceCountByHost(@Param("host") String host); public int update(InstanceInfo instanceInfo); /** * 获取一台机器的所有实例 * * @param ip * @return */ public List getInstListByIp(@Param("ip") String ip); /** * 机器实例数map * * @return */ public List> getMachineInstanceCountMap(); /** *

* Description:获取有效的实例id *

* @author chenshi * @version 1.0 * @date 2017/8/14 */ public List> getTotalEffectiveInst(); List getAppIdListByIp(List ipList); /** * 更新实例状态 * @param appId * @param ip * @param port * @param status */ public void updateStatus(@Param("appId") long appId,@Param("ip") String ip,@Param("port") int port,@Param("status") int status); /** * 根据条件查询实例列表 * @param instanceInfo * @return */ public List getInstancesByCondition(InstanceInfo instanceInfo); /** * 根据条件(应用ids, 实例ip:port)查询已下线实例列表 * @param appIds * @param hostports * @return */ public List getOfflineInstByAppIdAndHostport(@Param("appIds") List appIds, @Param("hostports") List hostports); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceFaultDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.InstanceFault; import java.util.List; /** * Created by yijunzhang on 14-12-29. */ public interface InstanceFaultDao { /** * 添加InstanceFault实例 * * @return */ int insert(InstanceFault instanceFault); /** * 实例故障列表 * * @param instId * @return */ List getListByInstId(int instId); /** * 应用故障列表 * * @param appId * @return */ List getListByAppId(long appId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceLatencyHistoryDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientStatisticGather; import com.sohu.cache.entity.InstanceLatencyHistory; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Map; /** * @Author: rucao * @Date: 2020/5/7 4:57 下午 */ @Repository public interface InstanceLatencyHistoryDao { int batchSave(List instanceLatencyHistoryList); List> getAppLatencyStats(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); int getAppLatencyStatsCount(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); List> getAppLatencyStatsGroupByInstance(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime); List> getAppLatencyInfo(@Param("appId") long appId, @Param("startTime") long startTime, @Param("endTime") long endTime, @Param("event") String event); List getAppLatencyCountStat(@Param("startTime") long startTime, @Param("endTime") long endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceReshardProcessDao.java ================================================ package com.sohu.cache.dao; import java.util.Date; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.InstanceReshardProcess; /** * 实例Reshard进度保存 * @author leifu * @Date 2017年6月24日 * @Time 下午7:17:36 */ public interface InstanceReshardProcessDao { int save(InstanceReshardProcess instanceReshardProcess); List getByAuditId(@Param("auditId") long auditId); int updateStatus(@Param("id") long id, @Param("status") int status); int updateEndTime(@Param("id") long id, @Param("endTime") Date endTime); int increaseFinishSlotNum(@Param("id") long id); int updateMigratingSlot(@Param("id") int id, @Param("migratingSlot") int migratingSlot); InstanceReshardProcess get(@Param("id") int id); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceSlowLogDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.AppClientStatisticGather; import com.sohu.cache.entity.InstanceSlowLog; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Param; /** * 实例慢查询dao * * @author leifu * @Date 2016年2月22日 * @Time 下午1:48:43 */ public interface InstanceSlowLogDao { /** * 批量报错实例慢查询 * @param instanceSlowLogList */ int batchSave(List instanceSlowLogList); /** * 按照应用id获取慢查询列表 * @param appId * @return */ List getByAppId(@Param("appId") long appId); /** * 搜索慢查询日志 */ List search(@Param("appId") long appId, @Param("startDate") Date startDate, @Param("endDate") Date endDate); List getByInstanceExecuteTime(@Param("instanceId") long instanceId, @Param("executeDate") String executeDate); /** * * @param appId * @param startDate * @param endDate * @return */ List> getInstanceSlowLogCountMapByAppId(@Param("appId") long appId, @Param("startDate") Date startDate, @Param("endDate") Date endDate); /** * 获取指定日期慢查询个数 * @param appId * @param startDate * @param endDate * @return */ int getAppSlowLogCount(@Param("appId") long appId, @Param("startDate") Date startDate, @Param("endDate") Date endDate); List getAppSlowLogCountStat(@Param("startTime") long startTime, @Param("endTime") long endTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/InstanceStatsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.entity.MachineInstanceStat; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** * 实例统计相关DAO */ public interface InstanceStatsDao { public void updateInstanceStats(InstanceStats instanceStats); public InstanceStats getInstanceStatsByHost(@Param("ip") String ip, @Param("port") long port); public InstanceStats getInstanceStatsByInsId(@Param("id") long id); public List getInstanceStatsByAppId(@Param("appId") long appId); public List getInstanceStats(); public List getInstanceStatsByIp(@Param("ip") String ip); Map getMachineMemByIp(@Param("ip") String ip); /** *

* Description:获取所有的memory *

* @author chenshi * @version 1.0 * @date 2017/8/14 */ public Map getTotalMem(); /** *

* Description:获取有效redis实例 master使用的memory *

* @author chenshi * @version 1.0 * @date 2017/8/14 */ public Map getTotalAppMem(List instancelist); /** *

* Description: 获取实例统计信息 *

* @author chenshi * @version 1.0 * @date 2019/2/22 */ public List getMachineInstanceStatList(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/MachineDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineMemStatInfo; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** * 机器相关的操作 *

* User: lingguo * Date: 14-6-12 * Time: 下午2:33 */ public interface MachineDao { /** * 返回所有可用的机器资源 * * @return */ public List getAllMachines(); /** * 通过ip查询机器信息 * * @param ip * @return */ public MachineInfo getMachineInfoByIp(@Param("ip") String ip); /** * 通过ip&版本安装情况机器信息 * * @param ipLike * @param versionStr * @return */ public List getMachineInfoByCondition(@Param("ipLike") String ipLike, @Param("useType") int useType, @Param("type") int type, @Param("versionStr") String versionStr, @Param("k8sType") int k8sType, @Param("realip") String realip); /** * 通过ip模糊查找机器 * @param ipLike * @param realIpLike * @return */ public List getMachineListByCondition(@Param("ipLike") String ipLike, @Param("realIpLike") String realIpLike); /** * @Description: 通过room&useType查询机器信息 * @Author: caoru * @CreateDate: 2018/10/12 11:39 */ List getMachineMemStatInfoByCondition(@Param("room") String room, @Param("useType") int useType); List getMachineMemStatInfoByIpList(@Param("list") List list); /** * 通过ip列表查询机器信息 * @param list * @return */ List getMachineInfoByIpList(@Param("list") List list); /** * 通过ip模糊查询机器信息 * * @param ipLike * @return */ public List getMachineInfoByLikeIp(@Param("ipLike") String ipLike); /** * 保存一条机器信息 * * @param machineInfo */ public void saveMachineInfo(MachineInfo machineInfo); /** * 根据ip删除一台机器的信息; * * @param ip */ public void removeMachineInfoByIp(@Param("ip") String ip); /** * 根据ip更新物理机ip * * @param real_ip * @param ip * @return */ int updateMachineRealIpByIp(@Param("real_ip") String real_ip, @Param("ip") String ip); /** * k8s容器:ip+k8s_type * * @param ip * @return */ MachineInfo existk8sMachine(@Param("ip") String ip); /** * 获取k8s机器的信息 * * @return */ List getK8sMachineList(); /** * 获取k8s容器的信息 * * @return */ List getMachineList(); /** * 通过type查询机器列表 * * @param type * @return */ public List getMachineInfoByType(@Param("type") int type); /** *

* Description:获取所有机器的内存统计情况 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/8/14 */ public Map getTotalMachineMem(); /** *

* Description: 获取机房分布情况 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2019/2/27 */ public List> getRoomStat(); /** * 更新机器分配状态 * * @param ip * @param status */ public void updateMachineAllocate(@Param("ip") String ip, @Param("status") int status); /** * 获取机器配置信息及已分布redis实例(数量、申请内存、使用内存、使用内存rss等) */ public List getMachineInfoAndUsedInfo(@Param("room") String room, @Param("type") Integer type, @Param("useType") Integer useType, @Param("disType") Integer disType, @Param("ip") String ip); /** * 通过realIp查找机器 * @param realIp * @return */ public List getMachineListByRealIp(@Param("realIp") String realIp); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/MachineRelationDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.MachineRelation; import org.apache.ibatis.annotations.Param; import java.util.List; /** * Created by chenshi on 2019/5/21. */ public interface MachineRelationDao { /** * 保存pod实例变更状态 * * @param machineRelation */ public void saveOrUpdateMachineRelation(MachineRelation machineRelation); /** * 更新任务taskid */ public void updateMachineRelation(@Param("id") int id, @Param("taskid") long taskid, @Param("is_sync") long is_sync); /** * 获取容器的trace记录 * * @param ip */ public List getRelationList(@Param("ip") String ip); /** * 获取pod online的容器记录 * @param ip * @param status */ public List getOnlinePodList(@Param("ip") String ip,@Param("status") int status); /** * 获取容器的trace记录 * * @param ip * @param real_ip */ public List getUnSyncRelationList(@Param("ip") String ip, @Param("real_ip") String real_ip); /** * 更新机器同步状态 * * @param id * @param is_sync */ public void updateMachineSyncStatus(@Param("id") int id, @Param("is_sync") int is_sync); /** * 检测任务的状态 * @param ip * @param real_ip * @param is_sync * @return */ public List getMachineSyncStatus(@Param("ip") String ip, @Param("real_ip") String real_ip, @Param("is_sync") long is_sync); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/MachineRoomDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.MachineRoom; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Options; import org.apache.ibatis.annotations.Select; import java.util.List; /** * Created by chenshi on 2018/10/16. */ public interface MachineRoomDao { @Select("select * from machine_room where status=1") List getEffectiveRoom(); @Select("select * from machine_room") List getAllRoom(); @Insert("insert into machine_room(id, name, status, `desc`, ip_network, operator) values (#{id},#{name},#{status},#{desc},#{ipNetwork},#{operator})" + " on duplicate key update name=#{name},status=#{status},`desc`=#{desc},ip_network=#{ipNetwork},operator=#{operator}") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") int saveRoom(MachineRoom room); @Delete("delete from machine_room where id=#{id}") void removeRoom(long id); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/MachineStatsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.entity.MachineStats; import org.apache.ibatis.annotations.Param; import java.util.List; /** * Created by yijunzhang on 14-6-25. */ public interface MachineStatsDao { /** * 插入或更新machineInfo */ public void mergeMachineStats(MachineStats machineStats); /** * 查询机器下的所有实例的信息 * * @param ip * @return */ public List getInstInfoOfMachine(@Param("ip") String ip); /** * 查询ip所在的机器的最新状态信息 * * @param ip ip * @return 机器的最新状态 */ public MachineStats getMachineStatsByIp(@Param("ip") String ip); /** * 根据机器的hostId查询机器的最新状态信息 * * @param hostId * @return */ public MachineStats getMachineStatsByHostId(@Param("hostId") long hostId); /** * 查询机器下的所有实例的最新状态信息 * * @param hostId 机器的hostId * @return 该机器下所有实例的最新统计状态 */ public List getInstStatOfMachine(@Param("hostId") long hostId); /** * 分页查询机器统计 * @param ipLike * @return */ public List getMachineStats(@Param("ipLike") String ipLike); /** * 获取全部机器统计 * @return */ public List getAllMachineStats(); /** * 删除机器统计信息 * @param ip * @return */ public void deleteMachineStatsByIp(@Param("ip") String ip); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/QuartzDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.TriggerInfo; import org.apache.ibatis.annotations.Param; import java.util.List; /** * quartz相关的dao操作 * * @author: lingguo * @time: 2014/10/13 14:44 */ public interface QuartzDao { public List getTriggersByJobGroup(String jobGroup); public List getAllTriggers(); public List searchTriggerByNameOrGroup(String queryString); public int getMisFireTriggerCount(); public int getTriggerStateCount(@Param("triggerState") String triggerState); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/ResourceDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.SystemResource; import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** * Created by chenshi on 2020/7/6. */ public interface ResourceDao { List getResourceList(@Param("resourceType") int resourceType); List getResourceListByName(@Param("resourceType") int resourceType,@Param("searchName") String searchName); SystemResource getResourceById(@Param("resourceId") int resourceId); SystemResource getResourceByName(@Param("resourceName") String resourceName); void save(SystemResource systemResource); void update(SystemResource systemResource); List> getAppUseRedis(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/ServerStatusDao.java ================================================ package com.sohu.cache.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.sohu.cache.entity.ServerInfo; import com.sohu.cache.entity.ServerStatus; import com.sohu.cache.server.data.Server; /** * 服务器状态信息持久化 */ public interface ServerStatusDao { /** * 查询服务器基本信息 * @param ip * @return @ServerInfo */ public ServerInfo queryServerInfo(@Param("ip") String ip); public List getAllServerInfo(); /** * 保存服务器发行版信息 * @param ip * @param dist from /etc/issue */ public void saveServerInfo(@Param("ip") String ip, @Param("dist") String dist); /** * 删除服务器信息 * @param ip * @return 删除的数量 */ public Integer deleteServerInfo(@Param("ip") String ip); /** * 保存/更新服务器信息 * @param server * @return 影响的行数 */ public Integer saveAndUpdateServerInfo(@Param("server")Server server); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerStatus(@Param("ip") String ip, @Param("cdate") String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerOverview(@Param("ip") String ip, @Param("cdate") String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerCpu(@Param("ip") String ip, @Param("cdate") String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerNet(@Param("ip") String ip, @Param("cdate") String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerDisk(@Param("ip") String ip, @Param("cdate") String date); /** * 保存服务器状态 * @param Server */ public void saveServerStat(@Param("server") Server server); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/StandardStatsDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.entity.StandardStats; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; /** * 实例统计相关DAO */ public interface StandardStatsDao { public int mergeStandardStats(StandardStats standardStats); public int mergeInstanceMinuteStats(StandardStats standardStats); public StandardStats getStandardStats(@Param("collectTime") long collectTime, @Param("ip") String ip, @Param("port") int port, @Param("dbType") String dbType); public List getDiffJsonList(@Param("beginTime") long beginTime, @Param("endTime") long endTime, @Param("ip") String ip, @Param("port") int port, @Param("dbType") String dbType); public int deleteStandardStatsLessCreatedTime(@Param("createdTime") Date createdTime); public List getStandardStatsByCreateTime(@Param("beginTime") Date beginTime, @Param("endTime") Date endTime, @Param("dbType") String dbType); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/TaskQueueDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.task.entity.TaskSearch; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; public interface TaskQueueDao { /** * @param taskQueue */ void save(TaskQueue taskQueue); /** * @param taskId * @return */ TaskQueue getById(@Param("taskId") long taskId); /** * 更新任务状态 * * @param taskId * @param status */ void updateStatus(@Param("taskId") long taskId, @Param("status") int status); /** * 更新任务参数 * * @param taskId * @param param */ void updateParam(@Param("taskId") long taskId, @Param("param") String param); /** * 根据status获取任务列表 * * @param status * @return */ List getTaskQueueListByStatus(@Param("status") int status); /** * 更新开始时间 * * @param taskId * @param startTime */ void updateStartTime(@Param("taskId") long taskId, @Param("startTime") Date startTime); /** * 更新结束时间 * * @param taskId * @param endTime */ void updateEndTime(@Param("taskId") long taskId, @Param("endTime") Date endTime); /** * @param taskSearch * @return */ int getTaskQueueCount(TaskSearch taskSearch); /** * @param taskSearch * @return */ List getTaskQueueList(TaskSearch taskSearch); /** * @param taskId * @return */ List getChildTaskQueueList(@Param("taskId") long taskId); /** * @param status * @return */ int getStatusCount(int status); /** * @param taskId * @param executeIpPort */ void updateExecuteIpPort(@Param("taskId") long taskId, @Param("executeIpPort") String executeIpPort); /** * @param appId * @param className * @return */ List getByAppAndClass(@Param("appId") long appId, @Param("className") String className); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/TaskStepFlowDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.task.entity.TaskStepFlow; import org.apache.ibatis.annotations.Param; import java.util.Date; import java.util.List; public interface TaskStepFlowDao { /** * @param taskStepFlow */ void save(TaskStepFlow taskStepFlow); /** * @param taskId * @param className * @param stepName * @return */ TaskStepFlow getByTaskClassStep(@Param("taskId") long taskId, @Param("className") String className, @Param("stepName") String stepName); /** * 更新状态 * * @param id * @param status */ void updateStatus(@Param("id") long id, @Param("status") int status); /** * 更新日志 * * @param id * @param log */ void updateLog(@Param("id") long id, @Param("log") String log); /** * 更新开始时间 * * @param id * @param startTime */ void updateStartTime(@Param("id") long id, @Param("startTime") Date startTime); /** * 更新结束时间 * * @param id * @param endTime */ void updateEndTime(@Param("id") long id, @Param("endTime") Date endTime); /** * 获取任务的流列表 * * @param taskId * @return */ List getTaskStepFlowList(@Param("taskId") long taskId); /** * @param id * @param childTaskId */ void updateChildTaskId(@Param("id") long id, @Param("childTaskId") long childTaskId); /** * @param taskId * @param executeIpPort */ void updateExecuteIpPort(@Param("taskId") long taskId, @Param("executeIpPort") String executeIpPort); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/dao/TaskStepMetaDao.java ================================================ package com.sohu.cache.dao; import com.sohu.cache.task.entity.TaskStepMeta; import org.apache.ibatis.annotations.Param; import java.util.List; public interface TaskStepMetaDao { /** * @param taskStepMeta */ void save(TaskStepMeta taskStepMeta); /** * @param className * @return */ List getTaskStepMetaList(@Param("className") String className); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppAlertRecord.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import java.util.Date; /** * @Author: zengyizhao * @DateTime: 2021/9/3 12:00 * @Description: 报警记录 */ @Data public class AppAlertRecord { /** * 记录id */ private long id; /** * 创建时间 */ private Date createTime; /** * 重要度(0:一般;1:重要;2:紧急) */ private int importantLevel; /** * 可见类型(0:均可见;1:仅管理员可见;) */ private int visibleType; /** * 应用id */ private Long appId; /** * 实例id */ private Long instanceId; /** * ip地址 */ private String ip; /** * 端口 */ private Integer port; /** * 报警标题 */ private String title; /** * 报警内容 */ private String content; public String getCreateTimeDesc(){ return DateUtil.formatYYYYMMddHHMMSS(createTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppAudit.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.AppAuditType; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by yijunzhang */ @Data public class AppAudit { private long id; private long appId; private long userId; private long operateId; private String userName; /** * 申请类型:AppAuditType */ private int type; /** * 预留参数1 */ private String param1; /** * 预留参数2 */ private String param2; /** * 预留参数3 */ private String param3; /** * 申请描述 */ private String info; /** * 0:等待审批; 1:审批通过; -1:驳回 */ private int status; private Date createTime; private Date modifyTime; /** * 驳回原因 */ private String refuseReason; /** * 任务ID */ private long taskId; private AppDesc appDesc; private AppAuditLog appAuditLog; public Date getCreateTime() { if (createTime != null) { return (Date) createTime.clone(); } return null; } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getModifyTime() { if (modifyTime == null) { return null; } return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { this.modifyTime = (Date) modifyTime.clone(); } public String getTypeDesc() { if (AppAuditType.getAppAuditType(type) != null) { return AppAuditType.getAppAuditType(type).getInfo(); } return ""; } public String getStatusDesc() { // 0:等待审批; 1:审批通过; -1:驳回 if (status == 0) { return "等待审批"; } else if (status == 1) { return "审批通过"; } else if (status == -1) { return "驳回"; } else { return status + ""; } } public String getCreateTimeFormat() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (createTime != null) { return sdf.format(createTime); } return ""; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppAuditLog.java ================================================ package com.sohu.cache.entity; import java.io.Serializable; import java.util.Date; import lombok.Data; import net.sf.json.JSONObject; import com.sohu.cache.constant.AppAuditLogTypeEnum; /** * 资源的审批发布日志 * @author leifu */ @Data public class AppAuditLog implements Serializable { /** * 日志id */ private Long id; /** * 应用id */ private Long appId; /** * 审批id */ private Long appAuditId; /** * 用户id */ private Long userId; /** * 用户 */ private AppUser appUser; /** * 日志详情 是个json */ private String info; /** * 创建时间 */ private Date createTime; /** * 日志类型 */ private Integer type; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } /** * 生成日志 * @param appDesc * @param appUser * @param appAuditId * @param type * @return */ public static AppAuditLog generate(AppDesc appDesc, AppUser appUser, Long appAuditId, AppAuditLogTypeEnum type){ if(appDesc == null || appUser == null || appAuditId == null){ return null; } AppAuditLog log = new AppAuditLog(); log.setAppId(appDesc.getAppId()); log.setUserId(appUser.getId()); log.setAppAuditId(appAuditId); log.setType(type.value()); log.setCreateTime(new Date()); log.setInfo(JSONObject.fromObject(appDesc).toString()); return log; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppBiz.java ================================================ package com.sohu.cache.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import java.io.Serializable; /** * 系统用户所属业务组 * * @author zengyizhao */ @Data @ApiModel @RequiredArgsConstructor(staticName = "of") @NoArgsConstructor @AllArgsConstructor public class AppBiz implements Serializable { /** * 自增id */ @ApiModelProperty(value = "业务组id",hidden = true) private Long id; /** * 业务组名称 */ @NonNull @ApiModelProperty(value = "业务组名称",required = true) private String name; /** * 备注 */ @NonNull @ApiModelProperty(value = "备注") private String bizDesc; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppCapacityMonitor.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * @Author: zengyizhao * @DateTime: 2022/10/10 9:38 * @Description: 应用容量(自动扩容、缩容审计报表) */ @Data public class AppCapacityMonitor { /** * 记录id */ private long id; /** * 应用id */ private Long appId; /** * 应用主节点数 */ private Integer shardingMasterNum; /** * 应用初始内存 */ private long mem; /** * 应用当前内存 */ private long curMem; /** * 应用使用内存 */ private long memUsed; /** * 应用已使用内存(历史最大值) */ private long memUsedHistory; /** * 应用分片初始内存 */ private long shardingMem; /** * 应用分片当前内存 */ private long curShardingMem; /** * 分片已使用内存(最大值) */ private long shardingMemUsed; /** * 应用扩容内存使用百分比 */ private Integer expandMemPercent; /** * 扩容比率,单次扩容比率 */ private Integer expandRatio; /** * 当日总扩容比率(超出不可扩容),0:不限制 */ private Integer expandRatioTotal; /** * 是否可扩容: 0否,1是 */ private Integer isExpand; /** * 是否可缩容: 0否,1是 */ private Integer isReduce; /** * 缩容内存使用率最小值 */ private Integer reduceRatioMin; /** * 缩容内存使用率最大值 */ private Integer reduceRatioMax; /** * 更新时间 */ private Date updateTime; /** * 扩容时间(上次扩容时间) */ private Date expandTime; /** * 计划状态:0:无意义;1:待缩容;2:待扩容 */ private Integer scheduleStatus; /** * 计划处理时间 */ private Date scheduleTime; /** * 当日扩容次数限制 */ private int expandCount; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppCapacityStatisticsResult.java ================================================ package com.sohu.cache.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @Author: zengyizhao * @CreateTime: 2023/6/14 16:20 * @Description: 查询应用内存、内存审计统计信息 * @Version: 1.0 */ @Data @NoArgsConstructor @AllArgsConstructor public class AppCapacityStatisticsResult { private long appId; private int versionId; private Long curMem; private Long memUsed; private Integer shardingMasterNum; private double memUsedRatio; public double getMemUsedRatio() { double ratio = 0D; if(curMem != null && memUsed != null && curMem != 0){ String format = String.format("%.2f", memUsed * 1D/ curMem * 100); return Double.parseDouble(format); } return ratio; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientCommandStatistics.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.sql.Date; /** * Created by rucao on 2019/12/13 */ @Data public class AppClientCommandStatistics { private long id; /** * 格式yyyyMMddHHmm00 */ private long currentMin; /** * 客户端ip */ private String clientIp; /** * 应用id */ private long appId; /** * 创建时间 */ private Date createTime; /** * 命令明文 */ private String command; /** * 命令累计毫秒耗时 */ private long cost; /** * 命令调用量 */ private long count; /** * 输入流量 */ private long bytesIn; /** * 输出流量 */ private long bytesOut; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientCostTimeStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * 客户端耗时统计 * @author leifu */ @Data public class AppClientCostTimeStat { private long id; /** * 应用id */ private long appId; /** * 格式yyyyMMddHHmm00 */ private long collectTime; /** * 客户端ip */ private String clientIp; /** * 上报时间 */ private Date reportTime; /** * 创建时间 */ private Date createTime; /** * 命令 */ private String command; /** * 调用次数 */ private int count; /** * 实例ip */ private String instanceHost; /** * 实例port */ private int instancePort; /** * 实例id */ private long instanceId; /** * 中位值 */ private int median; /** * 平均值 */ private double mean; /** * 90%最大值 */ private int ninetyPercentMax; /** * 99%最大值 */ private int ninetyNinePercentMax; /** * 100%最大值 */ private int hundredMax; public Date getReportTime() { return (Date) reportTime.clone(); } public void setReportTime(Date reportTime) { this.reportTime = (Date) reportTime.clone(); } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Long getCollectTimeStamp() throws ParseException{ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Date date; try { date = sdf.parse(String.valueOf(this.collectTime)); return date.getTime(); } catch (Exception e) { return 0L; } } public Long getTimeStamp() throws ParseException{ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); Date date = sdf.parse(String.valueOf(this.collectTime)); return date.getTime(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((clientIp == null) ? 0 : clientIp.hashCode()); result = prime * result + (int) (instanceId ^ (instanceId >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AppClientCostTimeStat other = (AppClientCostTimeStat) obj; if (clientIp == null) { if (other.clientIp != null) return false; } else if (!clientIp.equals(other.clientIp)) return false; if (instanceId != other.instanceId) return false; return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientCostTimeTotalStat.java ================================================ package com.sohu.cache.entity; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import lombok.Data; import org.apache.commons.lang.math.NumberUtils; /** * 基于应用全局耗时统计(uniquekey: app_id, command, collect_time) * @author leifu */ @Data public class AppClientCostTimeTotalStat { private long id; /** * 应用id */ private long appId; /** * 格式yyyyMMddHHmm00 */ private long collectTime; /** * 创建时间 */ private Date createTime; /** * 命令 */ private String command; /** * 调用总次数 */ private long totalCount; /** * 调用总耗时 */ private double totalCost; /** * 中位值 */ private int median; /** * 平均值 */ private double mean; /** * 90%最大值 */ private int ninetyPercentMax; /** * 99%最大值 */ private int ninetyNinePercentMax; /** * 100%最大值 */ private int hundredMax; /** * 实例ip */ private String maxInstanceHost; /** * 实例port */ private int maxInstancePort; /** * 实例id */ private long maxInstanceId; /** * 客户端 */ private String maxClientIp; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public AppClientCostTimeTotalStat(long id, long appId, long collectTime, Date createTime, String command, long totalCount, double totalCost, int median, double mean, int ninetyPercentMax, int ninetyNinePercentMax, int hundredMax, String maxInstanceHost, int maxInstancePort, long maxInstanceId, String maxClientIp) { this.id = id; this.appId = appId; this.collectTime = collectTime; this.createTime = createTime; this.command = command; this.totalCount = totalCount; this.totalCost = totalCost; this.median = median; this.mean = mean; this.ninetyPercentMax = ninetyPercentMax; this.ninetyNinePercentMax = ninetyNinePercentMax; this.hundredMax = hundredMax; this.maxInstanceHost = maxInstanceHost; this.maxInstancePort = maxInstancePort; this.maxInstanceId = maxInstanceId; this.maxClientIp = maxClientIp; } public AppClientCostTimeTotalStat() { } public Long getTimeStamp() { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); try { Date date = sdf.parse(String.valueOf(this.collectTime)); return date.getTime(); } catch (ParseException e) { return 0L; } } public static AppClientCostTimeTotalStat getFromAppClientCostTimeStat(AppClientCostTimeStat stat) { AppClientCostTimeTotalStat appClientCostTimeTotalStat = new AppClientCostTimeTotalStat(); appClientCostTimeTotalStat.setAppId(stat.getAppId()); appClientCostTimeTotalStat.setCollectTime(stat.getCollectTime()); appClientCostTimeTotalStat.setCommand(stat.getCommand()); appClientCostTimeTotalStat.setCreateTime(stat.getCreateTime()); appClientCostTimeTotalStat.setMean(stat.getMean()); appClientCostTimeTotalStat.setMedian(stat.getMedian()); appClientCostTimeTotalStat.setHundredMax(stat.getHundredMax()); appClientCostTimeTotalStat.setNinetyPercentMax(stat.getNinetyPercentMax()); appClientCostTimeTotalStat.setNinetyNinePercentMax(stat.getNinetyNinePercentMax()); appClientCostTimeTotalStat.setMaxClientIp(stat.getClientIp()); appClientCostTimeTotalStat.setMaxInstanceHost(stat.getInstanceHost()); appClientCostTimeTotalStat.setMaxInstancePort(stat.getInstancePort()); appClientCostTimeTotalStat.setMaxInstanceId(stat.getInstanceId()); appClientCostTimeTotalStat.setMaxClientIp(stat.getClientIp()); //保留两位小数 DecimalFormat df = new DecimalFormat("#.00"); appClientCostTimeTotalStat.setTotalCost(NumberUtils.toDouble(df.format(stat.getMean() * stat.getCount()))); appClientCostTimeTotalStat.setTotalCount(stat.getCount()); return appClientCostTimeTotalStat; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientDataSizeStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 客户端内收集数据map的尺寸 * * @author leifu */ @Data public class AppClientDataSizeStat { private long id; /** * 格式yyyyMMddHHmm00 */ private long collectTime; /** * 客户端ip */ private String clientIp; /** * 上报时间 */ private Date reportTime; /** * 创建时间 */ private Date createTime; /** * 耗时map尺寸 */ private int costMapSize; /** * 值map尺寸 */ private int valueMapSize; /** * 异常map尺寸 */ private int exceptionMapSize; /** * 收集map尺寸 */ private int collectMapSize; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getReportTime() { return (Date) reportTime.clone(); } public void setReportTime(Date reportTime) { this.reportTime = (Date) reportTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientExceptionStat.java ================================================ package com.sohu.cache.entity; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import lombok.Data; /** * 客户端异常统计 * @author leifu */ @Data public class AppClientExceptionStat { private long id; /** * 应用id */ private long appId; /** * 格式yyyyMMddHHmm00 */ private long collectTime; /** * 客户端ip */ private String clientIp; /** * 上报时间 */ private Date reportTime; /** * 创建时间 */ private Date createTime; /** * 异常类 */ private String exceptionClass; /** * 异常数 */ private Long exceptionCount; /** * 实例ip */ private String instanceHost; /** * 实例port */ private Integer instancePort; /** * 实例id */ private Integer instanceId; /** * 异常类型,参考ClientExceptionType.type */ private Integer type; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getReportTime() { return (Date) reportTime.clone(); } public void setReportTime(Date reportTime) { this.reportTime = (Date) reportTime.clone(); } public String getCollectTimeFormat(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); try { Date date = sdf.parse(String.valueOf(collectTime)); SimpleDateFormat newSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return newSdf.format(date); } catch (ParseException e) { return ""; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientExceptionStatistics.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.sql.Date; /** * Created by rucao on 2019/12/13 */ @Data public class AppClientExceptionStatistics { private long id; /** * 格式yyyyMMddHHmm00 */ private long currentMin; /** * 客户端ip */ private String clientIp; /** * 客户端连接池配置信息 */ private String redisPoolConfig; /** * 0:连接失败;1:命令调用超时 */ private int type; /** * 应用id */ private long appId; /** * 创建时间 */ private Date createTime; /** * 节点信息host:port */ private String node; /** * type=4(连接失败):累计连接失败次数 * type=5(命令调用超时):累计超时次数 */ private long count; /** * type=4(连接失败):累计连接失败毫秒耗时 * type=5(命令调用超时):累计超时毫秒耗时 */ private long cost; /** * type=5(命令调用超时):统计命令topN id,逗号分隔 */ private String latencyCommands; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientLatencyCommand.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by rucao on 2019/12/13 */ @Data public class AppClientLatencyCommand { private long id; /** * 长命令裁剪后明文 */ private String command; /** * args 截取的命令明文 */ private String args; /** * 命令参数大小 */ private long size; /** * 命令执行时间 */ private long invokeTime; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientStatisticGather.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.sql.Date; /** * Created by rucao on 2019/12/29 */ @Data public class AppClientStatisticGather { private long id; /** * 创建时间 */ private Date createTime; /** * 应用id */ private long appId; /** * 格式yyyy-MM-dd 收集时间 */ private String gatherTime; /** * 累计命令调用次数 */ private long cmdCount; /** * 平均命令调用耗时 */ private double avgCmdCost; /** * 累计连接异常事件次数 */ private int connExpCount; /** * 平均连接异常事件耗时 */ private double avgConnExpCost; /** * 累计命令超时事件次数 */ private int cmdExpCount; /** * 平均命令超时事件耗时 */ private double avgCmdExpCost; /** * 应用实例数 */ private int instanceCount; /** * 平均碎片率 */ private double avgMemFragRatio; /** * 内存使用率 */ private double memUsedRatio; /** * 异常数(旧,待下线) */ private int exceptionCount; /** * 慢查询次数 */ private int slowLogCount; /** * 延迟事件统计 */ private int latencyCount; /** * 客户端连接数 */ /** * 存储对象数 */ private long objectSize; /** * 应用客户端连接数 */ private long connectedClients; /** * 内存占用 byte */ private long usedMemory; /** * 物理内存占用 byte */ private long usedMemoryRss; /** * 进程系统态消耗(单位:秒) */ private long maxCpuSys; /** * 进程用户态消耗(单位:秒) */ private long maxCpuUser; /** * 拓扑诊断结果,0:正常,1:异常 */ private int topologyExamResult; /** * 磁盘使用量 byte */ private long usedDisk; /** * server端统计的命令调用次数 */ private long serverCmdCount; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientValueDistriSimple.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.ValueSizeDistriEnum; import lombok.Data; /** * @author leifu */ @Data public class AppClientValueDistriSimple { /** * 值分布类型 */ private int distributeType; /** * 调用次数 */ private long count; public String getDistributeDesc() { ValueSizeDistriEnum valueSizeDistriEnum = ValueSizeDistriEnum.getByType(distributeType); return valueSizeDistriEnum == null ? "" : valueSizeDistriEnum.getInfo(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientValueDistriStatTotal.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 客户端值分布统计 * * @author leifu */ @Data public class AppClientValueDistriStatTotal { /** * 应用id */ private long appId; /** * 格式yyyyMMddHHmm00 */ private long collectTime; /** * 创建时间 */ private Date updateTime; /** * 命令 */ private String command; /** * 值分布类型 */ private int distributeType; /** * 调用次数 */ private int count; public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppClientVersion.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 客户端版本 * @author leifu */ @Data public class AppClientVersion { /** * 自增id */ private long id; /** * 应用id */ private long appId; /** * 客户端ip */ private String clientIp; /** * 客户端版本 */ private String clientVersion; /** * 上报时间 */ private Date reportTime; public Date getReportTime() { return (Date) reportTime.clone(); } public void setReportTime(Date reportTime) { this.reportTime = (Date) reportTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppCommandGroup.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 命令分布 */ @Data public class AppCommandGroup { /** * 命令名 */ private String commandName; /** * 调用次数 */ private long count; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppCommandStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * Created by yijunzhang */ @Data public class AppCommandStats implements Comparable { /** * 应用id */ private long appId; /** * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH */ private long collectTime; /** * 命令名称 */ private String commandName; /** * 命令执行次数 */ private long commandCount; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date modifyTime; @Override public int compareTo(AppCommandStats o) { if (o.commandCount > this.commandCount) { return 1; } else if (o.commandCount < this.commandCount) { return -1; } return 0; } public Date getCreateTime() { if(createTime == null){ return createTime; } return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getModifyTime() { if(modifyTime == null){ return modifyTime; } return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { this.modifyTime = (Date) modifyTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppDailyData.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.vo.AppDetailVO; import lombok.Data; import org.apache.commons.collections.MapUtils; import java.util.Date; import java.util.Map; /** * 应用日报数据 * * @author leifu */ @Data public class AppDailyData { /** * 应用id */ private long appId; /** * 开始日期 */ private Date startDate; /** * 结束日期 */ private Date endDate; /** * 日期 */ private Date date; /** * bigkey次数 */ private long bigKeyTimes; /** * bigkey信息 */ private String bigKeyInfo; /** * 慢查询次数 */ private long slowLogCount; /** * 延迟事件个数 */ private long latencyCount; /** * 客户端异常个数 */ private long clientExceptionCount; /** * 累计命令调用次数 */ private long clientCmdCount; /** * 平均命令调用耗时 */ private double clientAvgCmdCost; /** * 累计连接异常事件次数 */ private long clientConnExpCount; /** * 平均连接异常事件耗时 */ private double clientAvgConnExpCost; /** * 累计命令超时事件次数 */ private long clientCmdExpCount; /** * 平均命令超时事件耗时 */ private double clientAvgCmdExpCost; /** * 每分钟最大客户端连接数 */ private long maxMinuteClientCount; /** * 每分钟平均客户端连接数 */ private long avgMinuteClientCount; /** * 每分钟最大命令数 */ private long maxMinuteCommandCount; /** * 每分钟平均命令数 */ private long avgMinuteCommandCount; /** * 平均命中率 */ private double avgHitRatio; /** * 每分钟最小命中率 */ private double minMinuteHitRatio; /** * 每分钟最大命中率 */ private double maxMinuteHitRatio; /** * 平均内存使用量 */ private long avgUsedMemory; /** * 最大内存使用量 */ private long maxUsedMemory; /** * 过期键个数 */ private long expiredKeysCount; /** * 剔除键个数 */ private long evictedKeysCount; /** * 每分钟平均网络input量 */ private double avgMinuteNetInputByte; /** * 每分钟最大网络input量 */ private double maxMinuteNetInputByte; /** * 每分钟平均网络output量 */ private double avgMinuteNetOutputByte; /** * 每分钟最大网络output量 */ private double maxMinuteNetOutputByte; /** * 键个数平均值 */ private long avgObjectSize; /** * 键个数最大值 */ private long maxObjectSize; /** * 平均磁盘使用量 */ private long avgUsedDisk; /** * 最大磁盘使用量 */ private long maxUsedDisk; /** * 值分布 */ private Map valueSizeDistributeCountMap; /** * 应用详情 */ private AppDetailVO appDetailVO; public String getValueSizeDistributeCountDesc() { if (MapUtils.isEmpty(valueSizeDistributeCountMap)) { return "无"; } StringBuffer desc = new StringBuffer(); for (Map.Entry entry : valueSizeDistributeCountMap.entrySet()) { desc.append(entry.getKey()).append(":").append(entry.getValue()).append("次
"); } return desc.toString(); } public String getValueSizeDistributeCountDescHtml() { return bigKeyInfo.replace("\n", "
").replace(":", ":\t"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppDataMigrateSearch.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.util.Page; import lombok.Data; /** * 应用数据迁移搜索 * * @author leifu */ @Data public class AppDataMigrateSearch { /** * 迁移id */ private Long migrateId; /** * 源应用id */ private Long sourceAppId; /** * 目标应用id */ private Long targetAppId; /** * 源实例 */ private String sourceInstanceIp; /** * 目标实例 */ private String targetInstanceIp; /** * 迁移机器 */ private String migrateMachine; /** * 操作人 */ private Long userId; /** * 开始时间 */ private String startDate; /** * 结束时间 */ private String endDate; /** * 状态 -2全部,0全量同步,1同步结束,2同步异常,3增量同步 */ private int status = 3; /** * 分页 */ private Page page; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppDataMigrateStatus.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.AppDataMigrateEnum; import com.sohu.cache.constant.AppDataMigrateStatusEnum; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * 迁移状态 */ @Data public class AppDataMigrateStatus { /** * 自增id */ private long id; /** * 迁移任务id */ private String migrateId; /** * 迁移工具 0:redis-shake;1:redis-migrate-tool */ private int migrateTool; /** * 迁移工具所在机器ip */ private String migrateMachineIp; /** * 迁移工具所占port */ private int migrateMachinePort; /** * 目标实例列表 */ private String sourceServers; /** * 源迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy */ private int sourceMigrateType; /** * 目标实例列表 */ private String targetServers; /** * 目标迁移类型,0:single,1:redis cluster,2:rdb file,3:twemproxy */ private int targetMigrateType; /** * 源应用id */ private long sourceAppId; /** * 目标应用id */ private long targetAppId; /** * 源redis版本 */ private String redisSourceVersion; /** * 目标redis版本 */ private String redisTargetVersion; /** * 操作人id */ private long userId; /** * 操作人name */ private String userName; /** * 迁移执行状态 */ private int status; /** * 迁移开始执行时间 */ private Date startTime; /** * 迁移结束执行时间 */ private Date endTime; /** * 日志路径 */ private String logPath; /** * 配置路径 */ private String configPath; public String getStatusDesc() { AppDataMigrateStatusEnum appDataMigrateStatusEnum = AppDataMigrateStatusEnum.getByStatus(status); return appDataMigrateStatusEnum == null ? "异常" : appDataMigrateStatusEnum.getInfo(); } public String getTargetMigrateTypeDesc() { AppDataMigrateEnum appDataMigrateEnum = AppDataMigrateEnum.getByIndex(targetMigrateType); return appDataMigrateEnum == null ? "异常" : appDataMigrateEnum.getType(); } public String getSourceMigrateTypeDesc() { AppDataMigrateEnum appDataMigrateEnum = AppDataMigrateEnum.getByIndex(sourceMigrateType); return appDataMigrateEnum == null ? "异常" : appDataMigrateEnum.getType(); } public String getStartTimeFormat() { if (startTime == null) { return ""; } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(startTime); } public String getEndTimeFormat() { if (endTime == null) { return ""; } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(endTime); } public Date getStartTime() { if (null == startTime) { return null; } return (Date) startTime.clone(); } public void setStartTime(Date startTime) { if (null == startTime) { this.startTime = null; } else { this.startTime = (Date) startTime.clone(); } } public Date getEndTime() { if (null == endTime) { return null; } return (Date) endTime.clone(); } public void setEndTime(Date endTime) { if (null == endTime) { this.endTime = null; } else { this.endTime = (Date) endTime.clone(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppDesc.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.AppDescEnum; import com.sohu.cache.constant.AppDescEnum.AppImportantLevel; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.redis.util.AuthUtil; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.AppTypeEnum; import lombok.Data; import org.apache.commons.lang.StringUtils; import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; /** * 应用的信息 * User: lingguo */ @Data public class AppDesc implements Serializable { private static final long serialVersionUID = -3507970915810652761L; /** * 应用id */ private long appId; /** * 应用秘钥 */ private String appKey; /** * 应用名称 */ private String name; /** * 用户id */ private long userId; /** * 应用状态, 0未分配,1是申请了未审批,2是审批并发布, 3应用下线 4 驳回 */ private int status; /** * 应用描述 */ private String intro; /** * 创建时间 */ private Date createTime; /** * 申请通过的时间 */ private Date passedTime; /** * 类型 */ private int type; /** * 类型描述 */ private String typeDesc; /** * 负责人,用户id,逗号分隔 */ private String officer; /** * 版本号 */ private int verId; /** * 类型:0:正式 1:测试 2:试用 */ private int isTest; /** * 是否有后端数据源: 1是0否 */ private int hasBackStore; /** * 是否需要持久化: 1是0否 */ private int needPersistence; /** * 预估qps */ private int forecaseQps; /** * 是否需要热备: 1是0否 */ private int needHotBackUp; /** * 预估条目数 */ private int forecastObjNum; /** * 内存报警阀值 */ private int memAlertValue; /** * 客户端连接数报警阀值 */ private int clientConnAlertValue; /** * 客户端命中率报警阀值 0:默认不监控 */ private int hitPrecentAlertValue; /** * 客户端是否接入 全局监控 */ private int isAccessMonitor; /** * 客户端机器机房 */ private String clientMachineRoom; /** * redis密码 */ private String pkey; /** * 重要度,默认重要 */ private int importantLevel = AppImportantLevel.IMPORTANT.getValue(); /** * Redis版本id,名称 */ private int versionId; private String versionName; /** * Redis小版本是否可以升级 0:最新版本 1:可升小版本 */ private int isVersionUpgrade = 0; /** * 自定义密码,优先级最高 */ private String customPassword; /** * 持久化类型(0:常规;1:主aof自动刷盘;从常规;2:主关闭aof,从常规) * 见AppDescEnum.AppPersistenceType */ private Integer persistenceType; /** * 最大内存淘汰策略 * 见AppDescEnum.MaxmemoryPolicyType */ private Integer maxmemoryPolicy; /** * 所属业务组,多个之间以,分割 */ private String bizGroup; /** * 是否开启rdb备份 */ private Integer backupType; public String getAuthPassword() { if(StringUtils.isNotBlank(customPassword)){ return customPassword; } String authPassword = appId + AuthUtil.SPLIT_KEY; if (StringUtils.isNotBlank(pkey)) { authPassword += getAppPassword(); } return authPassword; } public boolean isSetCustomPassword(){ if(StringUtils.isNotBlank(customPassword)){ return true; } return false; } public String getPasswordMd5() { if (StringUtils.isNotBlank(pkey)) { return AuthUtil.getAppIdMD5(pkey); } return null; } public String getAppPassword() { if(StringUtils.isNotBlank(customPassword)){ return customPassword; } if (StringUtils.isNotBlank(pkey)) { return AuthUtil.getAppIdMD5(pkey); } return null; } /** * 应用运行天数 */ public int getAppRunDays() { if (createTime == null) { return -1; } Date now = new Date(); long diff = now.getTime() - createTime.getTime(); return (int) (diff / TimeUnit.DAYS.toMillis(1)); } public String getTypeDesc() { if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { return "redis-cluster"; } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) { return "redis-sentinel"; } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { return "redis-standalone"; } else if (type == ConstUtils.CACHE_REDIS_TWEMPROXY) { return "redis-twemproxy"; } else if (type == ConstUtils.CACHE_PIKA_SENTINEL) { return "pika-sentinel"; } else if (type == ConstUtils.CACHE_PIKA_TWEMPROXY) { return "pika-twemproxy"; } return ""; } public String getStatusDesc() { AppStatusEnum appStatusEnum = AppStatusEnum.getByStatus(status); if (appStatusEnum != null) { return appStatusEnum.getInfo(); } return ""; } /** * 是否上线 * * @return */ public boolean isOnline() { return status == AppStatusEnum.STATUS_PUBLISHED.getStatus(); } /** * 是否下线 * * @return */ public boolean isOffline() { return status == AppStatusEnum.STATUS_OFFLINE.getStatus(); } /** * 是否是测试 * * @return */ public boolean isTestOk() { return isTest == AppDescEnum.AppTest.IS_TEST.getValue(); } /** * 非常重要 * * @return */ public boolean isVeryImportant() { return importantLevel == AppDescEnum.AppImportantLevel.VERY_IMPORTANT.getValue(); } /** * 超级重要 * * @return */ public boolean isSuperImportant() { return importantLevel == AppDescEnum.AppImportantLevel.SUPER_IMPORTANT.getValue(); } /** * memcache相关 * * @return */ public boolean isMemcached() { return AppTypeEnum.MEMCACHED.getType() == type; } public Date getCreateTime() { if (createTime != null) { return (Date) createTime.clone(); } return null; } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getPassedTime() { if (passedTime != null) { return (Date) passedTime.clone(); } return null; } public void setPassedTime(Date passedTime) { this.passedTime = (Date) passedTime.clone(); } public String getMaxmemoryPolicyDesc() { if(maxmemoryPolicy != null){ AppDescEnum.MaxmemoryPolicyType policyType = AppDescEnum.MaxmemoryPolicyType.getByType(maxmemoryPolicy); if(policyType != null){ return policyType.getName(); } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppImport.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * @Author: rucao * @Date: 2021/1/7 下午6:00 */ @Data public class AppImport { private long id; private long appId; private int memSize; private int sourceType; private String redisVersionName; private String instanceInfo; private String redisPassword; private int status; private int step; private long appBuildTaskId; private long migrateId; private Date createTime; private Date updateTime; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppInfoApi.java ================================================ package com.sohu.cache.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; /** * 构建应用对象 * * @author chenshi */ @Data @ApiModel public class AppInfoApi { /** * 应用名称 */ @ApiModelProperty(value = "应用名称", required = true) private String name; /** * 应用介绍 */ @ApiModelProperty(value = "应用详情", required = true) private String desc; /** * 申请人信息 */ @ApiModelProperty(value = "申请人信息", required = true) private AppUser user; /** * 机器列表信息 */ @ApiModelProperty(value = "应用部署机器信息", required = true) private List iplist; /** * 应用内存总量 */ @ApiModelProperty(value = "应用申请总内存,单位G", required = true) private int memTotalSize; /** * 是否有从节点 0:无 1:有 */ @ApiModelProperty(value = "是否有从节点 0:无 1:有", required = true) private int hasSlave; /** * 应用申请类型: 2:cluster 5:sentinel 6:standalone */ @ApiModelProperty(value = "应用申请类型: 2:cluster 5:sentinel 6:standalone", required = true) private int type; /** * 是否测试: 0:测试 1:正式 */ @ApiModelProperty(value = "是否测试: 0:正式 1:测试 2:试用集群", required = true) private int isTest; /** * redis version版本 */ @ApiModelProperty(value = "redis version版本,可选 redis-3.0.7/redis-3.2.12/redis-4.0.11", required = true) private String redisVersion; /** * 机房名称 */ @ApiModelProperty(value = "机房名称,亦庄/兆维/北显/上海归侨/腾讯黑石", required = false) private String room; @ApiModelProperty(value = "redis实例数量", hidden = true) private int instanceNum; @ApiModelProperty(value = "sentinel实例数量,sentinel应用可传,默认值:3") private int sentinelNum; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppInstanceClientRelation.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 应用下实例与客户端对应关系 * * @author leifu */ @Data public class AppInstanceClientRelation { /** * 应用id */ private long appId; /** * 客户端ip */ private String clientIp; /** * 节点ip */ private String instanceHost; /** * 节点端口 */ private int instancePort; /** * 节点端口 */ private long instanceId; /** * 日期 */ private Date day; public AppInstanceClientRelation(long appId, String clientIp, String instanceHost, int instancePort, long instanceId, Date day) { this.appId = appId; this.clientIp = clientIp; this.instanceHost = instanceHost; this.instancePort = instancePort; this.instanceId = instanceId; this.day = day; } public AppInstanceClientRelation() { } public static AppInstanceClientRelation generateFromAppClientCostTimeStat( AppClientCostTimeStat appClientCostTimeStat) { if (appClientCostTimeStat == null) { return null; } else { return new AppInstanceClientRelation(appClientCostTimeStat.getAppId(), appClientCostTimeStat.getClientIp(), appClientCostTimeStat.getInstanceHost(), appClientCostTimeStat .getInstancePort(), appClientCostTimeStat.getInstanceId(), new Date( System.currentTimeMillis())); } } public Date getDay() { return (Date) day.clone(); } public void setDay(Date day) { this.day = (Date) day.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppMonitorStatisticsResult.java ================================================ package com.sohu.cache.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @Author: zengyizhao * @CreateTime: 2023/6/14 16:20 * @Description: 查询应用统计信息(前端)实体类 * @Version: 1.0 */ @Data @NoArgsConstructor @AllArgsConstructor public class AppMonitorStatisticsResult { private long appId; private Long connExpCount; private Long cmdExpCount; private Long slowLogCount; private Long latencyCount; private Long cmdCount; private String gatherTime; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppSearch.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.util.Page; import lombok.Data; /** * 搜索实体 * * @author leifu */ @Data public class AppSearch { /** * 应用id */ private Long appId; /** * 应用名 */ private String appName; /** * 应用类型 */ private Integer appType; /** * 申请状态 */ private Integer appStatus; /** * 应用类型 0:正式 1:测试 2:试用 */ private Integer isTest; /** * 命中率排序 */ private String orderBy; /** * 重要度 */ private Integer importantLevel; /** * Redis版本 ,默认查询所有版本 */ private Integer versionId = -1; /** * 相关用户id */ private long userId; /** * 相关业务组id */ private long bizId; /** * 持久化类型 */ private Integer persistenceType; /** * 是否备份 */ private Integer backupType; /** * 分页 */ private Page page; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppStatisticsSearch.java ================================================ package com.sohu.cache.entity; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; /** * @Author: zengyizhao * @CreateTime: 2023/6/14 16:20 * @Description: 查询应用统计信息(前端)实体类 * @Version: 1.0 */ @Data @NoArgsConstructor @AllArgsConstructor @Builder public class AppStatisticsSearch { private Long userId; private Boolean isAdmin; private String startTime; private String endTime; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import org.apache.commons.lang.math.NumberUtils; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Date; import java.util.List; /** * Created by yijunzhang on 14-6-9. */ @Data public class AppStats { /** * 应用id */ private long appId; /** * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH */ private long collectTime; /** * 命中数量 */ private long hits; /** * 未命中数量 */ private long misses; /** * 命令执行次数 */ private long commandCount; /** * 内存占用 */ private long usedMemory; /** * 物理内存占用 */ private long usedMemoryRss; /** * 过期key数量 */ private long expiredKeys; /** * 驱逐key数量 */ private long evictedKeys; /** * 网络输入字节 */ private long netInputByte; /** * 网络输出字节 */ private long netOutputByte; /** * 客户端连接数 */ private int connectedClients; /** * 存储对象数 */ private long objectSize; /** * 进程系统态消耗(单位:秒) */ private long cpuSys; /** * 进程用户态消耗(单位:秒) */ private long cpuUser; /** * 子进程内核态消耗(单位:秒) */ private long cpuSysChildren; /** * 子进程用户态消耗(单位:秒) */ private long cpuUserChildren; /** * 累加的实例数 */ private int accumulation; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date modifyTime; /** * 命令统计集合 */ private List commandStatsList; /** * 磁盘占用 */ private long usedDisk; /** * 命中率 * * @return */ public long getHitPercent() { long total = hits + misses; if (total == 0) { return 0; } else { NumberFormat formatter = new DecimalFormat("0"); return NumberUtils.toLong(formatter.format(hits * 100.0 / total)); } } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getModifyTime() { return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { this.modifyTime = (Date) modifyTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppToUser.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.io.Serializable; /** * 应用和用户的对应关系 * * @author leifu */ @Data public class AppToUser implements Serializable { private static final long serialVersionUID = 1326072190198022633L; /** * 自增id */ private Long id; /** * 用户id */ private Long userId; /** * 应用id */ private Long appId; public AppToUser() { } public AppToUser(Long userId, Long appId) { super(); this.userId = userId; this.appId = appId; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppTopMemFragRatio.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * @author wenruiwu * @create 2019/11/13 11:09 * @description */ @Data public class AppTopMemFragRatio extends AppDesc{ /** * 应用实例数 */ private int instanceCount; //应用实例数 /** * 平均碎片率 */ private double avgMemFragRatio; //平均碎片率 /** * 内存使用率 */ private double memUsedRatio; //内存使用率百分比 /** * 异常数 */ private int exceptionCount; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/AppUser.java ================================================ package com.sohu.cache.entity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * 系统用户信息 * * @author leifu */ @Data @ApiModel public class AppUser implements Serializable { private static final long serialVersionUID = 7425158151337667662L; /** * 自增id */ @ApiModelProperty(value = "用户id",hidden = true) private Long id; /** * 用户名(英文,域账户) */ @ApiModelProperty(value = "用户名(英文,域账户)",required = true) private String name; /** * 密码 */ @ApiModelProperty(value = "密码") private String password; /** * 中文名 */ @ApiModelProperty(value = "中文名",required = true) private String chName; /** * 用户域账户邮箱 */ @ApiModelProperty(value = "用户域账户邮箱",required = true) private String email; /** * 用户手机 */ @ApiModelProperty(value = "用户手机",required = true) private String mobile; /** * 用户微信号 */ @ApiModelProperty(value = "用户微信号",required = true) private String weChat; /** * 用户类型(类型参考AppUserTypeEnum) */ @ApiModelProperty(value = "用户类型",hidden = true) private int type; /** * 是否接收报警 */ @ApiModelProperty(value = "是否接收报警 0:不接收报警 1:接收报警",hidden = true) private int isAlert; /** * 公司名 */ @ApiModelProperty(value = "公司名") private String company; /** * 目的 */ @ApiModelProperty(value = "目的") private String purpose; /** * 注册时间 */ @ApiModelProperty(value = "注册时间") private Date registerTime; /** * 所属业务组id */ @ApiModelProperty(value = "所属业务组id") private Long bizId; public static AppUser buildFrom(Long userId, String name, String chName, String email, String mobile, String weChat, Integer type) { AppUser appUser = new AppUser(); appUser.setId(userId); appUser.setName(name); appUser.setChName(chName); appUser.setEmail(email); appUser.setMobile(mobile); appUser.setWeChat(weChat); appUser.setType(type); return appUser; } public static AppUser buildFrom(Long userId, String name, String chName, String email, String mobile, String weChat, Integer type,Integer isAlert) { AppUser appUser = new AppUser(); appUser.setId(userId); appUser.setName(name); appUser.setChName(chName); appUser.setEmail(email); appUser.setMobile(mobile); appUser.setWeChat(weChat); appUser.setType(type); appUser.setIsAlert(isAlert); return appUser; } public static AppUser buildFrom(Long userId, String name, String chName, String email, String mobile, String weChat, Integer type,Integer isAlert, String company, String purpose, Long bizId) { AppUser appUser = new AppUser(); appUser.setId(userId); appUser.setName(name); appUser.setChName(chName); appUser.setEmail(email); appUser.setMobile(mobile); appUser.setWeChat(weChat); appUser.setType(type); appUser.setIsAlert(isAlert); appUser.setCompany(company); appUser.setPurpose(purpose); appUser.setBizId(bizId); return appUser; } public static AppUser buildFrom(Long userId, String name, String chName, String email, String mobile, String weChat, Integer type,Integer isAlert, String password, String company, String purpose, Long bizId) { AppUser appUser = new AppUser(); appUser.setId(userId); appUser.setName(name); appUser.setChName(chName); appUser.setEmail(email); appUser.setMobile(mobile); appUser.setWeChat(weChat); appUser.setType(type); appUser.setIsAlert(isAlert); appUser.setPassword(password); appUser.setCompany(company); appUser.setPurpose(purpose); appUser.setBizId(bizId); return appUser; } public AppUser() { } public AppUser(String name, String chName, String email, String mobile, String weChat, int type) { this.name = name; this.chName = chName; this.email = email; this.mobile = mobile; this.weChat = weChat; this.type = type; } public AppUser(String name, String chName, String email, String mobile, String weChat, int type, int isAlert) { this.name = name; this.chName = chName; this.email = email; this.mobile = mobile; this.weChat = weChat; this.type = type; this.isAlert = isAlert; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/BrevityScheduleTask.java ================================================ package com.sohu.cache.entity; import com.alibaba.fastjson.annotation.JSONField; import com.sohu.cache.schedule.brevity.BrevityScheduleType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; /** * Created by yijunzhang */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class BrevityScheduleTask { @JSONField(serialize = false) private Integer id; private Integer type; private Long version; private String host; private Integer port; private Date createTime; private BrevityScheduleType brevityScheduleType; private Integer instanceType; @JSONField(serialize = false) public BrevityScheduleType getBrevityScheduleType() { return BrevityScheduleType.typeOf(type); } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } @JSONField(serialize = false) public String getHostPort(){ return this.getHost() + ":" + this.getPort(); } @JSONField(serialize = false) public String getKeyField(){ return this.getType() + "_" + this.getHost() + "_" + this.getPort(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ClientInstanceException.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 客户端实例异常 * * @author leifu */ @Data public class ClientInstanceException { private long appId; private long instanceId; private String instanceHost; private int instancePort; private int exceptionCount; public ClientInstanceException(long appId, long instanceId, String instanceHost, int instancePort, int exceptionCount) { this.appId = appId; this.instanceId = instanceId; this.instanceHost = instanceHost; this.instancePort = instancePort; this.exceptionCount = exceptionCount; } public ClientInstanceException() { } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ConfigRestartRecord.java ================================================ package com.sohu.cache.entity; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.web.util.Page; import lombok.Data; import java.util.Date; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/10/14 15:52 * @Description: 配置重启记录 */ @Data public class ConfigRestartRecord { /** * */ private long id; /** * 应用id */ private Long appId; /** * 应用名称 */ private String appName; /** * 重启类型(滚动重启,修改配置强制重启) */ private int operateType; /** * 初始化任务参数(json):不变 */ private String param; /** * 状态:0等待,1运行,2失败 */ private Integer status; /** * 日志信息 */ private String log; /** * 实例信息 */ private String instances; /** * 操作人员id */ private long userId; /** * 操作人员名称 */ private String userName; /** * 开始时间 */ private Date startTime; /** * 结束时间 */ private Date endTime; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date updateTime; /** * 分页参数 */ private Page page; private List logList; private List instanceIdList; public List getLogList(){ List logList = JSONObject.parseArray(log, String.class); return logList; } public List getInstanceIdList(){ List logList = JSONObject.parseArray(instances, Integer.class); return logList; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/DbPoolStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 数据库连接池统计 * @author fulei * @date 2018年8月17日 * @time 上午11:40:05 */ @Data public class DbPoolStat { private long id; /** * 进程ip */ private String ip; /** * 进程port */ private int port; private String dbPoolName; private long collectTime; private Date collectDate; private int maxSize; private int minSize; private int busySize; private int idleSize; private int totalSize; private Date createTime; private Date updateTime; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getCollectDate() { return (Date) collectDate.clone(); } public void setCollectDate(Date collectDate) { this.collectDate = (Date) collectDate.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/DeployInfo.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.enums.NodeEnum; import lombok.Data; /** * Created by rucao */ @Data public class DeployInfo { /** * 部署形态: 参考 ConstUtils * 2: Redis Cluster * 5: Redis+Sentinel * 7: Redis+Twemproxy * 8: Pika+Sentinel * 9: Pika+Twemproxy * 6: Redis Standalone */ private Integer deployType; /** * 分配内存大小,单位M */ private Integer memSize; /** * Redis node */ private String masterIp; private String slaveIp; /** * Pika node */ private String masterPikaIp; private String slavePikaIp; /** * sentinel/twemproxy node */ private String sentinelIp; private String twemproxyIp; public DeployInfo() { } public DeployInfo(Integer deployType, String masterIp, Integer memSize) { this.deployType = deployType; this.masterIp = masterIp; this.memSize = memSize; } public DeployInfo(Integer deployType, String masterIp, Integer memSize, String slaveIp) { this.deployType = deployType; this.masterIp = masterIp; this.memSize = memSize; this.slaveIp = slaveIp; } public DeployInfo(Integer deployType, String sentinelIp) { this.deployType = deployType; this.sentinelIp = sentinelIp; } /** * 获取Redis实例信息 */ public static DeployInfo getRedisInfo(Integer deployType, String masterIp, Integer memSize, String slaveIp) { DeployInfo deployInfo = new DeployInfo(); deployInfo.setDeployType(deployType); deployInfo.setMasterIp(masterIp); deployInfo.setMemSize(memSize); deployInfo.setSlaveIp(slaveIp); return deployInfo; } /** * 获取Pika实例信息 */ public static DeployInfo getPikaInfo(Integer deployType, String masterPikaIp, Integer memSize, String slavePikaIp) { DeployInfo deployInfo = new DeployInfo(); deployInfo.setDeployType(deployType); deployInfo.setMasterPikaIp(masterPikaIp); deployInfo.setMemSize(memSize); deployInfo.setSlavePikaIp(slavePikaIp); return deployInfo; } /** * 获取Sentinel实例信息 */ public static DeployInfo getSentinelInfo(Integer deployType, String sentinelIp) { DeployInfo deployInfo = new DeployInfo(); deployInfo.setDeployType(deployType); deployInfo.setSentinelIp(sentinelIp); return deployInfo; } /** * 获取Twemproxy实例信息 */ public static DeployInfo getTwemproxyInfo(Integer deployType, String twemproxyIp) { DeployInfo deployInfo = new DeployInfo(); deployInfo.setDeployType(deployType); deployInfo.setTwemproxyIp(twemproxyIp); return deployInfo; } /** * 判断是否Redis/Pika节点 */ public static Boolean isRedisNode(int type){ if(type == NodeEnum.REDIS_NODE.getValue()){ return true; } return false; } /** * 判断是否Sentinel/Twemproxy节点 */ public static Boolean isSentinelNode(int type){ if(type == NodeEnum.SENTINEL_NODE.getValue() ){ return true; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/DeployInfoStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by rucao on 2018/10/10 */ @Data public class DeployInfoStat { private Integer masterNum; private Integer slaveNum; private Integer sentinelNum; private Integer twemproxyNum; public DeployInfoStat(Integer masterNum, Integer slaveNum, Integer sentinelNum) { this.masterNum = masterNum; this.slaveNum = slaveNum; this.sentinelNum = sentinelNum; } public DeployInfoStat(Integer masterNum, Integer slaveNum, Integer sentinelNum, Integer twemproxyNum) { this.masterNum = masterNum; this.slaveNum = slaveNum; this.sentinelNum = sentinelNum; this.twemproxyNum = twemproxyNum; } public DeployInfoStat() { this.masterNum = 0; this.slaveNum = 0; this.sentinelNum = 0; this.twemproxyNum = 0; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/DiagnosticTaskRecord.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * @Author: rucao * @Date: 2020/6/9 16:42 */ @Data public class DiagnosticTaskRecord { private long id; /** * 任务流id */ private long taskId; /** * 父任务id */ private long parentTaskId; /** * 审批id */ private long auditId; /** * 诊断类型:0scan 1bigkey 2idle key 3hotkey 4del key 5slot analysis 6topology exam */ private int type; /** * 诊断状态:0开始 1结束 2异常 */ private int status; /** * 应用id */ private long appId; /** * ip:port */ private String node; /** * 诊断条件 */ private String diagnosticCondition; /** * 备用参数1 */ private String param1; /** * 备用参数2 */ private String param2; /** * 结果的key */ private String redisKey; /** * 耗时,毫秒 */ private long cost; private String formatCostTime; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date modifyTime; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceAlertConfig.java ================================================ package com.sohu.cache.entity; import java.util.Date; import java.util.concurrent.TimeUnit; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.redis.enums.InstanceAlertCheckCycleEnum; import com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum; import com.sohu.cache.redis.enums.InstanceAlertTypeEnum; import lombok.Data; /** * 实例报警阀值配置 * @author leifu */ @Data public class InstanceAlertConfig { /** * 自增id */ private long id; /** * 报警配置 */ private String alertConfig; /** * 报警阀值 */ private String alertValue; /** * 详见CompareTypeEnumNew */ private int compareType; /** * 配置说明 */ private String configInfo; /** * 详见TypeEnum */ private int type; /** * -1全局配置,其他代表实例id */ private long instanceId; /** * 实例信息 */ private InstanceInfo instanceInfo; /** * 相关StatusEnum */ private int status; /** * 详见CheckCycleEnum */ private int checkCycle; /** * 配置更新时间 */ private Date updateTime; /** * 上次检测时间 */ private Date lastCheckTime; /** * 重要度(参照ImportantLevelTypeEnum)(0:一般;1:重要;2:紧急) */ private Integer importantLevel; /** * 应用类型(0:redis;) */ private Integer appType; public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getLastCheckTime() { return (Date) lastCheckTime.clone(); } public void setLastCheckTime(Date lastCheckTime) { this.lastCheckTime = (Date) lastCheckTime.clone(); } public String getCompareInfo() { return InstanceAlertCompareTypeEnum.getInstanceAlertCompareTypeEnum(compareType).getInfo(); } public Long getCheckCycleMillionTime() { if (InstanceAlertCheckCycleEnum.ONE_MINUTE.getValue() == checkCycle) { return TimeUnit.MINUTES.toMillis(1); } else if (InstanceAlertCheckCycleEnum.FIVE_MINUTE.getValue() == checkCycle) { return TimeUnit.MINUTES.toMillis(5); } else if (InstanceAlertCheckCycleEnum.HALF_HOUR.getValue() == checkCycle) { return TimeUnit.MINUTES.toMillis(30); } else if (InstanceAlertCheckCycleEnum.ONE_HOUR.getValue() == checkCycle) { return TimeUnit.MINUTES.toMillis(60); } else if (InstanceAlertCheckCycleEnum.ONE_DAY.getValue() == checkCycle) { return TimeUnit.DAYS.toMillis(1); } return null; } public boolean isSpecail() { return instanceId > 0 && (type == InstanceAlertTypeEnum.INSTANCE_ALERT.getValue() || type == InstanceAlertTypeEnum.APP_ALERT.getValue()); } @Override public String toString() { return JSONObject.toJSONString(this); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceAlertValueResult.java ================================================ package com.sohu.cache.entity; import com.alibaba.fastjson.JSONObject; import lombok.Data; /** * 实例报警结果 * @author leifu */ @Data public class InstanceAlertValueResult { /** * 实例报警配置 */ private InstanceAlertConfig instanceAlertConfig; /** * 实例信息 */ private InstanceInfo instanceInfo; /** * 当前值 */ private String currentValue; /** * 应用id */ private long appId; /** * 单位 */ private String unit; /** * 应用信息 */ private AppDesc appDesc; /** * 其他信息 */ private String otherInfo; public InstanceAlertValueResult() { } public InstanceAlertValueResult(InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo, String currentValue, long appId, String unit) { this.instanceAlertConfig = instanceAlertConfig; this.instanceInfo = instanceInfo; this.currentValue = currentValue; this.appId = appId; this.unit = unit; } public String getAlertMessage() { return String.format("实际值为%s%s,%s预设值%s%s", currentValue, unit, instanceAlertConfig.getCompareInfo(), instanceAlertConfig.getAlertValue(), unit); } @Override public String toString() { return JSONObject.toJSONString(this); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceCommandStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @Data public class InstanceCommandStats implements Comparable { /** * 应用id */ private long instanceId; /** * 收集时间:格式yyyyMMddHHmm/yyyyMMdd/yyyyMMddHH */ private long collectTime; /** * 命令名称 */ private String commandName; /** * 命令执行次数 */ private long commandCount; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date modifyTime; @Override public int compareTo(InstanceCommandStats o) { if (o.commandCount > this.commandCount) { return 1; } else if (o.commandCount < this.commandCount) { return -1; } return 0; } public Long getTimeStamp() throws ParseException{ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); Date date = sdf.parse(String.valueOf(this.collectTime)); return date.getTime(); } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getModifyTime() { return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { this.modifyTime = (Date) modifyTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceConfig.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * 实例配置模板 * * @author leifu */ @Data public class InstanceConfig { private long id; /** * 配置名:为了防止与key冲突 */ private String configKey; /** * 配置值:为了防止与value冲突 */ private String configValue; /** * 配置说明 */ private String info; /** * 更新时间 */ private Date updateTime; /** * Redis类型(参考ConstUtil) */ private int type; /** * 状态,1有效0无效 */ private int status; /** * 配置项绑定redis版本主键id */ private int versionId; /** * 是否可重置:0不可,1可重置 (默认值:1) */ private int refresh = 1; /** * 取值类型(0:默认值 config_value;1:从主节点拷贝),默认0 */ private int valueType; public InstanceConfig() { } public InstanceConfig(String configKey, String configValue){ this.configKey = configKey; this.configValue = configValue; } public String getStatusDesc() { if (1 == status) { return "有效"; } else if (0 == status) { return "无效"; } else { return ""; } } public boolean isEffective() { if (1 == getStatus()) { return true; } return false; } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceFault.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.io.Serializable; import java.util.Date; @Data public class InstanceFault implements Serializable { private static final long serialVersionUID = 8141174905675892249L; private int id; private int appId; private int instId; private String ip; private int port; private int status; private int type; private Date createTime; private String reason; public String getTypeDesc() { InstanceInfo info = new InstanceInfo(); info.setType(type); return info.getTypeDesc(); } public String getStatusDesc() { InstanceInfo info = new InstanceInfo(); info.setStatus(this.status); return info.getStatusDesc(); } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceInfo.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.BooleanEnum; import lombok.Data; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.Date; /** * 实例信息 * User: lingguo */ @Data public class InstanceInfo implements Serializable { private static final long serialVersionUID = -903896025243493024L; /** * 实例id */ private int id; /** * 应用id */ private long appId; /** * host id */ private long hostId; /** * ip */ private String ip; /** * 端口 */ private int port; /** * 是否启用 0:节点异常,1:正常启用,2:节点下线 */ private int status; /** * 开启的内存 */ private int mem; /** * 连接数 */ private int conn; /** * 启动命令 或者 redis-sentinel的masterName */ private String cmd; private int type; private String typeDesc; private int masterInstanceId; private String masterHost; private int masterPort; private String roleDesc; private int groupId; private Date updateTime; public String getTypeDesc() { if (type <= 0) { typeDesc = ""; } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { typeDesc = "redis-cluster"; } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) { typeDesc = "redis-sentinel"; } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { typeDesc = "redis-standalone"; } return typeDesc; } public String getStatusDesc() { InstanceStatusEnum instanceStatusEnum = InstanceStatusEnum.getByStatus(status); if (instanceStatusEnum != null) { return instanceStatusEnum.getInfo(); } return ""; } /** * 判断当前节点是否下线 * * @return */ public boolean isOffline() { return status == InstanceStatusEnum.OFFLINE_STATUS.getStatus() || status == InstanceStatusEnum.FORGET_STATUS.getStatus(); } /** * 判断当前节点是否在线 */ public boolean isOnline() { return status == InstanceStatusEnum.GOOD_STATUS.getStatus(); } public String getRoleDesc() { if (type == ConstUtils.CACHE_REDIS_SENTINEL) { return "sentinel"; } else { return roleDesc; } } public void setRoleDesc(BooleanEnum isMaster) { if (isMaster == BooleanEnum.OTHER) { roleDesc = "未知"; } else if (isMaster == BooleanEnum.TRUE) { roleDesc = "master"; } else if (isMaster == BooleanEnum.FALSE) { roleDesc = "slave"; } } public String getHostPort() { return ip + ":" + port; } public boolean isMemcached() { return InstanceInfoEnum.InstanceTypeEnum.MEMCACHE.getType() == type; } public boolean isNutCracker() { return InstanceInfoEnum.InstanceTypeEnum.NUTCRACKER.getType() == type; } public boolean isPika() { return InstanceInfoEnum.InstanceTypeEnum.PIKA.getType() == type; } /** * 是否是redis数据节点 * * @return */ public boolean isRedisData() { if (type == InstanceInfoEnum.InstanceTypeEnum.REDIS_SERVER.getType() || type == InstanceInfoEnum.InstanceTypeEnum.REDIS_CLUSTER.getType()) { return true; } return false; } public Date getUpdateTime() { if(updateTime != null){ return (Date) updateTime.clone(); } return null; } public String getUpdateTimeDesc() { if(updateTime != null){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format((Date) updateTime.clone()); } else { return ""; } } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } @Override public String toString() { return "InstanceInfo{" + "id=" + id + ", appId=" + appId + ", hostId=" + hostId + ", ip='" + ip + '\'' + ", port=" + port + ", status=" + status + ", mem=" + mem + ", conn=" + conn + ", cmd='" + cmd + '\'' + ", type=" + type + ", typeDesc='" + typeDesc + '\'' + ", masterInstanceId=" + masterInstanceId + ", masterHost='" + masterHost + '\'' + ", masterPort=" + masterPort + ", roleDesc='" + roleDesc + '\'' + ", groupId=" + groupId + ", updateTime=" + updateTime + '}'; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceLatencyHistory.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * @Author: rucao * @Date: 2020/5/7 3:12 下午 */ @Data public class InstanceLatencyHistory { private long id; /** * 实例id */ private long instanceId; /** * app id */ private long appId; /** * ip地址 */ private String ip; /** * port */ private int port; /** * 创建时间 */ private Date createTime; /** * 延迟事件名称 */ private String event; /** * 事件出现延迟毛刺日期时间 */ private Date executeDate; /** * 延迟(单位:毫秒) */ private long executionCost; public InstanceLatencyHistory(long instanceId, long appId, String ip, int port, String event, Date executeDate, long executionCost) { this.instanceId = instanceId; this.appId = appId; this.ip = ip; this.port = port; this.event = event; this.executeDate = executeDate; this.executionCost = executionCost; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceMinuteStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) public class InstanceMinuteStats extends InstanceCommandStats { /** * 内存碎片率 */ private double memFragmentationRatio; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceReshardProcess.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.ReshardStatusEnum; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * 进度持久化 * * @author leifu */ @Data public class InstanceReshardProcess { private int id; /** * 应用id */ private long appId; /** * 审批id */ private long auditId; /** * 源实例id */ private int sourceInstanceId; /** * 源实例 */ private InstanceInfo sourceInstanceInfo; /** * 目标实例id */ private int targetInstanceId; /** * 目标实例 */ private InstanceInfo targetInstanceInfo; /** * 开始slot */ private int startSlot; /** * 结束slot */ private int endSlot; /** * 正在迁移的slot */ private int migratingSlot; /** * 0是,1否 */ private int isPipeline; /** * 已完成迁移的slot数量 */ private int finishSlotNum; /** * 0:运行中 1:完成 2:出错 */ private int status; /** * 迁移开始时间 */ private Date startTime; /** * 迁移结束时间 */ private Date endTime; /** * 创建时间 * * @return */ private Date createTime; /** * 更新时间 */ private Date updateTime; private final static String dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; public String getStartTimeFormat() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); return simpleDateFormat.format(startTime); } public String getEndTimeFormat() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); return simpleDateFormat.format(endTime); } public String getCreateTimeFormat() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); return simpleDateFormat.format(createTime); } public String getUpdateTimeFormat() { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateTimeFormat); return simpleDateFormat.format(updateTime); } public int getTotalSlot() { return endSlot - startSlot + 1; } public String getStatusDesc() { ReshardStatusEnum reshardStatusEnum = ReshardStatusEnum.getReshardStatusEnum(status); return reshardStatusEnum == null ? "" : reshardStatusEnum.getInfo(); } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getStartTime() { return (Date) startTime.clone(); } public void setStartTime(Date startTime) { this.startTime = (Date) startTime.clone(); } public Date getEndTime() { return (Date) endTime.clone(); } public void setEndTime(Date endTime) { this.endTime = (Date) endTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceSlotModel.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.List; /** * 实例slot * * @author leifu */ @Data public class InstanceSlotModel { /** * slot分布,例如: 0-4096 或者0-8 9-4096 */ private List slotDistributeList; /** * slot列表 */ private List slotList; /** * ip */ private String host; /** * 端口 */ private int port; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceSlowLog.java ================================================ package com.sohu.cache.entity; import lombok.Data; import org.apache.commons.lang.StringUtils; import java.sql.Timestamp; /** * 实例慢查询日志 * * @author leifu */ @Data public class InstanceSlowLog { private long id; /** * 实例id */ private long instanceId; /** * app id */ private long appId; /** * ip地址 */ private String ip; /** * port */ private int port; /** * 慢查询日志id */ private long slowLogId; /** * 耗时 */ private int costTime; /** * 命令 */ private String command; /** * 记录创建时间 */ private Timestamp createTime; /** * 慢查询发生时间 */ private Timestamp executeTime; public String getCommand() { int maxLength = 30; if (StringUtils.isNotBlank(command) && command.length() > maxLength) { return command.substring(0, maxLength) + "..."; } return command; } public Timestamp getCreateTime() { return (Timestamp) createTime.clone(); } public void setCreateTime(Timestamp createTime) { this.createTime = (Timestamp) createTime.clone(); } public Timestamp getExecuteTime() { return (Timestamp) executeTime.clone(); } public void setExecuteTime(Timestamp executeTime) { this.executeTime = (Timestamp) executeTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/InstanceStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.sql.Timestamp; import java.text.DecimalFormat; import java.util.Map; /** * 实例的简化的统计信息 * * User: lingguo */ @Data public class InstanceStats { /* id */ private long id; /* 实例id */ private long instId; /* app id */ private long appId; /* host id */ private long hostId; /* ip地址 */ private String ip; /* port */ private int port; /* 主从,1主2从 */ private byte role; /* 启用实例时设置的内存,单位:byte */ private long maxMemory; /* 实例当前已用的内存,单位:byte */ private long usedMemory; /* * 实例内存使用率 */ private double memUsePercent; /* 当前的item数 */ private long currItems; /* 当前的连接数 */ private int currConnections; /* 未命中数*/ private long misses; /* 命中数 */ private long hits; /* 开始收集时间 */ private Timestamp createTime; /* 最后更新时间 */ private Timestamp modifyTime; /** * 内存碎片率 */ private double memFragmentationRatio; /** * aof阻塞次数 */ private int aofDelayedFsync; private boolean isRun; /** * 实例相关全部统计指标 */ private Map infoMap; /* 实例当前已用的磁盘空间,单位:byte */ private long usedDisk; public double getMemUsePercent() { if(maxMemory<=0){ return 0.0D; } double percent = 100 * (double) usedMemory / (maxMemory); DecimalFormat df = new DecimalFormat("##.##"); return Double.parseDouble(df.format(percent)); } /** * 命中率 * @return */ public String getHitPercent(){ long totalHits = hits + misses; if (totalHits <= 0) { return "无命令执行"; } double percent = 100 * (double) hits / totalHits; DecimalFormat df = new DecimalFormat("##.##"); return df.format(percent) + "%"; } public Timestamp getCreateTime() { if(createTime != null){ return (Timestamp) createTime.clone(); } return null; } public void setCreateTime(Timestamp createTime) { this.createTime = (Timestamp) createTime.clone(); } public Timestamp getModifyTime() { return (Timestamp) modifyTime.clone(); } public void setModifyTime(Timestamp modifyTime) { this.modifyTime = (Timestamp) modifyTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/LoginResult.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.enums.AdminEnum; import com.sohu.cache.web.enums.LoginEnum; import lombok.Data; /** * 登录结果 * * @author leifu */ @Data public class LoginResult { /** * 登录验证结果 */ private LoginEnum loginEnum; /** * 是否是管理员 */ private AdminEnum adminEnum; public LoginResult(LoginEnum loginEnum, AdminEnum adminEnum) { this.loginEnum = loginEnum; this.adminEnum = adminEnum; } public LoginResult() { } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineInfo.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.constant.MachineInfoEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * 机器的属性信息 *

*/ @Data @ApiModel public class MachineInfo { /** * 机器id */ @ApiModelProperty(hidden = true) private long id; /** * ssh用户名 */ @ApiModelProperty(hidden = true) private String sshUser; /** * ssh密码 */ @ApiModelProperty(hidden = true) private String sshPasswd; /** * ip地址 */ @ApiModelProperty(value = "机器ip", required = true) private String ip; /** * 机房 */ @ApiModelProperty(hidden = true) private String room; /** * 内存,单位G */ @ApiModelProperty(value = "内存,单位G", required = true) private int mem; /** * cpu数量 */ @ApiModelProperty(value = "cpu核数", required = true) private int cpu; /** * 磁盘空间, 单位G */ @ApiModelProperty(value = "磁盘空间",required = true) private int disk; /** * 是否虚机,0否,1是 */ @ApiModelProperty(value = "是否虚拟机", required = true) private int virtual; /** * 宿主机ip */ @ApiModelProperty(value = "宿主机ip(虚机需要填写)", required = true) private String realIp; /** * 上线时间 */ @ApiModelProperty(hidden = true) private Date serviceTime; /** * 故障次数 */ @ApiModelProperty(hidden = true) private int faultCount; /** * 修改时间 */ @ApiModelProperty(hidden = true) private Date modifyTime; /** * 是否启用报警,0否,1是 */ @ApiModelProperty(hidden = true) private int warn; /** * 是否可用,MachineInfoEnum.AvailableEnum */ @ApiModelProperty(hidden = true) private int available; /** * 机器类型:详见MachineInfoEnum.TypeEnum */ @ApiModelProperty(hidden = true) private int type; /** * 机器类型:详见MachineInfoEnum.DisTypeEnum */ @ApiModelProperty(hidden = true) private int disType; /** * groupId */ @ApiModelProperty(hidden = true) private int groupId; /** * 额外说明:(例如本机器有其他web或者其他服务) */ @ApiModelProperty(value = "备注说明") private String extraDesc; @ApiModelProperty(value = "如是专用机器,请填写项目名称") private String projectName; /** * 是否收集服务器信息,0否,1是 */ @ApiModelProperty(hidden = true) private int collect; /** * redis版本安装情况 版本号#安装标识 -1:获取安装信息异常 0:未安装 1:安装成功 */ @ApiModelProperty(hidden = true) private String versionInstall; /** * 使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2) */ @ApiModelProperty(value = "使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis sentienl部署(3)", required = true) private int useType; @ApiModelProperty(value = "机器是否分配,1是0否") private int isAllocating; /** * 是否k8s容器:0:不是 1:是 */ @ApiModelProperty(value = "是否k8s容器:0:不是 1:是", required = false) private int k8sType; @ApiModelProperty(value = "pod变更时间,单位 ms", required = false) private long podUpdateTime; @ApiModelProperty(value = "机架信息", required = false) private String rack; /** * 判断机器是否已经下线 * * @return */ public boolean isOffline() { return MachineInfoEnum.AvailableEnum.NO.getValue() == this.available; } /** * 是否是云主机 * * @return */ public boolean isYunMachine() { //return isYun == 1; return false; } public boolean isK8sMachine(int k8sType) { if (k8sType == 1) { return true; } return false; } /** * 时间格式化 */ public String getUpdateTimeFormat() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(modifyTime); } public Date getModifyTime() { if(modifyTime == null){ return null; } return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { if(modifyTime != null){ this.modifyTime = (Date) modifyTime.clone(); } } public Date getServiceTime() { if(serviceTime == null){ return null; } return (Date) serviceTime.clone(); } public void setServiceTime(Date serviceTime) { if(serviceTime != null){ this.serviceTime = (Date) serviceTime.clone(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineInstanceStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; @Data public class MachineInstanceStat { private String ip; private long maxMemory; private long usedMemory; private long applyDisk; private long usedDisk; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineMemInfo.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by hym on 14-10-30. */ @Data public class MachineMemInfo { private String ip; private long applyMem; private long usedMem; private long applyDisk;//磁盘分配 private long usedDisk;//磁盘实例使用 private double usedMemRss; public long getLockedMem() { return this.applyMem - this.usedMem; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineMemStatInfo.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by rucao */ @Data public class MachineMemStatInfo { /** * 机器id */ private long id; /** * ip地址 */ private String ip; /** * 机房 */ private String room; /** * 使用类型:Redis专用机器(0),Redis测试机器(1),混合部署机器(2),Redis迁移工具机器(3) */ private int useType; /** * cpu数量 */ private int cpu; private int instanceNum; /** * 内存,单位G */ private int mem; /** * 该机器已分配的内存, 单位byte */ private long applyMem; /** * 该机器的已使用的内存, 单位byte */ private long usedMem; /** * 宿主机ip */ private String realIp; /** * 机架信息 */ private String rack; /** * 该机器的redis部署实际使用内存, 单位byte */ private Long usedMemRss; /** * 操作系统发行版本,0:centos;1:ubuntu */ private Integer disType; /** * 该机器的已使用的磁盘, 单位byte */ private long usedDisk; /** * 机器磁盘总大小, 单位G */ private long disk; /** * 类型:如Redis机器(0),RediSSD机器(6) * 详见 MachineInfoEnum.TypeEnum */ private int type; public double getCpuUsage(){ if(cpu != 0){ return ((double)instanceNum)/cpu; } return 0; } public long getFreeMem(){ if(usedMemRss == null){ return mem * 1024; } return mem * 1024 - usedMemRss/1024/1024; } public long getFreeApplyMem(){ return mem * 1024 - applyMem/1024/1024; } public long getFreeDisk(){ return disk * 1024 - usedDisk/1024/1024; } public void addUsedMem(long mem){ this.usedMem += mem; this.usedMemRss += mem; } public void addApplyMem(long mem){ this.applyMem += mem; } public void addUsedDisk(long disk){ this.usedDisk += disk; } public void addInstanceNum(int instanceNum){ this.instanceNum += instanceNum; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineRelation.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * Created by chenshi on 2019/5/21. */ @Data public class MachineRelation { /** * 主键id */ private int id; /** * 虚拟ip */ private String ip; /** * 宿主机ip */ private String realIp; /** * 更新时间 */ private Date updateTime; /** * pod 描述信息 */ private String extraDesc; /** * pod状态 0:offline 下线 1:online 上线 2:pending * PodStatusEnum.OFFLINE PodStatusEnum.ONLINE */ private int status; private int isSync; private String syncTime; /** * 任务id */ private long taskid; public MachineRelation() { } public MachineRelation(String ip, String realIp, Date updateTime, String extraDesc, int status) { this.ip = ip; this.realIp = realIp; this.updateTime = updateTime; this.extraDesc = extraDesc; this.status = status; } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineRoom.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** *

* Description: 机房信息 *

* * @author chenshi */ @Data public class MachineRoom { /** * 机房id */ private int id; /** * 机房名称 */ private String name; /** * 是否有效 0:无效 1:有效 */ private int status; /** * 机房信息 */ private String desc; /** * 网段信息 */ private String ipNetwork; /** * 运营商 */ private String operator; public MachineRoom() { } public MachineRoom(String name, int status, String desc, String ipNetwork, String operator) { this.name = name; this.status = status; this.desc = desc; this.ipNetwork = ipNetwork; this.operator = operator; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/MachineStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import org.apache.commons.lang.StringUtils; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; /** * Created by yijunzhang */ @Data public class MachineStats{ private long id; private long hostId; private String ip; private String cpuUsage; private String load; private String traffic; private String memoryUsageRatio; /** * 如果机器是物理机/虚机,收集内存占用空间正常;如果是容器,收集可能不是实际内存占用空间 */ private String memoryFree; private String memoryTotal; private int memoryAllocated; /** * 机器入库内存 MB */ private int machineMemory; /** * 分配内存 MB */ private int maxMemory; /** * 机器实例使用内存总和 MB */ private int usedMemory; private MachineInfo info; private MachineMemInfo machineMemInfo; private String versionInfo; private Map diskUsageMap; /** * 实例个数 */ private int instanceCount; /** * 创建时间 */ private Date createTime; /** * 修改时间 */ private Date modifyTime; /** * Redis是否全部安装成功 0:未全部安装 1:全部安装成功 */ private int isInstall; private String diskTotal; private String diskAvailable; private String diskUsageRatio; /** * 时间格式化 */ public String getUpdateTimeFormat() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(modifyTime); } //统计数据是否有效 public boolean validate() { if (StringUtils.isBlank(load) && StringUtils.isBlank(cpuUsage) && StringUtils.isBlank(memoryFree) && StringUtils.isBlank(memoryTotal)) { return false; } return true; } public Date getCreateTime() { if(null == createTime){ return null; } return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { if(null == createTime){ this.createTime = null; }else{ this.createTime = (Date) createTime.clone(); } } public Date getModifyTime() { if(null == modifyTime){ return null; } return (Date) modifyTime.clone(); } public void setModifyTime(Date modifyTime) { if(null == modifyTime){ this.modifyTime = null; }else{ this.modifyTime = (Date) modifyTime.clone(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/OperationAlertValueResult.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by rucao */ @Data public class OperationAlertValueResult { String ip; MachineInfo machineInfo; String type; String status; String message; public OperationAlertValueResult(String ip, MachineInfo machineInfo, String type, String status, String message) { this.ip = ip; this.machineInfo = machineInfo; this.type = type; this.status = status; this.message = message; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ParamCount.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 用于group by结果 * @author fulei */ @Data public class ParamCount { private String param; private double count; private String url; public ParamCount() { } /** * @param param * @param count * @param url */ public ParamCount(String param, double count, String url) { super(); this.param = param; this.count = count; this.url = url; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/RedisVersion.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Created by chenshi on 2018/8/23. */ @Data public class RedisVersion { /** * 主键id */ private int id; /** * redis版本名称 格式:redis-主.子.小版本号 */ private String name; /** * 是否有效 1:有效 0:无效 */ private int status; /** * 安装目录 */ private String dir; /** * redis大版本号 格式:redis-主.子版本号 */ private String groups; /** * 大版本默认版本号(推荐) */ private int isBind; /** * 资源id */ private int resourceId; public RedisVersion() { } public RedisVersion(int id) { this.id = id; } public RedisVersion(String name, int status) { this.name = name; this.status = status; } public RedisVersion(String name, int status, String dir) { this.name = name; this.status = status; this.dir = dir; } public RedisVersion(String name, int status, String dir, String groups, int isBind, int resourceId) { this.name = name; this.status = status; this.dir = dir; this.groups = groups; this.isBind = isBind; this.resourceId = resourceId; } public RedisVersion(int id, String name, int status, String dir, String groups, int isBind, int resourceId) { this.id = id; this.name = name; this.status = status; this.dir = dir; this.groups = groups; this.isBind = isBind; this.resourceId = resourceId; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/RedisVersionStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * Redis版本管理统计信息 */ @Data public class RedisVersionStat { /** * Redis版本信息 */ SystemResource redisVersion; /** * 已安装机器数量 */ int installNum; /** * 未安装机器数量 */ int uninstallNum; /** * 安装异常机器数量 */ int installExceptionNum; /** * 机器总量 */ int totalMachineNum; /** * 已安装比例 num% */ int installRatio; /** * 应用使用数量 */ int appUsedNum; /** * 总应用数量 */ int totalAppNum; /** * 未安装机器ip */ int unInstallIp; public RedisVersionStat() { } public RedisVersionStat(SystemResource redisVersion) { this.redisVersion = redisVersion; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ServerInfo.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 服务器信息 */ @Data public class ServerInfo { private String ip; private String host; //逻辑cpu个数 private int cpus; //nmon版本 private String nmon; //cpu型号 private String cpuModel; //内核版本 private String kernel; //发行版本 private String dist; //ulimit private String ulimit; // gcc version private String gcc; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ServerStatus.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 服务器状态 */ @Data public class ServerStatus { private String cdate; private String ctime; private float cuser; private float csys; private float cwio; private String cExt; private float cload1; private float cload5; private float cload15; private float mtotal; private float mfree; private float mcache; private float mbuffer; private float mswap; private float mswapFree; private float nin; private float nout; private int tuse; private int torphan; private int twait; private String ninExt; private String noutExt; private float dread; private float dwrite; private float diops; private float dbusy; private String dExt; private String dspace; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/StandardStats.java ================================================ package com.sohu.cache.entity; import lombok.Data; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** * 实例基准统计 * Created by zhangyijun */ @Data public class StandardStats { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * id */ private long id; /** * 实例IP */ private String ip; /** * 实例端口号/hostId */ private int port; /** * 实例类型 */ private String dbType; /** * 收集时间:格式yyyyMMddHHmm */ private long collectTime; /** * 实例收集的json数据 */ private String infoJson; /** * 与上一次收集差异的json数据 */ private String diffJson; /** * 实例收集的cluster info json数据 */ private String clusterInfoJson; /** * infoJson的Map输出 */ private Map infoMap; /** * diffJson的Map输出 */ private Map diffMap; /** * clusterInfoJson的Map输出 */ private Map clusterInfoMap; private Date createdTime; public Map getInfoMap() { if (infoMap != null) { return infoMap; } else { if (StringUtils.isNotBlank(infoJson)) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(infoJson); Map map = transferMapByJson(jsonObject); infoMap = map; } catch (Exception e) { logger.error(e.getMessage()); } } } return infoMap; } public void setInfoMap(Map infoMap) { if (infoJson == null) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(infoMap); infoJson = jsonObject.toString(); } catch (Exception e) { logger.error(e.getMessage()); } } this.infoMap = infoMap; } public Map getDiffMap() { if (diffMap != null) { return diffMap; } else { if (StringUtils.isNotBlank(diffJson)) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(diffJson); Map map = transferMapByJson(jsonObject); diffMap = map; } catch (Exception e) { logger.error(e.getMessage()); } } } return diffMap; } /** * 递归转换JsonObject * * @param jsonObject * @return */ private Map transferMapByJson(JSONObject jsonObject) { Map map = new LinkedHashMap(); for (Iterator keys = jsonObject.keys(); keys.hasNext(); ) { String key = String.valueOf(keys.next()); Object value = jsonObject.get(key); if (value instanceof JSONObject) { JSONObject subJsonObject = (JSONObject) value; Map subMap = transferMapByJson(subJsonObject); map.put(key, subMap); } else { map.put(key, value); } } return map; } public void setDiffMap(Map diffMap) { if (diffJson == null) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(diffMap); diffJson = jsonObject.toString(); } catch (Exception e) { logger.error(e.getMessage()); } } this.diffMap = diffMap; } public Map getClusterInfoMap() { if (clusterInfoMap != null) { return clusterInfoMap; } else { if (StringUtils.isNotBlank(clusterInfoJson)) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(clusterInfoJson); Map map = transferMapByJson(jsonObject); clusterInfoMap = map; } catch (Exception e) { logger.error(e.getMessage()); } } } return clusterInfoMap; } public void setClusterInfoMap(Map clusterInfoMap) { if (clusterInfoJson == null) { JSONObject jsonObject; try { jsonObject = JSONObject.fromObject(clusterInfoMap); clusterInfoJson = jsonObject.toString(); } catch (Exception e) { logger.error(e.getMessage()); } } this.clusterInfoMap = clusterInfoMap; } public Date getCreatedTime() { return (Date) createdTime.clone(); } public void setCreatedTime(Date createdTime) { this.createdTime = (Date) createdTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/SystemConfig.java ================================================ package com.sohu.cache.entity; import lombok.Data; /** * 系统配置 * * @author leifu */ @Data public class SystemConfig { private String configKey; private String configValue; private String info; private int status; private int orderId; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/SystemResource.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * Created by chenshi on 2020/7/6. */ @Data public class SystemResource { private int id; private String name; private String intro; private int type; private String dir; private Date lastmodify; private String url; private int status; private int ispush; private String username; private long taskId; private String compileInfo; private int orderNum; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/ThreadPoolStat.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.util.Date; /** * @author fulei * @date 2018年8月11日 * @time 上午11:16:22 */ @Data public class ThreadPoolStat { private long id; /** * 进程ip */ private String ip; /** * 进程port */ private int port; private String threadPoolName; private long collectTime; private Date collectDate; private int maximumPoolSize; private int corePoolSize; private int activeCount; private long diffTaskCount; private long taskCount; private long completedTaskCount; private int queueSize; private Date createTime; private Date updateTime; public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getCollectDate() { return (Date) collectDate.clone(); } public void setCollectDate(Date collectDate) { this.collectDate = (Date) collectDate.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/TimeBetween.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * @author leifu */ @Data public class TimeBetween { private long startTime; private long endTime; private Date startDate; private Date endDate; public TimeBetween() { } public TimeBetween(long startTime, long endTime, Date startDate, Date endDate) { this.startTime = startTime; this.endTime = endTime; this.startDate = startDate; this.endDate = endDate; } public String getFormatStartDate() { String dateFormat = "yyyy-MM-dd"; SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); if (startDate != null) { return sdf.format(startDate); } return ""; } public String getFormatStartDate(String dateFormat) { SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); if (startDate != null) { return sdf.format(startDate); } return ""; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/TimeDimensionality.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.dao.AppStatsDao; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; /** * Created by yijunzhang */ @Data public class TimeDimensionality { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final long begin; private final long end; private final int dimensionality; public TimeDimensionality(long begin, long end, String format) { Date beginDate = DateUtil.getDateByFormat(String.valueOf(begin), format); Date endDate = DateUtil.getDateByFormat(String.valueOf(end), format); this.dimensionality = getSuitableDimensionality(beginDate, endDate); if (dimensionality == AppStatsDao.MINUTE_DIMENSIONALITY) { this.begin = Long.parseLong(DateUtil.formatDate(beginDate, "yyyyMMddHHmm")); } else { this.begin = Long.parseLong(DateUtil.formatDate(beginDate, "yyyyMMddHH")); } if (dimensionality == AppStatsDao.MINUTE_DIMENSIONALITY) { this.end = Long.parseLong(DateUtil.formatDate(endDate, "yyyyMMddHHmm")); } else { this.end = Long.parseLong(DateUtil.formatDate(endDate, "yyyyMMddHH")); } } /** * 获取合适的维度 */ private int getSuitableDimensionality(Date begin, Date end) { try { long s1 = begin.getTime(); long s2 = end.getTime(); long hour = (s2 - s1) / 1000 / 60 / 60; if (hour >= 48) { return AppStatsDao.HOUR_DIMENSIONALITY; } else { return AppStatsDao.MINUTE_DIMENSIONALITY; } } catch (Exception e) { logger.error(e.getMessage(), e); } return AppStatsDao.MINUTE_DIMENSIONALITY; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/TopologyExamResult.java ================================================ package com.sohu.cache.entity; import lombok.Data; import java.text.SimpleDateFormat; import java.util.Date; /** * Created by rucao on 2019/1/31 */ @Data public class TopologyExamResult { private long id; private long appId; private String type; private String status; private String description; private Date createTime; public TopologyExamResult(long appId, String type, String status, String description){ this.appId=appId; this.type=type; this.status=status; this.description=description; this.createTime=new Date(); } public String getCreateTimeFormat() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); if (createTime != null) { return sdf.format(createTime); } return ""; } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/entity/TriggerInfo.java ================================================ package com.sohu.cache.entity; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import java.util.Date; /** * trigger的信息及状态 */ @Data public class TriggerInfo { private String schedName; private String triggerName; private String triggerGroup; private String jobName; private String jobGroup; private String description; private long nextFireTime; private String nextFireDate; private long prevFireTime; private String prevFireDate; private int priority; private String triggerState; private String triggerType; private long startTime; private String startDate; private long endTime; private String endDate; private String calendarName; private short misfireInstr; private String cron; public String getNextFireDate() { if (nextFireTime > 0) { return DateUtil.formatYYYYMMddHHMMSS(new Date(nextFireTime)); } return ""; } public String getPrevFireDate() { if (prevFireTime > 0) { return DateUtil.formatYYYYMMddHHMMSS(new Date(prevFireTime)); } return ""; } public String getStartDate() { if (startTime > 0) { return DateUtil.formatYYYYMMddHHMMSS(new Date(startTime)); } return ""; } public String getEndDate() { if (endTime > 0) { return DateUtil.formatYYYYMMddHHMMSS(new Date(endTime)); } return ""; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/exception/IllegalParamException.java ================================================ package com.sohu.cache.exception; /** * 参数异常 * * @author leifu * @Date 2016-1-26 * @Time 下午9:21:03 */ public class IllegalParamException extends Exception { private static final long serialVersionUID = -1148039976867829902L; public IllegalParamException() { super(); } public IllegalParamException(String message) { super(message); } public IllegalParamException(String message, Throwable cause) { super(message, cause); } public IllegalParamException(Throwable cause) { super(cause); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/exception/SSHException.java ================================================ package com.sohu.cache.exception; /** * ssh异常 * @author leifu * @Date 2016-1-26 * @Time 下午9:18:54 */ public class SSHException extends Exception { private static final long serialVersionUID = -6213665149000064880L; public SSHException() { super(); } public SSHException(String message) { super(message); } public SSHException(String message, Throwable cause) { super(message, cause); } public SSHException(Throwable cause) { super(cause); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/InspectHandler.java ================================================ package com.sohu.cache.inspect; import java.util.List; /** * Created by yijunzhang on 15-1-20. */ public interface InspectHandler { public void handle(); public void setInspectorList(List inspectorList); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/InspectParamEnum.java ================================================ package com.sohu.cache.inspect; /** * Created by yijunzhang on 15-1-20. */ public enum InspectParamEnum { /** * 分组字段: * HostInspectHandler 表示host * AppInspectHandler 表示appId */ SPLIT_KEY("split_key"), INSTANCE_LIST("instance_list"); private String value; InspectParamEnum(String value) { this.value = value; } public String value(){ return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/Inspector.java ================================================ package com.sohu.cache.inspect; import java.util.Map; /** * Created by yijunzhang on 15-1-20. */ public interface Inspector { /** * 执行检测逻辑 * * @return */ public boolean inspect(Map paramMap); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/InspectorJob.java ================================================ package com.sohu.cache.inspect; import com.sohu.cache.schedule.jobs.CacheBaseJob; import com.sohu.cache.util.EnvUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; /** * Created by yijunzhang */ public class InspectorJob extends CacheBaseJob { private static final long serialVersionUID = -4277329946053271489L; @Override public void action(JobExecutionContext context) { try { long start = System.currentTimeMillis(); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); Environment env = applicationContext.getBean(Environment.class); if (EnvUtil.isDev(env)) { logger.warn("environment is dev ignored"); return; } // 应用相关 InspectHandler inspectHandler; JobDataMap jobDataMap = context.getMergedJobDataMap(); String inspectorType = MapUtils.getString(jobDataMap, "inspectorType"); if (StringUtils.isBlank(inspectorType)) { logger.error("=====================InspectorJob:inspectorType is null====================="); return; } else if (inspectorType.equals("host")) { inspectHandler = applicationContext.getBean("hostInspectHandler", InspectHandler.class); } else if (inspectorType.equals("app")) { inspectHandler = applicationContext.getBean("appInspectHandler", InspectHandler.class); } else { logger.error("=====================InspectorJob:inspectorType not match:{}=====================", inspectorType); return; } inspectHandler.handle(); long end = System.currentTimeMillis(); logger.info("=====================InspectorJob {} Done! cost={} ms=====================", inspectHandler.getClass().getSimpleName(), (end - start)); } catch (Exception e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/AbstractInspectHandler.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.async.NamedThreadFactory; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.inspect.InspectHandler; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * Created by yijunzhang on 15-1-20. */ public abstract class AbstractInspectHandler implements InspectHandler { protected final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired protected InstanceDao instanceDao; @Autowired protected AsyncService asyncService; protected List inspectorList; protected abstract String getThreadPoolKey(); protected abstract Map> getSplitMap(); public void init() { asyncService.assemblePool(getThreadPoolKey(), new ThreadPoolExecutor(10, 100, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(1024), new NamedThreadFactory(getThreadPoolKey(), true))); } public void handle() { if (inspectorList == null || inspectorList.isEmpty()) { logger.warn("inspectorList is null"); return; } Map> splitMap = getSplitMap(); for (Map.Entry> entry : splitMap.entrySet()) { String splitKey = entry.getKey(); List instances = entry.getValue(); final Map paramMap = new HashMap(); paramMap.put(InspectParamEnum.SPLIT_KEY, splitKey); paramMap.put(InspectParamEnum.INSTANCE_LIST, instances); String key = getThreadPoolKey() + "-" + splitKey; asyncService.submitFuture(getThreadPoolKey(), new KeyCallable(key) { @Override public Boolean execute() { for (Inspector inspector : inspectorList) { boolean isSuccess = false; try { isSuccess = inspector.inspect(paramMap); } catch (Throwable e) { logger.error(e.getMessage(), e); } if (!isSuccess) { logger.error(getThreadPoolKey() + "-failed:" + inspector.getClass().getName()); return false; } } return true; } }); } } public void setInspectorList(List inspectorList) { this.inspectorList = inspectorList; } public List getAllInstanceList() { return instanceDao.getAllInsts(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/AppClientConnInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import java.util.Arrays; import java.util.List; import java.util.Map; /** * 应用客户端连接监控 * * @author leifu * @Date 2016年6月16日 * @Time 上午9:44:34 */ public class AppClientConnInspector extends BaseAlertService implements Inspector { /** * app统计相关 */ private AppStatsCenter appStatsCenter; /** * 实例统计相关 */ private InstanceStatsCenter instanceStatsCenter; @Override public boolean inspect(Map paramMap) { Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY); AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId); if (appDetailVO == null) { logger.warn("appId {} appDetailVO is empty", appId); return true; } List appInstanceInfoList = (List) paramMap.get(InspectParamEnum.INSTANCE_LIST); if (CollectionUtils.isEmpty(appInstanceInfoList)) { logger.warn("appId {} instanceList is empty", appId); return true; } // 报警阀值 int appClientConnThreshold = getClientConnThreshold(appDetailVO.getAppDesc()); int appClientConnNum = appDetailVO.getConn(); // 阀值乘以分片个数 int instanceCount = appInstanceInfoList.size(); if (appClientConnNum > appClientConnThreshold * instanceCount) { alertAppClientConn(appDetailVO, appClientConnThreshold, instanceCount); } else { for (InstanceInfo instanceInfo : appInstanceInfoList) { if (instanceInfo == null) { continue; } if (instanceInfo.isOffline()) { continue; } if (!TypeUtil.isRedisType(instanceInfo.getType())) { continue; } // 忽略sentinel观察者 if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } long instanceId = instanceInfo.getId(); InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId); if (instanceStats == null) { continue; } double instanceClientConnNum = instanceStats.getCurrConnections(); // 大于标准值 if (instanceClientConnNum > appClientConnThreshold) { alertInstanceClientConn(instanceStats, appDetailVO, appClientConnThreshold); } } } return true; } /** * 获取报警阀值(如果用户预设超过系统预设,以系统为准,反之以用户为准) * @param appDesc * @return */ private int getClientConnThreshold(AppDesc appDesc) { int userClientConnThreshold = appDesc.getClientConnAlertValue(); int systemClientConnThreshold = ConstUtils.APP_CLIENT_CONN_THRESHOLD; return userClientConnThreshold > systemClientConnThreshold ? systemClientConnThreshold : userClientConnThreshold; } /** * 应用连接数报警 * @param appDetailVO * @param appClientConnThreshold * @param instanceCount */ private void alertAppClientConn(final AppDetailVO appDetailVO, final int appClientConnThreshold, final int instanceCount) { AppDesc appDesc = appDetailVO.getAppDesc(); String content = String.format("应用(%s)-客户端连接数报警-预设阀值每个分片为%s-现已达到%s(分片个数:%s)-请及时关注", appDesc.getAppId(), appClientConnThreshold, appDetailVO.getConn(), instanceCount); String title = "CacheCloud系统-客户端连接数报警"; logger.warn("app title {}", title); logger.warn("app content {}", content); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.APP_CLIENT_CONNECTION, title, content, appDetailVO); emailComponent.sendMail(title, content, appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); weChatComponent.sendWeChatToAll(title,content,appDetailVO.getWeChatList()); } /** * 单个分片连接数报警 * @param instanceStats * @param appDetailVO * @param appClientConnThreshold */ private void alertInstanceClientConn(final InstanceStats instanceStats, final AppDetailVO appDetailVO, final int appClientConnThreshold) { String instanceHostPort = instanceStats.getIp() + ":" + instanceStats.getPort(); String content = String.format("分片(%s,应用(%s))客户端连接数报警-预设%s-现已达到%s-请及时关注", instanceHostPort, instanceStats.getAppId(), appClientConnThreshold, instanceStats.getCurrConnections()); String title = "CacheCloud系统-分片客户端连接数报警"; logger.warn("instance title {}", title); logger.warn("instace content {}", content); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.APP_SHARD_CLENT_CONNECTION, title, content, appDetailVO, instanceStats); emailComponent.sendMail(title, content, appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); weChatComponent.sendWeChatToAll(title,content,appDetailVO.getWeChatList()); } public void setAppStatsCenter(AppStatsCenter appStatsCenter) { this.appStatsCenter = appStatsCenter; } public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) { this.instanceStatsCenter = instanceStatsCenter; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/AppHitPrecentInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.dao.AppDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; /** * Created by chenshi on 2017/9/11. */ public class AppHitPrecentInspector extends BaseAlertService implements Inspector { /** * app统计相关 */ private AppStatsCenter appStatsCenter; /** * 应用相关dao */ private AppDao appDao; @Override public boolean inspect(Map paramMap) { Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY); List appDescList = new ArrayList(); AppDesc app = appDao.getAppDescById(appId); if (app != null) { appDescList.add(app); } if (CollectionUtils.isEmpty(appDescList)) { logger.error("appList is empty, appId={}", appId); return true; } // 执行检查逻辑 for (AppDesc appDesc : appDescList) { // 测试不检查 if (appDesc.getIsTest() == 1) { continue; } long checkAppid = appDesc.getAppId(); // 监控命中率阀值(阀值为0不监控) int hitprecent_alertValue = appDesc.getHitPrecentAlertValue(); if (hitprecent_alertValue == 0) { //logger.error("ignore hitprcent monitor, appId={}", appId); return true; } AppDetailVO appDetailVO = appStatsCenter.getAppDetail(checkAppid); if (appDetailVO == null) { continue; } // 全局命中率 double hitPercent = appDetailVO.getHitPercent(); if (hitPercent < hitprecent_alertValue) { // 报警 alertAppHitPrecnt(appDetailVO); } } return false; } /** *

* Description:命中率低于监控阀值 *

* * @param appDetailVO 应用信息 * @return void * @author chenshi * @version 1.0 * @date 2017/9/11 */ private void alertAppHitPrecnt(final AppDetailVO appDetailVO) { AppDesc appDesc = appDetailVO.getAppDesc(); String content = String.format("应用(%s)-应用平均命中率报警-当前命中率百分之%s-现已低于预设百分之%s-请及时关注", appDesc.getAppId(), appDetailVO.getHitPercent(), appDesc.getHitPrecentAlertValue()); String title = "CacheCloud系统-应用平均命中率报警"; appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.APP_HIT_RATIO, title, content, appDetailVO); emailComponent.sendMail(title, content, appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); weChatComponent.sendWeChatToAll(title,content,appDetailVO.getWeChatList()); } public void setAppStatsCenter(AppStatsCenter appStatsCenter) { this.appStatsCenter = appStatsCenter; } public void setAppDao(AppDao appDao) { this.appDao = appDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/AppInspectHandler.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.entity.InstanceInfo; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Created by yijunzhang on 15-1-20. */ public class AppInspectHandler extends AbstractInspectHandler{ private final static String inspectPoolKey="inspector-app-pool"; @Override public String getThreadPoolKey() { return inspectPoolKey; } @Override protected Map> getSplitMap() { List list = getAllInstanceList(); Map> hostMap = new TreeMap>(); for (InstanceInfo instanceInfo : list) { String appId = String.valueOf(instanceInfo.getAppId()); if (hostMap.containsKey(appId)) { hostMap.get(appId).add(instanceInfo); } else { List hostInstances = new ArrayList(); hostInstances.add(instanceInfo); hostMap.put(appId, hostInstances); } } return hostMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/AppMemInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.dao.AppDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.service.AppAutoCapacityService; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by yijunzhang on 15-1-20. */ public class AppMemInspector extends BaseAlertService implements Inspector { /** * app统计相关 */ private AppStatsCenter appStatsCenter; /** * 应用相关dao */ private AppDao appDao; /** * 实例统计相关 */ private InstanceStatsCenter instanceStatsCenter; /** * 自动扩容 */ private AppAutoCapacityService appAutoCapacityService; @Override public boolean inspect(Map paramMap) { Long appId = MapUtils.getLong(paramMap, InspectParamEnum.SPLIT_KEY); List appDescList = new ArrayList(); AppDesc app = appDao.getAppDescById(appId); if (app != null) { appDescList.add(app); } if (CollectionUtils.isEmpty(appDescList)) { logger.error("appList is empty, appId={}", appId); return true; } for (AppDesc appDesc : appDescList) { //测试不检查 if(appDesc.getIsTest() == 1){ continue; } long checkAppId = appDesc.getAppId(); AppDetailVO appDetailVO = appStatsCenter.getAppDetail(checkAppId); if (appDetailVO == null) { continue; } double appMemUsePercent = appDetailVO.getMemUsePercent(); double appDiskUsePercent = appDetailVO.getDiskUsePercent(); int appUseSetMemAlertValue = appDesc.getMemAlertValue(); Map instanceStatsMap = new HashMap<>(); List appInstanceInfoList = (List) paramMap.get(InspectParamEnum.INSTANCE_LIST); if (CollectionUtils.isNotEmpty(appInstanceInfoList)) { for (InstanceInfo instanceInfo : appInstanceInfoList) { if (instanceInfo == null) { continue; } if (!TypeUtil.isRedisType(instanceInfo.getType())) { continue; } // 忽略sentinel观察者 if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } long instanceId = instanceInfo.getId(); InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId); instanceStatsMap.put(instanceInfo, instanceStats); } } // 先检查应用的内存使用率是否超过阀值,如果没有再检查分片 if (appMemUsePercent > appUseSetMemAlertValue) { // 报警 alertAppMemUse(appDetailVO); } else { if (CollectionUtils.isNotEmpty(appInstanceInfoList)) { for (InstanceInfo instanceInfo : appInstanceInfoList) { if (instanceInfo == null) { continue; } if (!TypeUtil.isRedisType(instanceInfo.getType())) { continue; } // 忽略sentinel观察者 if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } long instanceId = instanceInfo.getId(); InstanceStats instanceStats = instanceStatsMap.get(instanceInfo); if(instanceStats == null){ continue; } double instanceMemUsePercent = instanceStats.getMemUsePercent(); // 大于标准值 if (instanceMemUsePercent > appUseSetMemAlertValue) { alertInstanceMemUse(instanceStats, appDetailVO); } } } } appAutoCapacityService.checkAndExpandCapacity(appDesc, Double.valueOf(appMemUsePercent).intValue(), instanceStatsMap); } return true; } /** * @param appDetailVO */ private void alertAppMemUse(final AppDetailVO appDetailVO) { AppDesc appDesc = appDetailVO.getAppDesc(); String content = String.format("应用(%s)-内存使用率报警-预设百分之%s-现已达到百分之%s-请及时关注", appDesc.getAppId(), appDesc.getMemAlertValue(), appDetailVO.getMemUsePercent()); String title = "CacheCloud系统-应用内存使用率报警"; appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.APP_MEM_USED_RATIO, title, content, appDetailVO); emailComponent.sendMail(title, content, appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); weChatComponent.sendWeChatToAll(title,content,appDetailVO.getWeChatList()); } private void alertInstanceMemUse(final InstanceStats instanceStats, final AppDetailVO appDetailVO) { String instanceInfo = instanceStats.getIp() + ":" + instanceStats.getPort(); String content = String.format("分片(%s,应用(%s))内存使用率报警-预设百分之%s-现已达到百分之%s-应用的内存使用率百分之%s-请及时关注", instanceInfo, instanceStats.getAppId(), appDetailVO.getAppDesc().getMemAlertValue(), instanceStats.getMemUsePercent(), appDetailVO.getMemUsePercent()); String title = "CacheCloud系统-分片内存使用率报警"; appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.APP_SHARD_MEM_USED_RATIO, title, content, appDetailVO, instanceStats); emailComponent.sendMail(title, content, appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); weChatComponent.sendWeChatToAll(title,content,appDetailVO.getWeChatList()); } public void setAppStatsCenter(AppStatsCenter appStatsCenter) { this.appStatsCenter = appStatsCenter; } public void setAppDao(AppDao appDao) { this.appDao = appDao; } public void setInstanceStatsCenter(InstanceStatsCenter instanceStatsCenter) { this.instanceStatsCenter = instanceStatsCenter; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/HostInspectHandler.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.entity.InstanceInfo; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * Created by yijunzhang on 15-1-20. */ public class HostInspectHandler extends AbstractInspectHandler{ private final static String inspectPoolKey="inspector-host-pool"; @Override public String getThreadPoolKey() { return inspectPoolKey; } @Override protected Map> getSplitMap() { List list = getAllInstanceList(); Map> hostMap = new TreeMap>(); for (InstanceInfo instanceInfo : list) { String host = instanceInfo.getIp(); if (hostMap.containsKey(host)) { hostMap.get(host).add(instanceInfo); } else { List hostInstances = new ArrayList(); hostInstances.add(instanceInfo); hostMap.put(host, hostInstances); } } return hostMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/InstanceRunInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.InstanceFaultDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceFault; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.enums.BooleanEnum; import org.apache.commons.collections4.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.util.Date; import java.util.List; import java.util.Map; /** * Created by yijunzhang on 15-1-20. */ public class InstanceRunInspector extends BaseAlertService implements Inspector { /** * 实例相关 */ @Autowired private InstanceDao instanceDao; /** * redis相关 */ @Autowired private RedisCenter redisCenter; /** * 应用相关dao */ @Autowired private AppDao appDao; @Autowired private InstanceFaultDao instanceFaultDao; @Override public boolean inspect(Map paramMap) { String host = MapUtils.getString(paramMap, InspectParamEnum.SPLIT_KEY); List list = (List) paramMap.get(InspectParamEnum.INSTANCE_LIST); for (InstanceInfo info : list) { final int port = info.getPort(); final int type = info.getType(); long appId = info.getAppId(); if (TypeUtil.isRedisType(type)) { boolean isRun; if (TypeUtil.isRedisSentinel(type)) { isRun = redisCenter.isRun(host, port); } else { isRun = redisCenter.isRun(appId, host, port); } BooleanEnum isUpdate = updateInstanceByRun(isRun, info); // 错误 if (isUpdate != BooleanEnum.OTHER) { alertInstanceInfo(info); } } } return true; } /** * 邮箱+短信 * * @param info */ private void alertInstanceInfo(InstanceInfo info) { sendEmailAlert(info); } /** * 发送邮箱报警 * * @param info */ private void sendEmailAlert(InstanceInfo info) { if (info == null) { return; } String title = "实例(" + info.getIp() + ":" + info.getPort() + ")状态发生变化"; String message = generateMessage(info, true); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.INSTANCE_RUNNING_STATE_CHANGE, title, message, info); emailComponent.sendMailToAdmin(title, message); } /** * 返回示例消息 * * @param info * @return */ private String generateMessage(InstanceInfo info, boolean isEmail) { StringBuffer message = new StringBuffer(); long appId = info.getAppId(); AppDesc appDesc = appDao.getAppDescById(appId); message.append("CacheCloud系统-实例(" + info.getIp() + ":" + info.getPort() + ")-"); if (info.getStatus() == InstanceStatusEnum.ERROR_STATUS.getStatus()) { message.append("由运行中变为心跳停止"); } else if (info.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) { message.append("由心跳停止变为运行中"); } if (isEmail) { message.append(", appId:"); message.append(appId + "-" + appDesc.getName()); } else { message.append("-appId(" + appId + "-" + appDesc.getName() + ")"); } return message.toString(); } private void saveFault(InstanceInfo info, boolean isRun) { InstanceFault instanceFault = new InstanceFault(); instanceFault.setAppId((int) info.getAppId()); instanceFault.setInstId(info.getId()); instanceFault.setIp(info.getIp()); instanceFault.setPort(info.getPort()); instanceFault.setType(info.getType()); instanceFault.setCreateTime(new Date()); if (isRun) { instanceFault.setReason("恢复运行"); } else { instanceFault.setReason("心跳停止"); } instanceFaultDao.insert(instanceFault); } private BooleanEnum updateInstanceByRun(boolean isRun, InstanceInfo info) { try { InstanceInfo info_new = instanceDao.getInstanceInfoById(info.getId()); info.setStatus(info_new.getStatus()); if (isRun) { if (info.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { info.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceDao.update(info); logger.warn("instance:{} instance is run", info); saveFault(info, isRun); return BooleanEnum.TRUE; } } else { if (info.getStatus() != InstanceStatusEnum.ERROR_STATUS.getStatus() && info.getStatus() != InstanceStatusEnum.OFFLINE_STATUS.getStatus()) { info.setStatus(InstanceStatusEnum.ERROR_STATUS.getStatus()); instanceDao.update(info); logger.error("instance:{} instance failed", info); saveFault(info, isRun); return BooleanEnum.FALSE; }else if(info.getStatus() == InstanceStatusEnum.OFFLINE_STATUS.getStatus()){ logger.error("instance:{} instance is offline", info); saveFault(info, isRun); return BooleanEnum.OTHER; } } } catch (Exception e) { logger.error(e.getMessage(), e); } return BooleanEnum.OTHER; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/InstanceStateInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.FreemakerUtils; import freemarker.template.Configuration; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Component public class InstanceStateInspector extends BaseAlertService { /** * 实例相关 */ @Autowired private InstanceDao instanceDao; @Autowired private AppService appService; @Autowired private UserService userService; @Autowired private Configuration configuration; public boolean inspect() { List alertInstInfo = new ArrayList<>(); List heartStopInstances = instanceDao.getAllHeartStopInstance(); if (!CollectionUtils.isEmpty(heartStopInstances)) { for (InstanceInfo info : heartStopInstances) { long appId = info.getAppId(); AppDesc appDesc = appService.getByAppId(appId); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); InstanceAlertValueResult instanceAlert = new InstanceAlertValueResult(); instanceAlert.setInstanceInfo(info); instanceAlert.setAppId(appId); instanceAlert.setAppDesc(appDesc); instanceAlert.setOtherInfo(InstanceStatusEnum.getByStatus(info.getStatus()).getInfo()); alertInstInfo.add(instanceAlert); } String emailTitle = String.format("Redis实例异常状态监控报警"); Map context = new HashMap<>(); context.put("instanceAlertValueResultList", alertInstInfo); String emailContent = FreemakerUtils.createText("instanceState.ftl", configuration, context); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.INATANCE_EXCEPTION_STATE_MONITOR, emailTitle, null, alertInstInfo); emailComponent.sendMailToAdmin(emailTitle, emailContent); logger.info(emailContent); } return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/inspect/impl/RedisIsolationPersistenceInspector.java ================================================ package com.sohu.cache.inspect.impl; import com.sohu.cache.alert.impl.BaseAlertService; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.inspect.InspectParamEnum; import com.sohu.cache.inspect.Inspector; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.enums.RedisInfoEnum; import com.sohu.cache.util.IdempotentConfirmer; import com.sohu.cache.util.TypeUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Value; import redis.clients.jedis.Jedis; import java.util.*; import java.util.concurrent.TimeUnit; /** * Created by yijunzhang on 15-1-30. */ public class RedisIsolationPersistenceInspector extends BaseAlertService implements Inspector { public static final int REDIS_DEFAULT_TIME = 5000; private RedisCenter redisCenter; @Value("${aof.rewrite.ignore-appIds:#{null}}") private String aofRewriteIgnoreAppIds; @Override public boolean inspect(Map paramMap) { Set aofRewriteIgnoreSet = new HashSet<>(); if(StringUtils.isNotEmpty(aofRewriteIgnoreAppIds)){ String[] appIds = aofRewriteIgnoreAppIds.split(";"); if(appIds != null && appIds.length > 0){ aofRewriteIgnoreSet.addAll(Arrays.asList(appIds)); } } final String host = MapUtils.getString(paramMap, InspectParamEnum.SPLIT_KEY); List list = (List) paramMap.get(InspectParamEnum.INSTANCE_LIST); outer: for (InstanceInfo info : list) { final int port = info.getPort(); final int type = info.getType(); final long appId = info.getAppId(); int status = info.getStatus(); //非正常节点 if (status != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } //过滤不重写appId if(aofRewriteIgnoreSet.contains(String.valueOf(appId))){ continue; } if (TypeUtil.isRedisDataType(type)) { Jedis jedis = redisCenter.getAdminJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { Map persistenceMap = parseMap(jedis); if (persistenceMap.isEmpty()) { logger.error("{}:{} get persistenceMap failed", host, port); continue; } if (!isAofEnabled(persistenceMap)) { continue; } long aofCurrentSize = MapUtils.getLongValue(persistenceMap, RedisInfoEnum.aof_current_size.getValue()); long aofBaseSize = MapUtils.getLongValue(persistenceMap, RedisInfoEnum.aof_base_size.getValue()); //阀值大于60% long aofThresholdSize = (long) (aofBaseSize * 1.6); double percentage = getPercentage(aofCurrentSize, aofBaseSize); if (aofCurrentSize >= aofThresholdSize //大于64Mb && aofCurrentSize > (64 * 1024 * 1024)) { //bgRewriteAof boolean isInvoke = invokeBgRewriteAof(jedis); if (!isInvoke) { logger.error("{}:{} invokeBgRewriteAof failed", host, port); continue; } else { logger.warn("{}:{} invokeBgRewriteAof started percentage={}", host, port, percentage); } while (true) { try { //before wait 1s TimeUnit.SECONDS.sleep(1); Map loopMap = parseMap(jedis); Integer aofRewriteInProgress = MapUtils.getInteger(loopMap, "aof_rewrite_in_progress", null); if (aofRewriteInProgress == null) { logger.error("loop watch:{}:{} return failed", host, port); break; } else if (aofRewriteInProgress <= 0) { //bgrewriteaof Done logger.warn("{}:{} bgrewriteaof Done lastSize:{}Mb,currentSize:{}Mb", host, port, getMb(aofCurrentSize), getMb(MapUtils.getLongValue(loopMap, "aof_current_size"))); break; } else { //wait 1s TimeUnit.SECONDS.sleep(1); } } catch (Exception e) { logger.error(e.getMessage(), e); } } } else { if (percentage > 50D) { long currentSize = getMb(aofCurrentSize); logger.debug("checked {}:{} aof increase percentage:{}% currentSize:{}Mb", host, port, percentage, currentSize > 0 ? currentSize : "<1"); } } } finally { jedis.close(); } } } return true; } private long getMb(long bytes) { return (long) (bytes / 1024 / 1024); } private boolean isAofEnabled(Map infoMap) { Integer aofEnabled = MapUtils.getInteger(infoMap, "aof_enabled", null); return aofEnabled != null && aofEnabled == 1; } private double getPercentage(long aofCurrentSize, long aofBaseSize) { if (aofBaseSize == 0) { return 0.0D; } String format = String.format("%.2f", (Double.valueOf(String.valueOf(aofCurrentSize - aofBaseSize)) * 100 / aofBaseSize)); return Double.parseDouble(format); } private Map parseMap(final Jedis jedis) { final StringBuilder builder = new StringBuilder(); boolean isInfo = new IdempotentConfirmer() { @Override public boolean execute() { String persistenceInfo = null; try { persistenceInfo = jedis.info("Persistence"); } catch (Exception e) { logger.warn(e.getMessage() + "-{}:{}", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()); } boolean isOk = StringUtils.isNotBlank(persistenceInfo); if (isOk) { builder.append(persistenceInfo); } return isOk; } }.run(); if (!isInfo) { logger.error("{}:{} info Persistence failed", jedis.getClient().getHost(), jedis.getClient().getPort()); return Collections.emptyMap(); } String persistenceInfo = builder.toString(); if (StringUtils.isBlank(persistenceInfo)) { return Collections.emptyMap(); } Map map = new LinkedHashMap(); String[] array = persistenceInfo.split("\r\n"); for (String line : array) { String[] cells = line.split(":"); if (cells.length > 1) { map.put(cells[0], cells[1]); } } return map; } public boolean invokeBgRewriteAof(final Jedis jedis) { return new IdempotentConfirmer() { @Override public boolean execute() { try { String response = jedis.bgrewriteaof(); if (response != null && response.contains("rewriting started")) { return true; } } catch (Exception e) { String message = e.getMessage(); if (message.contains("rewriting already")) { return true; } logger.error(message, e); } return false; } }.run(); } public void setRedisCenter(RedisCenter redisCenter) { this.redisCenter = redisCenter; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/interceptor/AppAndInstanceAuthorityInterceptor.java ================================================ package com.sohu.cache.interceptor; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.entity.AppToUser; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.service.UserService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.util.List; /** * 应用和实例权限验证 * * @author leifu * @Date 2014年10月29日 * @Time 下午3:18:00 */ public class AppAndInstanceAuthorityInterceptor extends HandlerInterceptorAdapter { private Logger logger = LoggerFactory.getLogger(AppAndInstanceAuthorityInterceptor.class); @Autowired private AppService appService; @Autowired private UserService userService; @Autowired private InstanceStatsCenter instanceStatsCenter; @Autowired private UserLoginStatusService userLoginStatusService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1. 获取用户 String userName = userLoginStatusService.getUserNameFromLoginStatus(request); //未登录 if (StringUtils.isBlank(userName)) { String redirectUrl = userLoginStatusService.getRedirectUrl(request); response.sendRedirect(redirectUrl); return false; } AppUser user = userService.getByName(userName); if (user == null || user.getType() == -1) { String redirectUrl = userLoginStatusService.getRegisterUrl(user); response.sendRedirect(redirectUrl); return false; } // 2. 管理员直接跳过 if (AppUserTypeEnum.ADMIN_USER.value().equals(user.getType())) { return true; } // 3. 应用id String appId = request.getParameter("appId"); if (StringUtils.isNotBlank(appId)) { checkUserAppPower(response, request.getSession(true), user, NumberUtils.toLong(appId)); } // 4. 实例权限检测(其实也是应用) String instanceId = request.getParameter("instanceId"); if (StringUtils.isNotBlank(instanceId)) { InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(Long.parseLong(instanceId)); checkUserAppPower(response, request.getSession(true), user, instanceInfo.getAppId()); } return true; } /** * 检查用户应用的权限 * * @param response * @param session * @param user * @param appId * @return */ private void checkUserAppPower(HttpServletResponse response, HttpSession session, AppUser user, Long appId) { // 应用下的用户 List appToUsers = appService.getAppToUserList(appId); if (CollectionUtils.isNotEmpty(appToUsers)) { for (AppToUser tempAppToUser : appToUsers) { if (user.getId().equals(tempAppToUser.getUserId())) { return; } } // 没权限 String path = session.getServletContext().getContextPath(); try { response.sendRedirect(path + "/web/resource/noPower?appId=" + appId); } catch (IOException e) { logger.error(e.getMessage(), e); } } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/interceptor/FrontUserLoginInterceptor.java ================================================ package com.sohu.cache.interceptor; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.service.UserService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 前置登陆验证 * * @author leifu */ public class FrontUserLoginInterceptor extends HandlerInterceptorAdapter { @Autowired private UserService userService; @Autowired private UserLoginStatusService userLoginStatusService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String userName = userLoginStatusService.getUserNameFromLoginStatus(request); //未登录 if (StringUtils.isBlank(userName)) { String redirectUrl = userLoginStatusService.getRedirectUrl(request); response.sendRedirect(redirectUrl); return false; } AppUser user = userService.getByName(userName); //新用户 if (user == null || user.getType() == -1) { String redirectUrl = userLoginStatusService.getRegisterUrl(user); response.sendRedirect(redirectUrl); return false; } request.setAttribute("userInfo", user); request.setAttribute("uri", request.getRequestURI()); return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/interceptor/ManageUserLoginInterceptor.java ================================================ package com.sohu.cache.interceptor; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.service.UserService; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 管理端登录验证 * @author leifu */ public class ManageUserLoginInterceptor extends HandlerInterceptorAdapter { private Logger logger = LoggerFactory.getLogger(ManageUserLoginInterceptor.class); @Autowired private UserService userService; @Autowired private UserLoginStatusService userLoginStatusService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String userName = userLoginStatusService.getUserNameFromLoginStatus(request); //未登录 if (StringUtils.isBlank(userName)) { String redirectUrl = userLoginStatusService.getRedirectUrl(request); response.sendRedirect(redirectUrl); return false; } AppUser user = userService.getByName(userName); //新用户 if (user == null || user.getType() == -1) { String redirectUrl = userLoginStatusService.getRegisterUrl(user); response.sendRedirect(redirectUrl); return false; } //必须是管理员 if (user.getType() != AppUserTypeEnum.ADMIN_USER.value()) { String redirectUrl = userLoginStatusService.getRedirectUrl(request); response.sendRedirect(redirectUrl); return false; } request.setAttribute("userInfo", user); request.setAttribute("uri", request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/log/CustLogAppenderInit.java ================================================ package com.sohu.cache.log; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @Component public class CustLogAppenderInit implements ApplicationRunner{ @Autowired private TaskFlowRecordAppender taskFlowRecordAppender; private final org.slf4j.Logger logger = LoggerFactory.getLogger(CustLogAppenderInit.class); @Override public void run(ApplicationArguments args) throws Exception { logger.warn("custLogAppender init begin!"); if (LoggerFactory.getILoggerFactory() instanceof LoggerContext) { LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); Logger rootLogger = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME); //自定义任务流appender taskFlowRecordAppender.setContext(loggerContext); taskFlowRecordAppender.start(); rootLogger.addAppender(taskFlowRecordAppender); logger.warn("custLogAppender init Done!"); } else { logger.error("custLogAppender init failed , LoggerFactory.getILoggerFactory()={}", LoggerFactory.getILoggerFactory()); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/log/TaskFlowRecordAppender.java ================================================ package com.sohu.cache.log; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.AppenderBase; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Marker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.sql.Date; import java.text.SimpleDateFormat; @Component public class TaskFlowRecordAppender extends AppenderBase { @Autowired private AssistRedisService assistRedisService; @Override protected void append(ILoggingEvent event) { if (event == null) { return; } Marker marker = event.getMarker(); if (marker != null && marker.getName().equals(BaseTask.MARKER_NAME)) { String taskFlowId = event.getMDCPropertyMap().get(TaskConstants.TASK_STEP_FLOW_ID); if (StringUtils.isBlank(taskFlowId)) { return; } String customLog = generateCustomLog(event); String taskFlowIdKey = ConstUtils.getTaskFlowRedisKey(taskFlowId); assistRedisService.rpush(taskFlowIdKey, customLog); } } private String generateCustomLog(ILoggingEvent event) { Date date = new Date(event.getTimeStamp()); String formatDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(date); String threadName = event.getThreadName(); String logLevel = event.getLevel().toString(); String className = event.getLoggerName(); String simpleClassName = getSimpleClassName(className); String formatMessage = event.getFormattedMessage(); return String.format("%s {%s} %s %s - %s", formatDate, threadName, logLevel, simpleClassName, formatMessage); } private String getSimpleClassName(String className) { int index = className.lastIndexOf("."); if (index >= 0) { return className.substring(index + 1); } return className; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/MachineCenter.java ================================================ package com.sohu.cache.machine; import com.sohu.cache.constant.MachineInfoEnum.TypeEnum; import com.sohu.cache.entity.*; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.web.enums.MachineMemoryDistriEnum; import com.sohu.cache.web.vo.MachineStatsVo; import java.util.Date; import java.util.List; import java.util.Map; /** * 基于host的操作 * User: lingguo */ public interface MachineCenter { /** * 收集host的状态信息 * * @param hostId 机器id * @param collectTime 收集时间 * @param ip ip * @return 机器的信息 */ public Map collectMachineInfo(final long hostId, final long collectTime, final String ip); /** * 异步收集host的状态信息 * * @param hostId 机器id * @param collectTime 收集时间 * @param ip ip */ public void asyncCollectMachineInfo(final long hostId, final long collectTime, final String ip); /** * 监控机器的状态信息,向上层汇报或者报警 * * @param hostId 机器id * @param ip ip * @return */ public void monitorMachineStats(final long hostId, final String ip); /** * 异步监控机器的状态信息,向上层汇报或者报警 * * @param hostId 机器id * @param ip ip * @return */ public void asyncMonitorMachineStats(final long hostId, final String ip); /** * 在主机ip上的端口port上启动一个进程,并check是否启动成功; * * @param ip ip * @param port 端口 * @param shell shell命令 * @return 是否成功 */ public boolean startProcessAtPort(String ip, int port, final String shell); /** * 执行shell命令并获取返回结果 * * @param ip * @param shell * @return */ public String executeShell(final String ip, String shell); String executeShell(final String ip, String shell, Integer timeout); /** * 根据类型返回机器可用端口 * * @param ip * @param type * @return */ public Integer getAvailablePort(final String ip, final int type); /** * 创建远程文件 * * @param host * @param fileName * @param content * @return 是否创建成功 */ public String createRemoteFile(final String host, String fileName, List content); /** * 获取机器列表 * * @param ipLike * @return */ public List getMachineStats(String ipLike); /** * 获取机器列表 * * @param ipLike * @param versionId * @param isInstall */ public List getMachineStats(String ipLike, Integer useType,Integer type, Integer versionId, Integer isInstall,Integer k8sType,String realip); /** * 获取全部机器列表 * * @return */ public List getAllMachineStats(); List getAllValidMachineMem(List excludeMachineList, String room, Integer useType); List getValidMachineMemByIpList(List ipList); /** * 根据ip获取机器信息 * * @param ip * @return */ public MachineInfo getMachineInfoByIp(String ip); MachineStats getMachineMemoryDetail(String ip); /** * 获取一台机器的所有实例 * * @param ip * @return */ List getMachineInstanceInfo(String ip); /** * 获取一台机器的所有实例统计信息 * * @param ip * @return */ List getMachineInstanceStatsByIp(String ip); /** * 获取指定机器某个redis端口的最近日志 * * @param maxLineNum * @return */ String showInstanceRecentLog(InstanceInfo instanceInfo, int maxLineNum); /** * 根据机器类型获取机器列表 * * @param typeEnum * @return */ List getMachineInfoByType(TypeEnum typeEnum); /** * 获取机器下实例数map * * @return */ public Map getMachineInstanceCountMap(); public Map getK8sMachineMap(); /** *

* Description: 获取有效机房 *

* * @author chenshi * @version 1.0 * @date 2018/10/16 */ public List getEffectiveRoom(); List getAllRoom(); /** * 机器使用内存分布 * @return */ public Map getMaxMemoryDistribute(); /** * 机器最大内存分布 * @return */ public Map getUsedMemoryDistribute(); public int getMachineNum(int type); /** * 获取机器性能统计分布 * @return */ public List getmachineStatsVoList(); /** * @param appId * @param port * @param instanceTypeEnum * @return */ public String getInstanceRemoteBasePath(long appId, int port, InstanceTypeEnum instanceTypeEnum); /** * 获取机器的部署路径 * 1.物理机/虚机/docker: /opt/cachecloud/conf /opt/cachecloud/data /opt/cachecloud/logs * 1.k8s容器: /opt/cachecloud/conf/${host}/ /opt/cachecloud/data/${host}/ /opt/cachecloud/logs/${host} * @param host 机器ip * @return */ public String getMachineRelativeDir(String host,int dirType); /** * 是否k8s机器 * @param host 机器ip * @return true:是 false:否 */ public Boolean isK8sMachine(String host); public Map getAllMachineEnv(Date searchDate,int type); public Map getExceptionMachineEnv(Date searchDate); /** * 获取机器列表的第一台机器资源 * @return */ public String getFirstMachineIp(); /** * 检查机器内存是否充足 容器内存*0.85 * @param ip 检测机器 * true: 内存充足 false:内存使用率>85% */ public boolean checkMachineMemory(String ip); public List getMachineListByRealIp(String realIp); /** * 获取机器配置信息及已分布redis实例(数量、申请内存、使用内存、使用内存rss等) */ public List getMachineInfoAndUsedInfo(String room, Integer type, Integer useType, Integer disType, String ip); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/MachineDeployCenter.java ================================================ package com.sohu.cache.machine; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineRelation; import com.sohu.cache.entity.MachineRoom; import com.sohu.cache.web.enums.SuccessEnum; import java.util.List; /** * 机器部署相关 * @author leifu * changed @Date 2016-4-24 * @Time 下午5:07:30 */ public interface MachineDeployCenter { /** * 增加一台机器:入db和开启统计 * * @param machineInfo */ public boolean addMachine(MachineInfo machineInfo); boolean addMachineRoom(MachineRoom room); boolean removeMachineRoom(int roomId); /** * 移除一台机器:删db数据和关闭统计 * * @param machineInfo */ public boolean removeMachine(MachineInfo machineInfo); /** * 记录pod每次变更虚ip和宿主机关系 */ public void updateMachineRelation(int id, Long taskid, int is_sync); /** * 查询容器 pod每次变更节点 */ public List getMachineRelationList(String containerIp); /** * 检测是同步任务状态 * @param containerIp * @param sourceIp * @return true:有同步中任务 false:没有同步中任务 */ public SuccessEnum checkMachineSyncStatus(String containerIp, String sourceIp, int is_sync); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/MachineProperty.java ================================================ package com.sohu.cache.machine; import com.google.common.collect.ComparisonChain; import java.io.Serializable; import java.util.Comparator; /** * 选择机器时根据机器的memory、traffic和load进行排序; * 在memory满足的情况,排序规则是:traffic > load > memory * * @author: lingguo * @time: 2014/9/17 12:04 */ public class MachineProperty implements Comparator, Serializable { private static final long serialVersionUID = 2498956982032225654L; private long hostId; private long memory; private double traffic; private double load; public MachineProperty() { } public MachineProperty(long hostId, long memory, double traffic, double load) { this.hostId = hostId; this.memory = memory; this.traffic = traffic; this.load = load; } public long getHostId() { return hostId; } public void setHostId(long hostId) { this.hostId = hostId; } public long getMemory() { return memory; } public void setMemory(long memory) { this.memory = memory; } public double getTraffic() { return traffic; } public void setTraffic(double traffic) { this.traffic = traffic; } public double getLoad() { return load; } public void setLoad(double load) { this.load = load; } @Override public int compare(MachineProperty o1, MachineProperty o2) { return ComparisonChain.start() .compare(o1.traffic, o2.traffic) .compare(o1.load, o2.load) .compare(o2.memory, o1.memory) .result(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/PortGenerator.java ================================================ package com.sohu.cache.machine; import com.sohu.cache.constant.EmptyObjectConstant; import com.sohu.cache.constant.SymbolConstant; import com.sohu.cache.exception.SSHException; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.util.ConstUtils; import com.google.common.util.concurrent.AtomicLongMap; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 生成一个redis可用端口 * * @author: lingguo * @time: 2014/8/25 20:57 */ public class PortGenerator { private static Logger logger = LoggerFactory.getLogger(PortGenerator.class); /** * redis port常量 */ private static final Integer REDIS_START_PORT = 6379; private static AtomicLongMap redisPortHolder = AtomicLongMap.create(); private static AtomicLongMap redisSentinelPortHolder = AtomicLongMap.create(); /** * 返回一个redis的可用端口: * - 1. 通过shell查询redis当前已用的最大port; * - 2. 为什么同步:防止多线程访问时获取到同样的端口; * - 3. 为什么还用原子计数:连续两次调用时,如果进程还没启动,则拿到的仍然是相同的端口; * * @param ip * @return */ public static synchronized Integer getRedisPort(final String ip) { if (redisPortHolder.get(ip) == 0L) { redisPortHolder.put(ip, REDIS_START_PORT); } String maxPortStr = ""; try { int sshPort = SSHUtil.getSshPort(ip); maxPortStr = getMaxPortStr(ip, sshPort); } catch (SSHException e) { logger.error("cannot get max port of redis by ssh, ip: {}", ip, e); } logger.warn("{} maxPort is {}", ip, maxPortStr); if (StringUtils.isBlank(maxPortStr) || !StringUtils.isNumeric(maxPortStr)) { logger.warn("{} the max port of redis is invalid, maxPortStr: {}", ip, maxPortStr); return (int)redisPortHolder.getAndIncrement(ip); } int availablePort = Integer.parseInt(maxPortStr) + 1; // 兼容连续调用的情况 if (availablePort < redisPortHolder.get(ip)) { availablePort = (int)redisPortHolder.getAndIncrement(ip); } else { // 正常情况,以及兼容系统重启和当前端口不可用的情形 redisPortHolder.put(ip, availablePort + 1L); } logger.warn("first {} maxPort is {}", ip, availablePort); try { while (SSHUtil.isPortUsed(ip, availablePort)) { availablePort++; } } catch (SSHException e) { logger.error("check port error, ip: {}, port: {}", ip, availablePort, e); } logger.warn("final {} maxPort is {}", ip, availablePort); redisPortHolder.put(ip, availablePort + 1L); return availablePort; } @Deprecated public static String getMaxPortStrOld(String ip, int sshPort) throws SSHException { String redisPidCmd = "ps -ef | grep redis | grep -v 'grep' | awk -F '*:' '{print $2}' " + " | awk -F ' ' '{print $1}' | sort -r | head -1"; return SSHUtil.execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, redisPidCmd); } /** * 直接解析ps -ef | grep redis | grep -v 'grep' * @param ip * @param sshPort * @return * @throws SSHException */ public static String getMaxPortStr(String ip, int sshPort) throws SSHException { String redisPidCmd = "ps -ef | grep redis-server | grep -v 'grep'"; String redisProcessStr = SSHUtil.execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, redisPidCmd); if (StringUtils.isBlank(redisProcessStr)) { logger.warn("{} excute {}, result is empty", ip, redisPidCmd); return EmptyObjectConstant.EMPTY_STRING; } int maxPort = 0; String[] lines = redisProcessStr.split(SymbolConstant.ENTER); for (String line : lines) { if (StringUtils.isBlank(line)) { continue; } int redisServerIndex = line.indexOf("redis-server"); if (redisServerIndex >= 0) { line = line.substring(redisServerIndex); } if (redisServerIndex < 0) { continue; } String[] items = line.split(SymbolConstant.SPACE); if (items.length >= 2) { String hostPort = items[1]; if (StringUtils.isBlank(hostPort)) { continue; } String[] hostPortArr = hostPort.split(SymbolConstant.COLON); if (hostPortArr.length != 2) { continue; } String portStr = hostPortArr[1]; if (!NumberUtils.isDigits(portStr)) { continue; } int port = NumberUtils.toInt(portStr); if (port > maxPort) { maxPort = port; } } } return maxPort == 0 ? EmptyObjectConstant.EMPTY_STRING : String.valueOf(maxPort); } public static synchronized Integer getRedisSentinelPort(final String ip) { if (redisSentinelPortHolder.get(ip) == 0L) { redisSentinelPortHolder.put(ip, ConstUtils.REDIS_SENTINEL_BASE_PORT); } String maxPortStr = ""; try { int sshPort = SSHUtil.getSshPort(ip); maxPortStr = getMaxSentinelPortStr(ip, sshPort); } catch (SSHException e) { logger.error("cannot get max port of redis by ssh, ip: {}", ip, e); } logger.warn("{} maxPort is {}", ip, maxPortStr); if (StringUtils.isBlank(maxPortStr) || !StringUtils.isNumeric(maxPortStr)) { logger.warn("{} the max port of redis is invalid, maxPortStr: {}", ip, maxPortStr); return (int)redisSentinelPortHolder.getAndIncrement(ip); } int availablePort = Integer.parseInt(maxPortStr) + 1; // 兼容连续调用的情况 if (availablePort < redisSentinelPortHolder.get(ip)) { availablePort = (int)redisSentinelPortHolder.getAndIncrement(ip); } else { // 正常情况,以及兼容系统重启和当前端口不可用的情形 redisSentinelPortHolder.put(ip, availablePort + 1L); } logger.warn("first {} maxPort is {}", ip, availablePort); try { while (SSHUtil.isPortUsed(ip, availablePort)) { availablePort++; } } catch (SSHException e) { logger.error("check port error, ip: {}, port: {}", ip, availablePort, e); } logger.warn("final {} maxPort is {}", ip, availablePort); redisSentinelPortHolder.put(ip, availablePort + 1L); return availablePort; } /** * 直接解析ps -ef | grep redis-sentinel | grep -v 'grep' * @param ip * @param sshPort * @return * @throws SSHException */ public static String getMaxSentinelPortStr(String ip, int sshPort) throws SSHException { String redisPidCmd = "ps -ef | grep redis-sentinel | grep -v 'grep'"; String redisProcessStr = SSHUtil.execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, redisPidCmd); if (StringUtils.isBlank(redisProcessStr)) { logger.warn("{} excute {}, result is empty", ip, redisPidCmd); return EmptyObjectConstant.EMPTY_STRING; } int maxPort = 0; String[] lines = redisProcessStr.split(SymbolConstant.ENTER); for (String line : lines) { if (StringUtils.isBlank(line)) { continue; } int redisSentinelIndex = line.indexOf("redis-sentinel"); if (redisSentinelIndex >= 0) { line = line.substring(redisSentinelIndex); } if (redisSentinelIndex < 0) { continue; } String[] items = line.split(SymbolConstant.SPACE); if (items.length >= 2) { String hostPort = items[1]; if (StringUtils.isBlank(hostPort)) { continue; } String[] hostPortArr = hostPort.split(SymbolConstant.COLON); if (hostPortArr.length != 2) { continue; } String portStr = hostPortArr[1]; if (!NumberUtils.isDigits(portStr)) { continue; } int port = NumberUtils.toInt(portStr); if (port > maxPort) { maxPort = port; } } } return maxPort == 0 ? EmptyObjectConstant.EMPTY_STRING : String.valueOf(maxPort); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/impl/MachineCenterImpl.java ================================================ package com.sohu.cache.machine.impl; import com.google.common.base.Strings; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.constant.MachineConstant; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.constant.MachineInfoEnum.TypeEnum; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.machine.PortGenerator; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.report.ReportDataComponent; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.*; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.CheckEnum; import com.sohu.cache.web.enums.MachineMemoryDistriEnum; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.service.AppAlertRecordService; import com.sohu.cache.web.vo.MachineEnv; import com.sohu.cache.web.vo.MachineStatsVo; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import redis.clients.jedis.HostAndPort; import javax.annotation.PostConstruct; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkArgument; /** * 机器接口的实现 * User: lingguo */ @Service("machineCenter") public class MachineCenterImpl implements MachineCenter { private final Logger logger = LoggerFactory.getLogger(MachineCenterImpl.class); @Autowired private InstanceStatsCenter instanceStatsCenter; @Autowired private MachineStatsDao machineStatsDao; @Autowired private InstanceDao instanceDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired private MachineDao machineDao; @Autowired private RedisCenter redisCenter; @Autowired private AppDao appDao; @Autowired private ResourceDao resourceDao; @Autowired private MachineRoomDao machineRoomDao; @Autowired private SSHService sshService; @Autowired protected AsyncService asyncService; @Autowired private ForkJoinPool forkJoinPool; @Autowired private AppAlertRecordService appAlertRecordService; @Autowired private ReportDataComponent reportDataComponent; /** * 邮箱报警 */ @Autowired private EmailComponent emailComponent; @PostConstruct public void init() { asyncService.assemblePool(AsyncThreadPoolFactory.MACHINE_POOL, AsyncThreadPoolFactory.MACHINE_THREAD_POOL); } //异步执行任务 public void asyncCollectMachineInfo(final long hostId, final long collectTime, final String ip) { String key = "collect-machine-" + hostId + "-" + ip + "-" + collectTime; asyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable(key) { public Boolean execute() { try { Map map = collectMachineInfo(hostId, collectTime, ip); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); } /** * 收集当前host的状态信息,保存到mysql; * 这里将hostId作为参数传入,mysql中集合名为:ip:hostId * * @param hostId 机器id * @param collectTime 收集时间,格式:yyyyMMddHHmm * @param ip ip * @return 机器的统计信息 */ @Override public Map collectMachineInfo(final long hostId, final long collectTime, final String ip) { Map infoMap = new HashMap(); MachineStats machineStats = null; try { int sshPort = SSHUtil.getSshPort(ip); // todo 合并SSHUTIL 到 SSHService machineStats = SSHUtil.getMachineInfo(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD); MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); machineStats.setHostId(hostId); if (machineStats != null && machineStats.validate()) { infoMap.put(MachineConstant.Ip.getValue(), machineStats.getIp()); infoMap.put(MachineConstant.CpuUsage.getValue(), machineStats.getCpuUsage()); infoMap.put(MachineConstant.MemoryUsageRatio.getValue(), machineStats.getMemoryUsageRatio()); /** * SSHUtil返回的内存单位为k,由于实例的内存基本存储单位都是byte,所以统一为byte */ if (machineStats.getMemoryFree() != null) { infoMap.put(MachineConstant.MemoryFree.getValue(), Long.parseLong(machineStats.getMemoryFree()) * ConstUtils._1024); } else { infoMap.put(MachineConstant.MemoryFree.getValue(), 0); } if (machineStats.getMemoryTotal() != null) { infoMap.put(MachineConstant.MemoryTotal.getValue(), Long.parseLong(machineStats.getMemoryTotal()) * ConstUtils._1024); } else { infoMap.put(MachineConstant.MemoryTotal.getValue(), 0); } infoMap.put(MachineConstant.Load.getValue(), machineStats.getLoad()); infoMap.put(MachineConstant.Traffic.getValue(), machineStats.getTraffic()); infoMap.put(MachineConstant.DiskUsage.getValue(), machineStats.getDiskUsageMap()); infoMap.put(ConstUtils.COLLECT_TIME, collectTime); instanceStatsCenter.saveStandardStats(infoMap, new HashMap(0), ip, (int) hostId, ConstUtils.MACHINE); machineStats.setMemoryFree(Long.parseLong(machineStats.getMemoryFree()) * ConstUtils._1024 + ""); machineStats.setMemoryTotal(Long.parseLong(machineStats.getMemoryTotal()) * ConstUtils._1024 + ""); machineStats.setModifyTime(new Date()); // 获取maxmemory和运行实例总数 int maxMemory = instanceDao.getMemoryByHost(ip); machineStats.setMaxMemory(maxMemory); int instanceCount = instanceDao.getInstanceCountByHost(ip); machineStats.setInstanceCount(instanceCount); // 获取物理机入库内存 machineStats.setMachineMemory(machineInfo.getMem() * 1024); machineStatsDao.mergeMachineStats(machineStats); //上报数据 reportDataComponent.reportMachineData(machineStats); logger.debug("collect machine info done, host: {}, time: {}", ip, collectTime); } } catch (RuntimeException e) { throw e; } catch (Exception e) { logger.error("host:{} collectMachineErrorStats=>{}", ip, machineStats); logger.error(e.getMessage(), e); } return infoMap; } //异步执行任务 public void asyncMonitorMachineStats(final long hostId, final String ip) { String key = "monitor-machine-" + hostId + "-" + ip; asyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable(key) { public Boolean execute() { try { monitorMachineStats(hostId, ip); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); } /** * 监控机器的状态 * * @param hostId 机器id * @param ip ip */ @Override public void monitorMachineStats(final long hostId, final String ip) { Assert.isTrue(hostId > 0); Assert.hasText(ip); MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); if (machineStats == null) { logger.warn("machine stats is null, ip: {}, time: {}", ip, new Date()); return; } double cpuUsage = ObjectConvert.percentToDouble(machineStats.getCpuUsage(), 0); int memTotal = 0; double memoryUsage = 0.0; try { MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); memTotal = machineInfo.getMem() * 1024; Map machineMemDetail = instanceStatsDao.getMachineMemByIp(ip); long memUsed = MapUtils.getLongValue(machineMemDetail, "usedMem", 0l); double memUsedRss = MapUtils.getDoubleValue(machineMemDetail, "usedMemRss", 0d); double memAllocRatio = memUsedRss / 1024 / 1024 / memTotal * 100; DecimalFormat df = new DecimalFormat("#.00"); memoryUsage = ObjectConvert.percentToDouble(df.format(memAllocRatio), 0); } catch (Exception e) { logger.info("get memoryUsage error:{}", e.getMessage()); } double memoryThreshold = ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD; /** * 当机器的状态超过预设的阀值时,向上汇报或者报警 */ StringBuilder alertContent = new StringBuilder(); // 内存使用率 if (memoryUsage > memoryThreshold) { logger.warn("memoryUsageRatio is above security line, ip: {}, memTotal: {}, memoryUsage: {}%", ip, memTotal, memoryUsage); alertContent.append("ip:").append(ip).append(",memTotal(G):").append(memTotal / 1024).append(",memUse(%):").append(memoryUsage); } // 报警 if (StringUtils.isNotBlank(alertContent.toString())) { String title = "cachecloud机器内存报警:"; appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.MACHINE_MEMORY_OVER_PRESET, title, alertContent.toString(), ip); emailComponent.sendMailToAdmin(title, alertContent.toString()); } } /** * 在主机ip上的端口port上启动一个进程,并check是否启动成功; * * @param ip ip * @param port port * @param shell shell命令 * @return 成功返回true,否则返回false; */ @Override public boolean startProcessAtPort(final String ip, final int port, final String shell) { checkArgument(!Strings.isNullOrEmpty(ip), "invalid ip."); checkArgument(port > 0 && port < 65536, "invalid port"); checkArgument(!Strings.isNullOrEmpty(shell), "invalid shell."); boolean success = true; try { // 执行shell命令,有的是后台执行命令,没有返回值; 如果端口被占用,表示启动成功; SSHUtil.execute(ip, shell); success = isPortUsed(ip, port); } catch (SSHException e) { logger.error("execute shell command error, ip: {}, port: {}, shell: {}", ip, port, shell); logger.error(e.getMessage(), e); } return success; } /** * 多次验证是否进程已经启动 * * @param ip * @param port * @return */ private boolean isPortUsed(final String ip, final int port) { boolean isPortUsed = new IdempotentConfirmer() { private int sleepTime = 100; @Override public boolean execute() { try { boolean success = SSHUtil.isPortUsed(ip, port); if (!success) { TimeUnit.MILLISECONDS.sleep(sleepTime); sleepTime += 100; } return success; } catch (SSHException e) { logger.error(e.getMessage(), e); return false; } catch (InterruptedException e) { logger.error(e.getMessage(), e); return false; } } }.run(); return isPortUsed; } /** * 执行shell命令,并将结果返回; * * @param ip 机器ip * @param shell shell命令 * @return 命令的返回值 */ @Override public String executeShell(final String ip, final String shell) { checkArgument(!Strings.isNullOrEmpty(ip), "invalid ip."); checkArgument(!Strings.isNullOrEmpty(shell), "invalid shell."); String result = null; try { result = SSHUtil.execute(ip, shell); } catch (SSHException e) { logger.error("execute shell: {} at ip: {} error.", shell, ip, e); result = ConstUtils.INNER_ERROR; } return result; } @Override public String executeShell(String ip, String shell, Integer timeout) { checkArgument(!Strings.isNullOrEmpty(ip), "invalid ip."); checkArgument(!Strings.isNullOrEmpty(shell), "invalid shell."); String result = null; try { result = SSHUtil.execute(ip, shell, timeout); } catch (SSHException e) { logger.error("execute shell: {} at ip: {} error, timeout: {}", shell, ip, timeout, e); result = ConstUtils.INNER_ERROR; } return result; } /** * 获取指定server上的一个可用的端口;type表示cache的类型; * PortGenerator是线程安全的; * * @param ip 目标server; * @param type cache类型 * @return 可用端口,如果为null,则表示发生异常; */ @Override public Integer getAvailablePort(final String ip, final int type) { Integer availablePort = null; if (type == ConstUtils.CACHE_REDIS_STANDALONE || type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { availablePort = PortGenerator.getRedisPort(ip); // 去实例表中再check一下,该端口是否从来没被使用过 while (instanceDao.getCountByIpAndPort(ip, availablePort) > 0) { availablePort++; } } else if (type == ConstUtils.CACHE_REDIS_SENTINEL) { availablePort = PortGenerator.getRedisSentinelPort(ip); // 去实例表中再check一下,该端口是否从来没被使用过 while (instanceDao.getCountByIpAndPort(ip, availablePort) > 0) { availablePort++; } } return availablePort; } /** * 根据content的配置内容创建配置文件,并推送到目标server的约定目录下; * 文件内容有更新,会覆写; * * @param host 要推送到的目标server; * @param fileName 配置文件名 * @param content 配置文件的内容 * @return 配置文件在远程server上的绝对路径,如果为null则表示失败; */ @Override public String createRemoteFile(final String host, String fileName, List content) { checkArgument(!Strings.isNullOrEmpty(host), "invalid host."); checkArgument(!Strings.isNullOrEmpty(fileName), "invalid fileName."); checkArgument(content != null && content.size() > 0, "content is empty."); String tmpDirectory = MachineProtocol.TMP_DIR + host + "/"; String localAbsolutePath = tmpDirectory + fileName; File tmpDir = new File(tmpDirectory); if (!tmpDir.exists()) { if (!tmpDir.mkdirs()) { logger.error("cannot create dir:{} directory. ", tmpDir.getAbsolutePath()); } } Path path = Paths.get(tmpDirectory + fileName); String confDir = getMachineRelativeDir(host, DirEnum.CONF_DIR.getValue()); String remotePath = confDir + fileName; /** * 将配置文件的内容写到本地 */ try { BufferedWriter bufferedWriter = Files .newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8)); try { for (String line : content) { bufferedWriter.write(line); bufferedWriter.newLine(); } } finally { if (bufferedWriter != null) bufferedWriter.close(); } } catch (IOException e) { logger.error("write redis config file error, ip: {}, filename: {}, content: {}, e", host, fileName, content, e); return null; } finally { } /** * 将配置文件推送到目标机器上 */ try { // k8s资源创建相关目录 if (isK8sMachine(host)) { String mkdirCommand = "mkdir " + MachineProtocol.getK8sConfDir(host) + " " + MachineProtocol.getK8sDataDir(host) + " " + MachineProtocol.getK8sLogDir(host); String mkdirResult = SSHUtil.execute(host, mkdirCommand); logger.info("execute mkdir :" + mkdirResult); } SSHUtil.scpFileToRemote(host, localAbsolutePath, confDir); } catch (SSHException e) { logger.error("scp config file to remote server error: ip: {}, fileName: {}", host, fileName, e); return null; } /** * 删除临时文件 */ File file = new File(localAbsolutePath); if (file.exists()) { boolean del = file.delete(); if (!del) { logger.warn("file.delete:{}", del); } } return remotePath; } @Override public List getMachineStats(String ipLike) { List machineInfoList = machineDao.getMachineInfoByLikeIp(ipLike); List versionList = resourceDao.getResourceList(ResourceEnum.REDIS.getValue()); String versionStr = "";//获取Redis所有有效安装版本 StringBuilder sb = new StringBuilder(); if (versionList != null && versionList.size() > 0) { for (SystemResource version : versionList) { sb.append(version.getName()).append("#1;"); } versionStr = sb.toString(); } List machineStatsList = new ArrayList(); for (MachineInfo machineInfo : machineInfoList) { String ip = machineInfo.getIp(); MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); if (machineStats == null) { machineStats = new MachineStats(); } machineStats.setMemoryAllocated(instanceDao.getMemoryByHost(ip)); machineStats.setInfo(machineInfo); machineStats.setIsInstall(1);//设置Redis都已经安装 // 判断是否已安装完成Redis if (!StringUtils.isEmpty(versionStr)) { for (String version : versionStr.split(";")) { if (StringUtils.isEmpty(machineInfo.getVersionInstall())) { machineStats.setIsInstall(0); } if (!StringUtils.isEmpty(version) && !StringUtils.isEmpty(machineInfo.getVersionInstall()) && machineInfo.getVersionInstall().indexOf(version) == -1) { machineStats.setIsInstall(0); } } } machineStatsList.add(machineStats); } return machineStatsList; } /** * 获取机器列表 * * @param ipLike * @param versionId * @param isInstall */ public List getMachineStats(String ipLike, Integer useType, Integer type, Integer versionId, Integer isInstall, Integer k8sType, String realip) { // 版本安装条件过滤 String versionName = (versionId == null || versionId == -1) ? "" : resourceDao.getResourceById(versionId).getName(); String installInfo = (isInstall == null || isInstall == -1) ? "" : String.valueOf(isInstall); String versionCondition = ""; if (!StringUtil.isBlank(versionName) || !StringUtil.isBlank(installInfo)) { versionCondition = versionName + "#" + installInfo; } List machineList = machineDao.getMachineInfoByCondition(ipLike, useType == null ? -1 : useType.intValue(), type == null ? -1 : type.intValue(), versionCondition, k8sType == null ? -1 : k8sType.intValue(), realip); List versionList = resourceDao.getResourceList(ResourceEnum.REDIS.getValue()); //获取Redis所有有效安装版本 final String versionStr = versionList.stream().map(version -> version.getName() + "#1").collect(Collectors.joining(";")); return machineList.parallelStream().map(machineInfo -> { String ip = machineInfo.getIp(); MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); if (machineStats == null) { machineStats = new MachineStats(); machineStats.setIp(ip); } machineStats.setMemoryAllocated(instanceDao.getMemoryByHost(ip)); machineStats.setInfo(machineInfo); machineStats.setIsInstall(1); // 判断是否已安装完成Redis if (!StringUtils.isEmpty(versionStr)) { for (String version : versionStr.split(";")) { if (StringUtils.isEmpty(machineInfo.getVersionInstall()) || (!StringUtils.isEmpty(version) && machineInfo.getVersionInstall().indexOf(version) == -1)) { machineStats.setIsInstall(0); } } } //填充machineMemInfo信息 MachineMemInfo machineMemInfo = new MachineMemInfo(); Map memRes = instanceStatsDao.getMachineMemByIp(ip); machineMemInfo.setIp(ip); machineMemInfo.setApplyMem(MapUtils.getLongValue(memRes, "applyMem", 0l)); machineMemInfo.setUsedMem(MapUtils.getLongValue(memRes, "usedMem", 0l)); machineMemInfo.setUsedMemRss(MapUtils.getDoubleValue(memRes, "usedMemRss", 0d)); machineStats.setMachineMemInfo(machineMemInfo); return machineStats; }).collect(Collectors.toList()); } @Override public List getAllMachineStats() { List list = machineStatsDao.getAllMachineStats(); for (MachineStats ms : list) { String ip = ms.getIp(); MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); if (machineInfo == null || machineInfo.isOffline()) { continue; } int memoryHost = instanceDao.getMemoryByHost(ip); getMachineMemoryDetail(ms.getIp()); //获取机器申请和使用内存 long applyMem = 0; long usedMem = 0; List instanceStats = instanceStatsDao.getInstanceStatsByIp(ip); for (InstanceStats instance : instanceStats) { applyMem += instance.getMaxMemory(); usedMem += instance.getUsedMemory(); } MachineMemInfo machineMemInfo = new MachineMemInfo(); machineMemInfo.setIp(ip); machineMemInfo.setApplyMem(applyMem); machineMemInfo.setUsedMem(usedMem); ms.setMachineMemInfo(machineMemInfo); ms.setMemoryAllocated(memoryHost); ms.setInfo(machineInfo); } return list; } @Override public List getAllValidMachineMem(List excludeMachineList, String room, Integer useType) { List machineMemStatInfoList = machineDao.getMachineMemStatInfoByCondition(room, useType); return machineMemStatInfoList.parallelStream().filter(memStatInfo -> !excludeMachineList.contains(memStatInfo.getIp())) .map(memStatInfo -> { MachineMemStatInfo memStatInfoNew = memStatInfo; Map memRes = instanceStatsDao.getMachineMemByIp(memStatInfo.getIp()); memStatInfoNew.setApplyMem(MapUtils.getLong(memRes, "applyMem", 0l)); memStatInfoNew.setUsedMem(MapUtils.getLong(memRes, "usedMem", 0l)); memStatInfoNew.setInstanceNum(MapUtils.getIntValue(memRes, "instanceNum", 0)); return memStatInfoNew; }) .collect(Collectors.toList()); } @Override public List getValidMachineMemByIpList(List ipList) { if (ipList != null) { try { List memStatInfoList = machineDao.getMachineMemStatInfoByIpList(ipList); for (MachineMemStatInfo memStatInfo : memStatInfoList) { Map memRes = instanceStatsDao.getMachineMemByIp(memStatInfo.getIp()); memStatInfo.setApplyMem(MapUtils.getLong(memRes, "applyMem", 0l)); memStatInfo.setUsedMem(MapUtils.getLong(memRes, "usedMem", 0l)); memStatInfo.setInstanceNum(MapUtils.getIntValue(memRes, "instanceNum", 0)); } return memStatInfoList; } catch (Exception e) { logger.info("getValidMachineMemByIpList error: {}", e.getMessage()); } } return null; } @Override public MachineInfo getMachineInfoByIp(String ip) { return machineDao.getMachineInfoByIp(ip); } @Override public MachineStats getMachineMemoryDetail(String ip) { long applyMem = 0; long usedMem = 0; long usedMemRss = 0; long usedDisk = 0; List instanceStats = instanceStatsDao.getInstanceStatsByIp(ip); for (InstanceStats instance : instanceStats) { applyMem += instance.getMaxMemory(); usedMem += instance.getUsedMemory(); double memFragmentationRatio = instance.getMemFragmentationRatio(); if (memFragmentationRatio > 1d) { usedMemRss += instance.getUsedMemory() * memFragmentationRatio; } else { usedMemRss += instance.getUsedMemory(); } usedDisk += instance.getUsedDisk(); } MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); // 机器下线 查不到相关信息 if (machineStats == null) { return null; } // 机器下线 查不到相关信息 if (machineInfo != null) { machineStats.setInfo(machineInfo); } MachineMemInfo machineMemInfo = new MachineMemInfo(); machineMemInfo.setIp(ip); machineMemInfo.setApplyMem(applyMem); machineMemInfo.setUsedMem(usedMem); machineMemInfo.setUsedMemRss(usedMemRss); machineMemInfo.setUsedDisk(usedDisk); machineStats.setMachineMemInfo(machineMemInfo); int memoryHost = instanceDao.getMemoryByHost(ip); machineStats.setMemoryAllocated(memoryHost); return machineStats; } public List getMachineInstanceStatsByIp(String ip) { return instanceStatsDao.getInstanceStatsByIp(ip); } @Override public List getMachineInstanceInfo(String ip) { List resultList = instanceDao.getInstListByIp(ip); if (resultList != null && resultList.size() > 0) { for (InstanceInfo instanceInfo : resultList) { int type = instanceInfo.getType(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); long appId = instanceInfo.getAppId(); AppDesc appDesc = appDao.getAppDescById(appId); String password = appDesc.getAppPassword(); BooleanEnum isMaster = redisCenter.isMaster(appId, host, port); instanceInfo.setRoleDesc(isMaster); if (isMaster == BooleanEnum.FALSE) { HostAndPort hap = redisCenter.getMaster(host, port, password); if (hap != null) { instanceInfo.setMasterHost(hap.getHost()); instanceInfo.setMasterPort(hap.getPort()); for (InstanceInfo innerInfo : resultList) { if (innerInfo.getIp().equals(hap.getHost()) && innerInfo.getPort() == hap.getPort()) { instanceInfo.setMasterInstanceId(innerInfo.getId()); break; } } } } } } } else { return resultList; } return resultList; } @Override public String showInstanceRecentLog(InstanceInfo instanceInfo, int maxLineNum) { String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); String logType = ""; if (TypeUtil.isRedisDataType(type)) { logType = "redis-"; } else if (TypeUtil.isRedisSentinel(type)) { logType = "redis-sentinel-"; } String remoteFilePath = getMachineRelativeDir(host, DirEnum.LOG_DIR.getValue()) + logType + port + "-*.log"; StringBuilder command = new StringBuilder(); command.append("/usr/bin/tail -n").append(maxLineNum).append(" ").append(remoteFilePath); try { return SSHUtil.execute(host, command.toString()); } catch (SSHException e) { logger.error(e.getMessage(), e); return ""; } } @Override public List getMachineInfoByType(TypeEnum typeEnum) { try { return machineDao.getMachineInfoByType(typeEnum.getType()); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public Map getMachineInstanceCountMap() { List> mapList = instanceDao.getMachineInstanceCountMap(); if (CollectionUtils.isEmpty(mapList)) { return Collections.emptyMap(); } Map resultMap = new HashMap(); for (Map map : mapList) { String ip = MapUtils.getString(map, "ip", ""); if (StringUtils.isBlank(ip)) { continue; } int count = MapUtils.getIntValue(map, "count"); resultMap.put(ip, count); } return resultMap; } public Map getK8sMachineMap() { Map k8sMachineMaps = new HashMap(); List k8sMachineList = machineDao.getK8sMachineList(); if (!CollectionUtils.isEmpty(k8sMachineList)) { for (MachineInfo machineInfo : k8sMachineList) { k8sMachineMaps.put(machineInfo.getIp(), machineInfo); } } return k8sMachineMaps; } public List getEffectiveRoom() { return machineRoomDao.getEffectiveRoom(); } @Override public List getAllRoom() { return machineRoomDao.getAllRoom(); } @Override public Map getMaxMemoryDistribute() { Map resultMap = new HashMap(); List machineStatsList = machineStatsDao.getAllMachineStats(); for (MachineStats machineStats : machineStatsList) { int percent = 0; if (machineStats.getMachineMemory() > 0) { percent = machineStats.getMaxMemory() * 100 / machineStats.getMachineMemory(); } MachineMemoryDistriEnum machineMemoryDistriEnum = MachineMemoryDistriEnum.getRightPercentDistri(percent); if (resultMap.containsKey(machineMemoryDistriEnum)) { resultMap.put(machineMemoryDistriEnum, resultMap.get(machineMemoryDistriEnum) + 1); } else { resultMap.put(machineMemoryDistriEnum, 1); } } return resultMap; } @Override public Map getUsedMemoryDistribute() { Map resultMap = new HashMap(); //机器自身统计map List machineStatsList = machineStatsDao.getAllMachineStats(); //机器实例统计map List machineInstanceStatList = instanceStatsDao.getMachineInstanceStatList(); Map machineInstanceStatMap = new HashMap(); for (MachineInstanceStat machineInstanceStat : machineInstanceStatList) { machineInstanceStatMap.put(machineInstanceStat.getIp(), machineInstanceStat); } for (MachineStats machineStats : machineStatsList) { int machineMemory = machineStats.getMachineMemory(); long usedMemory = machineInstanceStatMap.containsKey(machineStats.getIp()) ? machineInstanceStatMap.get(machineStats.getIp()).getUsedMemory() / 1024 / 1024 : 0; int percent = 0; if (machineMemory > 0) { percent = (int) (usedMemory * 100 / machineMemory); } MachineMemoryDistriEnum machineMemoryDistriEnum = MachineMemoryDistriEnum.getRightPercentDistri(percent); if (machineMemoryDistriEnum == null) { logger.warn("=======ip {} percent {} is not is MachineMemoryDistriEnum========", machineStats.getIp(), percent); continue; } if (resultMap.containsKey(machineMemoryDistriEnum)) { resultMap.put(machineMemoryDistriEnum, resultMap.get(machineMemoryDistriEnum) + 1); } else { resultMap.put(machineMemoryDistriEnum, 1); } } return resultMap; } public int getMachineNum(int type) { List machineInfoList = machineDao.getMachineInfoByType(type); return machineInfoList.size(); } @Override public List getmachineStatsVoList() { List machineInfoList = machineDao.getAllMachines(); //机器自身统计map List machineStatsList = machineStatsDao.getAllMachineStats(); Map machineStatsMap = new HashMap(); for (MachineStats machineStats : machineStatsList) { machineStatsMap.put(machineStats.getIp(), machineStats); } //机器实例统计map List machineInstanceStatList = instanceStatsDao.getMachineInstanceStatList(); Map machineInstanceStatMap = new HashMap(); for (MachineInstanceStat machineInstanceStat : machineInstanceStatList) { machineInstanceStatMap.put(machineInstanceStat.getIp(), machineInstanceStat); } Map machineRoomMachineStatsVoMap = new HashMap(); Set realIpSet = new HashSet<>(); for (MachineInfo machineInfo : machineInfoList) { String ip = machineInfo.getIp(); String realIp = machineInfo.getRealIp(); //机器统计 MachineStats machineStats = machineStatsMap.get(ip); if (machineStats == null) { machineStats = new MachineStats(); } // 单位MB long machineMemoryTotal = machineInfo.getMem() * 1024L; long machineFreeTotal = machineMemoryTotal - machineStats.getMaxMemory(); //实例统计 MachineInstanceStat machineInstanceStat = machineInstanceStatMap.get(ip); if (machineInstanceStat == null) { machineInstanceStat = new MachineInstanceStat(); } long instanceMaxMemory = machineInstanceStat.getMaxMemory(); long instanceUsedmemory = machineInstanceStat.getUsedMemory(); long instanceApplyDisk = machineInstanceStat.getApplyDisk(); long instanceUsedDisk = machineInstanceStat.getUsedDisk(); String diskTotal = machineStats.getDiskTotal(); String diskAvailable = machineStats.getDiskAvailable(); long machineDiskTotal = 0; long machineDiskAvailable = 0; if (StringUtils.isEmpty(realIp) || !realIpSet.contains(realIp)) { if (StringUtils.isNotEmpty(diskTotal)) { machineDiskTotal = Long.parseLong(diskTotal); } if (StringUtils.isNotEmpty(diskAvailable)) { machineDiskAvailable = Long.parseLong(diskAvailable); } } realIpSet.add(realIp); String machineRoom = machineInfo.getRoom(); if (machineRoomMachineStatsVoMap.containsKey(machineRoom)) { MachineStatsVo machineStatsVo = machineRoomMachineStatsVoMap.get(machineRoom); machineStatsVo.setTotalMachineMem(machineMemoryTotal + machineStatsVo.getTotalMachineMem()); machineStatsVo.setTotalMachineFreeMem(machineFreeTotal + machineStatsVo.getTotalMachineFreeMem()); machineStatsVo.setTotalInstanceMaxMem(instanceMaxMemory + machineStatsVo.getTotalInstanceMaxMem()); machineStatsVo.setTotalInstanceUsedMem(instanceUsedmemory + machineStatsVo.getTotalInstanceUsedMem()); machineStatsVo.setTotalMachineDisk(machineDiskTotal + machineStatsVo.getTotalMachineDisk()); machineStatsVo.setTotalMachineFreeDisk(machineDiskAvailable + machineStatsVo.getTotalMachineFreeDisk()); machineStatsVo.setTotalInstanceApplyDisk(instanceApplyDisk + machineStatsVo.getTotalInstanceApplyDisk()); machineStatsVo.setTotalInstanceUsedDisk(instanceUsedDisk + machineStatsVo.getTotalInstanceUsedDisk()); } else { MachineStatsVo machineStatsVo = new MachineStatsVo(); machineStatsVo.setMachineRoom(machineRoom); machineStatsVo.setTotalMachineMem(machineMemoryTotal); machineStatsVo.setTotalMachineFreeMem(machineFreeTotal); machineStatsVo.setTotalInstanceMaxMem(instanceMaxMemory); machineStatsVo.setTotalInstanceUsedMem(instanceUsedmemory); machineStatsVo.setTotalMachineDisk(machineDiskTotal); machineStatsVo.setTotalMachineFreeDisk(machineDiskAvailable); machineStatsVo.setTotalInstanceApplyDisk(instanceApplyDisk); machineStatsVo.setTotalInstanceUsedDisk(instanceUsedDisk); machineRoomMachineStatsVoMap.put(machineRoom, machineStatsVo); } } List machineStatsVoList = new ArrayList(machineRoomMachineStatsVoMap.values()); MachineStatsVo totalMachineStatsVo = new MachineStatsVo(); totalMachineStatsVo.setMachineRoom("total"); for (MachineStatsVo machineStatsVo : machineStatsVoList) { totalMachineStatsVo.setTotalMachineMem(totalMachineStatsVo.getTotalMachineMem() + machineStatsVo.getTotalMachineMem()); totalMachineStatsVo.setTotalMachineFreeMem(totalMachineStatsVo.getTotalMachineFreeMem() + machineStatsVo.getTotalMachineFreeMem()); totalMachineStatsVo.setTotalInstanceMaxMem(totalMachineStatsVo.getTotalInstanceMaxMem() + machineStatsVo.getTotalInstanceMaxMem()); totalMachineStatsVo.setTotalInstanceUsedMem(totalMachineStatsVo.getTotalInstanceUsedMem() + machineStatsVo.getTotalInstanceUsedMem()); totalMachineStatsVo.setTotalMachineDisk(totalMachineStatsVo.getTotalMachineDisk() + machineStatsVo.getTotalMachineDisk()); totalMachineStatsVo.setTotalMachineFreeDisk(totalMachineStatsVo.getTotalMachineFreeDisk() + machineStatsVo.getTotalMachineFreeDisk()); totalMachineStatsVo.setTotalInstanceApplyDisk(totalMachineStatsVo.getTotalInstanceApplyDisk() + machineStatsVo.getTotalInstanceApplyDisk()); totalMachineStatsVo.setTotalInstanceUsedDisk(totalMachineStatsVo.getTotalInstanceUsedDisk() + machineStatsVo.getTotalInstanceUsedDisk()); } machineStatsVoList.add(0, totalMachineStatsVo); return machineStatsVoList; } /** * 获取redis基准目录 * 例如/media/disk1/fordata/redis_server/redis-cluster/cluster_mmuIllegalDupUnhandledCount_zw/sentinel-22090 * * @param appId * @param port * @param instanceTypeEnum * @return */ @Override public String getInstanceRemoteBasePath(long appId, int port, InstanceTypeEnum instanceTypeEnum) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.warn(BaseTask.marker, "appId {} appDesc is null", appId); return ""; } String instanceTypeName = instanceTypeEnum.getName(); String basePath = InstanceTypeEnum.PIKA.getType() == instanceTypeEnum.getType() ? ConstUtils.PIKA_INSTALL_BASE_DIR : ConstUtils.REDIS_INSTALL_BASE_DIR; return String.format("%s/%s/%s-%d", basePath, appDesc.getName(), instanceTypeName, port); } public String getMachineRelativeDir(String host, int dirType) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo != null && machineInfo.isK8sMachine(machineInfo.getK8sType())) { return MachineProtocol.getK8sDir(host, dirType); } return MachineProtocol.getDir(dirType); } public Boolean isK8sMachine(String host) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo != null && machineInfo.isK8sMachine(machineInfo.getK8sType())) { return true; } return false; } public Map getExceptionMachineEnv(Date searchDate) { Map exceptionMap = new HashMap(); Map allMachineEnvMap = getAllMachineEnv(searchDate, MachineInfoEnum.MachineTypeEnum.ALL.getValue()); // 过滤需要监控的数据 List> containerlist = (List>) allMachineEnvMap.get(MachineInfoEnum.MachineEnum.CONTAINER.getValue()); List> hostlist = (List>) allMachineEnvMap.get(MachineInfoEnum.MachineEnum.HOST.getValue()); exceptionMap.put(MachineInfoEnum.MachineEnum.CONTAINER.getValue(), containerlist.stream().filter(map -> MapUtils.getInteger(map, "status") != CheckEnum.CONSISTENCE.getValue()).collect(Collectors.toList())); exceptionMap.put(MachineInfoEnum.MachineEnum.HOST.getValue(), hostlist.stream().filter(map -> MapUtils.getInteger(map, "status") != CheckEnum.CONSISTENCE.getValue()).collect(Collectors.toList())); return exceptionMap; } public Map getAllMachineEnv(Date searchDate, int type) { Map resultMap = new HashMap(); List allMachines = machineDao.getAllMachines(); Map ipMap = new HashMap<>(); Set hostlist = new HashSet(); SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH); if (!CollectionUtils.isEmpty(allMachines)) { for (MachineInfo machineInfo : allMachines) { ipMap.put(machineInfo.getIp(), machineInfo); if (StringUtils.isNotBlank(machineInfo.getRealIp())) { hostlist.add(machineInfo.getRealIp()); } } } /** * 检测容器: * 1.内存分配策略 * 2.thp大内存页配置 * 3.内存swap配置 * 4.容器nproc配置 */ String container_cmd = "cat /proc/sys/vm/overcommit_memory;" + "cat /proc/sys/vm/swappiness;" + "cat /sys/kernel/mm/transparent_hugepage/enabled;" + "cat /sys/kernel/mm/transparent_hugepage/defrag;" + "cat /etc/security/limits.d/*-nproc.conf | grep '* soft nproc'" + ""; String ubuntu_container_cmd = "cat /proc/sys/vm/overcommit_memory;" + "cat /proc/sys/vm/swappiness;" + "cat /sys/kernel/mm/transparent_hugepage/enabled;" + "cat /sys/kernel/mm/transparent_hugepage/defrag;" + "cat /etc/security/limits.conf | grep '* soft nproc'" + ""; /** * 检测宿主机: * 1.检测用户连接的进程数 大于>=1024 * 2.检测宿主机所有实例aof写盘阻塞 >=3次 * 3.检测 somaxconn 512 * 4.检测 sshpass安装 * 5.运行redis实例总数 * 6.ulimit 打开文件句柄检测 * 7.磁盘/内存使用情况 */ String machine_cmd = "cat /proc/sys/net/core/somaxconn;" + "cat /data/redis/logs/*/* | grep '" + dateFormat.format(searchDate) + "' | grep 'slow down Redis' | wc -l;" + "ps -u cachecloud -L | wc -l;" + "sshpass -V | head -1;" + "ulimit -n;" + "echo 0;" + "df -h | grep '/dev' | grep '/data' | awk '{print $5\"(\"$3\"/\"$2\")\"}';" + "ps -ef | grep redis | wc -l;" + "cat /etc/security/limits.d/*-nproc.conf | grep '* soft nproc';" + ""; List> containerInfo = new ArrayList<>(); List> machineInfo = new ArrayList<>(); long phase1 = System.currentTimeMillis(); if (type == MachineInfoEnum.MachineTypeEnum.CONTAINER.getValue() || type == MachineInfoEnum.MachineTypeEnum.ALL.getValue()) { if (MapUtils.isNotEmpty(ipMap)) { ForkJoinTask>> container_task = forkJoinPool.submit(() -> ipMap.entrySet().parallelStream() .collect(Collectors.toMap(ipEntry -> ipEntry.getKey(), ipEntry -> { if (ipEntry.getValue().getDisType() == MachineInfoEnum.DisTypeEnum.CENTOS.getType()) { return new MachinetaskCallable(ipEntry.getKey(), container_cmd, sshService, MachineInfoEnum.MachineEnum.CONTAINER.getValue()).call(); } else { return new MachinetaskCallable(ipEntry.getKey(), ubuntu_container_cmd, sshService, MachineInfoEnum.MachineEnum.CONTAINER.getValue()).call(); } }))); try { Map> container_result = container_task.get(30, TimeUnit.SECONDS); if (!MapUtils.isEmpty(container_result)) { for (Map.Entry> container : container_result.entrySet()) { Map res = container.getValue(); if (!MapUtils.isEmpty(res)) { containerInfo.add(res); } } } logger.info("container result size:{}", container_result.size()); } catch (InterruptedException e) { logger.error("container error", e); } catch (ExecutionException e) { logger.error("container error", e); } catch (TimeoutException e) { logger.error("container error", e); } } } long phase2 = System.currentTimeMillis(); logger.info("container check env cost time:{} ms", phase2 - phase1); if (type == MachineInfoEnum.MachineTypeEnum.HOST.getValue() || type == MachineInfoEnum.MachineTypeEnum.ALL.getValue()) { if (!CollectionUtils.isEmpty(hostlist)) { ForkJoinTask>> machine_task = forkJoinPool.submit(() -> hostlist.parallelStream().collect(Collectors.toMap(machineIp -> machineIp, machineIp -> new MachinetaskCallable(machineIp, machine_cmd, sshService, MachineInfoEnum.MachineEnum.HOST.getValue()).call()))); try { Map> host_result = machine_task.get(30, TimeUnit.SECONDS); if (!MapUtils.isEmpty(host_result)) { for (Map.Entry> host : host_result.entrySet()) { Map res = host.getValue(); if (!MapUtils.isEmpty(res)) { machineInfo.add(res); } } } logger.info("machine result size:{}", host_result.size()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } } } logger.info("host check env cost time:{} ms", System.currentTimeMillis() - phase2); resultMap.put(MachineInfoEnum.MachineEnum.CONTAINER.getValue(), containerInfo); resultMap.put(MachineInfoEnum.MachineEnum.HOST.getValue(), machineInfo); return resultMap; } private class MachinetaskCallable implements Callable> { private String ip; private String cmd; private SSHService sshService; private String type; public MachinetaskCallable(String ip, String cmd, SSHService sshService, String type) { this.ip = ip; this.cmd = cmd; this.sshService = sshService; this.type = type; } @Override public Map call() { Map machineResult = new HashMap(); String info = null; try { info = sshService.execute(ip, cmd); machineResult.put("ip", ip); if (!StringUtil.isBlank(info)) { if (type.equals(MachineInfoEnum.MachineEnum.CONTAINER.getValue())) { MachineEnv containerEnv = convertContainer(info); if (containerEnv != null) { machineResult.put("envs", containerEnv); machineResult.put("status", MachineEnv.checkContainer(containerEnv)); } else { machineResult.put("status", CheckEnum.EXCEPTION.getValue()); machineResult.put("envs", MachineEnv.getDefaultEnv()); } } else if (type.equals(MachineInfoEnum.MachineEnum.HOST.getValue())) { MachineEnv hostEnv = convertHost(info); if (hostEnv != null) { machineResult.put("envs", hostEnv); machineResult.put("status", MachineEnv.checkHost(hostEnv)); } else { machineResult.put("status", CheckEnum.EXCEPTION.getValue()); machineResult.put("envs", MachineEnv.getDefaultEnv()); } } } else { machineResult.put("status", CheckEnum.EXCEPTION.getValue()); machineResult.put("envs", MachineEnv.getDefaultEnv()); } } catch (SSHException e) { logger.error("MachinetaskCallable ip:{} error msg :{}", ip, e.getMessage()); machineResult.put("status", CheckEnum.EXCEPTION.getValue()); machineResult.put("envs", MachineEnv.getDefaultEnv()); } return machineResult; } } public MachineEnv convertContainer(String cmdResult) { String[] envs = cmdResult.split("\n"); String nproc = ""; try { if(envs.length >= 5){ nproc = StringUtils.isBlank(envs[4]) ? "" : envs[4]; } } catch (Exception e) { logger.error("MachineEnv convertContainer cmdResult:{} error {}:", cmdResult, e.getMessage()); } return new MachineEnv(envs[0], envs[1], envs[2], envs[3], nproc); } public MachineEnv convertHost(String cmdResult) { int fsync_delay_times = -1; int nproc_threads = -1; int unlimit = -1; int unlimit_used = -1; int instanceNum = -1; try { String[] envs = cmdResult.split(System.lineSeparator()); fsync_delay_times = StringUtils.isBlank(envs[1]) ? -1 : Integer.parseInt(envs[1]); nproc_threads = StringUtils.isBlank(envs[2]) ? -1 : Integer.parseInt(envs[2]); unlimit = StringUtils.isBlank(envs[4]) ? -1 : Integer.parseInt(envs[4]); unlimit_used = StringUtils.isBlank(envs[5]) ? -1 : Integer.parseInt(envs[5]); instanceNum = StringUtils.isBlank(envs[7]) ? -1 : Integer.parseInt(envs[7]); return new MachineEnv(envs[0], fsync_delay_times, nproc_threads, envs[3], unlimit_used, unlimit, envs[6], instanceNum); } catch (Exception e) { logger.error("convertMachine error :{} {}", cmdResult, e.getMessage(), e); return new MachineEnv("-1", fsync_delay_times, nproc_threads, "", unlimit_used, unlimit, "", instanceNum); } } public String getFirstMachineIp() { List machines = machineDao.getAllMachines(); if (!CollectionUtils.isEmpty(machines)) { return machines.get(0).getIp(); } return null; } public boolean checkMachineMemory(String ip) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); float memThreshold = Float.parseFloat(machineStats.getMemoryFree()) / Float.parseFloat(machineStats.getMemoryTotal()); if (machineStats == null || memThreshold < 0.15) { return false; } return true; } public List getMachineListByRealIp(String realIp){ return machineDao.getMachineListByRealIp(realIp); } /** * 获取机器配置信息及已分布redis实例(数量、申请内存、使用内存、使用内存rss等) */ public List getMachineInfoAndUsedInfo(String room, Integer type, Integer useType, Integer disType, String ip){ return machineDao.getMachineInfoAndUsedInfo(room, type, useType, disType, ip); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/machine/impl/MachineDeployCenterImpl.java ================================================ package com.sohu.cache.machine.impl; import com.google.common.base.Strings; import com.sohu.cache.dao.*; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineRelation; import com.sohu.cache.entity.MachineRoom; import com.sohu.cache.machine.MachineDeployCenter; import com.sohu.cache.web.enums.SuccessEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * 机器部署相关 * * @author leifu * changed @Date 2016-4-24 * @Time 下午5:07:30 */ @Service("machineDeployCenter") public class MachineDeployCenterImpl implements MachineDeployCenter { private Logger logger = LoggerFactory.getLogger(MachineDeployCenterImpl.class); @Autowired private MachineDao machineDao; @Autowired private MachineRoomDao machineRoomDao; @Autowired private MachineStatsDao machineStatsDao; @Autowired private ServerStatusDao serverStatusDao; @Autowired private MachineRelationDao machineRelationDao; /** * 将机器加入资源池并统计、监控 * * @param machineInfo * @return */ @Override public boolean addMachine(MachineInfo machineInfo) { boolean success = true; if (machineInfo == null || Strings.isNullOrEmpty(machineInfo.getIp())) { logger.error("machineInfo is null or ip is valid."); return false; } // 将机器信息保存到db中 try { machineDao.saveMachineInfo(machineInfo); } catch (Exception e) { logger.error("save machineInfo: {} to db error.", machineInfo.toString(), e); return false; } if (success) { logger.info("save and deploy machine ok, machineInfo: {}", machineInfo.toString()); } return success; } @Override public boolean addMachineRoom(MachineRoom room) { boolean success = true; try { machineRoomDao.saveRoom(room); } catch (Exception e) { logger.error("save machineRoom: {} to db error.", room.toString(), e); return false; } if (success) { logger.info("save machineRoom ok, machineRoom: {}", room.toString()); } return success; } @Override public boolean removeMachineRoom(int roomId) { try { machineRoomDao.removeRoom(roomId); } catch (Exception e) { logger.error("remove machineRoom from db error, machineRoom: {}", roomId, e); return false; } logger.info("remove machineRoom ok: {}", roomId); return true; } /** * 删除机器,并删除相关的定时任务 * * @param machineInfo * @return */ @Override public boolean removeMachine(MachineInfo machineInfo) { if (machineInfo == null || Strings.isNullOrEmpty(machineInfo.getIp())) { logger.warn("machineInfo is null or ip is empty."); return false; } String machineIp = machineInfo.getIp(); // 从db中删除machine和相关统计信息 try { machineDao.removeMachineInfoByIp(machineIp); machineStatsDao.deleteMachineStatsByIp(machineIp); serverStatusDao.deleteServerInfo(machineIp); } catch (Exception e) { logger.error("remove machineInfo from db error, machineInfo: {}", machineInfo.toString(), e); return false; } logger.info("remove and undeploy machine ok: {}", machineInfo.toString()); return true; } @Override public void updateMachineRelation(int id, Long taskid, int is_sync) { try { machineRelationDao.updateMachineRelation(id, taskid, is_sync); } catch (Exception e) { logger.error("update machineRelation id:{} taskid :{} error, machineRelation: {}", id, taskid, e.getMessage()); } } public List getMachineRelationList(String ip) { List relationList = new ArrayList(); try { relationList = machineRelationDao.getRelationList(ip); } catch (Exception e) { logger.error("get machine relation : containerIp:{} , error message:{}", ip, e.getMessage(), e); } return relationList; } public SuccessEnum checkMachineSyncStatus(String containerIp, String sourceIp, int is_sync) { List machineRelationList = null; try { machineRelationList = machineRelationDao.getMachineSyncStatus(containerIp, sourceIp, is_sync); } catch (Exception e) { logger.error("check machine relation error : containerIp: {} sourceIp:{} is_sync:{} ,error message: {}", containerIp, sourceIp, is_sync, e.getMessage(), e); return SuccessEnum.ERROR; } if (machineRelationList != null && machineRelationList.size() > 0) { logger.info("check machine relation containerIp: {} sourceIp:{} is_sync:{} size :{} ", containerIp, sourceIp, is_sync, machineRelationList.size()); return SuccessEnum.REPEAT; } else { return SuccessEnum.NO_REPEAT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/protocol/MachineProtocol.java ================================================ package com.sohu.cache.protocol; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.util.ConstUtils; /** * 机器相关的一些常量 * * @author: lingguo * @time: 2014/8/26 16:18 */ public class MachineProtocol { /** * 统一的目录结构 */ public static final String CONF_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/conf/"; public static final String DATA_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/data/"; public static final String LOG_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/logs/"; /** * k8s容器目录结构 */ public static final String K8S_CONF_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/conf/%s/"; public static final String K8S_DATA_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/data/%s/"; public static final String K8S_LOG_DIR = ConstUtils.CACHECLOUD_BASE_DIR + "/cachecloud/logs/%s/"; /** * 配置文件的临时目录; */ public static final String TMP_DIR = "/tmp/cachecloud/"; /** * 编码 */ public static final String ENCODING_UTF8 = "UTF-8"; /** * 配置目录 * @param instanceBasePath * @return */ public static String getConfPath(String instanceBasePath) { return instanceBasePath + "/conf"; } /** * 支持k8s挂载宿主机文件 * * @param host * @return */ public static String getK8sConfDir(String host) { return String.format(K8S_CONF_DIR, host); } public static String getK8sDataDir(String host) { return String.format(K8S_DATA_DIR, host); } public static String getK8sLogDir(String host) { return String.format(K8S_LOG_DIR, host); } /** * 获取k8s相关目录 * * @param host * @param dirType * @return */ public static String getK8sDir(String host, int dirType) { if (dirType == DirEnum.CONF_DIR.getValue()) { return String.format(K8S_CONF_DIR, host); } else if (dirType == DirEnum.DATA_DIR.getValue()) { return String.format(K8S_DATA_DIR, host); } else if (dirType == DirEnum.LOG_DIR.getValue()) { return String.format(K8S_LOG_DIR, host); } return null; } /** * 获取普通容器目录 * * @param dirType * @return */ public static String getDir(int dirType) { if (dirType == DirEnum.CONF_DIR.getValue()) { return CONF_DIR; } else if (dirType == DirEnum.DATA_DIR.getValue()) { return DATA_DIR; } else if (dirType == DirEnum.LOG_DIR.getValue()) { return LOG_DIR; } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/protocol/RedisProtocol.java ================================================ package com.sohu.cache.protocol; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.lang.StringUtils; import java.util.Date; /** * Created by yijunzhang on 14-11-26. */ public class RedisProtocol { private static final String RUN_SHELL_VERSION = "%s/src/redis-server %s > " + MachineProtocol.LOG_DIR + "redis-%d-%s.log 2>&1 &"; private static final String SENTINEL_SHELL_VERSION = "%s/src/redis-sentinel %s --sentinel > " + MachineProtocol.LOG_DIR + "redis-sentinel-%d-%s.log 2>&1 &"; private static final String K8S_RUN_SHELL_VERSION = "%s/src/redis-server %s > %sredis-%d-%s.log 2>&1 &"; private static final String K8S_SENTINEL_SHELL_VERSION = "%s/src/redis-sentinel %s --sentinel > %sredis-sentinel-%d-%s.log 2>&1 &"; private static final String CLUSTER_CONFIG = "redis-cluster-%d.conf"; private static final String COMMON_CONFIG = "redis-sentinel-%d.conf"; /** * 2018-08-28 根据不同版本路径启动redis-cluster * * @param port * @param isCluster * @param dir redis启动路径 * @return 启动redis命令 */ public static String getRunShellByVersion(int port, boolean isCluster, String dir) { return String.format(RUN_SHELL_VERSION, dir, MachineProtocol.CONF_DIR + getConfig(port, isCluster), port, DateUtil.formatYYYYMMddHHMM(new Date())); } /** * 2018-08-28 根据不同版本路径启动redis-sentinel * * @param port * @param dir redis启动路径 * @return 启动redis命令 */ public static String getSentinelShellByVersion(int port, String dir) { return String.format(SENTINEL_SHELL_VERSION, dir, MachineProtocol.CONF_DIR + getConfig(port, false), port, DateUtil.formatYYYYMMddHHMM(new Date())); } /** * 2019-05-14 k8s容器启动路径 /opt/cachecloud/conf/${host}/redis-${port}.conf * * @param host * @param port * @param isCluster * @param dir * @return 启动redis命令 */ public static String getK8sRunShellByVersion(String host, int port, boolean isCluster, String dir) { return String.format(K8S_RUN_SHELL_VERSION, dir, MachineProtocol.getK8sConfDir(host) + getConfig(port, isCluster), MachineProtocol.getK8sLogDir(host), port, DateUtil.formatYYYYMMddHHMM(new Date())); } /** * 2019-05-14 k8s容器启动路径 /opt/cachecloud/conf/${host}/redis-${port}.conf * * @param host * @param port * @param dir * @return 启动redis sentinel命令 */ public static String getK8sSentinelShellByVersion(String host, int port, String dir) { return String.format(K8S_SENTINEL_SHELL_VERSION, dir, MachineProtocol.getK8sConfDir(host) + getConfig(port, false), MachineProtocol.getK8sLogDir(host), port, DateUtil.formatYYYYMMddHHMM(new Date())); } public static String getExecuteCommandShell(String host, int port, String password, String command) { StringBuffer shell = new StringBuffer(); shell.append(String.format("redis-cli -h %s -p %s", host, port)); if (StringUtils.isNotBlank(password)) { shell.append(String.format(" -a %s", password)); } shell.append(String.format(" --raw %s", command)); return shell.toString(); } public static String getExecuteAdminCommandShell(String host, int port, String password, String command) { StringBuffer shell = new StringBuffer(); shell.append(String.format("redis-cli -h %s -p %s", host, port)); if (StringUtils.isNotBlank(password)) { shell.append(String.format(" -a %s", password)); } shell.append(String.format(" %s", command)); return shell.toString(); } public static String getConfig(int port, boolean isCluster) { if (isCluster) { return String.format(CLUSTER_CONFIG, port); } else { return String.format(COMMON_CONFIG, port); } } public static String getRedisPortPidFilePath() { return "logs/redis-port.pid"; } private static final String NUT_CRACKER_SHELL = "bin/nutcracker -c %s/%s -p %s/%s -o %s/%s -s %d -v %d"; public static String getNutCrackerConfName() { return "nutcracker.conf"; } public static String getNutCrackerPidName() { return "nutcracker.pid"; } public static String getNutCrackerLogName() { return "nutcracker.log"; } public static String getNutCrackerShell(String confFilePath, String pidPath, String logPath, int statPort, int logLevel) { return String.format(NUT_CRACKER_SHELL, confFilePath, getNutCrackerConfName(), pidPath, getNutCrackerPidName(), logPath, getNutCrackerLogName(), statPort, logLevel); } public static String getNutCrackerStartCmd(String confFilePath, String pidPath, String logPath, int statPort, int logLevel) { return String.format("bin/mon -a 60 -d \"%s\"", getNutCrackerShell(confFilePath, pidPath, logPath, statPort, logLevel)); } public static String getNutCrackerRunCmd(String confFilePath, String pidPath, String logPath, int statPort, int logLevel) { return getNutCrackerShell(confFilePath, pidPath, logPath, statPort, logLevel); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/AssistRedisService.java ================================================ package com.sohu.cache.redis; import redis.clients.jedis.Tuple; import redis.clients.jedis.params.SetParams; import java.util.List; import java.util.Map; import java.util.Set; /** * CacheCloud 内部使用的辅助redis */ public interface AssistRedisService { boolean reloadSentinel(); boolean set(String key, T value); boolean set(String key, T value, int timeout); boolean setNx(String key, String value) ; String set(String key, String value, SetParams params) ; boolean setWithNoSerialize(String key, T value); String getWithNoSerialize(String key); boolean setWithNoSerialize(String key, T value, int seconds); boolean remove(String key); T get(String key); boolean rpush(String key, String item); boolean rpush(String key, String... item); boolean rpushList(String key, List items); boolean saddSet(String key, Set items); boolean sadd(String key, String item); Set smembers(String key); boolean srem(String key, String item); List lrange(String key, int start, int end); Long llen(final String key); String lpop(final String key); Long lrem(final String key, long count, String element); String ltrim(final String key, long start, long end); boolean zadd(String key, long score, String member); String hget(String key, String field); boolean hset(String key, String field, String value); Long hsetnx(String key, String field, String value); boolean hmset(String key, Map map); Map hgetAll(String key); Long hdel(String key, String field); boolean del(String key); boolean delMulti(String... keys); void zincrby(String key, double score, String member); Set zrangeWithScores(String key, long start, long end); boolean exists(String key); boolean setNEX(String key, String value, int seconds); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/RedisCenter.java ================================================ package com.sohu.cache.redis; import com.sohu.cache.entity.*; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.vo.RedisSlowLog; import org.apache.commons.lang3.tuple.Pair; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisSentinelPool; import redis.clients.jedis.commands.ProtocolCommand; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Future; /** * redis相关操作接口 * Created by yijunzhang on 14-6-10. */ public interface RedisCenter { /** * 收集redis统计信息 * * @param appId * @param host * @param port * @return */ public Map> collectRedisInfo(long appId, long collectTime, String host, int port); /** * 收集redis统计信息 * * @param host * @param port * @return */ public Map> getInfoStats(long appId, String host, int port); /** * 节点cluster info信息 * * @param appId * @param host * @param port * @return */ public Map getClusterInfoStats(long appId, String host, int port); /** * 节点cluster info信息 * * @param appId * @param instanceInfo * @return */ public Map getClusterInfoStats(long appId, InstanceInfo instanceInfo); /** * 根据ip和port判断redis实例当前是主还是从 * * @param ip ip * @param port port * @return 主返回true,从返回false,返回null代表未知; */ public BooleanEnum isMaster(long appId, String ip, int port); /** * 判断实例是否为从节点,并且与主节点连接有效 * * @param appDesc * @param slaveInstance * @param masterInstance * @return */ public BooleanEnum isSlaveAndPointedMasterUp(AppDesc appDesc, InstanceInfo slaveInstance, InstanceInfo masterInstance); /** * 获取行数 * * @param appId * @param ip * @param port * @return */ long getDbSize(long appId, String ip, int port); Future> findInstancePatternKeys(long appId, String ip, int port, String pattern); List findInstanceBigKey(long appId, String ip, int port, long startBytes, long endBytes); List findClusterBigKey(long appId, long startBytes, long endBytes); List findInstanceIdleKeys(long appId, String ip, int port, long idleDays); List findClusterIdleKeys(long appId, long idleDays); void delInstancePatternKeys(long appId, String ip, int port, String pattern); void delClusterPatternKey(long appId, String pattern); /** * 根据ip和port判断redis实例当前是否有从节点 * * @param ip ip * @param port port * @return 主返回true,从返回false; */ public BooleanEnum hasSlaves(long appId, String ip, int port); /** * 获取从节点的主节点地址 * * @param ip * @param port * @param password * @return */ public HostAndPort getMaster(String ip, int port, String password); public HostAndPort getSlave0(String ip, int port, String password); /** * 判断实例是否运行 * * @param appId * @param ip * @param port * @return */ public boolean isRun(final long appId, String ip, int port); /** * 判断实例是否运行 * * @param ip * @param port * @param retryTimes 重试次数 * @return */ public boolean isRun(final String ip, final int port, final int retryTimes); /** * 判断实例是否运行 * * @param ip * @param port * @return */ public boolean isRun(String ip, int port); /** * 判断实例是否运行 * * @param ip * @param port * @param password * @return */ public boolean isRun(String ip, int port, String password); /** * 下线指定实例 * * @param ip * @param port * @return */ public boolean shutdown(String ip, int port); /** * 下线指定实例 * * @param appId * @param ip * @param port * @return */ public boolean shutdown(long appId, String ip, int port); /** * 校验下线指定实例是否成功 * * @param instanceInfo * @return */ public boolean checkShutdownSuccess(InstanceInfo instanceInfo); /** * forget指定实例 * * @param appId * @param ip * @param port * @param nodeClusterId * @return */ public boolean forget(long appId, String ip, int port, String nodeClusterId); /** * 获取cluster myid * * @param ip * @param port * @return */ public String getClusterMyId(long appId, String ip, int port); /** * 获取cluster nodes * * @param ip * @param port * @return */ public String getClusterNodes(long appId, String ip, int port); /** * 执行redis命令返回结果 * * @param appDesc * @param command * @param userName * @return */ public String executeCommand(AppDesc appDesc, String command, String userName); /** * 实例执行redis命令 * * @param appId * @param host * @param port * @param command * @return */ public String executeCommand(long appId, String host, int port, String command); /** * 执行redis命令,无白名单限制,仅供管理员使用 * * @param appDesc * @param command * @param args * @return */ Object executeAdminCommand(AppDesc appDesc, ProtocolCommand command, String... args); /** * 实例执行redis命令,无白名单限制,仅供管理员使用 * * @param appId * @param host * @param port * @param command * @param timeout * @return */ String executeAdminCommand(long appId, String host, int port, String command, Integer timeout); /** * 执行redis命令, 无黑白名单限制,仅供管理员使用 * * @param jedis * @param command * @param args * @return */ Object executeAdminRedisCommandByJedis(Jedis jedis, ProtocolCommand command, String... args); /** * 获取jedisSentinelPool实例,必须是sentinel类型应用 * * @param appDesc * @return */ public JedisSentinelPool getJedisSentinelPool(AppDesc appDesc); /** * 获取redis实例配置信息 * * @param instanceId * @return */ public Map getRedisConfigList(int instanceId); /** * 获取redis 命令列表 * @param instanceId * @return */ public List getRedisCommand(int instanceId); /** * 获取重命名命令列表 * @param instanceId * @return */ List> getConfigsInConfigFile(int instanceId, String configName); /** * 获取redis实例慢查询 * * @param instanceId * @return */ public List getRedisSlowLogs(int instanceId, int maxCount); /** * 获取client连接信息 * * @param instanceId * @return */ List getClientList(int instanceId); List> formatClientList(List clientList); List> getAppClientList(long appId, int condition); /** * 配置重写 * * @return */ public boolean configRewrite(final long appId, final String host, final int port); /** * 配置重写 * * @param jedis * @return */ public boolean configRewrite(Jedis jedis); /** * 获取maxmemory配置 * * @param appId * @param host * @param port * @return */ public Long getRedisMaxMemory(long appId, String host, int port); /** * 清理app数据 * * @param appDesc * @param appUser * @return */ public boolean cleanAppData(AppDesc appDesc, AppUser appUser); /** * 判断是否为孤立节点 * * @param appId * @param host * @param port * @return */ public boolean isSingleClusterNode(long appId, String host, int port); /** * 获取集群中失联的slots * * @param appId * @return */ public Map getClusterLossSlots(long appId); /** * 获取集群中失联的slots * @param appId * @param instanceInfo * @return */ public Map getClusterLossSlots(long appId, InstanceInfo instanceInfo); /** * 获取集群中失联的slots * * @param appId * @param host * @param port * @return */ public List getClusterLossSlots(long appId, String host, int port); /** * 获取集群中失联的slots * * @param appId * @param healthyHost * @param healthyPort * @param lossSlotsHost * @param lossSlotsPort * @return */ public List getInstanceSlots(long appId, String healthyHost, int healthyPort, String lossSlotsHost, int lossSlotsPort); /** * 从一个应用中获取一个健康的实例 * * @param appId * @return */ public InstanceInfo getHealthyInstanceInfo(long appId); /** * 从一个应用中获取所有健康的master实例 * * @param appId * @return */ public List getAllHealthyInstanceInfo(long appId); /** * 收集redis延迟信息 * * @param appId * @param collectTime * @param host * @param port * @return */ List collectRedisLatencyInfo(long appId, long collectTime, String host, int port); /** * 收集redis慢查询日志 * * @param appId * @param host * @param port * @return */ public List collectRedisSlowLog(long appId, long collectTime, String host, int port); /** * 按照appid获取慢查询日志 * * @param appId * @return */ public List getInstanceSlowLogByAppId(long appId); /** * 按照appid获取慢查询日志 * * @param appId * @param startDate * @param endDate * @return */ public List getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate); /** * 按照appid获取慢查询日志数关系 * * @param appId * @param startDate * @param endDate * @return */ public Map getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate); /** * 获取集群的slots分布 * * @param appId * @return */ Map getClusterSlotsMap(long appId); /** * 获取集群slot分布 * -> > * * @param appId * @param instanceInfo * @return */ Map> getClusterSlotMap(long appId, InstanceInfo instanceInfo); /** * 获取Redis版本 * * @param appId * @param ip * @param port * @return */ public String getRedisVersion(long appId, String ip, int port); /** *

* Description: 获取redis failover之后数据状态,判断是否failover完成 *

* * @param ip 当前failover slave ip * @param port 当前failover slave port * @return false:定时轮询检测 true:检测完毕 * @version 1.0 * @date 2018/9/17 */ public Boolean getRedisReplicationStatus(long appId, String ip, int port); /** * @param appId * @param ip * @param port * @return */ public Map getRedisRoleAndMasterStatus(long appId, String ip, int port); /** *

* Description: 获取redis failover之后状态,判断是否failover完成 *

* * @param ip 当前failover slave ip * @param port 当前failover slave port * @return false:定时轮询检测 true:检测完毕 * @version 1.0 * @date 2023/2/28 */ public Boolean getRedisFailoverForceStatus(long appId, String ip, int port); /** * 获取nodeId * * @param appId * @param ip * @param port * @return */ public String getNodeId(long appId, String ip, int port); Jedis getJedis(String host, int port, String password); Jedis getAdminJedis(String host, int port, String password); Jedis getJedis(String host, int port); Jedis getJedis(long appId, String host, int port); Jedis getAdminJedis(long appId, String host, int port); Jedis getJedis(long appId, String host, int port, int connectionTimeout, int soTimeout); Jedis getAdminJedis(long appId, String host, int port, int connectionTimeout, int soTimeout); Jedis getJedis(String host, int port, String password, int connectionTimeout, int soTimeout); public boolean sendDeployRedisRelateCollectionMsg(long appId, String host, int port); /** * 检查配置nutcracker配置是否一致 * * @param appId * @return */ public boolean checkNutCrackerConfIsSame(long appId); /** * 检查nutcracker哈希是否一致 * * @param appId * @param isDelete 检查后删除数据 * @return */ public List checkNutCrackerHashIsSame(long appId, boolean isDelete); String configGet(long appId, String host, int port, String key); boolean configSetAndRewrite(long appId, String host, int port, String key, String value); //检测从节点是否准备OK boolean checkSlaveReady(long appId, String ip, int port, long offset); //检测从节点是否准备OK boolean checkSlaveReady(Jedis jedis, Long offset); //获取节点角色描述 String getInstanceRole(Jedis jedis); //获取节点角色描述 String getInstanceRole(long appId, String ip, int port); //检测bgsave是否完成 boolean checkBgsaveFinish(Jedis jedis, int checkTimes); //检测load rdb是否完成 boolean checkLoadFinish(Jedis jedis, int checkTimes); //获取rdb文件名 String getRdbFileName(Jedis jedis); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/RedisClusterNode.java ================================================ package com.sohu.cache.redis; /** * Created by yijunzhang on 14-8-25. */ public class RedisClusterNode { /** * 主节点地址 */ private String masterHost; /** * 从节点地址 */ private String slaveHost; public String getMasterHost() { return masterHost; } public void setMasterHost(String masterHost) { this.masterHost = masterHost; } public String getSlaveHost() { return slaveHost; } public void setSlaveHost(String slaveHost) { this.slaveHost = slaveHost; } public RedisClusterNode(String masterHost, String slaveHost) { this.masterHost = masterHost; this.slaveHost = slaveHost; } public RedisClusterNode() { } @Override public String toString() { return "RedisClusterNode{" + "masterHost='" + masterHost + '\'' + ", slaveHost='" + slaveHost + '\'' + '}'; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/RedisClusterReshard.java ================================================ package com.sohu.cache.redis; import com.sohu.cache.constant.ReshardStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceReshardProcessDao; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceReshardProcess; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.util.IdempotentConfirmer; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.Protocol; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.params.MigrateParams; import redis.clients.jedis.util.SafeEncoder; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * 水平扩容重构 * * @author leifu * @Date 2016年12月7日 * @Time 上午10:13:00 */ public class RedisClusterReshard { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Map nodeIdCachedMap = new HashMap(); /** * migrate超时时间 */ private int migrateTimeout = 10000; /** * 普通jedis操作超时时间 */ private int defaultTimeout = Protocol.DEFAULT_TIMEOUT * 5; /** * 每次迁移key个数 */ private int migrateBatch = 10; /** * 所有有效节点 */ private Set hosts; /** * redis操作封装 */ private RedisCenter redisCenter; private InstanceReshardProcessDao instanceReshardProcessDao; private AppDao appDao; private ResourceDao resourceDao; public RedisClusterReshard(Set hosts, RedisCenter redisCenter, InstanceReshardProcessDao instanceReshardProcessDao) { this.hosts = hosts; this.redisCenter = redisCenter; this.instanceReshardProcessDao = instanceReshardProcessDao; } /** *

* Description: 需要获取应用密码 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/12/25 */ public RedisClusterReshard(Set hosts, RedisCenter redisCenter, InstanceReshardProcessDao instanceReshardProcessDao, AppDao appDao, ResourceDao resourceDao) { this.hosts = hosts; this.redisCenter = redisCenter; this.instanceReshardProcessDao = instanceReshardProcessDao; this.appDao = appDao; this.resourceDao = resourceDao; } /** * 加入主从分片 */ public boolean joinCluster(long appId, String masterHost, int masterPort, final String slaveHost, final int slavePort) { Jedis mJedis = null; Jedis sJedis = null; try{ //1. 确认主从节点是否正常 mJedis = redisCenter.getAdminJedis(appId, masterHost, masterPort, defaultTimeout, defaultTimeout); final Jedis masterJedis = mJedis; boolean isRun = redisCenter.isRun(appId, masterHost, masterPort); if (!isRun) { logger.error(String.format("joinCluster: master host=%s,port=%s is not run", masterHost, masterPort)); return false; } boolean hasSlave = StringUtils.isNotBlank(slaveHost) && slavePort > 0; sJedis = hasSlave ? redisCenter.getAdminJedis(appId, slaveHost, slavePort, defaultTimeout, defaultTimeout) : null; final Jedis slaveJedis = sJedis; if (hasSlave) { isRun = redisCenter.isRun(appId, slaveHost, slavePort); if (!isRun) { logger.error(String.format("joinCluster: slave host=%s,port=%s is not run", slaveHost, slavePort)); return false; } } //2. 对主从节点进行meet操作 //获取所有主节点 List masterHostAndPostList = getMasterNodeList(appId); //meet master boolean isClusterMeet = clusterMeet(appId, masterHostAndPostList, masterHost, masterPort); if (!isClusterMeet) { logger.error("master isClusterMeet failed {}:{}", masterHost, masterPort); return false; } if (hasSlave) { isClusterMeet = clusterMeet(appId, masterHostAndPostList, slaveHost, slavePort); if (!isClusterMeet) { logger.error("slave isClusterMeet failed {}:{}", slaveHost, slavePort); return false; } } //3.复制 if (hasSlave) { final String masterNodeId = getNodeId(appId, masterJedis); if (masterNodeId == null) { logger.error(String.format("joinCluster:host=%s,port=%s nodeId is null", masterHost, masterPort)); return false; } return new IdempotentConfirmer() { @Override public boolean execute() { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } String response = slaveJedis.clusterReplicate(masterNodeId); logger.info("clusterReplicate-{}:{}={}", slaveHost, slavePort, response); return response != null && response.equalsIgnoreCase("OK"); } }.run(); } else { return true; } }finally { if(mJedis != null){ mJedis.close(); } if(sJedis != null){ sJedis.close(); } } } /** * 将source中的startSlot到endSlot迁移到target * */ // public boolean migrateSlotOld(long appId, long appAuditId, InstanceInfo sourceInstanceInfo, InstanceInfo targetInstanceInfo, int startSlot, int endSlot, PipelineEnum pipelineEnum) { // long startTime = System.currentTimeMillis(); // InstanceReshardProcess instanceReshardProcess = saveInstanceReshardProcess(appId, appAuditId, sourceInstanceInfo, targetInstanceInfo, startSlot, endSlot, pipelineEnum); // //源和目标Jedis // Jedis sourceJedis = redisCenter.getJedis(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort(), defaultTimeout, defaultTimeout); // Jedis targetJedis = redisCenter.getJedis(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort(), defaultTimeout, defaultTimeout); // //逐个slot迁移 // boolean hasError = false; // for (int slot = startSlot; slot <= endSlot; slot++) { // long slotStartTime = System.currentTimeMillis(); // try { // instanceReshardProcessDao.updateMigratingSlot(instanceReshardProcess.getId(), slot); // //num是迁移key的总数 // int num = migrateSlotData(appId, sourceJedis, targetJedis, slot, pipelineEnum); // instanceReshardProcessDao.increaseFinishSlotNum(instanceReshardProcess.getId()); // logger.warn("clusterReshard:{}->{}, slot={}, keys={}, costTime={} ms", sourceInstanceInfo.getHostPort(), // targetInstanceInfo.getHostPort(), slot, num, (System.currentTimeMillis() - slotStartTime)); // } catch (Exception e) { // logger.error(e.getMessage(), e); // hasError = true; // break; // } // } // long endTime = System.currentTimeMillis(); // logger.warn("clusterReshard:{}->{}, slot:{}->{}, costTime={} ms", sourceInstanceInfo.getHostPort(), // targetInstanceInfo.getHostPort(), startSlot, endSlot, (endTime - startTime)); // if (hasError) { // instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.ERROR.getValue()); // return false; // } else { // instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.FINISH.getValue()); // instanceReshardProcessDao.updateEndTime(instanceReshardProcess.getId(), new Date()); // return true; // } // } /** * 节点meet * * @param masterHostAndPostList * @param host * @param port * @return */ private boolean clusterMeet(long appId, List masterHostAndPostList, final String host, final int port) { boolean isSingleNode = redisCenter.isSingleClusterNode(appId, host, port); if (!isSingleNode) { logger.error("{}:{} isNotSingleNode", host, port); return false; } else { logger.warn("{}:{} isSingleNode", host, port); } for (HostAndPort hostAndPort : masterHostAndPostList) { String clusterHost = hostAndPort.getHost(); int clusterPort = hostAndPort.getPort(); final Jedis jedis = redisCenter.getAdminJedis(appId, clusterHost, clusterPort, defaultTimeout, defaultTimeout); //logger.info("jedis {}:{} meet singlenode",clusterHost,clusterPort); try { boolean isClusterMeet = new IdempotentConfirmer() { @Override public boolean execute() { //将新节点添加到集群当中,成为集群中已知新节点 String meet = jedis.clusterMeet(host, port); return meet != null && meet.equalsIgnoreCase("OK"); } }.run(); if (isClusterMeet) { return true; } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } } return false; } /** * 将source中的startSlot到endSlot迁移到target */ public boolean migrateSlot(InstanceReshardProcess instanceReshardProcess) { long appId = instanceReshardProcess.getAppId(); AppDesc appDesc = appDao.getAppDescById(appId); String password = null; List versionList = new ArrayList<>(); boolean isRedisType = TypeUtil.isRedisType(appDesc.getType()); if(appDesc != null && isRedisType){ password = appDesc.getPasswordMd5(); // Redis版本信息 SystemResource resource = resourceDao.getResourceById(appDesc.getVersionId()); String name = resource.getName(); if(name != null){ String[] split = name.split("-"); if(split != null && split.length == 2){ String[] versionArray = split[1].split("\\."); versionList = Arrays.asList(versionArray).stream().map(ver -> Integer.valueOf(ver)).collect(Collectors.toList()); } } } int migratingSlot = instanceReshardProcess.getMigratingSlot(); int endSlot = instanceReshardProcess.getEndSlot(); int isPipeline = instanceReshardProcess.getIsPipeline(); InstanceInfo sourceInstanceInfo = instanceReshardProcess.getSourceInstanceInfo(); InstanceInfo targetInstanceInfo = instanceReshardProcess.getTargetInstanceInfo(); long startTime = System.currentTimeMillis(); //源和目标Jedis try(Jedis sourceJedis = redisCenter.getAdminJedis(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort(), defaultTimeout, defaultTimeout); Jedis targetJedis = redisCenter.getAdminJedis(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort(), defaultTimeout, defaultTimeout);){ //逐个slot迁移 boolean hasError = false; for (int slot = migratingSlot; slot <= endSlot; slot++) { long slotStartTime = System.currentTimeMillis(); try { instanceReshardProcessDao.updateMigratingSlot(instanceReshardProcess.getId(), slot); //num是迁移key的总数 int num = 0; if(isRedisType){ num = migrateSlotData(appId, sourceJedis, targetJedis, slot, isPipeline, password, versionList); } instanceReshardProcessDao.increaseFinishSlotNum(instanceReshardProcess.getId()); logger.warn("clusterReshard:{}->{}, slot={}, keys={}, costTime={} ms", sourceInstanceInfo.getHostPort(), targetInstanceInfo.getHostPort(), slot, num, (System.currentTimeMillis() - slotStartTime)); } catch (Exception e) { logger.error(e.getMessage(), e); hasError = true; break; } } long endTime = System.currentTimeMillis(); logger.warn("clusterReshard:{}->{}, slot:{}->{}, costTime={} ms", sourceInstanceInfo.getHostPort(), targetInstanceInfo.getHostPort(), migratingSlot, endSlot, (endTime - startTime)); if (hasError) { instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.ERROR.getValue()); return false; } else { instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.FINISH.getValue()); instanceReshardProcessDao.updateEndTime(instanceReshardProcess.getId(), new Date()); return true; } } } /** * 迁移slot数据,并稳定slot配置 * * @throws Exception */ private int moveSlotData(final long appId, final Jedis source, final Jedis target, final int slot, int isPipeline, String password, List versionList) throws Exception { int num = 0; while (true) { final Set keys = new HashSet(); boolean isGetKeysInSlot = new IdempotentConfirmer() { @Override public boolean execute() { List perKeys = source.clusterGetKeysInSlot(slot, migrateBatch); if (perKeys != null && perKeys.size() > 0) { keys.addAll(perKeys); } return true; } }.run(); if (!isGetKeysInSlot) { throw new RuntimeException(String.format("get keys failed slot=%d num=%d", slot, num)); } if (keys.isEmpty()) { break; } for (final String key : keys) { boolean isKeyMigrate = new IdempotentConfirmer() { // 失败后,迁移时限加倍 private int migrateTimeOutFactor = 1; @Override public boolean execute() { String response = null; Integer bigVer = 0; Integer smallVer = 0; Integer fixVer = 0; if(CollectionUtils.isNotEmpty(versionList)){ bigVer = versionList.get(0); smallVer = versionList.get(1); fixVer = versionList.get(2); } if(bigVer < 4 || (bigVer == 4 && smallVer == 0 && fixVer < 7)){ response = source.migrate(target.getClient().getHost(), target.getClient().getPort(), key, 0, migrateTimeout * (migrateTimeOutFactor++)); }else{ response = source.migrate(target.getClient().getHost(), target.getClient().getPort(), 0, migrateTimeout * (migrateTimeOutFactor++), MigrateParams.migrateParams().auth(password), key); } return response != null && (response.equalsIgnoreCase("OK") || response.equalsIgnoreCase("NOKEY")); } }.run(); if (!isKeyMigrate) { throw new RuntimeException("migrate key=" + key + failedInfo(source, slot)); } else { num++; // logger.info("migrate key={};response=OK", key); } } } final String targetNodeId = getNodeId(appId, target); boolean isClusterSetSlotNode; //设置 slot新归属节点 isClusterSetSlotNode = new IdempotentConfirmer() { @Override public boolean execute() { boolean isOk = false; List masterNodesList = getMasterNodeList(appId); // 增加cluster SETSLOT slot NODE node-id sequence // target, source, and optional other master nodes HostAndPort targetHostPort = new HostAndPort(target.getClient().getHost(), target.getClient().getPort()); HostAndPort sourceHostPort = new HostAndPort(source.getClient().getHost(), source.getClient().getPort()); masterNodesList = masterNodesList.stream(). filter(hostAndPort -> !hostAndPort.equals(targetHostPort) && !hostAndPort.equals(sourceHostPort)) .collect(Collectors.toList()); masterNodesList.add(0, targetHostPort); masterNodesList.add(1, sourceHostPort); for (HostAndPort hostAndPort : masterNodesList) { Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, hostAndPort.getHost(), hostAndPort.getPort()); String response = jedis.clusterSetSlotNode(slot, targetNodeId); isOk = response != null && response.equalsIgnoreCase("OK"); if (!isOk) { logger.error("clusterSetSlotNode-{}={}", getNodeId(appId, target), response); break; } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } } return isOk; } }.run(); if (!isClusterSetSlotNode) { throw new RuntimeException("clusterSetSlotNode:" + failedInfo(target, slot)); } return num; } /** * 指派迁移节点数据 * CLUSTER SETSLOT IMPORTING 从 node_id 指定的节点中导入槽 slot 到本节点。 * CLUSTER SETSLOT MIGRATING 将本节点的槽 slot 迁移到 node_id 指定的节点中。 * CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。 * MIGRATE host port key destination-db timeout [COPY] [REPLACE] * CLUSTER SETSLOT NODE 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。 */ private int migrateSlotData(long appId, final Jedis source, final Jedis target, final int slot, int isPipeline, String password, List versionList) { int num = 0; final String sourceNodeId = getNodeId(appId, source); final String targetNodeId = getNodeId(appId, target); boolean isError = false; if (sourceNodeId == null || targetNodeId == null) { throw new JedisException(String.format("sourceNodeId = %s || targetNodeId = %s", sourceNodeId, targetNodeId)); } boolean isImport = new IdempotentConfirmer() { @Override public boolean execute() { String importing = target.clusterSetSlotImporting(slot, sourceNodeId); logger.info("slot={},clusterSetSlotImporting={}", slot, importing); return importing != null && importing.equalsIgnoreCase("OK"); } }.run(); if (!isImport) { isError = true; logger.error("clusterSetSlotImporting" + failedInfo(target, slot)); } boolean isMigrate = new IdempotentConfirmer() { @Override public boolean execute() { String migrating = source.clusterSetSlotMigrating(slot, targetNodeId); logger.info("slot={},clusterSetSlotMigrating={}", slot, migrating); return migrating != null && migrating.equalsIgnoreCase("OK"); } }.run(); if (!isMigrate) { isError = true; logger.error("clusterSetSlotMigrating" + failedInfo(source, slot)); } try { num = moveSlotData(appId, source, target, slot, isPipeline, password, versionList); } catch (Exception e) { isError = true; logger.error(e.getMessage(), e); } if (!isError) { return num; } else { String errorMessage = "source=%s target=%s slot=%d num=%d reShard failed"; throw new RuntimeException(String.format(errorMessage, getNodeKey(source), getNodeKey(target), slot, num)); } } private String failedInfo(Jedis jedis, int slot) { return String.format(" failed %s:%d slot=%d", jedis.getClient().getHost(), jedis.getClient().getPort(), slot); } /** * 获取所有主节点 * * @return */ private List getMasterNodeList(long appId) { List masterNodeList = new ArrayList(); /** * 获取RedisCluster所有节点:新加节点从jedisClusterInfoCache获取master node不全, 如果新加节点且没有分配slot,jedisClusterInfoCache node节点不会缓存该节点 * 解决:直接遍历 host 节点,判断是否master节点 */ // 获取master节点列表 try { for (HostAndPort host : hosts) { String ip = host.getHost(); int port = host.getPort(); if (redisCenter.isMaster(appId, ip, port) != BooleanEnum.TRUE) { continue; } // 添加当前所有master节点 masterNodeList.add(new HostAndPort(ip, port)); } } catch (Exception e) { logger.error(e.getMessage(), e); throw new RuntimeException("migrate get host:" + hosts + " masterNodelist error!"); } return masterNodeList; } public String getNodeId(final long appId, final Jedis jedis) { String nodeKey = getNodeKey(jedis); if (nodeIdCachedMap.get(nodeKey) != null) { return nodeIdCachedMap.get(nodeKey); } else { String nodeId = redisCenter.getNodeId(appId, jedis.getClient().getHost(), jedis.getClient().getPort()); nodeIdCachedMap.put(nodeKey, nodeId); return nodeId; } } protected String getNodeKey(Jedis jedis) { return jedis.getClient().getHost() + ":" + jedis.getClient().getPort(); } public void setMigrateTimeout(int migrateTimeout) { this.migrateTimeout = migrateTimeout; } public void setDefaultTimeout(int defaultTimeout) { this.defaultTimeout = defaultTimeout; } public void setInstanceReshardProcessDao(InstanceReshardProcessDao instanceReshardProcessDao) { this.instanceReshardProcessDao = instanceReshardProcessDao; } public void setRedisCenter(RedisCenter redisCenter) { this.redisCenter = redisCenter; } public void setAppDao(AppDao appDao) { this.appDao = appDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/RedisConfigTemplateService.java ================================================ package com.sohu.cache.redis; import com.sohu.cache.entity.InstanceConfig; import com.sohu.cache.entity.SystemResource; import org.apache.commons.lang3.tuple.Pair; import java.util.List; import java.util.Map; /** * redis配置模板服务 * @author leifu * @Date 2016年6月23日 * @Time 下午2:08:03 */ public interface RedisConfigTemplateService { /** * 获取所有配置模板列表 * @return */ List getAllInstanceConfig(); /** * 根据type获取配置模板列表 * * @param type * @return */ List getByType(int type); /** * 根据type,versionId获取配置模板列表 * * @param type * @return */ List getByVesionAndType(int type,int versionId); /** * 根据versionId获取模板所有配置 * * @param versionId * @return 版本对应所有有效配置项 */ List getByVesion(int versionId); /** * 保存或者更新配置模板 * * @param instanceConfig * @return */ int saveOrUpdate(InstanceConfig instanceConfig); /** * 根据id获取配置模板 * * @param id * @return */ InstanceConfig getById(long id); /** * 根据configKey和type获取配置 * * @param configKey * @param type * @return */ InstanceConfig getByConfigKeyAndType(String configKey, int type); /** * 更改配置状态 * @param id * @param status * @return */ int updateStatus(long id, int status); /** * 删除配置 * @param id */ int remove(long id); /** * 普通节点配置 * @param port * @param maxMemory * @param maxMemoryPolicy * @param versionId Redis版本 * @return 普通配置列表 */ List handleCommonConfig(String host, int port, int maxMemory, String maxMemoryPolicy, int versionId); /** * sentinel节点配置(兼容k8s) * @param masterName * @param host master节点ip * @param port master节点port * @param sentinelHost sentinel host * @param sentinelPort sentinel port * @param versionId * @param customConfigs 自定义配置 * @return */ List handleSentinelConfig(String masterName, String host, int port,String sentinelHost, int sentinelPort, int versionId, List> customConfigs); /** * cluster节点配置 * @param port * @param versionId Redis版本 * @return */ List handleClusterConfig(int port, int versionId); // /** // * 普通节点默认配置 // * @param port // * @param maxMemory // * @return // */ // List handleCommonDefaultConfig(int port, int maxMemory); /** * sentinel节点默认配置 * @param masterName * @param host * @param port * @param sentinelPort * @return */ List handleSentinelDefaultConfig(String masterName, String host, int port, int sentinelPort); // /** // * cluster节点默认配置 // * @param port // * @return // */ // List handleClusterDefaultConfig(int port); /** * 通过redis名称查询是否重复 */ public SystemResource getRedisVersionByName(String versionName); /** * 202007 */ public String copyRedisConfig(int versionCopyId,SystemResource resource); /** * 更新机器安装redis版本情况 * @return SuccessEnum.SUCCESS SuccessEnum.FAIL */ public String updateMachineInstallRedis(String host); public Boolean checkAndInstallRedisResource(String host,SystemResource redisResource); public Boolean checkAndInstallRedisTool(String host,SystemResource redisResource); /** * slave更新为新版本配置 */ public Map slaveUpdateConfig(long appId,Integer upgradeVersionId,String upgradeVersionName); /** * master-slave failover */ public Map slaveFailover(long appid); /** * 检查slave psync是否成功 */ public Boolean slaveIsPsync(long appId,String ip,int port); List handleRedisConfig(String host, int port, int versionId, int maxMemory, String maxMemoryPolicy, boolean isCluster, List> customConfigs, Map copyFromConfigMap); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/RedisDeployCenter.java ================================================ package com.sohu.cache.redis; import com.sohu.cache.constant.ClusterOperateResult; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.web.enums.RedisOperateEnum; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import java.util.List; import java.util.Map; /** * redis 部署配置 * Created by yijunzhang on 14-7-1. */ public interface RedisDeployCenter { /** * 部署cluster 集群 * * @param appId 应用id * @param clusterNodes redis实例集合 * @param maxMemory 实例最大内存,单位MB * @return 实例是否部署成功 */ public boolean deployClusterInstance(long appId, List clusterNodes, int maxMemory); public boolean startCluster(final long appId, Map clusterMap); public boolean startClusterMaster(final long appId, Map clusterMap); public boolean startClusterSlave(final long appId, Map clusterMap); /** * 部署redis sentinel实例 实例组 * * @param appId 应用id * @param masterHost 主节点地址 * @param slaveHost 从节点地址 * @param maxMemory 实例最大内存,单位MB * @param sentinelList sentinel-host列表 * @param * @return 实例是否部署成功 */ public boolean deploySentinelInstance(long appId, String masterHost, String slaveHost, int maxMemory, List sentinelList); /** * 部署Standalone redis实例 * * @param appId 应用id * @param host 节点地址 * @param maxMemory 实例最大内存,单位MB * @return 实例是否部署成功 */ public boolean deployStandaloneInstance(long appId, String host, int maxMemory); /** * 修改app下所有实例的配置 * * @param appId * @param parameter * @param value * @return */ public boolean modifyAppConfig(long appId, String parameter, String value); /** * 修改实例配置 * * @param appId * @param host * @param port * @param parameter * @param value * @return */ public boolean modifyInstanceConfig(long appId, String host, int port, String parameter, String value); /** * 获取实例配置 * @param appId * @param host * @param port * @param parameter * @return */ public String getInstanceConfig(final long appId, final String host, final int port, final String parameter); /** * 为应用appId添加sentinel服务器 * * @param appId * @param sentinelHost * @return */ public boolean addSentinel(long appId, String sentinelHost) throws Exception; /** * 为主节点添加从节点 * * @param appId * @param masterInstanceId * @param slaveHost * @return */ public boolean addSlave(long appId, int masterInstanceId, String slaveHost) throws Exception; /** * 为主节点添加从节点 * * @param appDesc * @param masterHost * @param masterPort * @param mem 单位Mb * @param slaveInstance 配置有slaveHost,添加成功,将设置slavePort * @return */ public boolean addSlave(AppDesc appDesc, String masterHost, int masterPort, int mem, InstanceInfo slaveInstance) throws Exception; String genSlaveIp(long appId, int instanceId) throws Exception; /** * 填充集群中失败的slots,添加一个master节点 * * @param appId * @param instanceId * @param masterHost * @return * @throws Exception */ public RedisOperateEnum addSlotsFailMaster(long appId, int instanceId, String masterHost) throws Exception; /** * 创建一个redis实例 * * @param appDesc * @param host * @param port * @param maxMemory * @return */ public boolean createRunNode(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster); /** * 获取Redis执行的runshell * * @param host * @param port * @param redisDir * @return */ public String getRedisRunShell(boolean isCluster, String host, int port, String redisDir); /** * 获取Sentinel执行的runshell * * @param host * @param port * @param redisDir * @return */ public String getSentinelRunShell(String host, int port, String redisDir); /** *

* Description: 生成新配置 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2018/9/12 */ public boolean bornConfigAndRunNode(AppDesc appDesc, InstanceInfo instanceInfo, String host, Integer port, int maxMemory, boolean isCluster); /** * sentinel类型应用执行Failover,主从切换 * * @param appId * @return */ public boolean sentinelFailover(long appId) throws Exception; /** * sentinel类型应用执行Reset,重置状态 * * @param appId * @return */ public boolean sentinelReset(long appId) throws Exception; /** * cluster类型应用执行Failover,主从切换,只能在从节点执行 * * @param appId * @param slaveInstanceId * @param failoverParam * @return */ public boolean clusterFailover(long appId, int slaveInstanceId, String failoverParam) throws Exception; /** * 根据 host port进行 * @param appId * @param failoverParam * @return * @throws Exception */ public boolean clusterFailover(long appId, HostAndPort hostAndPort, String failoverParam) throws Exception; /** * 检查是否具备forget的条件 * * @param appId * @param forgetInstanceId * @return */ public ClusterOperateResult checkClusterForget(Long appId, int forgetInstanceId); /** * 删除节点 * * @param appId * @param delNodeInstanceId * @return */ public ClusterOperateResult delNode(Long appId, int delNodeInstanceId); /** * 应用级别配置密码并将密码更新到应用信息中。 * 步骤: * 1:根据应用类型设置密码 * 2:确保配置持久化 * 3:更新密码pkey到应用信息中 * 4:检查所有节点密码是否一致。 * * @param appId * @param pkey 如果为空,表示清空密码,默认传递appId * @return */ public boolean fixPassword(Long appId, String pkey); /** * 应用级别配置密码并将密码更新到应用信息中。 * 步骤: * 1:根据应用类型设置密码 * 2:确保配置持久化 * 3:更新密码pkey到应用信息中 * 4:检查所有节点密码是否一致。 * * @param appId * @param password 如果为空,表示默认逻辑,默认传递appId,也可传自定义密码 * @param customPwdFlag 是否为自定义密码 * @param initRedisFlag 是否为初始redis服务 * @return */ public boolean fixPassword(Long appId, String password, Boolean customPwdFlag, boolean initRedisFlag); /** * 检查应用密码是否有效并且一致 * * @param appId * @return */ public boolean checkAuths(Long appId); /** * slaveof 用管理员 * * @param appId * @param masterHost * @param masterPort * @param slaveHost * @param slavePort * @return */ public boolean slaveOf(final long appId, final String masterHost, final int masterPort, final String slaveHost, final int slavePort); /** * 用默认用户slaveof * @param appId * @param masterHost * @param masterPort * @param slaveHost * @param slavePort * @return */ public boolean slaveOfByDefaultUser(final long appId, final String masterHost, final int masterPort, final String slaveHost, final int slavePort); /** * 添加实例,是否可以指定rdb,及slots * @param appId * @param newInstHost * @param newInstPort * @param pointedRdb 是否已在目录下导入了rdb * @param mem 实例最大内存(与runInstId 必须至少一个不为空) * @param runInstId 运行实例信息 * @param slots * @return */ public boolean addInstanceToUnhealthyApp(long appId, final String newInstHost, final Integer newInstPort, final boolean pointedRdb, Integer mem, final int[] slots, Integer runInstId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/AppTypeToAlertTypeEnum.java ================================================ package com.sohu.cache.redis.enums; import com.sohu.cache.util.ConstUtils; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * 实例报警类型枚举 * @author leifu * @Date 2017年6月14日 * @Time 上午10:22:10 */ public enum AppTypeToAlertTypeEnum { REDIS_ALERT(0, ConstUtils.REDIS); private final static List appTypeToAlertTypeEnumList = new ArrayList<>(); static { for (AppTypeToAlertTypeEnum instanceAlertTypeEnum : AppTypeToAlertTypeEnum.values()) { appTypeToAlertTypeEnumList.add(instanceAlertTypeEnum); } } /** * 报警应用类型 */ private int type; /** * 报警应用描述 */ private String info; private AppTypeToAlertTypeEnum(int type, String info) { this.type = type; this.info = info; } public int getType() { return type; } public String getInfo() { return info; } public static Optional getAppTypeToAlertTypeEnum(String appType) { return appTypeToAlertTypeEnumList.stream().filter(appTypeToAlertTypeEnum -> appTypeToAlertTypeEnum.getInfo().equals(appType)).findFirst(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/DirEnum.java ================================================ package com.sohu.cache.redis.enums; /** * Created by chenshi on 2019/5/14. */ public enum DirEnum { CONF_DIR(1, "配置文件目录"), DATA_DIR(2, "数据文件目录"), LOG_DIR(3, "日志文件目录"); private int value; private String info; DirEnum(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertCheckCycleEnum.java ================================================ package com.sohu.cache.redis.enums; import java.util.ArrayList; import java.util.List; /** * 实例报警检测周期枚举 * @author leifu * @Date 2017年6月14日 * @Time 上午10:21:29 */ public enum InstanceAlertCheckCycleEnum { ONE_MINUTE(1, "1分钟"), FIVE_MINUTE(2, "5分钟"), HALF_HOUR(3, "30分钟"), ONE_HOUR(4, "1小时"), ONE_DAY(5, "1天"), ; private final static List instanceAlertCheckCycleEnumList = new ArrayList(); static { for (InstanceAlertCheckCycleEnum instanceAlertCheckCycleEnum : InstanceAlertCheckCycleEnum.values()) { instanceAlertCheckCycleEnumList.add(instanceAlertCheckCycleEnum); } } private int value; private String info; private InstanceAlertCheckCycleEnum(int value, String info) { this.value = value; this.info = info; } public static List getInstanceAlertCheckCycleEnumList() { return instanceAlertCheckCycleEnumList; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertCompareTypeEnum.java ================================================ package com.sohu.cache.redis.enums; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 实例报警比较枚举 * @author leifu * @Date 2017年6月14日 * @Time 上午10:20:47 */ public enum InstanceAlertCompareTypeEnum { LESS_THAN(1, "小于"), EQUAL(2, "等于"), MORE_THAN(3, "大于"), NOT_EQUAL(4, "不等于"); private final static List instanceAlertCompareTypeEnumList = new ArrayList(); static { for (InstanceAlertCompareTypeEnum instanceAlertCompareTypeEnum : InstanceAlertCompareTypeEnum.values()) { instanceAlertCompareTypeEnumList.add(instanceAlertCompareTypeEnum); } } private final static Map instanceAlertCompareTypeEnumMap = new HashMap(); static { for (InstanceAlertCompareTypeEnum instanceAlertCompareTypeEnum : InstanceAlertCompareTypeEnum.values()) { instanceAlertCompareTypeEnumMap.put(instanceAlertCompareTypeEnum.getValue(), instanceAlertCompareTypeEnum); } } private int value; private String info; private InstanceAlertCompareTypeEnum(int value, String info) { this.value = value; this.info = info; } public static List getInstanceAlertCompareTypeEnumList() { return instanceAlertCompareTypeEnumList; } public static InstanceAlertCompareTypeEnum getInstanceAlertCompareTypeEnum(int value) { return instanceAlertCompareTypeEnumMap.get(value); } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertStatusEnum.java ================================================ package com.sohu.cache.redis.enums; /** * 实例报警有效性枚举 * @author leifu * @Date 2017年6月14日 * @Time 上午10:22:39 */ public enum InstanceAlertStatusEnum { YES(1, "有效"), NO(0, "无效"); private int value; private String info; private InstanceAlertStatusEnum(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/InstanceAlertTypeEnum.java ================================================ package com.sohu.cache.redis.enums; import java.util.ArrayList; import java.util.List; /** * 实例报警类型枚举 * @author leifu * @Date 2017年6月14日 * @Time 上午10:22:10 */ public enum InstanceAlertTypeEnum { ALL_ALERT(1, "全局报警"), INSTANCE_ALERT(2, "实例报警"), APP_ALERT(3, "应用报警"); private final static List instanceAlertTypeEnumList = new ArrayList(); static { for (InstanceAlertTypeEnum instanceAlertTypeEnum : InstanceAlertTypeEnum.values()) { instanceAlertTypeEnumList.add(instanceAlertTypeEnum); } } private int value; private String info; private InstanceAlertTypeEnum(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisAlertConfigEnum.java ================================================ package com.sohu.cache.redis.enums; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Redis报警配置枚举 * @author leifu * @Date 2017年6月13日 * @Time 下午5:34:42 */ public enum RedisAlertConfigEnum { aof_current_size("aof_current_size", "aof当前尺寸(单位:MB)"), minute_aof_delayed_fsync("aof_delayed_fsync", "分钟aof阻塞个数"), client_biggest_input_buf("client_biggest_input_buf", "输入缓冲区最大buffer大小(单位:MB)"), client_longest_output_list("client_longest_output_list", "输出缓冲区最大队列长度"), instantaneous_ops_per_sec("instantaneous_ops_per_sec", "实时ops"), latest_fork_usec("latest_fork_usec", "上次fork所用时间(单位:微秒)"), mem_fragmentation_ratio("mem_fragmentation_ratio", "内存碎片率(检测大于500MB)"), rdb_last_bgsave_status("rdb_last_bgsave_status", "上一次bgsave状态"), minute_rejected_connections("rejected_connections", "分钟拒绝连接数"), minute_sync_partial_err("sync_partial_err", "分钟部分复制失败次数"), minute_sync_partial_ok("sync_partial_ok", "分钟部分复制成功次数"), minute_sync_full("sync_full", "分钟全量复制执行次数"), minute_total_net_input_bytes("total_net_input_bytes", "分钟网络输入流量(单位:MB)"), minute_total_net_output_bytes("total_net_output_bytes", "分钟网络输出流量(单位:MB)"), master_slave_offset_diff("master_slave_offset_diff", "主从节点偏移量差(单位:字节)"), cluster_state("cluster_state", "集群状态"), cluster_slots_ok("cluster_slots_ok", "集群成功分配槽个数"), used_cpu_sys("used_cpu_sys","系统cpu消耗(单位:秒)"), used_cpu_user("used_cpu_user","用户cpu消耗(单位:秒)"), used_cpu_sys_children("used_cpu_sys_children","系统子进程cpu消耗(单位:秒)"), used_cpu_user_children("used_cpu_user_children","用户子进程cpu消耗(单位:秒)"), other_default_common_config("other_default_common_config","除上述之外的其他默认通用配置") ; private final static List redisAlertConfigEnumList = new ArrayList(); static { for (RedisAlertConfigEnum redisAlertConfigEnum : RedisAlertConfigEnum.values()) { redisAlertConfigEnumList.add(redisAlertConfigEnum); } } private final static Map redisAlertConfigEnumMap = new HashMap(); static { for (RedisAlertConfigEnum redisAlertConfigEnum : RedisAlertConfigEnum.values()) { redisAlertConfigEnumMap.put(redisAlertConfigEnum.getValue(), redisAlertConfigEnum); } } private String value; private String info; public static List getRedisAlertConfigEnumList() { return redisAlertConfigEnumList; } public static Map getRedisAlertConfigEnumMap() { return redisAlertConfigEnumMap; } public static RedisAlertConfigEnum getRedisAlertConfig(String alertConfig) { return redisAlertConfigEnumMap.get(alertConfig); } private RedisAlertConfigEnum(String value, String info) { this.value = value; this.info = info; } public String getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisClusterConfigEnum.java ================================================ package com.sohu.cache.redis.enums; /** * Created by yijunzhang on 14-8-25. */ public enum RedisClusterConfigEnum { CLUSTER_ENABLED("cluster-enabled", "yes", "是否开启集群模式"), CLUSTER_NODE_TIMEOUT("cluster-node-timeout", "15000", "集群节点超时时间,默认15秒"), CLUSTER_SLAVE_VALIDITY_FACTOR("cluster-slave-validity-factor", "10", "集群从节点,延迟有效性判断因子,默认10秒:(node-timeout * slave-validity-factor) + repl-ping-slave-period"), CLUSTER_MIGRATION_BARRIER("cluster-migration-barrier", "1", "cluster主从迁移至少需要的从节点数,默认1个"), CLUSTER_CONFIG_FILE("cluster-config-file", "nodes-%d.conf", "集群配置文件名称,格式:nodes-{port}.conf"), CLUSTER_REQUIRE_FULL_COVERAGE("cluster-require-full-coverage", "no", "节点部分失败期间,其他节点是否继续工作"); private String key; private String value; private String desc; RedisClusterConfigEnum(String key, String value, String desc) { this.key = key; this.value = value; this.desc = desc; } public String getValue() { return value; } public String getDesc() { return desc; } public String getKey() { return key; } public static RedisClusterConfigEnum get(String key) { if (key == null) { return null; } for (RedisClusterConfigEnum config : RedisClusterConfigEnum.values()) { if (config.key.equals(key)) { return config; } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisClusterInfoEnum.java ================================================ package com.sohu.cache.redis.enums; /** * cluster info枚举 * @author leifu * @Date 2017年6月21日 * @Time 下午2:36:47 */ public enum RedisClusterInfoEnum { cluster_state("cluster_state", "集群状态", false), cluster_slots_assigned("cluster_slots_assigned", "分配slot个数", false), cluster_slots_ok("cluster_slots_ok", "成功分配slot个数", false), cluster_slots_pfail("cluster_slots_pfail", "pfail个数", false), cluster_slots_fail("cluster_slots_fail", "fail个数", false), cluster_stats_messages_sent("cluster_stats_messages_sent", "发送消息字节数", false), cluster_stats_messages_received("cluster_stats_messages_received", "接收消息字节数", false), ; private String value; private String info; private boolean needCalDif; private RedisClusterInfoEnum(String value, String info, boolean needCalDif) { this.value = value; this.info = info; this.needCalDif = needCalDif; } public String getValue() { return value; } public String getInfo() { return info; } public boolean isNeedCalDif() { return needCalDif; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisConfigEnum.java ================================================ package com.sohu.cache.redis.enums; import com.sohu.cache.protocol.MachineProtocol; /** * Created by yijunzhang on 14-7-27. */ public enum RedisConfigEnum { DAEMONIZE("daemonize", "no", "是否守护进程"), TCP_BACKLOG("tcp-backlog", "511", "TCP连接完成队列"), TIMEOUT("timeout", "0", "客户端闲置多少秒后关闭连接,默认为0,永不关闭"), TCP_KEEPALIVE("tcp-keepalive", "0", "检测客户端是否健康周期,默认关闭"), LOGLEVEL("loglevel", "notice", "默认普通的verbose"), DATABASES("databases", "16", "可用的数据库数,默认值为16个,默认数据库为0"), DIR("dir", MachineProtocol.DATA_DIR, "redis工作目录,默认:" + MachineProtocol.DATA_DIR), STOP_WRITES_ON_BGSAVE_ERROR("stop-writes-on-bgsave-error", "no", "bgsave出错了不停写"), REPL_TIMEOUT("repl-timeout", "60", "master批量数据传输时间或者ping回复时间间隔,默认:60秒"), REPL_PING_SLAVE_PERIOD("repl-ping-slave-period", "10", "指定slave定期ping master的周期,默认:10秒"), REPL_DISABLE_TCP_NODELAY("repl-disable-tcp-nodelay", "no", "是否禁用socket的NO_DELAY,默认关闭,影响主从延迟"), REPL_BACKLOG_SIZE("repl-backlog-size", "10M", "复制缓存区,默认:1mb,配置为:10Mb"), REPL_BACKLOG_TTL("repl-backlog-ttl", "7200", "master在没有Slave的情况下释放BACKLOG的时间多久:默认:3600,配置为:7200"), SLAVE_SERVE_STALE_DATA("slave-serve-stale-data", "yes", "当slave服务器和master服务器失去连接后,或者当数据正在复制传输的时候,如果此参数值设置“yes”,slave服务器可以继续接受客户端的请求"), SLAVE_READ_ONLY("slave-read-only", "yes", "slave服务器节点是否只读,cluster的slave节点默认读写都不可用,需要调用readonly开启可读模式"), SLAVE_PRIORITY("slave-priority", "100", "slave的优先级,影响sentinel/cluster晋升master操作,0永远不晋升"), LUA_TIME_LIMIT("lua-time-limit", "5000", "Lua脚本最长的执行时间,单位为毫秒"), SLOWLOG_LOG_SLOWER_THAN("slowlog-log-slower-than", "10000", "慢查询被记录的阀值,默认10毫秒"), SLOWLOG_MAX_LEN("slowlog-max-len", "128", "最多记录慢查询的条数"), HASH_MAX_ZIPLIST_ENTRIES("hash-max-ziplist-entries", "512", "hash数据结构优化参数"), HASH_MAX_ZIPLIST_VALUE("hash-max-ziplist-value", "64", "hash数据结构优化参数"), LIST_MAX_ZIPLIST_ENTRIES("list-max-ziplist-entries", "512", "list数据结构优化参数"), LIST_MAX_ZIPLIST_VALUE("list-max-ziplist-value", "64", "list数据结构优化参数"), SET_MAX_INTSET_ENTRIES("set-max-intset-entries", "512", "set数据结构优化参数"), ZSET_MAX_ZIPLIST_ENTRIES("zset-max-ziplist-entries", "128", "zset数据结构优化参数"), ZSET_MAX_ZIPLIST_VALUE("zset-max-ziplist-value", "64", "zset数据结构优化参数"), ACTIVEREHASHING("activerehashing", "yes", "是否激活重置哈希,默认:yes"), CLIENT_OUTPUT_BUFFER_LIMIT_NORMAL("client-output-buffer-limit normal", "0 0 0", ""), CLIENT_OUTPUT_BUFFER_LIMIT_SLAVE("client-output-buffer-limit slave", "512mb 128mb 60", ""), CLIENT_OUTPUT_BUFFER_LIMIT_PUBSUB("client-output-buffer-limit pubsub", "32mb 8mb 60", ""), HZ("hz", "10", "执行后台task数量,默认:10"), PORT("port", "%d", "端口"), MAXMEMORY("maxmemory", "%dmb", "当前实例最大可用内存"), MAXMEMORY_POLICY("maxmemory-policy", "volatile-lru", "内存不够时,淘汰策略,默认:volatile-lru"), REQUIREPASS("requirepass", "", "密码"), MASTERAUTH("masterauth", "", "从节点需要配置的主节点密码"), AUTH_PASS("auth-pass", "", "sentinel节点需要配置的主节点密码"), APPENDONLY("appendonly", "yes", "开启append only持久化模式"), APPENDFSYNC("appendfsync", "everysec", "默认:aof每秒同步一次"), APPENDFILENAME("appendfilename", "appendonly-%d.aof", "aof文件名称,默认:appendonly-{port}.aof"), DBFILENAME("dbfilename", "dump-%d.rdb", "RDB文件默认名称,默认dump-{port}.rdb"), AOF_REWRITE_INCREMENTAL_FSYNC("aof-rewrite-incremental-fsync","yes","aof rewrite过程中,是否采取增量文件同步策略,默认:yes"), NO_APPENDFSYNC_ON_REWRITE("no-appendfsync-on-rewrite", "yes", "是否在后台aof文件rewrite期间调用fsync,默认调用,修改为yes,防止可能fsync阻塞,但可能丢失rewrite期间的数据"), AUTO_AOF_REWRITE_MIN_SIZE("auto-aof-rewrite-min-size", "64m", "触发rewrite的aof文件最小阀值,默认64m"), AUTO_AOF_REWRITE_PERCENTAGE("auto-aof-rewrite-percentage", "%d", "Redis重写aof文件的比例条件,默认从100开始,统一机器下不同实例按4%递减"), BIND("bind", "0.0.0.0", "设置绑定内网ip"); private String key; private String value; private String desc; RedisConfigEnum(String key, String value, String desc) { this.key = key; this.value = value; this.desc = desc; } public String getValue() { return value; } public String getDesc() { return desc; } public String getKey() { return key; } public static RedisConfigEnum get(String key) { if (key == null) { return null; } for (RedisConfigEnum config : RedisConfigEnum.values()) { if (config.key.equals(key)) { return config; } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisInfoEnum.java ================================================ package com.sohu.cache.redis.enums; import java.util.ArrayList; import java.util.List; import com.sohu.cache.constant.RedisConstant; /** * Redis报警配置枚举 * @author leifu * @Date 2017年6月13日 * @Time 下午5:34:42 */ public enum RedisInfoEnum { /** * Stats */ client_biggest_input_buf(RedisConstant.Stats, "client_biggest_input_buf", "输入缓冲区最大buffer大小(单位:字节)", false), client_longest_output_list(RedisConstant.Stats, "client_longest_output_list", "输出缓冲区最大队列长度", false), instantaneous_ops_per_sec(RedisConstant.Stats, "instantaneous_ops_per_sec", "实时ops", false), rejected_connections(RedisConstant.Stats, "rejected_connections", "拒绝客户端连接数", true), sync_partial_err(RedisConstant.Stats, "sync_partial_err", "部分复制失败次数", true), sync_partial_ok(RedisConstant.Stats, "sync_partial_ok", "部分复制成功次数", true), sync_full(RedisConstant.Stats, "sync_full", "全量复制执行次数", true), total_net_input_bytes(RedisConstant.Stats, "total_net_input_bytes", "网络输入流量(单位:字节)", true), total_net_output_bytes(RedisConstant.Stats, "total_net_output_bytes", "网络输出流量(单位:字节)", true), keyspace_hits(RedisConstant.Stats, "keyspace_hits", "键命中数", true), keyspace_misses(RedisConstant.Stats, "keyspace_misses", "键未命中数", true), evicted_keys(RedisConstant.Stats, "evicted_keys", "键剔除数", true), expired_keys(RedisConstant.Stats, "expired_keys", "键过期数", true), connected_clients(RedisConstant.Clients, "connected_clients", "客户端连接数", false), /** * Persistence */ aof_current_size(RedisConstant.Persistence, "aof_current_size", "aof当前尺寸(单位:字节)", false), aof_base_size(RedisConstant.Persistence, "aof_base_size", "aof基准尺寸(单位:字节)", false), aof_delayed_fsync(RedisConstant.Persistence, "aof_delayed_fsync", "aof阻塞次数", true), latest_fork_usec(RedisConstant.Persistence, "latest_fork_usec", "上次fork所用时间(单位:微秒)", false), rdb_last_bgsave_status(RedisConstant.Persistence, "rdb_last_bgsave_status", "上一次bgsave状态", false), rdb_bgsave_in_progress(RedisConstant.Persistence, "rdb_bgsave_in_progress", "是否正在进行bgsave", false), rdb_last_save_time(RedisConstant.Persistence, "rdb_last_save_time", "上一次bgsave时间", false), rdb_last_bgsave_time_sec(RedisConstant.Persistence, "rdb_last_bgsave_time_sec", "上一次bgsave花费时间", false), loading(RedisConstant.Persistence, "loading", "指示是否正在进行dump(rdb/aof)文件加载", false), loading_eta_seconds(RedisConstant.Persistence, "loading_eta_seconds", "dump加载完成预计完成时间(秒)", false), /** * CPU */ used_cpu_sys(RedisConstant.CPU, "used_cpu_sys", "redis进程系统态消耗(单位-秒)", true), used_cpu_user(RedisConstant.CPU, "used_cpu_user", "redis进程用户态消耗(单位-秒)", true), used_cpu_sys_children(RedisConstant.CPU, "used_cpu_sys_children", "redis子进程系统态消耗(单位-秒)", true), used_cpu_user_children(RedisConstant.CPU, "used_cpu_user_children", "redis子进程用户态消耗(单位-秒)", true), /** * Memory */ used_memory(RedisConstant.Memory, "used_memory", "内存使用(单位:字节)", false), used_memory_rss(RedisConstant.Memory, "used_memory_rss", "物理内存使用(单位:字节)", false), mem_fragmentation_ratio(RedisConstant.Memory, "mem_fragmentation_ratio", "内存碎片率", false), /** * Replication */ role(RedisConstant.Replication, "role", "主从角色", false), master_host(RedisConstant.Replication, "master_host", "主节点host", false), master_port(RedisConstant.Replication, "master_port", "主节点端口", false), connected_slaves(RedisConstant.Replication, "connected_slaves", "从节点数量", false), master_repl_offset(RedisConstant.Replication, "master_repl_offset", "主节点偏移量", false), master_link_status(RedisConstant.Replication, "master_link_status", "主节点连接状态", false), slave_repl_offset(RedisConstant.Replication, "slave_repl_offset", "从节点偏移量", false), master_sync_in_progress(RedisConstant.Replication, "master_sync_in_progress", "从节点是否正在同步主节点", false) ; private final static List RedisInfoEnumList = new ArrayList(); static { for (RedisInfoEnum redisInfoEnum : RedisInfoEnum.values()) { RedisInfoEnumList.add(redisInfoEnum); } } private RedisConstant redisConstant; private String value; private String info; private boolean needCalDif; private RedisInfoEnum(RedisConstant redisConstant, String value, String info, boolean needCalDif) { this.redisConstant = redisConstant; this.value = value; this.info = info; this.needCalDif = needCalDif; } /** * 获取需要计算差值的统计属性 * @return */ public static List getNeedCalDifRedisInfoEnumList() { List resultList = new ArrayList(); for (RedisInfoEnum redisInfoEnum : RedisInfoEnumList) { if (redisInfoEnum.isNeedCalDif()) { resultList.add(redisInfoEnum); } } return resultList; } public RedisConstant getRedisConstant() { return redisConstant; } public String getValue() { return value; } public String getInfo() { return info; } public boolean isNeedCalDif() { return needCalDif; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisReadOnlyCommandEnum.java ================================================ package com.sohu.cache.redis.enums; import com.sohu.cache.constant.SymbolConstant; import org.apache.commons.lang.StringUtils; /** * Created by yijunzhang on 14-10-14. */ public enum RedisReadOnlyCommandEnum { // debug("debug"), //去除debug命令 exists("exists"), object("object"), ttl("ttl"), type("type"), scan("scan"), get("get"), getbit("getbit"), getrange("getrange"), mget("mget"), setrange("setrange"), strlen("strlen"), hexists("hexists"), hget("hget"), hgetall("hgetall"), hkeys("hkeys"), hlen("hlen"), hmget("hmget"), hvals("hvals"), hscan("hscan"), lindex("lindex"), llen("llen"), lrange("lrange"), scard("scard"), sismember("sismember"), sscan("sscan"), srandmember("srandmember"), zcard("zcard"), zcount("zcount"), zrange("zrange"), zrangebyscore("zrangebyscore"), zrank("zrank"), zrevrange("zrevrange"), zscore("zscore"), zscan("zscan"), dbsize("dbsize"), info("info"), time("time"), lastsave("lastsave"), memory("memory"), JSON_GET("JSON.GET"), JSON_MGET("JSON.MGET"), JSON_ARRLEN("JSON.ARRLEN"), JSON_DEBUG_MEMORY("JSON.DEBUGMEMORY"), JSON_OBJKEYS("JSON.OBJKEYS"), JSON_OBJLEN("JSON.OBJLEN"), JSON_RESP("JSON.RESP"), JSON_TOGGLE("JSON.TOGGLE"), JSON_TYPE("JSON.TYPE"), FT_LIST("FT._LIST"), FT_CONFIG_GET("FT.CONFIGGET"), FT_EXPLAIN("FT.EXPLAIN"), FT_EXPLAINCLI("FT.EXPLAINCLI"), FT_INFO("FT.INFO"), FT_CURSOR_READ("FT.CURSORREAD"), FT_DICTDUMP("FT.DICTDUMP"), FT_SEARCH("FT.SEARCH"), FT_AGGREGATE("FT.AGGREGATE"), FT_PROFILE("FT.PROFILE"), FT_SYNDUMP("FT.SYNDUMP"), FT_TAGVALS("FT.TAGVALS"), BF_EXISTS("BF.EXISTS"), BF_MEXISTS("BF.MEXISTS"), BF_INFO("BF.INFO"), CF_COUNT("CF.COUNT"), CF_EXISTS("CF.EXISTS"), CF_INFO("CF.INFO"), CF_MEXISTS("CF.MEXISTS"), CMS_INFO("CMS.INFO"), CMS_QUERY("CMS.QUERY"); private String command; RedisReadOnlyCommandEnum(String command){ this.command = command; } public String getCommand() { return command; } public static boolean contains(String command) { if (StringUtils.isBlank(command)) { return false; } for (RedisReadOnlyCommandEnum readEnum : RedisReadOnlyCommandEnum.values()) { String readCommand = readEnum.getCommand(); command = StringUtils.remove(command, SymbolConstant.SPACE); if (command.length() < readCommand.toString().length()) { continue; } String head = StringUtils.substring(command, 0, readCommand.length()); if (readCommand.equalsIgnoreCase(head)) { return true; } } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/enums/RedisSentinelConfigEnum.java ================================================ package com.sohu.cache.redis.enums; /** * Created by yijunzhang on 14-8-25. */ public enum RedisSentinelConfigEnum { PORT("port", "%d", "sentinel实例端口"), DIR("dir", "/tmp", "文件目录"), MONITOR("sentinel monitor", "%s %s %d %d", "master名称定义和最少参与监控的sentinel数,格式:masterName ip port num"), DOWN_AFTER_MILLISECONDS("sentinel down-after-milliseconds", "%s 20000", "Sentinel判定服务器断线的毫秒数,默认:20秒"), FAILOVER_TIMEOUT("sentinel failover-timeout", "%s 180000", "故障迁移超时时间,默认:3分钟"), PARALLEL_SYNCS("sentinel parallel-syncs", "%s 1", "在执行故障转移时,最多有多少个从服务器同时对新的主服务器进行同步,默认:1"); private String key; private String value; private String desc; RedisSentinelConfigEnum(String key, String value, String desc) { this.key = key; this.value = value; this.desc = desc; } public String getValue() { return value; } public String getDesc() { return desc; } public String getKey() { return key; } public static RedisSentinelConfigEnum get(String key) { if (key == null) { return null; } for (RedisSentinelConfigEnum config : RedisSentinelConfigEnum.values()) { if (config.key.equals(key)) { return config; } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/impl/AssistRedisServiceImpl.java ================================================ package com.sohu.cache.redis.impl; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.util.Command; import com.sohu.cache.redis.util.ProtostuffSerializer; import org.apache.commons.lang.StringUtils; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.Protocol; import redis.clients.jedis.Tuple; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.params.SetParams; import redis.clients.jedis.util.SafeEncoder; import javax.annotation.PostConstruct; import java.nio.charset.Charset; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @Component public class AssistRedisServiceImpl implements AssistRedisService { private Logger logger = LoggerFactory.getLogger(AssistRedisServiceImpl.class); @Value("${cachecloud.redis.main.host:127.0.0.1}") private String mainHost; @Value("${cachecloud.redis.main.port:6379}") private int mainPort; @Value("${cachecloud.redis.main.password:}") private String mainPassword; private JedisPool jedisPoolMain; private ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer(); @PostConstruct public void init() { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); if(StringUtils.isNotBlank(mainPassword)){ jedisPoolMain = new JedisPool(config, mainHost, mainPort, Protocol.DEFAULT_TIMEOUT, mainPassword); }else{ logger.error("The assist redis password is not configured, please confirm and strongly recommend config it."); jedisPoolMain = new JedisPool(config, mainHost, mainPort, Protocol.DEFAULT_TIMEOUT); } } /** * low版本,应该用vip或者hystrix,这里是以防万一 * * @return */ private Jedis getFromJedisPool() throws Exception{ try { return jedisPoolMain.getResource(); } catch (JedisConnectionException ce){ logger.warn("Please Make sure the file:application-${profile}.yml connection pool is configured correctly ! cachecloud.redis.main.host:{} cachecloud.redis.main.port:{} cachecloud.redis.main.password:{}",mainHost,mainPort,mainPassword); throw ce; } catch (Exception e) { logger.warn(e.getMessage(),e); throw e; } } @Override public boolean rpush(String key, String item) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.rpush(key, item); return true; } catch (Exception e) { logger.warn("rpush {} {} error " + e.getMessage(), key, item, e); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean rpush(String key, String... items) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.rpush(key, items); return true; } catch (Exception e) { logger.warn("rpush {} {} error " + e.getMessage(), key, items, e); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public List lrange(String key, int start, int end) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.lrange(key, start, end); } catch (Exception e) { logger.warn("lrange {} {} {} error " + e.getMessage(), key, start, end); return Collections.emptyList(); } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean rpushList(String key, List items) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.rpush(key, items.toArray(new String[items.size()])); return true; } catch (Exception e) { logger.warn("rpushList {} {} error " + e.getMessage(), key, items); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public Long llen(final String key){ Jedis jedis = null; try { jedis = getFromJedisPool(); Long llen = jedis.llen(key); return llen; } catch (Exception e) { logger.warn("llen {} {} error " + e.getMessage(), key); return 0L; } finally { if (jedis != null) { jedis.close(); } } } @Override public String lpop(final String key){ Jedis jedis = null; try { jedis = getFromJedisPool(); String lpop = jedis.lpop(key); return lpop; } catch (Exception e) { logger.warn("rpushList {} {} error " + e.getMessage(), key); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public Long lrem(final String key, long count, String element){ Jedis jedis = null; try { jedis = getFromJedisPool(); Long lrem = jedis.lrem(key, count, element); return lrem; } catch (Exception e) { logger.warn("lrem {} {} {} error " + e.getMessage(), key, count, element); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public String ltrim(final String key, long start, long end){ Jedis jedis = null; try { jedis = getFromJedisPool(); String lrem = jedis.ltrim(key, start, end); return lrem; } catch (Exception e) { logger.warn("ltrim {} {} {} error " + e.getMessage(), key, start, end); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean saddSet(String key, Set items) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.sadd(key, items.toArray(new String[items.size()])); return true; } catch (Exception e) { logger.warn("saddList {} {} error " + e.getMessage(), key, items); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean sadd(String key, String item) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.sadd(key, item); return true; } catch (Exception e) { logger.warn("sadd {} {} error " + e.getMessage(), key, item); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public Set smembers(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.smembers(key); } catch (Exception e) { logger.warn("smembers {} error " + e.getMessage(), key); return Collections.emptySet(); } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean srem(String key, String item) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.srem(key, item); return true; } catch (Exception e) { logger.warn("srem {} {} error " + e.getMessage(), key, item); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean reloadSentinel() { return false; } @Override public boolean set(String key, T value) { if (value == null) { return false; } byte[] bytes = protostuffSerializer.serialize(value); Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.set(key.getBytes(Charset.forName("UTF-8")), bytes); return true; } catch (Exception e) { logger.warn("set {} error " + e.getMessage(), key, e); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean set(String key, T value, int seconds) { if (value == null) { return false; } byte[] bytes = protostuffSerializer.serialize(value); Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.setex(key.getBytes(Charset.forName("UTF-8")), seconds, bytes); return true; } catch (Exception e) { logger.warn("setex {} {} error " + e.getMessage(), key, seconds); return false; } finally { if (jedis != null) { jedis.close(); } } } public boolean setNx(String key, String value) { Jedis jedis = null; Long result = 0l; try { jedis = getFromJedisPool(); result = jedis.setnx(key, value); } catch (Exception e) { logger.warn("setnx {} {} error:{} ", key, value, e.getMessage()); } finally { if (jedis != null) { jedis.close(); } } return result == 1 ? true : false; } public String set(String key, String value, SetParams params) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.set(key, value, params); } catch (Exception e) { logger.warn("set {} {} {} error " + e.getMessage(), key, value, params); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean setWithNoSerialize(String key, T value) { if (value == null) { return false; } Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.set(key, value.toString()); return true; } catch (Exception e) { logger.warn("setWithNoSerialize {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean setWithNoSerialize(String key, T value, int seconds) { if (value == null) { return false; } Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.setex(key, seconds, value.toString()); return true; } catch (Exception e) { logger.warn("setWithNoSerialize {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public String getWithNoSerialize(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.get(key); } catch (Exception e) { logger.warn("getWithNoSerialize {} error " + e.getMessage(), key); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean remove(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.del(key); return true; } catch (Exception e) { logger.warn("remove {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean zadd(String key, long score, String member) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.zadd(key, score, member); return true; } catch (Exception e) { logger.warn("zadd {} {} {} error " + e.getMessage(), key, score, member); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public String hget(String key, String field){ Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.hget(key, field); } catch (Exception e) { logger.warn("hget {} {} error " + e.getMessage(), key, field); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean hset(String key, String field, String value) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.hset(key, field, value); return true; } catch (Exception e) { logger.warn("hset {} {} {} error " + e.getMessage(), key, field, value); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public Long hsetnx(String key, String field, String value){ Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.hsetnx(key, field, value); } catch (Exception e) { logger.warn("hsetnx {} {} {} error " + e.getMessage(), key, field, value); return 0L; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean hmset(String key, Map map) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.hmset(key, map); return true; } catch (Exception e) { logger.warn("hset {} {} error " + e.getMessage(), key, map); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public Map hgetAll(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.hgetAll(key); } catch (Exception e) { logger.warn("hgetAll {} error " + e.getMessage(), key); return Collections.emptyMap(); } finally { if (jedis != null) { jedis.close(); } } } @Override public Long hdel(String key, String field) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.hdel(key, field); } catch (Exception e) { logger.warn("hdel {} error " + e.getMessage(), key); return 0L; } finally { if (jedis != null) { jedis.close(); } } } @Override public T get(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); byte[] bytes = jedis.get(key.getBytes(Charset.forName("UTF-8"))); if (bytes == null) { return null; } T t = protostuffSerializer.deserialize(bytes); return t; } catch (Exception e) { logger.warn("get {} error " + e.getMessage(), key); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean del(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.del(key); return true; } catch (Exception e) { logger.warn("del {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean delMulti(String... keys) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.del(keys); return true; } catch (Exception e) { logger.warn("delMulti {} error " + e.getMessage(), keys); return false; } finally { if (jedis != null) { jedis.close(); } } } @Override public void zincrby(String key, double score, String member) { Jedis jedis = null; try { jedis = getFromJedisPool(); jedis.zincrby(key, score, member); } catch (Exception e) { logger.warn("zincrby {} {} {} error " + e.getMessage(), key, score, member); } finally { if (jedis != null) { jedis.close(); } } } @Override public Set zrangeWithScores(String key, long start, long end) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.zrangeWithScores(key, start, end); } catch (Exception e) { logger.warn("zrangeWithScores {} {} {}error " + e.getMessage(), key, start, end); return null; } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean exists(String key) { Jedis jedis = null; try { jedis = getFromJedisPool(); return jedis.exists(key); } catch (Exception e) { logger.warn("del {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } public void setProtostuffSerializer(ProtostuffSerializer protostuffSerializer) { this.protostuffSerializer = protostuffSerializer; } @Override public boolean setNEX(String key, String value, int seconds) { Jedis jedis = null; try { jedis = getFromJedisPool(); Object rst = jedis.sendCommand(Command.SET, key, value, "NX", "EX", String.valueOf(seconds)); if(rst != null){ String encode = SafeEncoder.encode((byte[]) rst); if("OK".equals(encode)){ return true; } } return false; } catch (Exception e) { logger.warn("smembers {} error " + e.getMessage(), key); return false; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/impl/RedisCenterImpl.java ================================================ package com.sohu.cache.redis.impl; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.*; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.redis.enums.RedisInfoEnum; import com.sohu.cache.redis.enums.RedisReadOnlyCommandEnum; import com.sohu.cache.redis.util.*; import com.sohu.cache.report.ReportDataComponent; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.util.*; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.ClientTypeEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.service.WebClientComponent; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.vo.RedisSlowLog; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisSentinelPool; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Protocol; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.exceptions.JedisAskDataException; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.exceptions.JedisMovedDataException; import redis.clients.jedis.util.SafeEncoder; import redis.clients.jedis.util.Slowlog; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.sql.Timestamp; import java.text.DecimalFormat; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; /** * Created by yijunzhang on 14-6-10. */ @Service("redisCenter") public class RedisCenterImpl implements RedisCenter { public static final int REDIS_DEFAULT_TIME = 1000; public static final String REDIS_SLOWLOG_POOL = "redis-slowlog-pool"; private static final int COUNT = 1000; private static List otherNeedCalDifRedisInfoEnumList = new ArrayList<>(); private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final Lock lock = new ReentrantLock(); @Autowired private AppStatsDao appStatsDao; @Autowired private AsyncService asyncService; @Autowired private InstanceDao instanceDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired private InstanceStatsCenter instanceStatsCenter; @Autowired @Lazy private MachineCenter machineCenter; private volatile Map jedisPoolMap = new HashMap(); @Autowired private AppDao appDao; @Autowired private AppAuditLogDao appAuditLogDao; @Autowired private AppService appService; @Autowired private InstanceSlowLogDao instanceSlowLogDao; @Autowired private InstanceLatencyHistoryDao instanceLatencyHistoryDao; @Autowired private WebClientComponent webClientComponent; @Autowired SSHService sshService; @Autowired private ReportDataComponent reportDataComponent; @PostConstruct public void init() { asyncService.assemblePool(getThreadPoolKey(), AsyncThreadPoolFactory.REDIS_SLOWLOG_THREAD_POOL); otherNeedCalDifRedisInfoEnumList.add(RedisInfoEnum.mem_fragmentation_ratio); } private JedisPool maintainJedisPool(String host, int port, String password) { String hostAndPort = ObjectConvert.linkIpAndPort(host, port); JedisPool jedisPool = jedisPoolMap.get(hostAndPort); if (jedisPool == null) { lock.lock(); try { //double check jedisPool = jedisPoolMap.get(hostAndPort); if (jedisPool == null) { try { if (StringUtils.isNotBlank(password)) { jedisPool = new JedisPool(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT, password); } else { jedisPool = new JedisPool(new GenericObjectPoolConfig(), host, port, Protocol.DEFAULT_TIMEOUT); } jedisPoolMap.put(hostAndPort, jedisPool); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { } } } finally { lock.unlock(); } } return jedisPool; } private String buildFutureKey(long appId, long collectTime, String host, int port) { StringBuilder keyBuffer = new StringBuilder("redis-"); keyBuffer.append(collectTime); keyBuffer.append("-"); keyBuffer.append(appId); keyBuffer.append("-"); keyBuffer.append(host + ":" + port); return keyBuffer.toString(); } @Override public List collectRedisSlowLog(long appId, long collectTime, String host, int port) { Assert.isTrue(appId > 0); Assert.hasText(host); Assert.isTrue(port > 0); InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(host, port); //不存在实例/实例异常/下线 if (instanceInfo == null) { return null; } if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { //忽略sentinel redis实例 return null; } // 从redis中获取慢查询日志 List redisLowLogList = getRedisSlowLogs(appId, host, port, 100); if (CollectionUtils.isEmpty(redisLowLogList)) { return Collections.emptyList(); } // transfer final List instanceSlowLogList = new ArrayList(); for (RedisSlowLog redisSlowLog : redisLowLogList) { InstanceSlowLog instanceSlowLog = transferRedisSlowLogToInstance(redisSlowLog, instanceInfo); if (instanceSlowLog == null) { continue; } instanceSlowLogList.add(instanceSlowLog); } if (CollectionUtils.isEmpty(instanceSlowLogList)) { return Collections.emptyList(); } //处理 String key = getThreadPoolKey() + "_" + host + "_" + port; boolean isOk = asyncService.submitFuture(getThreadPoolKey(), new KeyCallable(key) { @Override public Boolean execute() { try { instanceSlowLogDao.batchSave(instanceSlowLogList); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); if (!isOk) { logger.error("slowlog submitFuture failed,appId:{},collectTime:{},host:{},port:{}", appId, collectTime, host, port); } return instanceSlowLogList; } private InstanceSlowLog transferRedisSlowLogToInstance(RedisSlowLog redisSlowLog, InstanceInfo instanceInfo) { if (redisSlowLog == null) { return null; } String command = redisSlowLog.getCommand(); long executionTime = redisSlowLog.getExecutionTime(); //如果command=BGREWRITEAOF并且小于50毫秒,则忽略 if (command.equalsIgnoreCase("BGREWRITEAOF") && executionTime < 50000) { return null; } InstanceSlowLog instanceSlowLog = new InstanceSlowLog(); instanceSlowLog.setAppId(instanceInfo.getAppId()); instanceSlowLog.setCommand(redisSlowLog.getCommand()); instanceSlowLog.setCostTime((int) redisSlowLog.getExecutionTime()); instanceSlowLog.setCreateTime(new Timestamp(System.currentTimeMillis())); instanceSlowLog.setExecuteTime(new Timestamp(redisSlowLog.getDate().getTime())); instanceSlowLog.setInstanceId(instanceInfo.getId()); instanceSlowLog.setIp(instanceInfo.getIp()); instanceSlowLog.setPort(instanceInfo.getPort()); instanceSlowLog.setSlowLogId(redisSlowLog.getId()); return instanceSlowLog; } private String getThreadPoolKey() { return REDIS_SLOWLOG_POOL; } @Override public Map> collectRedisInfo(long appId, long collectTime, String host, int port) { long start = System.currentTimeMillis(); InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(host, port); //不存在实例/实例异常/下线 if (instanceInfo == null) { return null; } if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { //忽略sentinel redis实例 return null; } Map> infoMap = this.getInfoStats(appId, host, port); if (infoMap == null || infoMap.isEmpty()) { logger.error("appId:{},collectTime:{},host:{},port:{} cost={} ms redis infoMap is null", new Object[]{appId, collectTime, host, port, (System.currentTimeMillis() - start)}); return infoMap; } //上报数据 Map redisInfoMap = new HashMap<>(); redisInfoMap.put("instanceInfo", instanceInfo); redisInfoMap.put("collectTime", collectTime); redisInfoMap.put("info", infoMap); reportDataComponent.reportRedisInfoData(redisInfoMap); // cluster info统计 Map clusterInfoMap = getClusterInfoStats(appId, instanceInfo); boolean isOk = asyncService .submitFuture(new RedisKeyCallable(appId, collectTime, host, port, infoMap, clusterInfoMap)); if (!isOk) { logger.error("submitFuture failed,appId:{},collectTime:{},host:{},port:{} cost={} ms", new Object[]{appId, collectTime, host, port, (System.currentTimeMillis() - start)}); } return infoMap; } @Override public Map> getInfoStats(final long appId, final String host, final int port) { Map> infoMap = null; final StringBuilder infoBuilder = new StringBuilder(); try { boolean isOk = new IdempotentConfirmer() { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { jedis = getJedis(appId, host, port); jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); String info = jedis.info("all"); infoBuilder.append(info); return StringUtils.isNotBlank(info); } catch (Exception e) { logger.warn("{}:{}, redis-getInfoStats errorMsg:{}", host, port, e.getMessage()); return false; } finally { if (jedis != null) jedis.close(); } } }.run(); if (!isOk) { return infoMap; } infoMap = processRedisStats(infoBuilder.toString()); } catch (Exception e) { logger.error(e.getMessage() + " {}:{}", host, port, e); } if (infoMap == null || infoMap.isEmpty()) { logger.error("host:{},port:{} redis infoMap is null", host, port); return infoMap; } return infoMap; } @Override public Map getClusterInfoStats(final long appId, final String host, final int port) { InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port); return getClusterInfoStats(appId, instanceInfo); } @Override public Map getClusterInfoStats(final long appId, final InstanceInfo instanceInfo) { long startTime = System.currentTimeMillis(); if (instanceInfo == null) { logger.warn("getClusterInfoStats instanceInfo is null"); return Collections.emptyMap(); } if (!TypeUtil.isRedisCluster(instanceInfo.getType())) { return Collections.emptyMap(); } final String host = instanceInfo.getIp(); final int port = instanceInfo.getPort(); Map clusterInfoMap = null; final StringBuilder infoBuilder = new StringBuilder(); try { boolean isOk = new IdempotentConfirmer() { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { jedis = getJedis(appId, host, port); jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); String clusterInfo = jedis.clusterInfo(); infoBuilder.append(clusterInfo); return StringUtils.isNotBlank(clusterInfo); } catch (Exception e) { logger.warn("{}:{}, redis-getInfoStats errorMsg:{}", host, port, e.getMessage()); return false; } finally { if (jedis != null) jedis.close(); } } }.run(); if (!isOk) { return clusterInfoMap; } clusterInfoMap = processClusterInfoStats(infoBuilder.toString()); } catch (Exception e) { logger.error(e.getMessage() + " {}:{}", host, port, e); } if (MapUtils.isEmpty(clusterInfoMap)) { logger.error("{}:{} redis clusterInfoMap is null", host, port); return Collections.emptyMap(); } long costTime = System.currentTimeMillis() - startTime; if (costTime > 1000) { logger.warn("{}:{} cluster info cost time {} ms", host, port, costTime); } return clusterInfoMap; } private void fillAccumulationMap(Map> infoMap, Table table) { if (table == null || table.isEmpty()) { return; } Map accMap = infoMap.get(RedisConstant.DIFF); if (accMap == null) { accMap = new LinkedHashMap(); infoMap.put(RedisConstant.DIFF, accMap); } for (RedisConstant constant : table.rowKeySet()) { Map rowMap = table.row(constant); accMap.putAll(rowMap); } } private void fillDoubleAccumulationMap(Map> infoMap, Table table) { if (table == null || table.isEmpty()) { return; } Map accMap = infoMap.get(RedisConstant.DIFF); if (accMap == null) { accMap = new LinkedHashMap(); infoMap.put(RedisConstant.DIFF, accMap); } for (RedisConstant constant : table.rowKeySet()) { Map rowMap = table.row(constant); accMap.putAll(rowMap); } } /** * 内存碎片率统计最新值,不计算差值 */ private void fillMemFragRatioMap(Map> infoMap) { Map currentMap = new LinkedHashMap<>(); RedisInfoEnum acc = RedisInfoEnum.mem_fragmentation_ratio; Double count = getDoubleCount(infoMap, acc.getRedisConstant(), acc.getValue()); if (count != null) { currentMap.put(acc.getValue(), count); } //DecimalFormat df = new DecimalFormat("##.##"); Map accMap = infoMap.get(RedisConstant.DIFF); if (accMap == null) { accMap = new LinkedHashMap<>(); infoMap.put(RedisConstant.DIFF, accMap); } accMap.putAll(currentMap); } /** * 获取累加参数值 * * @param currentInfoMap * @return 累加差值map */ private Table getAccumulationDiff( Map> currentInfoMap, Map lastInfoMap) { //没有上一次统计快照,忽略差值统计 if (lastInfoMap == null || lastInfoMap.isEmpty()) { return HashBasedTable.create(); } Map currentMap = new LinkedHashMap(); for (RedisInfoEnum acc : RedisInfoEnum.getNeedCalDifRedisInfoEnumList()) { Long count = getCommonCount(currentInfoMap, acc.getRedisConstant(), acc.getValue()); if (count != null) { currentMap.put(acc, count); } } Map lastMap = new LinkedHashMap(); for (RedisInfoEnum acc : RedisInfoEnum.getNeedCalDifRedisInfoEnumList()) { Long lastCount = getCommonCount(lastInfoMap, acc.getRedisConstant(), acc.getValue()); if (lastCount != null) { lastMap.put(acc, lastCount); } } Table resultTable = HashBasedTable.create(); for (RedisInfoEnum key : currentMap.keySet()) { Long value = MapUtils.getLong(currentMap, key, null); Long lastValue = MapUtils.getLong(lastMap, key, null); if (value == null || lastValue == null) { //忽略 continue; } long diff = 0L; if (value > lastValue) { diff = value - lastValue; } resultTable.put(key.getRedisConstant(), key.getValue(), diff); } return resultTable; } /** * 获取累加参数值 * * @param currentInfoMap * @return 累加差值map */ private Table getDoubleAccumulationDiff( Map> currentInfoMap, Map lastInfoMap) { //没有上一次统计快照,忽略差值统计 if (lastInfoMap == null || lastInfoMap.isEmpty()) { return HashBasedTable.create(); } Map currentMap = new LinkedHashMap(); for (RedisInfoEnum acc : otherNeedCalDifRedisInfoEnumList) { Double count = getDoubleCount(currentInfoMap, acc.getRedisConstant(), acc.getValue()); if (count != null) { currentMap.put(acc, count); } } Map lastMap = new LinkedHashMap(); for (RedisInfoEnum acc : otherNeedCalDifRedisInfoEnumList) { Double lastCount = getDoubleCount(lastInfoMap, acc.getRedisConstant(), acc.getValue()); if (lastCount != null) { lastMap.put(acc, lastCount); } } DecimalFormat df = new DecimalFormat("##.##"); Table resultTable = HashBasedTable.create(); for (RedisInfoEnum key : currentMap.keySet()) { Double value = MapUtils.getDouble(currentMap, key, null); Double lastValue = MapUtils.getDouble(lastMap, key, null); if (value == null || lastValue == null) { //忽略 continue; } double diff = 0D; if (value > lastValue) { diff = value - lastValue; } diff = Double.parseDouble(df.format(diff)); resultTable.put(key.getRedisConstant(), key.getValue(), diff); } return resultTable; } /** * 获取命令差值统计 * * @param currentInfoMap * @param lastInfoMap * @return 命令统计 */ private Table getCommandsDiff(Map> currentInfoMap, Map lastInfoMap) { //没有上一次统计快照,忽略差值统计 if (lastInfoMap == null || lastInfoMap.isEmpty()) { return HashBasedTable.create(); } Map map = currentInfoMap.get(RedisConstant.Commandstats); Map currentMap = transferLongMap(map); Map lastObjectMap; if (lastInfoMap.get(RedisConstant.Commandstats.getValue()) == null) { lastObjectMap = new HashMap(); } else { lastObjectMap = (Map) lastInfoMap.get(RedisConstant.Commandstats.getValue()); } Map lastMap = transferLongMap(lastObjectMap); Table resultTable = HashBasedTable.create(); for (String command : currentMap.keySet()) { long lastCount = MapUtils.getLong(lastMap, command, 0L); long currentCount = MapUtils.getLong(currentMap, command, 0L); if (currentCount > lastCount) { resultTable.put(RedisConstant.Commandstats, command, currentCount - lastCount); } } return resultTable; } private AppStats getAppStats(long appId, long collectTime, Table table, Map> infoMap) { AppStats appStats = new AppStats(); appStats.setAppId(appId); appStats.setCollectTime(collectTime); appStats.setModifyTime(new Date()); appStats.setUsedMemory( MapUtils.getLong(infoMap.get(RedisConstant.Memory), RedisInfoEnum.used_memory.getValue(), 0L)); appStats.setUsedMemoryRss( MapUtils.getLong(infoMap.get(RedisConstant.Memory), RedisInfoEnum.used_memory_rss.getValue(), 0L)); appStats.setHits(MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.keyspace_hits.getValue(), 0L)); appStats.setMisses( MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.keyspace_misses.getValue(), 0L)); appStats.setEvictedKeys( MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.evicted_keys.getValue(), 0L)); appStats.setExpiredKeys( MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.expired_keys.getValue(), 0L)); appStats.setNetInputByte( MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.total_net_input_bytes.getValue(), 0L)); appStats.setNetOutputByte( MapUtils.getLong(table.row(RedisConstant.Stats), RedisInfoEnum.total_net_output_bytes.getValue(), 0L)); appStats.setConnectedClients(MapUtils.getIntValue(infoMap.get(RedisConstant.Clients), RedisInfoEnum.connected_clients.getValue(), 0)); appStats.setObjectSize(getObjectSize(infoMap)); appStats.setCpuSys(MapUtils.getLongValue(table.row(RedisConstant.CPU), RedisInfoEnum.used_cpu_sys.getValue(), 0)); appStats.setCpuUser( MapUtils.getLongValue(table.row(RedisConstant.CPU), RedisInfoEnum.used_cpu_user.getValue(), 0)); appStats.setCpuSysChildren( MapUtils.getLongValue(table.row(RedisConstant.CPU), RedisInfoEnum.used_cpu_sys_children.getValue(), 0)); appStats.setCpuUserChildren( MapUtils.getLongValue(table.row(RedisConstant.CPU), RedisInfoEnum.used_cpu_user_children.getValue(), 0)); logger.debug("appStats={} table={}", appStats, table); return appStats; } private AppStats getDefaultAppStats(long appId, long collectTime) { AppStats appStats = new AppStats(); appStats.setAppId(appId); appStats.setCollectTime(collectTime); appStats.setModifyTime(new Date()); appStats.setUsedMemory(0L); appStats.setUsedMemoryRss(0L); appStats.setHits(0); appStats.setMisses(0L); appStats.setEvictedKeys(0L); appStats.setExpiredKeys( 0L); appStats.setNetInputByte( 0L); appStats.setNetOutputByte( 0L); appStats.setConnectedClients(0); appStats.setObjectSize(0L); appStats.setCpuSys(0L); appStats.setCpuUser(0L); appStats.setCpuSysChildren(0L); appStats.setCpuUserChildren(0L); return appStats; } private long getObjectSize(Map> currentInfoMap) { Map sizeMap = currentInfoMap.get(RedisConstant.Keyspace); if (sizeMap == null || sizeMap.isEmpty()) { return 0L; } long result = 0L; Map longSizeMap = transferLongMap(sizeMap); for (Map.Entry entry : longSizeMap.entrySet()) { result += entry.getValue(); } return result; } private Long getCommonCount(Map infoMap, RedisConstant redisConstant, String commond) { Object constantObject = infoMap.get(redisConstant) == null ? infoMap.get(redisConstant.getValue()) : infoMap.get(redisConstant); if (constantObject != null && (constantObject instanceof Map)) { Map constantMap = (Map) constantObject; if (constantMap.get(commond) == null) { return null; } return MapUtils.getLongValue(constantMap, commond); } return null; } private Double getDoubleCount(Map infoMap, RedisConstant redisConstant, String commond) { Object constantObject = infoMap.get(redisConstant) == null ? infoMap.get(redisConstant.getValue()) : infoMap.get(redisConstant); if (constantObject != null && (constantObject instanceof Map)) { Map constantMap = (Map) constantObject; return MapUtils.getDoubleValue(constantMap, commond); } return null; } /** * 转换redis 命令行统计结果 * * @param commandMap * @return */ private Map transferLongMap(Map commandMap) { Map resultMap = new HashMap(); if (commandMap == null || commandMap.isEmpty()) { return resultMap; } for (Map.Entry entry : commandMap.entrySet()) { if (entry.getValue() == null) { continue; } String key = entry.getKey(); String value = entry.getValue().toString(); String[] stats = value.split(","); if (stats.length == 0) { continue; } String[] calls = stats[0].split("="); if (calls == null || calls.length < 2) { continue; } long callCount = Long.parseLong(calls[1]); resultMap.put(key, callCount); } return resultMap; } private List getCommandStatsList(long appId, long collectTime, Table table) { Map commandMap = table.row(RedisConstant.Commandstats); List list = new ArrayList(); if (commandMap == null) { return list; } for (String key : commandMap.keySet()) { String commandName = key.replace("cmdstat_", ""); long callCount = MapUtils.getLong(commandMap, key, 0L); if (callCount == 0L) { continue; } AppCommandStats commandStats = new AppCommandStats(); commandStats.setAppId(appId); commandStats.setCollectTime(collectTime); commandStats.setCommandName(commandName); commandStats.setCommandCount(callCount); commandStats.setModifyTime(new Date()); list.add(commandStats); } return list; } /** * 处理clusterinfo统计信息 * * @param clusterInfo * @return */ private Map processClusterInfoStats(String clusterInfo) { Map clusterInfoMap = new HashMap(); String[] lines = clusterInfo.split("\r\n"); for (String line : lines) { String[] pair = line.split(":"); if (pair.length == 2) { clusterInfoMap.put(pair[0], pair[1]); } } return clusterInfoMap; } /** * 处理redis统计信息 * * @param statResult 统计结果串 */ private Map> processRedisStats(String statResult) { Map> redisStatMap = new HashMap<>(); String[] data = statResult.split("\r\n"); String key; int i = 0; int length = data.length; while (i < length) { if (data[i].contains("#")) { int index = data[i].indexOf('#'); key = data[i].substring(index + 1); ++i; RedisConstant redisConstant = RedisConstant.value(key.trim()); if (redisConstant == null) { continue; } Map sectionMap = new LinkedHashMap(); while (i < length && data[i].contains(":")) { String[] pair = StringUtils.splitByWholeSeparator(data[i], ":"); sectionMap.put(pair[0], pair[1]); i++; } redisStatMap.put(redisConstant, sectionMap); } else { i++; } } return redisStatMap; } /** * 根据infoMap的结果判断实例的主从 * * @param infoMap * @return */ private BooleanEnum hasSlaves(Map> infoMap) { Map replicationMap = infoMap.get(RedisConstant.Replication); if (MapUtils.isEmpty(replicationMap)) { return BooleanEnum.OTHER; } for (Entry entry : replicationMap.entrySet()) { String key = entry.getKey(); //判断一个即可 if (key != null && key.contains("slave0")) { return BooleanEnum.TRUE; } } return BooleanEnum.FALSE; } /** * 根据infoMap的结果判断实例的主从 * * @param infoMap * @return */ private BooleanEnum isMaster(Map> infoMap) { Map map = infoMap.get(RedisConstant.Replication); if (map == null || map.get(RedisInfoEnum.role.getValue()) == null) { //return null; return BooleanEnum.OTHER; } if (String.valueOf(map.get(RedisInfoEnum.role.getValue())).equals("master")) { //return true; return BooleanEnum.TRUE; } //return false; return BooleanEnum.FALSE; } /** * 根据ip和port判断某一个实例当前是主还是从 * * @param ip ip * @param port port * @return 主返回true, 从返回false; */ @Override public BooleanEnum isMaster(long appId, String ip, int port) { Jedis jedis = null; try { jedis = getJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); String info = jedis.info("all"); Map> infoMap = processRedisStats(info); return isMaster(infoMap); } catch (Exception e) { logger.error(e.getMessage(), e); return BooleanEnum.OTHER; } finally { if (jedis != null) try{ jedis.close(); }catch (Exception e){ logger.error(e.getMessage(), e); } } } /** * 根据infoMap的结果判断实例的主从 * * @param infoMap * @return */ private BooleanEnum isSlaveAndPointedMasterUp(Map> infoMap, InstanceInfo masterInstance) { if(masterInstance == null){ return BooleanEnum.FALSE; } Map map = infoMap.get(RedisConstant.Replication); if (map == null || map.get(RedisInfoEnum.role.getValue()) == null) { //return null; return BooleanEnum.FALSE; } if (String.valueOf(map.get(RedisInfoEnum.role.getValue())).equals("slave") && (String.valueOf(map.get(RedisInfoEnum.master_link_status.getValue())).equals("up")) && (String.valueOf(map.get(RedisInfoEnum.master_host.getValue())).equals(masterInstance.getIp())) && (String.valueOf(map.get(RedisInfoEnum.master_port.getValue())).equals(String.valueOf(masterInstance.getPort()))) ){ return BooleanEnum.TRUE; } return BooleanEnum.FALSE; } /** * 判断实例是否为从节点,并且与主节点连接有效 * @param appDesc * @param slaveInstance * @param masterInstance * @return */ @Override public BooleanEnum isSlaveAndPointedMasterUp(AppDesc appDesc, InstanceInfo slaveInstance, InstanceInfo masterInstance){ Jedis jedis = null; try { jedis = getJedis(slaveInstance.getIp(), slaveInstance.getPort(), appDesc.getAppPassword()); String info = jedis.info("all"); Map> infoMap = processRedisStats(info); return isSlaveAndPointedMasterUp(infoMap, masterInstance); } catch (Exception e) { logger.error(e.getMessage(), e); return BooleanEnum.FALSE; } finally { if (jedis != null) jedis.close(); } } @Override public long getDbSize(long appId, String ip, int port) { Jedis jedis = getJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { return jedis.dbSize(); } catch (Exception e) { logger.error(e.getMessage(), e); return -1; } finally { jedis.close(); } } /** * @Description: scan key * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ @Async public Future> findInstancePatternKeys(long appId, String ip, int port, String pattern) { List list = new ArrayList(); Jedis jedis = getAdminJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String cursor = ScanParams.SCAN_POINTER_START; ScanParams params = new ScanParams().match(pattern).count(COUNT); do { ScanResult result = jedis.scan(cursor, params); list.addAll(result.getResult()); cursor = result.getCursor(); } while (!"0".equals(cursor)); return new AsyncResult>(list); } catch (Exception e) { logger.error(e.getMessage(), e); return new AsyncResult>(list); } finally { jedis.close(); } } /** * @Description: 查询单实例的big key * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public List findInstanceBigKey(long appId, String ip, int port, long startBytes, long endBytes) { List list = new ArrayList(); Jedis jedis = getAdminJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String cursor = ScanParams.SCAN_POINTER_START; ScanParams params = new ScanParams().count(COUNT); do { ScanResult result = jedis.scan(cursor, params); for (String key : result.getResult()) { String keyType = jedis.type(key); if ("string".equals(keyType)) { long len = jedis.strlen(key); if (len > startBytes && len < endBytes) { list.add(key); } } else { Long memoryUsageRes = jedis.memoryUsage(key); if (memoryUsageRes != null && memoryUsageRes > startBytes && memoryUsageRes < endBytes) { list.add(key); } } } cursor = result.getCursor(); } while (!"0".equals(cursor)); return list; } catch (Exception e) { logger.error(e.getMessage(), e); return list; } finally { jedis.close(); } } /** * @Description: 查询应用的big key * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public List findClusterBigKey(long appId, long startBytes, long endBytes) { List list = new ArrayList(); List allMasterInstance = getAllHealthyInstanceInfo(appId); for (InstanceInfo masterInstance : allMasterInstance) { String ip = masterInstance.getIp(); int port = masterInstance.getPort(); List res = findInstanceBigKey(appId, ip, port, startBytes, endBytes); list.addAll(res); } return list; } /** * @Description: 查询单实例的idle key * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public List findInstanceIdleKeys(long appId, String ip, int port, long idleDays) { List list = new ArrayList(); Jedis jedis = getAdminJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String cursor = ScanParams.SCAN_POINTER_START; ScanParams params = new ScanParams().count(COUNT); do { ScanResult result = jedis.scan(cursor, params); for (String key : result.getResult()) { Long ideltime = jedis.objectIdletime(key); if (ideltime != null && ideltime > idleDays * 3600 * 24) { list.add(key); } } cursor = result.getCursor(); } while (!"0".equals(cursor)); return list; } catch (Exception e) { logger.error(e.getMessage(), e); return list; } finally { jedis.close(); } } /** * @Description: 查询应用的idle key * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public List findClusterIdleKeys(long appId, long idleDays) { List list = new ArrayList(); List allMasterInstance = getAllHealthyInstanceInfo(appId); for (InstanceInfo masterInstance : allMasterInstance) { String ip = masterInstance.getIp(); int port = masterInstance.getPort(); List res = findInstanceIdleKeys(appId, ip, port, idleDays); list.addAll(res); } return list; } /** * @Description: 查询单实例匹配的pattern * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public void delInstancePatternKeys(long appId, String ip, int port, String pattern) { Jedis jedis = getAdminJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String cursor = ScanParams.SCAN_POINTER_START; ScanParams params = new ScanParams().match(pattern).count(COUNT); do { ScanResult result = jedis.scan(cursor, params); for (String key : result.getResult()) { jedis.del(key); } cursor = result.getCursor(); } while (!"0".equals(cursor)); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { jedis.close(); } } /** * @Description: 查询应用的匹配的pattern * @Author: caoru * @CreateDate: 2018/11/13 16:08 */ public void delClusterPatternKey(long appId, String pattern) { List allMasterInstance = getAllHealthyInstanceInfo(appId); for (InstanceInfo masterInstance : allMasterInstance) { String ip = masterInstance.getIp(); int port = masterInstance.getPort(); delInstancePatternKeys(appId, ip, port, pattern); } } /** * 根据ip和port判断redis实例当前是否有从节点 * * @param ip ip * @param port port * @return 主返回true,从返回false; */ public BooleanEnum hasSlaves(long appId, String ip, int port) { Jedis jedis = getAdminJedis(appId, ip, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String info = jedis.info("all"); Map> infoMap = processRedisStats(info); return hasSlaves(infoMap); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } finally { jedis.close(); } } @Override public HostAndPort getMaster(String ip, int port, String password) { JedisPool jedisPool = maintainJedisPool(ip, port, password); Jedis jedis = null; try { jedis = jedisPool.getResource(); String info = jedis.info(RedisConstant.Replication.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Replication); if (map == null) { return null; } String masterHost = MapUtils.getString(map, RedisInfoEnum.master_host.getValue(), null); int masterPort = MapUtils.getInteger(map, RedisInfoEnum.master_port.getValue(), 0); if (StringUtils.isNotBlank(masterHost) && masterPort > 0) { return new HostAndPort(masterHost, masterPort); } return null; } catch (Exception e) { logger.error("{}:{} getMaster failed {}", ip, port, e.getMessage(), e); return null; } finally { if (jedis != null) jedis.close(); } } public HostAndPort getSlave0(String ip, int port, String password) { JedisPool jedisPool = maintainJedisPool(ip, port, password); Jedis jedis = null; try { jedis = jedisPool.getResource(); String info = jedis.info(RedisConstant.Replication.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Replication); if (map == null) { return null; } String slaveInfo = MapUtils.getString(map, "slave0"); String slaveHost = ""; int slavePort = 0; if (!StringUtil.isBlank(slaveInfo)) { for (String slave0 : slaveInfo.split(",")) { if (slave0.indexOf("ip") > -1) { slaveHost = slave0.replaceAll("ip=", ""); } if (slave0.indexOf("port") > -1) { slavePort = Integer.parseInt(slave0.replaceAll("port=", "")); } } } if (StringUtils.isNotBlank(slaveHost) && slavePort > 0) { return new HostAndPort(slaveHost, slavePort); } return null; } catch (Exception e) { logger.error("{}:{} getMaster failed {}", ip, port, e.getMessage(), e); return null; } finally { if (jedis != null) jedis.close(); } } @Override public boolean isRun(final String ip, final int port, final int retryTimes) { return isRun(ip, port, null, retryTimes); } public boolean isRun(final String ip, final int port, final String password, final int retryTimes) { boolean isRun = new IdempotentConfirmer(retryTimes) { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { jedis = getJedis(ip, port, password); jedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); jedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); String pong = jedis.ping(); return pong != null && pong.equalsIgnoreCase("PONG"); } catch (JedisDataException e) { String message = e.getMessage(); logger.warn(e.getMessage()); if (StringUtils.isNotBlank(message) && message.startsWith("LOADING")) { return true; } return false; } catch (Exception e) { logger.warn("{}:{} error message is {} ", ip, port, e.getMessage()); return false; } finally { if (jedis != null) { jedis.close(); } } } }.run(); return isRun; } @Override public boolean isRun(final String ip, final int port) { return isRun(ip, port, null); } @Override public boolean isRun(final long appId, final String ip, final int port) { AppDesc appDesc = appDao.getAppDescById(appId); return isRun(ip, port, appDesc.getAppPassword()); } @Override public boolean isRun(final String ip, final int port, final String password) { boolean isRun = new IdempotentConfirmer() { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { jedis = getJedis(ip, port, password); jedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); jedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); String pong = jedis.ping(); return pong != null && pong.equalsIgnoreCase("PONG"); } catch (JedisDataException e) { String message = e.getMessage(); logger.warn(e.getMessage()); if (StringUtils.isNotBlank(message) && message.startsWith("LOADING")) { return true; } return false; } catch (Exception e) { logger.warn("{}:{} error count={} message is {} ", ip, port, timeOutFactor, e.getMessage()); return false; } finally { if (jedis != null) { jedis.close(); } } } }.run(); return isRun; } @Override public boolean shutdown(long appId, String ip, int port) { boolean isRun = isRun(appId, ip, port); if (!isRun) { return true; } final Jedis jedis = getAdminJedis(appId, ip, port); try { //关闭实例节点 boolean isShutdown = new IdempotentConfirmer() { @Override public boolean execute() { try{ jedis.shutdown(); }catch (JedisException e){ if(e.getMessage().contains("OK")){ return true; }else { throw e; } } return true; } }.run(); if (!isShutdown) { logger.error("{}:{} redis not shutdown!", ip, port); } return isShutdown; } finally { jedis.close(); } } @Override public boolean forget(long appId, String ip, int port, String nodeId) { boolean isRun = isRun(appId, ip, port); //todo: 除了isRun,是否还需要其他判断条件 if (!isRun) { return true; } boolean isForget = new IdempotentConfirmer() { @Override public boolean execute() { String response = null; Jedis jedis = null; try { jedis = getAdminJedis(appId, ip, port); response = jedis.clusterForget(nodeId); } catch (JedisDataException jde) { //处于handshake状态的节点会抛异常:ERR Unknown node 92e90269c5f86a663a692c5bcf766ecdda80aa9e logger.error(jde.getMessage(), jde); response = "OK"; } catch (Exception e) { logger.error("appId {} instance {}:{} forget instance {} error!", appId, ip, port, nodeId, e); } finally { if (jedis != null) { jedis.close(); } } return response != null && response.equalsIgnoreCase("OK"); } }.run(); return isForget; } @Override public boolean shutdown(String ip, int port) { boolean isRun = isRun(ip, port); if (!isRun) { return true; } final Jedis jedis = getJedis(ip, port); try { //关闭实例节点 boolean isShutdown = new IdempotentConfirmer() { @Override public boolean execute() { jedis.shutdown(); return true; } }.run(); if (!isShutdown) { logger.error("{}:{} redis not shutdown!", ip, port); } return isShutdown; } finally { jedis.close(); } } /** * 判断节点是否正常关闭,默认为关闭成功,仅在查到配置文件句柄一直未释放时,认为关闭失败 * @param instanceInfo * @return */ @Override public boolean checkShutdownSuccess(InstanceInfo instanceInfo){ if(instanceInfo == null){ return false; } //关闭节点后,判断配置文件句柄是否释放 boolean existeFlag = true; int tryTimes = 3; long sleepTime = 2L; String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); StringBuilder command = new StringBuilder(); command.append("ps -ef | grep redis | grep redis-server | grep :").append(port).append(" | grep -v \"grep\""); while(tryTimes-- > 0){ try{ String execute = SSHUtil.execute(host, command.toString()); if(StringUtils.isEmpty(execute)){ existeFlag = true; break; }else{ existeFlag = false; } logger.info(String.format("check Instance shutdown not success, will one more time, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command)); TimeUnit.SECONDS.sleep(sleepTime); }catch (Exception e){ logger.error(String.format("check Instance shutdown error, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), command), e); } } return existeFlag; } @Override public String getClusterMyId(long appId, String ip, int port) { final Jedis jedis = getAdminJedis(appId, ip, port); try { return jedis.clusterMyId(); } catch (Exception e) { logger.error(e.getMessage(), e); return ""; } finally { jedis.close(); } } @Override public String getClusterNodes(long appId, String ip, int port) { final Jedis jedis = getAdminJedis(appId, ip, port); try { return jedis.clusterNodes(); } catch (Exception e) { logger.error(e.getMessage(), e); return ""; } finally { jedis.close(); } } /** * 返回当前实例的一些关键指标 * * @param appId * @param ip * @param port * @param infoMap * @return */ public InstanceStats getInstanceStats(long appId, String ip, int port, Map> infoMap) { if (infoMap == null) { return null; } // 查询最大内存限制 Long maxMemory = this.getRedisMaxMemory(appId, ip, port); /** * 将实例的一些关键指标返回 */ InstanceStats instanceStats = new InstanceStats(); instanceStats.setAppId(appId); InstanceInfo curInst = instanceDao.getInstByIpAndPort(ip, port); if (curInst != null) { instanceStats.setHostId(curInst.getHostId()); instanceStats.setInstId(curInst.getId()); } else { logger.error("redis={}:{} not found", ip, port); return null; } instanceStats.setIp(ip); instanceStats.setPort(port); if (maxMemory != null) { instanceStats.setMaxMemory(maxMemory); } instanceStats.setUsedMemory( MapUtils.getLongValue(infoMap.get(RedisConstant.Memory), RedisInfoEnum.used_memory.getValue(), 0)); instanceStats.setHits( MapUtils.getLongValue(infoMap.get(RedisConstant.Stats), RedisInfoEnum.keyspace_hits.getValue(), 0)); instanceStats.setMisses( MapUtils.getLongValue(infoMap.get(RedisConstant.Stats), RedisInfoEnum.keyspace_misses.getValue(), 0)); instanceStats.setCurrConnections( MapUtils.getIntValue(infoMap.get(RedisConstant.Clients), RedisInfoEnum.connected_clients.getValue(), 0)); instanceStats.setCurrItems(getObjectSize(infoMap)); instanceStats.setRole((byte) 1); if (MapUtils.getString(infoMap.get(RedisConstant.Replication), RedisInfoEnum.role.getValue()).equals("slave")) { instanceStats.setRole((byte) 2); } instanceStats.setModifyTime(new Timestamp(System.currentTimeMillis())); instanceStats.setMemFragmentationRatio(MapUtils.getDoubleValue(infoMap.get(RedisConstant.Memory), RedisInfoEnum.mem_fragmentation_ratio.getValue(), 0.0)); instanceStats.setAofDelayedFsync( MapUtils.getIntValue(infoMap.get(RedisConstant.Persistence), RedisInfoEnum.aof_delayed_fsync.getValue(), 0)); return instanceStats; } @Override public Long getRedisMaxMemory(final long appId, final String ip, final int port) { final String key = "maxmemory"; final Map resultMap = new HashMap(); boolean isSuccess = new IdempotentConfirmer() { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { jedis = getJedis(appId, ip, port); jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); jedis.getClient().setSoTimeout(REDIS_DEFAULT_TIME * (timeOutFactor++)); List maxMemoryList = jedis.configGet(key); // 返回结果:list中是2个字符串,如:"maxmemory", // "4096000000" if (maxMemoryList != null && maxMemoryList.size() >= 2) { resultMap.put(key, Long.valueOf(maxMemoryList.get(1))); } return MapUtils.isNotEmpty(resultMap); } catch (Exception e) { logger.warn("{}:{} errorMsg: {}", ip, port, e.getMessage()); return false; } finally { if (jedis != null) { jedis.close(); } } } }.run(); if (isSuccess) { return MapUtils.getLong(resultMap, key); } else { logger.error("{}:{} getMaxMemory failed!", ip, port); return null; } } @Override public String executeCommand(AppDesc appDesc, String command, String userName) { //非测试应用只能执行白名单里面的命令 if (AppDescEnum.AppTest.NOT_TEST.getValue() == appDesc.getIsTest()) { if (!RedisReadOnlyCommandEnum.contains(command)) { return "online app only support read-only and safe command"; } } int type = appDesc.getType(); long appId = appDesc.getAppId(); String password = appDesc.getAppPassword(); if (type == ConstUtils.CACHE_REDIS_SENTINEL) { JedisSentinelPool jedisSentinelPool = getJedisSentinelPool(appDesc); if (jedisSentinelPool == null) { return "sentinel can not execute "; } Jedis jedis = null; try { jedis = jedisSentinelPool.getResource(); String host = jedis.getClient().getHost(); int port = jedis.getClient().getPort(); return executeCommand(appId, host, port, command); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } finally { if (jedis != null) jedis.close(); jedisSentinelPool.destroy(); } } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return "应用没有运行的实例"; } String host = null; int port = 0; for (InstanceInfo instanceInfo : instanceList) { host = instanceInfo.getIp(); port = instanceInfo.getPort(); break; } try { return executeCommand(appId, host, port, command); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return "应用没有运行的实例"; } Set clusterHosts = new LinkedHashSet(); for (InstanceInfo instance : instanceList) { if (instance != null && instance.isOnline()) { clusterHosts.add(new HostAndPort(instance.getIp(), instance.getPort())); } } if (clusterHosts.isEmpty()) { return "no run instance"; } String commandKey = getCommandKey(command); if(StringUtils.isEmpty(commandKey)){ logger.error(String.format("executeCommand with empty commandKey, appDesc is : %s, command is: %s, user is : %s", appDesc.getAppId(), command, userName)); } for (HostAndPort hostAndPort : clusterHosts) { HostAndPort rightHostAndPort = null; if(commandKey != null){ rightHostAndPort = getClusterRightHostAndPort(hostAndPort.getHost(), hostAndPort.getPort(), password, command, commandKey); }else{ rightHostAndPort = hostAndPort; } if (rightHostAndPort != null) { try { return executeCommand(appId, rightHostAndPort.getHost(), rightHostAndPort.getPort(), command); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } } } } return "不支持应用类型"; } @Override public Object executeAdminCommand(AppDesc appDesc, ProtocolCommand command, String... args) { int type = appDesc.getType(); long appId = appDesc.getAppId(); String password = appDesc.getAppPassword(); if (type == ConstUtils.CACHE_REDIS_SENTINEL) { List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return "应用没有运行的实例"; } String host = null; int port = 0; for (InstanceInfo instanceInfo : instanceList) { if(instanceInfo.getType() == ConstUtils.CACHE_REDIS_SENTINEL){ continue; } if(instanceInfo.isOffline()){ continue; } host = instanceInfo.getIp(); port = instanceInfo.getPort(); BooleanEnum isMaster = this.isMaster(appId, host, port); if(isMaster.equals(BooleanEnum.TRUE)){ break; }else{ host = null; port = 0; } } Jedis jedis = null; try { jedis = this.getAdminJedis(appId, host, port); return executeAdminRedisCommandByJedis(jedis, command, args); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } finally { if (jedis != null){ jedis.close(); } } } else if (type == ConstUtils.CACHE_REDIS_STANDALONE) { List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return "应用没有运行的实例"; } String host = null; int port = 0; for (InstanceInfo instanceInfo : instanceList) { host = instanceInfo.getIp(); port = instanceInfo.getPort(); BooleanEnum isMaster = this.isMaster(appId, host, port); if(isMaster.equals(BooleanEnum.TRUE)){ break; }else{ host = null; port = 0; } } Jedis jedis = null; try { jedis = this.getAdminJedis(appId, host, port); return executeAdminRedisCommandByJedis(jedis, command, args); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } finally { if (jedis != null){ jedis.close(); } } } else if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return "应用没有运行的实例"; } Set clusterHosts = new LinkedHashSet(); for (InstanceInfo instance : instanceList) { if (instance != null && instance.isOnline()) { clusterHosts.add(new HostAndPort(instance.getIp(), instance.getPort())); } } if (clusterHosts.isEmpty()) { return "no run instance"; } String commandKey = null; if(args != null && args.length > 0){ commandKey = args[0]; } HostAndPort rightHostAndPort = null; for (HostAndPort hostAndPort : clusterHosts) { if(commandKey != null){ rightHostAndPort = getClusterRightHostAndPort(hostAndPort.getHost(), hostAndPort.getPort(), password, command.toString(), commandKey); if(rightHostAndPort != null){ break; } }else{ BooleanEnum isMaster = this.isMaster(appId, hostAndPort.getHost(), hostAndPort.getPort()); if(isMaster.equals(BooleanEnum.TRUE)){ rightHostAndPort = hostAndPort; break; } } } if (rightHostAndPort != null) { Jedis jedis = null; try { jedis = this.getAdminJedis(appId, rightHostAndPort.getHost(), rightHostAndPort.getPort()); return executeAdminRedisCommandByJedis(jedis, command, args); } catch (Exception e) { logger.error(e.getMessage(), e); return "运行出错:" + e.getMessage(); } finally { if (jedis != null){ jedis.close(); } } } } return "不支持应用类型"; } /** * 获取key对应的节点 * * @param host * @param port * @param password * @param command * @param key * @return */ private HostAndPort getClusterRightHostAndPort(String host, int port, String password, String command, String key) { Jedis jedis = null; try { jedis = getJedis(host, port, password); jedis.type(key); return new HostAndPort(host, port); } catch (JedisMovedDataException e) { return e.getTargetNode(); } catch (JedisAskDataException e) { return e.getTargetNode(); } catch (Exception e) { logger.error("command {} is error", command, e.getMessage(), e); return null; } finally { if (jedis != null) { jedis.close(); } } } private String getCommandKey(String command) { String[] array = StringUtils.trim(command).split("\\s+"); if (array.length > 1) { return array[1]; } else { return null; } } @Override public String executeCommand(long appId, String host, int port, String command) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return "not exist appId"; } //非测试应用只能执行白名单里面的命令 if (AppDescEnum.AppTest.NOT_TEST.getValue() == appDesc.getIsTest()) { if (!RedisReadOnlyCommandEnum.contains(command)) { return "online app only support read-only and safe command "; } } String password = appDesc.getAppPassword(); String shell = RedisProtocol.getExecuteCommandShell(host, port, password, command); //记录客户端发送日志 logger.warn("executeRedisShell={}", shell); return machineCenter.executeShell(host, shell); } @Override public String executeAdminCommand(long appId, String host, int port, String command, Integer timeout) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return "not exist appId"; } String password = appDesc.getAppPassword(); String shell = RedisProtocol.getExecuteAdminCommandShell(host, port, password, command); //记录客户端发送日志 logger.warn("executeRedisShell={}", shell); return machineCenter.executeShell(host, shell, timeout); } @Override public Object executeAdminRedisCommandByJedis(Jedis jedis, ProtocolCommand command, String... args) { Object o = jedis.sendCommand(command, args); return o; } @Override public JedisSentinelPool getJedisSentinelPool(AppDesc appDesc) { if (appDesc == null) { logger.error("appDesc is null"); return null; } if (appDesc.getType() != ConstUtils.CACHE_REDIS_SENTINEL) { logger.error("type={} is not sentinel", appDesc.getType()); return null; } long appId = appDesc.getAppId(); List instanceInfos = instanceDao.getInstListByAppId(appId); instanceInfos = instanceInfos.stream().filter(instanceInfo -> instanceInfo.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()).collect(Collectors.toList()); String masterName = null; for (Iterator i = instanceInfos.iterator(); i.hasNext(); ) { InstanceInfo instanceInfo = i.next(); if (instanceInfo.getType() != ConstUtils.CACHE_REDIS_SENTINEL) { i.remove(); continue; } if (masterName == null && StringUtils.isNotBlank(instanceInfo.getCmd())) { masterName = instanceInfo.getCmd(); } } Set sentinels = new HashSet(); for (InstanceInfo instanceInfo : instanceInfos) { sentinels.add(instanceInfo.getIp() + ":" + instanceInfo.getPort()); } JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels); return jedisSentinelPool; } @Override public Map getRedisConfigList(int instanceId) { if (instanceId <= 0) { return Collections.emptyMap(); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { return Collections.emptyMap(); } if (TypeUtil.isRedisType(instanceInfo.getType())) { Jedis jedis = null; try { jedis = getJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); List configs = jedis.configGet("*"); Map configMap = new LinkedHashMap(); for (int i = 0; i < configs.size(); i += 2) { if (i < configs.size()) { String key = configs.get(i); String value = configs.get(i + 1); if (StringUtils.isBlank(value)) { continue; } configMap.put(key, value); } } return configMap; } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } } return Collections.emptyMap(); } @Override public List getRedisCommand(int instanceId) { List commandList = new ArrayList<>(); if (instanceId <= 0) { return commandList; } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { return commandList; } if (TypeUtil.isRedisType(instanceInfo.getType())) { Jedis jedis = null; try { if(TypeUtil.isRedisDataType(instanceInfo.getType())){ jedis = getAdminJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); }else{ jedis = getJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); } Client client = jedis.getClient(); client.sendCommand(Command.COMMAND); List nestedMultiBulkReply = client.getObjectMultiBulkReply(); for (Object obj : nestedMultiBulkReply) { List properties = (List) obj; commandList.add(new String((byte[])properties.get(0))); } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } } return commandList; } /** * 获取重命名命令列表 * @param instanceId * @return */ @Override public List> getConfigsInConfigFile(int instanceId, String configName){ List> configs = new ArrayList<>(); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { return configs; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); StringBuilder command = new StringBuilder(); String configFileName = null; if (TypeUtil.isRedisCluster(instanceInfo.getType())) { configFileName = RedisProtocol.getConfig(port, true); } else { configFileName = RedisProtocol.getConfig(port, false); } String confDir = machineCenter.getMachineRelativeDir(host, DirEnum.CONF_DIR.getValue()); String remotePath = confDir + configFileName; command.append("cat ").append(remotePath); if(StringUtils.isNotEmpty(configName)){ command.append(" | grep '").append(configName).append("'"); } command.append(" | grep -v '^#'"); try{ String sshRst = SSHUtil.execute(host, command.toString()); if(StringUtils.isNotEmpty(sshRst)){ String[] configStrs = sshRst.split(System.lineSeparator()); if(configStrs != null && configStrs.length > 0){ for (int i = 0; i < configStrs.length; i++) { String configStr = configStrs[i]; if(configStr.contains(" ")){ int index = configStr.indexOf(" "); configs.add(Pair.of(configStr.substring(0, index), configStr.substring(index + 1, configStr.length()))); } } } } logger.info(String.format("get Instance config from file success, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command)); }catch (Exception e){ logger.error(String.format("get Instance config from file error, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), command), e); } return configs; } @Override public List getRedisSlowLogs(int instanceId, int maxCount) { if (instanceId <= 0) { return Collections.emptyList(); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { return Collections.emptyList(); } if (TypeUtil.isRedisType(instanceInfo.getType())) { return getRedisSlowLogs(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), maxCount); } return Collections.emptyList(); } private List getRedisSlowLogs(long appId, String host, int port, int maxCount) { Jedis jedis = null; try { jedis = getAdminJedis(appId, host, port, REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); List resultList = new ArrayList(); List slowlogs = null; if (maxCount > 0) { slowlogs = jedis.slowlogGet(maxCount); } else { slowlogs = jedis.slowlogGet(); } if (slowlogs != null && slowlogs.size() > 0) { for (Slowlog sl : slowlogs) { RedisSlowLog rs = new RedisSlowLog(); rs.setId(sl.getId()); rs.setExecutionTime(sl.getExecutionTime()); long time = sl.getTimeStamp() * 1000L; rs.setDate(new Date(time)); rs.setTimeStamp(DateUtil.formatYYYYMMddHHMMSS(new Date(time))); rs.setCommand(StringUtils.join(sl.getArgs(), " ")); resultList.add(rs); } } return resultList; } catch (Exception e) { logger.error(String.format("get slowLog error, appId:%s host:%s port:%s, error:%s", appId, host, port, e.getMessage()), e); return Collections.emptyList(); } finally { if (jedis != null) { jedis.close(); } } } @Override public boolean configRewrite(final long appId, final String host, final int port) { return new IdempotentConfirmer() { @Override public boolean execute() { Jedis jedis = getAdminJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); try { String response = jedis.configRewrite(); return response != null && response.equalsIgnoreCase("OK"); } finally { jedis.close(); } } }.run(); } @Override public boolean configRewrite(Jedis jedis) { return new IdempotentConfirmer() { @Override public boolean execute() { String response = jedis.configRewrite(); return response != null && response.equalsIgnoreCase("OK"); } }.run(); } @Override public boolean cleanAppData(AppDesc appDesc, AppUser appUser) { if (appDesc == null) { return false; } long appId = appDesc.getAppId(); // 线上应用不能清理数据 if (AppDescEnum.AppTest.IS_TEST.getValue() != appDesc.getIsTest()) { logger.error("appId {} profile must be test", appId); return false; } // 必须是redis应用 if (!TypeUtil.isRedisType(appDesc.getType())) { logger.error("appId {} type must be redis", appId); return false; } // 实例验证 List instanceList = instanceDao.getInstListByAppId(appId); if (CollectionUtils.isEmpty(instanceList)) { logger.error("appId {} instanceList is empty", appId); return false; } // 开始清除 for (InstanceInfo instance : instanceList) { if (instance.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } String host = instance.getIp(); int port = instance.getPort(); // master + 非sentinel节点 BooleanEnum isMater = isMaster(appId, host, port); if (isMater == BooleanEnum.TRUE && !TypeUtil.isRedisSentinel(instance.getType())) { //异步线程处理 AsyncThreadPoolFactory.DEFAULT_ASYNC_THREAD_POOL.execute(new Runnable() { @Override public void run() { Jedis jedis = getAdminJedis(appId, host, port); jedis.getClient().setConnectionTimeout(REDIS_DEFAULT_TIME); jedis.getClient().setSoTimeout(60000); try { logger.warn("{}:{} start clear data", host, port); long start = System.currentTimeMillis(); String result = jedis.flushAll(); logger.warn("{}:{} finish clear data :{}, cost time:{} ms", host, port, result, (System.currentTimeMillis() - start)); } catch (Exception e) { logger.error("clear redis: " + e.getMessage(), e); } finally { jedis.close(); } } }); } } //记录日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, 0L, AppAuditLogTypeEnum.APP_CLEAN_DATA); appAuditLogDao.save(appAuditLog); return true; } @Override public boolean isSingleClusterNode(long appId, String host, int port) { final Jedis jedis = getJedis(appId, host, port); try { String clusterNodes = jedis.clusterNodes(); if (StringUtils.isBlank(clusterNodes)) { throw new RuntimeException(host + ":" + port + "clusterNodes is null"); } String[] nodeInfos = clusterNodes.split("\n"); if (nodeInfos.length == 1) { return true; } return false; } finally { jedis.close(); } } @Override public List getClientList(int instanceId) { if (instanceId <= 0) { return Collections.emptyList(); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { return Collections.emptyList(); } if (TypeUtil.isRedisType(instanceInfo.getType())) { Jedis jedis = null; try { jedis = getJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); jedis.clientList(); List resultList = new ArrayList(); String clientList = jedis.clientList(); if (StringUtils.isNotBlank(clientList)) { String[] array = clientList.split("\n"); resultList.addAll(Arrays.asList(array)); } return resultList; } catch (Exception e) { logger.error("instance getClientList error, instance:[{}:{}] error:{}", instanceInfo.getAppId(), instanceInfo.getHostPort(), e.getMessage()); logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } } return Collections.emptyList(); } @Override public List> formatClientList(List clientList) { List> clientMapList = clientList.stream().map(clientInfo -> parseClientInfo(clientInfo)).collect(Collectors.toList()); Map>> result = new HashMap<>(); clientMapList.stream().forEach(clientMap -> { String addr = MapUtils.getString(clientMap, "addr"); List> list = result.get(addr); if (CollectionUtils.isEmpty(list)) { list = new ArrayList<>(); result.put(addr, list); } list.add(clientMap); }); List> finalResult = getClientInfoMap(result); return finalResult; } @Override public List> getAppClientList(long appId, int condition) { Map> finalResult = new HashMap<>(); List instanceInfoList = appService.getAppOnlineInstanceInfo(appId); instanceInfoList.stream().forEach(instanceInfo -> { int instanceId = instanceInfo.getId(); List> instanceClientList = formatClientList(getClientList(instanceId)); for (Map map : instanceClientList) { String addr = MapUtils.getString(map, "addr"); Map result = MapUtils.getMap(finalResult, addr); if (MapUtils.isEmpty(result)) { result = new HashMap<>(); finalResult.put(addr, result); } result.put(instanceId, map); } }); return formatAppClientList(finalResult, appId, condition); } private List> formatAppClientList(Map> addrClientListMap, long appId, int condition) { List> finalResult = new ArrayList<>(); List ccWebClientList = webClientComponent.getWebClientIps(); List redisClientList = appService.getAppOnlineInstanceInfo(appId).stream().map(instanceInfo -> instanceInfo.getIp()).collect(Collectors.toList()); for (String addr : addrClientListMap.keySet()) { Map instanceClientListMap = addrClientListMap.get(addr); Map map = new HashMap<>(); map.put("addr", addr); Set flags = new HashSet<>(); int size = 0; for (Integer instanceId : instanceClientListMap.keySet()) { Map clientInfo = (HashMap) instanceClientListMap.get(instanceId); Set instanceFlags = (HashSet) clientInfo.get("clientTypeSet"); flags.addAll(instanceFlags); int count = MapUtils.getIntValue(clientInfo, "count"); size += count; } map.put("flags", flags); map.put("size", size); map.put("instanceClientStats", instanceClientListMap); switch (condition) { case 0: if (!ccWebClientList.contains(addr) && !redisClientList.contains(addr)) { finalResult.add(map); } break; case 1: if (ccWebClientList.contains(addr)) { finalResult.add(map); } break; case 2: if (redisClientList.contains(addr)) { finalResult.add(map); } break; case 3: finalResult.add(map); break; } } return finalResult; } private List> getClientInfoMap(Map>> map) { List> finalResult = new ArrayList<>(); for (String addr : map.keySet()) { List> clients = map.get(addr); Set flagsSet = clients.stream().map(clientInfo -> ClientTypeEnum.Method.getDesc(MapUtils.getString(clientInfo, "flags", ""))) .collect(Collectors.toSet()); Map clientMap = new HashMap<>(); clientMap.put("addr", addr); clientMap.put("clientTypeSet", flagsSet); clientMap.put("count", clients.size()); clientMap.put("clientInfoList", clients); finalResult.add(clientMap); } return finalResult; } private Map parseClientInfo(String clientInfo) { Map clientInfoMap = new HashMap<>(); String[] tmpArray1 = clientInfo.split(" "); if (tmpArray1 != null) { for (String tmp : tmpArray1) { String[] tmpArray2 = tmp.split("=|:"); if (tmpArray2.length == 3) { clientInfoMap.put(tmpArray2[0], tmpArray2[1]); clientInfoMap.put("port", tmpArray2[2]); } else if (tmpArray2.length == 2) { clientInfoMap.put(tmpArray2[0], tmpArray2[1]); } } } return clientInfoMap; } @Override public Map getClusterLossSlots(long appId) { // 1.从应用中获取一个健康的主节点 InstanceInfo sourceMasterInstance = getHealthyInstanceInfo(appId); if (sourceMasterInstance == null) { return Collections.emptyMap(); } // 2. 获取所有slot和节点的对应关系 Map slotHostPortMap = getSlotsHostPortMap(appId, sourceMasterInstance.getIp(), sourceMasterInstance.getPort()); // 3. 获取集群中失联的slot List lossSlotList = getClusterLossSlots(appId, sourceMasterInstance.getIp(), sourceMasterInstance.getPort()); // 3.1 将失联的slot列表组装成Map lossSlotList> Map> hostPortSlotMap = new HashMap>(); if (CollectionUtils.isNotEmpty(lossSlotList)) { for (Integer lossSlot : lossSlotList) { String key = slotHostPortMap.get(lossSlot); if (hostPortSlotMap.containsKey(key)) { hostPortSlotMap.get(key).add(lossSlot); } else { List list = new ArrayList(); list.add(lossSlot); hostPortSlotMap.put(key, list); } } } // 3.2 hostPortSlotMap组装成Map Map slotSegmentsMap = new HashMap(); for (Entry> entry : hostPortSlotMap.entrySet()) { List list = entry.getValue(); List slotSegments = new ArrayList(); int min = list.get(0); int max = min; for (int i = 1; i < list.size(); i++) { int temp = list.get(i); if (temp == max + 1) { max = temp; } else { slotSegments.add(String.valueOf(min) + "-" + String.valueOf(max)); min = temp; max = temp; } } slotSegments.add(String.valueOf(min) + "-" + String.valueOf(max)); slotSegmentsMap.put(entry.getKey(), slotSegments.toString()); } return slotSegmentsMap; } /** * 从一个应用中获取一个健康的主节点 * * @param appId * @return */ public InstanceInfo getHealthyInstanceInfo(long appId) { InstanceInfo sourceMasterInstance = null; List appInstanceInfoList = instanceDao.getInstListByAppId(appId); if (CollectionUtils.isEmpty(appInstanceInfoList)) { logger.error("appId {} has not instances", appId); return null; } for (InstanceInfo instanceInfo : appInstanceInfoList) { int instanceType = instanceInfo.getType(); if (!TypeUtil.isRedisCluster(instanceType)) { continue; } final String host = instanceInfo.getIp(); final int port = instanceInfo.getPort(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } boolean isRun = isRun(appId, host, port); if (!isRun) { logger.warn("{}:{} is not run", host, port); continue; } BooleanEnum isMaster = isMaster(appId, host, port); if (isMaster != BooleanEnum.TRUE) { logger.warn("{}:{} is not master", host, port); continue; } sourceMasterInstance = instanceInfo; break; } return sourceMasterInstance; } @Override public Map getClusterLossSlots(long appId, InstanceInfo instanceInfo) { // 2. 获取所有slot和节点的对应关系 Map slotHostPortMap = getSlotsHostPortMap(appId, instanceInfo.getIp(), instanceInfo.getPort()); // 3. 获取集群中失联的slot List lossSlotList = getClusterLossSlots(appId, instanceInfo.getIp(), instanceInfo.getPort()); // 3.1 将失联的slot列表组装成Map lossSlotList> Map> hostPortSlotMap = new HashMap>(); if (CollectionUtils.isNotEmpty(lossSlotList)) { for (Integer lossSlot : lossSlotList) { String key = slotHostPortMap.get(lossSlot); if (hostPortSlotMap.containsKey(key)) { hostPortSlotMap.get(key).add(lossSlot); } else { List list = new ArrayList(); list.add(lossSlot); hostPortSlotMap.put(key, list); } } } // 3.2 hostPortSlotMap组装成Map Map slotSegmentsMap = new HashMap(); for (Entry> entry : hostPortSlotMap.entrySet()) { List list = entry.getValue(); List slotSegments = new ArrayList(); int min = list.get(0); int max = min; for (int i = 1; i < list.size(); i++) { int temp = list.get(i); if (temp == max + 1) { max = temp; } else { slotSegments.add(String.valueOf(min) + "-" + String.valueOf(max)); min = temp; max = temp; } } slotSegments.add(String.valueOf(min) + "-" + String.valueOf(max)); slotSegmentsMap.put(entry.getKey(), slotSegments.toString()); } return slotSegmentsMap; } /** * 从一个应用中获取所有健康master节点 * * @param appId * @return 应用对应master节点列表 */ public List getAllHealthyInstanceInfo(long appId) { // return instances List allInstance = new ArrayList(); List appInstanceInfoList = instanceDao.getInstListByAppId(appId); if (CollectionUtils.isEmpty(appInstanceInfoList)) { logger.error("appId {} has not instances", appId); return null; } for (InstanceInfo instanceInfo : appInstanceInfoList) { int instanceType = instanceInfo.getType(); if (!TypeUtil.isRedisCluster(instanceType)) { continue; } final String host = instanceInfo.getIp(); final int port = instanceInfo.getPort(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } boolean isRun = isRun(appId, host, port); if (!isRun) { logger.warn("{}:{} is not run", host, port); continue; } BooleanEnum isMaster = isMaster(appId, host, port); if (isMaster != BooleanEnum.TRUE) { logger.warn("{}:{} is not master", host, port); continue; } // add exist redis allInstance.add(instanceInfo); } return allInstance; } @Override public List collectRedisLatencyInfo(long appId, long collectTime, String host, int port) { Assert.isTrue(appId > 0); Assert.hasText(host); Assert.isTrue(port > 0); InstanceInfo instanceInfo = instanceDao.getInstByIpAndPort(host, port); //不存在实例/实例异常/下线 if (instanceInfo == null) { return null; } if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { //忽略sentinel redis实例 return null; } // 从redis中获取延迟信息 List latencyHistoryList = getLatencyLatest(instanceInfo.getId(), appId, host, port); if (CollectionUtils.isEmpty(latencyHistoryList)) { return Collections.emptyList(); } //入库 String key = getThreadPoolKey() + "_" + host + "_" + port; boolean isOk = asyncService.submitFuture(getThreadPoolKey(), new KeyCallable(key) { @Override public Boolean execute() { try { instanceLatencyHistoryDao.batchSave(latencyHistoryList); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); if (!isOk) { logger.error("latencyHistory submitFuture failed,appId:{},collectTime:{},host:{},port:{}", appId, collectTime, host, port); } return latencyHistoryList; } private List getLatencyLatest(long instanceId, long appId, String host, int port) { Jedis jedis = null; try { jedis = getAdminJedis(appId, host, port, REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); List resultList = new ArrayList<>(); List latencyItems = JedisUtil.latencyLatest(jedis); List subResultList = null; if (CollectionUtils.isNotEmpty(latencyItems)) { List eventList = latencyItems.stream().map(latencyItem -> latencyItem.getEvent()).collect(Collectors.toList()); Pipeline pipeline = jedis.pipelined(); for (String event : eventList) { PipelineUtil.latencyHistory(pipeline, event); PipelineUtil.latencyReset(pipeline, event); } subResultList = pipeline.syncAndReturnAll(); if (CollectionUtils.isNotEmpty(subResultList)) { for (int i = 0; i < subResultList.size(); i++) { Object o = subResultList.get(i); if (o instanceof List) { String event = eventList.get(i / 2); List latencyHistoryItems = (List) o; List instanceLatencyHistoryList = latencyHistoryItems.stream() .map(data -> { List properties = (List) data; LatencyHistoryItem latencyHistory = new LatencyHistoryItem(properties); return new InstanceLatencyHistory( instanceId, appId, host, port, event, new Date(latencyHistory.getTimeStamp() * 1000L), latencyHistory.getExecutionTime()); }) .collect(Collectors.toList()); resultList.addAll(instanceLatencyHistoryList); } } } } return resultList; } catch (Exception e) { logger.error(String.format("appId:%s, host:%s,port:%s,error:%s", appId, host, port, e.getMessage()), e); return Collections.emptyList(); } finally { if (jedis != null) { jedis.close(); } } } /** * clusterslots命令拼接成Map * * @param host * @param port * @return */ private Map getSlotsHostPortMap(long appId, String host, int port) { Map slotHostPortMap = new HashMap(); Jedis jedis = null; try { jedis = getAdminJedis(appId, host, port); List slots = jedis.clusterSlots(); for (Object slotInfoObj : slots) { List slotInfo = (List) slotInfoObj; if (slotInfo.size() <= 2) { continue; } List slotNums = getAssignedSlotArray(slotInfo); // hostInfos List hostInfos = (List) slotInfo.get(2); if (hostInfos.size() <= 0) { continue; } HostAndPort targetNode = generateHostAndPort(hostInfos); for (Integer slot : slotNums) { slotHostPortMap.put(slot, targetNode.getHost() + ":" + targetNode.getPort()); } } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } return slotHostPortMap; } private HostAndPort generateHostAndPort(List hostInfos) { return new HostAndPort(SafeEncoder.encode((byte[]) hostInfos.get(0)), ((Long) hostInfos.get(1)).intValue()); } private List getAssignedSlotArray(List slotInfo) { List slotNums = new ArrayList(); for (int slot = ((Long) slotInfo.get(0)).intValue(); slot <= ((Long) slotInfo.get(1)) .intValue(); slot++) { slotNums.add(slot); } return slotNums; } @Override public List getClusterLossSlots(long appId, String host, int port) { InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port); if (instanceInfo == null) { logger.warn("{}:{} instanceInfo is null", host, port); return Collections.emptyList(); } if (!TypeUtil.isRedisCluster(instanceInfo.getType())) { logger.warn("{}:{} is not rediscluster type", host, port); return Collections.emptyList(); } List clusterLossSlots = new ArrayList(); Jedis jedis = null; try { jedis = getAdminJedis(appId, host, port, REDIS_DEFAULT_TIME, REDIS_DEFAULT_TIME); String clusterNodes = jedis.clusterNodes(); if (StringUtils.isBlank(clusterNodes)) { throw new RuntimeException(host + ":" + port + "clusterNodes is null"); } Set allSlots = new LinkedHashSet(); for (int i = 0; i <= 16383; i++) { allSlots.add(i); } // 解析 ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser(); for (String nodeInfo : clusterNodes.split("\n")) { if (StringUtils.isNotBlank(nodeInfo) && !nodeInfo.contains("disconnected") && !nodeInfo .contains("fail")) { if (nodeInfo.contains("@")) { // redis4.0 兼容集群协议 6397@16397 nodeInfo = nodeInfo.replaceAll(nodeInfo.substring(nodeInfo.indexOf("@"), nodeInfo.indexOf("@") + nodeInfo.split("@")[1].indexOf(" ") + 1), ""); } ClusterNodeInformation clusterNodeInfo = nodeInfoParser .parse(nodeInfo, new HostAndPort(host, port)); List availableSlots = clusterNodeInfo.getAvailableSlots(); for (Integer slot : availableSlots) { allSlots.remove(slot); } } } clusterLossSlots = new ArrayList(allSlots); } catch (Exception e) { logger.error("getClusterLossSlots: " + e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } return clusterLossSlots; } @Override public List getInstanceSlots(long appId, String healthHost, int healthPort, String lossSlotsHost, int lossSlotsPort) { InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(healthHost, healthPort); if (instanceInfo == null) { logger.warn("{}:{} instanceInfo is null", healthHost, healthPort); return Collections.emptyList(); } if (!TypeUtil.isRedisCluster(instanceInfo.getType())) { logger.warn("{}:{} is not rediscluster type", healthHost, healthPort); return Collections.emptyList(); } List clusterLossSlots = new ArrayList(); Jedis jedis = null; try { jedis = getAdminJedis(appId, healthHost, healthPort, REDIS_DEFAULT_TIME * 2, REDIS_DEFAULT_TIME * 2); String clusterNodes = jedis.clusterNodes(); if (StringUtils.isBlank(clusterNodes)) { throw new RuntimeException(healthHost + ":" + healthPort + "clusterNodes is null"); } // 解析获取丢失slots ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser(); for (String nodeInfo : clusterNodes.split("\n")) { if (StringUtils.isNotBlank(nodeInfo) && nodeInfo.contains("fail") && nodeInfo .contains(lossSlotsHost + ":" + lossSlotsPort)) { if (nodeInfo.contains("@")) { // redis4.0 兼容集群协议 6397@16397 nodeInfo = nodeInfo.replaceAll(nodeInfo.substring(nodeInfo.indexOf("@"), nodeInfo.indexOf("@") + nodeInfo.split("@")[1].indexOf(" ") + 1), ""); } ClusterNodeInformation clusterNodeInfo = nodeInfoParser .parse(nodeInfo, new HostAndPort(healthHost, healthPort)); clusterLossSlots = clusterNodeInfo.getAvailableSlots(); } } } catch (Exception e) { logger.error("getClusterLossSlots: " + e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } return clusterLossSlots; } @PreDestroy public void destory() { for (JedisPool jedisPool : jedisPoolMap.values()) { jedisPool.destroy(); } } @Override public List getInstanceSlowLogByAppId(long appId) { try { return instanceSlowLogDao.getByAppId(appId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate) { try { return instanceSlowLogDao.search(appId, startDate, endDate); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public Map getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate) { try { List> list = instanceSlowLogDao .getInstanceSlowLogCountMapByAppId(appId, startDate, endDate); if (CollectionUtils.isEmpty(list)) { return Collections.emptyMap(); } Map resultMap = new LinkedHashMap(); for (Map map : list) { long count = MapUtils.getLongValue(map, "count"); String hostPort = MapUtils.getString(map, "hostPort"); if (StringUtils.isNotBlank(hostPort)) { resultMap.put(hostPort, count); } } return resultMap; } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public Map getClusterSlotsMap(long appId) { AppDesc appDesc = appDao.getAppDescById(appId); if (!TypeUtil.isRedisCluster(appDesc.getType())) { return Collections.emptyMap(); } // 最终结果 Map resultMap = new HashMap(); // 找到一个运行的节点用来执行cluster slots List instanceList = instanceDao.getInstListByAppId(appId); String host = null; int port = 0; for (InstanceInfo instanceInfo : instanceList) { // 下线和心跳停止 均跳过 if (instanceInfo.isOffline() || instanceInfo.getStatus() == InstanceStatusEnum.ERROR_STATUS.getStatus()) { continue; } host = instanceInfo.getIp(); port = instanceInfo.getPort(); boolean isRun = isRun(appId, host, port); if (isRun) { break; } } if (StringUtils.isBlank(host) || port <= 0) { return Collections.emptyMap(); } // 获取cluster slots List clusterSlotList = null; Jedis jedis = null; try { jedis = getAdminJedis(appId, host, port); clusterSlotList = jedis.clusterSlots(); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } if (clusterSlotList == null || clusterSlotList.size() == 0) { return Collections.emptyMap(); } //clusterSlotList形如: // [0, 1, [[B@5caf905d, 6380], [[B@27716f4, 6379]] // [3, 4096, [[B@8efb846, 6380], [[B@2a84aee7, 6379]] // [12291, 16383, [[B@a09ee92, 6383], [[B@30f39991, 6382]] // [2, 2, [[B@452b3a41, 6381], [[B@4a574795, 6382]] // [8194, 12290, [[B@f6f4d33, 6381], [[B@23fc625e, 6382]] // [4097, 8193, [[B@3f99bd52, 6380], [[B@4f023edb, 6381]] for (Object clusterSlotObj : clusterSlotList) { List slotInfoList = (List) clusterSlotObj; if (slotInfoList.size() <= 2) { continue; } //获取slot的start到end相关 int startSlot = ((Long) slotInfoList.get(0)).intValue(); int endSlot = ((Long) slotInfoList.get(1)).intValue(); String slotDistribute = getStartToEndSlotDistribute(startSlot, endSlot); List slotList = getStartToEndSlotList(startSlot, endSlot); List masterInfoList = (List) slotInfoList.get(2); String tempHost = SafeEncoder.encode((byte[]) masterInfoList.get(0)); int tempPort = ((Long) masterInfoList.get(1)).intValue(); String hostPort = tempHost + ":" + tempPort; if (resultMap.containsKey(hostPort)) { InstanceSlotModel instanceSlotModel = resultMap.get(hostPort); instanceSlotModel.getSlotDistributeList().add(slotDistribute); instanceSlotModel.getSlotList().addAll(slotList); } else { InstanceSlotModel instanceSlotModel = new InstanceSlotModel(); instanceSlotModel.setHost(tempHost); instanceSlotModel.setPort(tempPort); List slotDistributeList = new ArrayList(); slotDistributeList.add(slotDistribute); instanceSlotModel.setSlotDistributeList(slotDistributeList); instanceSlotModel.setSlotList(slotList); resultMap.put(hostPort, instanceSlotModel); } } return resultMap; } /** * 获取集群slot分布 * -> > * @param instanceInfo * @return */ public Map> getClusterSlotMap(long appId, InstanceInfo instanceInfo){ Map> resultMap = new HashMap<>(); // 如未传入实例,则查找一个健康的实例 if(instanceInfo == null){ // 找到一个运行的节点来执行 List instanceList = instanceDao.getEffectiveInstListByAppId(appId); for (InstanceInfo instance : instanceList) { // 下线和心跳停止 均跳过 if (instance.isOffline() || instance.getStatus() == InstanceStatusEnum.ERROR_STATUS.getStatus()) { continue; } boolean isRun = isRun(appId, instance.getIp(), instance.getPort()); if (isRun) { instanceInfo = instance; break; } } } if(instanceInfo != null){ try (Jedis jedis = this.getJedis(appId, instanceInfo.getIp(), instanceInfo.getPort())) { List slots = jedis.clusterSlots(); for (Object clusterSlotObj : slots) { List slotInfoList = (List) clusterSlotObj; if (slotInfoList.size() <= 2) { continue; } //获取slot的start到end相关 String key = slotInfoList.get(0) + "-" + slotInfoList.get(1); List slotInstances = new ArrayList<>(); for(int i = 2; i < slotInfoList.size(); i++){ List nodeInfo = (List) slotInfoList.get(i); if(nodeInfo.size() <= 2){ continue; } String tempHost = SafeEncoder.encode((byte[]) nodeInfo.get(0)); int tempPort = ((Long) nodeInfo.get(1)).intValue(); slotInstances.add(new HostAndPort(tempHost, tempPort)); } if(CollectionUtils.isNotEmpty(slotInstances)){ resultMap.put(key, slotInstances); } } String clusterNodes = jedis.clusterNodes(); List needDeleteKeys = new ArrayList<>(); for (String nodeInfo : clusterNodes.split("\n")) { if (StringUtils.isNotBlank(nodeInfo) && nodeInfo.contains("fail")) { Set>> entrySet = resultMap.entrySet(); entrySet.forEach(entry -> { List hostAndPorts = entry.getValue(); if(CollectionUtils.isNotEmpty(hostAndPorts) && nodeInfo.contains(hostAndPorts.get(0).toString())){ needDeleteKeys.add(entry.getKey()); } }); } } needDeleteKeys.forEach(key -> resultMap.remove(key)); }catch (Exception e){ logger.error("getClusterSlotMap error,", e); } } return resultMap; } /** * 获取slot列表 * * @param startSlot * @param endSlot * @return */ private List getStartToEndSlotList(int startSlot, int endSlot) { List slotList = new ArrayList(); if (startSlot == endSlot) { slotList.add(startSlot); } else { for (int i = startSlot; i <= endSlot; i++) { slotList.add(i); } } return slotList; } /** * 0,4096 0-4096 * 2,2 2-2 * * @return */ private String getStartToEndSlotDistribute(int startSlot, int endSlot) { if (startSlot == endSlot) { return String.valueOf(startSlot); } else { return startSlot + "-" + endSlot; } } @Override public String getRedisVersion(long appId, String ip, int port) { Map> infoAllMap = getInfoStats(appId, ip, port); if (MapUtils.isEmpty(infoAllMap)) { return null; } Map serverMap = infoAllMap.get(RedisConstant.Server); if (MapUtils.isEmpty(serverMap)) { return null; } return MapUtils.getString(serverMap, "redis_version"); } public Boolean getRedisReplicationStatus(long appId, String ip, int port) { Map> infoAllMap = getInfoStats(appId, ip, port); if (MapUtils.isEmpty(infoAllMap)) { return false; } Map serverMap = infoAllMap.get(RedisConstant.Replication); if (MapUtils.isEmpty(serverMap)) { return false; } /** * 主从failover (info replication) slave0 state 状态变化: wait_bgsave -> send_bulk -> online * 1.slave0 ip=${ip},port=${port},state=online,offset=413125529634,lag=1 * 2.master_repl_offset 413125537241 */ String slave0 = MapUtils.getString(serverMap, "slave0"); String master_repl_offset = MapUtils.getString(serverMap, "master_repl_offset"); String role = MapUtils.getString(serverMap, "role"); logger.info("salve0 :{} ,master_repl_offset :{}", slave0, master_repl_offset); try { if (!StringUtils.isEmpty(slave0) && slave0.indexOf("state=online") > -1 && role.equals("master") && !StringUtils.isEmpty(master_repl_offset)) { long slave_offset = 0l; for (String info : slave0.split(",")) { if (info.indexOf("offset") > -1) { logger.info(" slave offset = {} ", info.replaceAll("offset=", "")); slave_offset = Long.parseLong(info.replaceAll("offset=", "")); } } // 从偏移量差值 ,load内存数据 offset if (slave_offset == 0) { return false; } return true; } else { return false; } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } /** * * @param appId * @param ip * @param port * @return */ @Override public Map getRedisRoleAndMasterStatus(long appId, String ip, int port){ Map resultMap = new HashMap<>(); try (Jedis jedis = getJedis(appId, ip, port);){ String info = jedis.info(RedisConstant.Replication.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Replication); if (map == null) { return resultMap; } String role = MapUtils.getString(map, RedisInfoEnum.role.getValue()); resultMap.put(RedisInfoEnum.role.getValue(), role); if(InstanceRoleEnum.SLAVE.getInfo().equals(role)){ String masterLinkStatus = MapUtils.getString(map, RedisInfoEnum.master_link_status.getValue()); resultMap.put(RedisInfoEnum.master_link_status.getValue(), masterLinkStatus); } } return resultMap; } @Override public Boolean getRedisFailoverForceStatus(long appId, String ip, int port){ Map> infoAllMap = getInfoStats(appId, ip, port); if (MapUtils.isEmpty(infoAllMap)) { return false; } Map serverMap = infoAllMap.get(RedisConstant.Replication); if (MapUtils.isEmpty(serverMap)) { return false; } /** * failover force 只管role角色变更, 且master_failover_state 未在进行中 */ String role = MapUtils.getString(serverMap, "role"); String master_repl_offset = MapUtils.getString(serverMap, "master_repl_offset"); String master_failover_state = MapUtils.getString(serverMap, "master_failover_state"); logger.info("redis failover force slave: {}:{} ,master_repl_offset :{}", ip, port, master_repl_offset); try { if (role.equals("master") && !StringUtils.isEmpty(master_repl_offset) && (StringUtils.isBlank(master_failover_state) || master_failover_state.equals("no-failover"))) { return true; } else { return false; } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } @Override public String getNodeId(long appId, String ip, int port) { final Jedis jedis = getAdminJedis(appId, ip, port); try { final StringBuilder clusterNodes = new StringBuilder(); boolean isGetNodes = new IdempotentConfirmer() { @Override public boolean execute() { String nodes = jedis.clusterNodes(); if (nodes != null && nodes.length() > 0) { clusterNodes.append(nodes); return true; } return false; } }.run(); if (!isGetNodes) { logger.error("{}:{} clusterNodes failed", jedis.getClient().getHost(), jedis.getClient().getPort()); return null; } for (String infoLine : clusterNodes.toString().split("\n")) { if (infoLine.contains("myself")) { String nodeId = infoLine.split(" ")[0]; return nodeId; } } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } return null; } @Override public Jedis getJedis(long appId, String host, int port) { Jedis jedis = getJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); return jedis; } @Override public Jedis getJedis(long appId, String host, int port, int connectionTimeout, int soTimeout) { AppDesc appDesc = appDao.getAppDescById(appId); String password = appDesc.getAppPassword(); Jedis jedis = getJedis(host, port, connectionTimeout, soTimeout, password); return jedis; } @Override public Jedis getJedis(String host, int port, String authPassword) { return getJedis(host, port, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, authPassword); } @Override public Jedis getAdminJedis(long appId, String host, int port) { Jedis jedis = getAdminJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); return jedis; } @Override public Jedis getAdminJedis(long appId, String host, int port, int connectionTimeout, int soTimeout) { AppDesc appDesc = appDao.getAppDescById(appId); String password = appDesc.getAppPassword(); Jedis jedis = getJedis(host, port, connectionTimeout, soTimeout, password); return jedis; } @Override public Jedis getAdminJedis(String host, int port, String adminPassword) { return getAdminJedis(host, port, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT, adminPassword); } @Override public Jedis getJedis(String host, int port) { return getJedis(host, port, null); } @Override public Jedis getJedis(String host, int port, String password, int connectionTimeout, int soTimeout){ return getJedis(host, port, connectionTimeout, soTimeout, password); } private Jedis getJedis(String host, int port, int connectionTimeout, int soTimeout, String authPassword) { Jedis jedis = new Jedis(host, port); jedis.getClient().setConnectionTimeout(connectionTimeout); jedis.getClient().setSoTimeout(soTimeout); try { if (StringUtils.isBlank(authPassword)) { // 保证存活性 jedis.ping(); } else { AuthUtil.auth(jedis, authPassword); } } catch (Exception e) { //防止加载RBD期间报:JedisDataException: LOADING Redis is loading the dataset in memory错误 logger.error(String.format("getJedis exception host:%s, port:%s, conTimeout:%s, soTimeout:%s, error:%s", host, port, connectionTimeout, soTimeout, e.getMessage()), e); } return jedis; } private Jedis getAdminJedis(String host, int port, int connectionTimeout, int soTimeout, String adminPassword) { return getJedis(host, port, connectionTimeout, soTimeout, adminPassword); } private void fixReadOnlyOfCluster(long appId, Jedis jedis) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return; } } @Override public boolean sendDeployRedisRelateCollectionMsg(long appId, String host, int port) { return true; } @Override public boolean checkNutCrackerConfIsSame(long appId) { List masterNameList = getMasterNameListFromNutCrackerConf(appId); if (CollectionUtils.isNotEmpty(masterNameList)) { return true; } return false; } private List getMasterNameListFromNutCrackerConf(long appId) { List> appNutCrackerMasterList = getFullInstanceListFromNutCrackerConf(appId); if (CollectionUtils.isEmpty(appNutCrackerMasterList)) { return Collections.emptyList(); } List nutCrackerMasterList = appNutCrackerMasterList.get(0); List masterNameList = new ArrayList(); for (String nutCrackerMaster : nutCrackerMasterList) { String[] arr = nutCrackerMaster.split("\\s+"); masterNameList.add(arr[arr.length - 1].trim()); } return masterNameList; } public List> getFullInstanceListFromNutCrackerConf(long appId) { Map> appNutCrackerMasterMap = getAppNutCrackerMasterList(appId); if (MapUtils.isEmpty(appNutCrackerMasterMap)) { logger.error(BaseTask.marker, "appId {} appNutCrackerMasterListMap is empty", appId); return Collections.emptyList(); } List ipPortList = new ArrayList(); List> appNutCrackerMasterList = new ArrayList>(); for (Entry> entry : appNutCrackerMasterMap.entrySet()) { ipPortList.add(entry.getKey()); appNutCrackerMasterList.add(entry.getValue()); } for (int i = 0; i < appNutCrackerMasterList.size() - 1; i++) { List appNutCrackerMasterList1 = appNutCrackerMasterList.get(i); List appNutCrackerMasterList2 = appNutCrackerMasterList.get(i + 1); if (appNutCrackerMasterList1.size() != appNutCrackerMasterList2.size()) { logger.error(BaseTask.marker, "{} and {} config size is not same", ipPortList.get(i), ipPortList.get(i + 1)); return Collections.emptyList(); } for (int j = 0; j < appNutCrackerMasterList1.size(); j++) { if (!appNutCrackerMasterList1.get(j).trim().equals(appNutCrackerMasterList2.get(j).trim())) { logger.error(BaseTask.marker, "{} and {} config content is not same", ipPortList.get(i), ipPortList.get(i + 1)); return Collections.emptyList(); } } } return appNutCrackerMasterList; } /** * 获取所有在线的proxy配置 * * @param appId * @return */ private Map> getAppNutCrackerMasterList(long appId) { Map> resultMap = new HashMap>(); List instanceInfoList = appService.getAppInstanceByType(appId, InstanceTypeEnum.NUTCRACKER); for (InstanceInfo instanceInfo : instanceInfoList) { if (!instanceInfo.isOnline()) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); String remoteBasePath = machineCenter.getInstanceRemoteBasePath(appId, instanceInfo.getPort(), InstanceTypeEnum.NUTCRACKER); String confPath = MachineProtocol.getConfPath(remoteBasePath) + "/" + RedisProtocol.getNutCrackerConfName(); String commandResult = machineCenter.executeShell(instanceInfo.getIp(), "cat " + confPath); if (StringUtils.isBlank(commandResult)) { logger.error(BaseTask.marker, "appId {} {}:{} nutcrack conf {} is empty", appId, host, port, confPath); return Collections.emptyMap(); } List masterNameList = new ArrayList(); String[] lines = commandResult.split("\n"); for (String line : lines) { if (StringUtils.isBlank(line)) { continue; } if (!line.contains("-")) { continue; } if (line.split(":").length < 2) { continue; } masterNameList.add(line); } resultMap.put(host + ":" + port, masterNameList); } return resultMap; } @Override public List checkNutCrackerHashIsSame(long appId, boolean isDelete) { return null; } private class RedisKeyCallable extends KeyCallable { private final long appId; private final long collectTime; private final String host; private final int port; private final Map> infoMap; private final Map clusterInfoMap; private RedisKeyCallable(long appId, long collectTime, String host, int port, Map> infoMap, Map clusterInfoMap) { super(buildFutureKey(appId, collectTime, host, port)); this.appId = appId; this.collectTime = collectTime; this.host = host; this.port = port; this.infoMap = infoMap; this.clusterInfoMap = clusterInfoMap; } @Override public Boolean execute() { //比对currentInfoMap和lastInfoMap,计算差值 long lastCollectTime = ScheduleUtil.getLastCollectTime(collectTime); Map lastInfoMap = instanceStatsCenter .queryStandardInfoMap(lastCollectTime, host, port, ConstUtils.REDIS); if (lastInfoMap == null || lastInfoMap.isEmpty()) { logger.error("[redis-lastInfoMap] : lastCollectTime = {} appId={} host:port = {}:{} is null", lastCollectTime, appId, host, port); } //基本统计累加差值 Table baseDiffTable = getAccumulationDiff(infoMap, lastInfoMap); fillAccumulationMap(infoMap, baseDiffTable); //命令累加差值 Table commandDiffTable = getCommandsDiff(infoMap, lastInfoMap); fillAccumulationMap(infoMap, commandDiffTable); //内存碎片率差值计算 //Table otherDiffTable = getDoubleAccumulationDiff(infoMap, lastInfoMap); //fillDoubleAccumulationMap(infoMap, otherDiffTable); fillMemFragRatioMap(infoMap); Map currentInfoMap = new LinkedHashMap(); for (Map.Entry> entry : infoMap.entrySet()) { currentInfoMap.put(((RedisConstant)(entry.getKey())).getValue(), entry.getValue()); } currentInfoMap.put(ConstUtils.COLLECT_TIME, collectTime); instanceStatsCenter.saveStandardStats(currentInfoMap, clusterInfoMap, host, port, ConstUtils.REDIS); // 更新实例在db中的状态 InstanceStats instanceStats = getInstanceStats(appId, host, port, infoMap); if (instanceStats != null) { instanceStatsDao.updateInstanceStats(instanceStats); } BooleanEnum isMaster = isMaster(infoMap); Table diffTable = HashBasedTable.create(); diffTable.putAll(baseDiffTable); diffTable.putAll(commandDiffTable); //更新命令统计 List commandStatsList = getCommandStatsList(appId, collectTime, diffTable); //写入app分钟统计 AppStats appStats = null; if (isMaster == BooleanEnum.TRUE){ //写入app分钟统计 appStats = getAppStats(appId, collectTime, diffTable, infoMap); this.mergeCommandStats(commandStatsList, appStats); logger.debug("collect redis info done, appId: {}, instance: {}:{}, time: {}", appId, host, port, collectTime); } return true; } private void mergeCommandStats(List commandStatsList, AppStats appStats){ long allCommandCount = 0L; for (AppCommandStats commandStats : commandStatsList) { //排除无效命令且存储有累加的数据 if (RedisExcludeCommand.isExcludeCommand(commandStats.getCommandName()) || commandStats.getCommandCount() <= 0L) { continue; } allCommandCount += commandStats.getCommandCount(); try { // todo 数据库(on duplicate key update)竞争优化 appStatsDao.mergeMinuteCommandStatus(commandStats); appStatsDao.mergeHourCommandStatus(commandStats); } catch (Exception e) { logger.error(e.getMessage() + appId, e); } } if(appStats != null){ try { appStats.setCommandCount(allCommandCount); // todo 数据库(on duplicate key update)竞争优化 appStatsDao.mergeMinuteAppStats(appStats); appStatsDao.mergeHourAppStats(appStats); } catch (Exception e) { logger.error(e.getMessage() + appId, e); } } } } @Override public String configGet(long appId, String host, int port, String key) { Jedis jedis = this.getAdminJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { List values = jedis.configGet(key); if (values == null || values.size() < 1) { return null; } return values.get(1); } catch (Exception e) { logger.error("config get {} from host:{} port:{} error: {}", key, host, port, e.getMessage()); } finally { jedis.close(); } return null; } @Override public boolean configSetAndRewrite(long appId, String host, int port, String key, String value) { Jedis jedis = this.getAdminJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { boolean isConfig = new IdempotentConfirmer() { @Override public boolean execute() { String result = jedis.configSet(key, value); boolean isConfig = result != null && result.equalsIgnoreCase("OK"); if (!isConfig) { logger.error("config set key:{} value:{} host:{} port:{} result:{}", key, value, host, port, result); return false; } return isConfig; } }.run(); String response = jedis.configRewrite(); boolean isRewrite = response != null && response.equalsIgnoreCase("OK"); if (!isRewrite) { logger.error("config rewrite after config set key:{} value:{} host:{} port:{} result:{}", key, value, host, port); } return isConfig; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } finally { if (jedis != null) jedis.close(); } } /** * 检测从节点是否准备OK * @param appId * @param ip * @param port * @param offset * @return */ @Override public boolean checkSlaveReady(long appId, String ip, int port, long offset) { Jedis jedis = null; try { jedis = getJedis(appId, ip, port); return this.checkSlaveReady(jedis, offset); } catch (Exception e) { logger.error("{}:{} checkSlaveReady failed {}", ip, port, e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } return false; } /** * 获取节点角色描述 * @param jedis * @return */ @Override public String getInstanceRole(Jedis jedis) { try { String info = jedis.info(RedisConstant.Replication.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Replication); if (map != null) { String role = MapUtils.getString(map, RedisInfoEnum.role.getValue(), null); return role; } } catch (Exception e) { logger.error("{}:{} getInstanceRole failed {}", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage(), e); } return null; } public String getInstanceRole(long appId, String ip, int port){ Jedis jedis = null; try { jedis = getJedis(appId, ip, port); return getInstanceRole(jedis); } catch (Exception e) { logger.error("{}:{} getInstanceRole failed {}", ip, port, e.getMessage(), e); } finally { if (jedis != null) jedis.close(); } return null; } /** * 检测从节点是否准备OK * @param jedis * @param offset * @return */ @Override public boolean checkSlaveReady(Jedis jedis, Long offset) { try { String info = jedis.info(RedisConstant.Replication.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Replication); if (map == null) { return false; } String role = MapUtils.getString(map, RedisInfoEnum.role.getValue(), null); String master_link_status = MapUtils.getString(map, RedisInfoEnum.master_link_status.getValue(), null); long slaveReplOffset = MapUtils.getLong(map, RedisInfoEnum.slave_repl_offset.getValue(), 0L); long masterReplOffset = MapUtils.getLong(map, RedisInfoEnum.master_repl_offset.getValue(), 0L); long masterSyncInProgress = MapUtils.getLong(map, RedisInfoEnum.master_sync_in_progress.getValue(), -1L); if("slave".equals(role) && "up".equals(master_link_status) && masterSyncInProgress == 0){ if(offset != null && slaveReplOffset >= 0 && masterReplOffset >= 0 && masterReplOffset - slaveReplOffset > offset){ return false; } return true; } } catch (Exception e) { logger.error(String.format("%s:%s checkSlaveReady failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } return false; } /** * 检测bgsave是否完成 * @param jedis * @return */ @Override public boolean checkBgsaveFinish(Jedis jedis, int checkTimes) { try { long rdb_last_bgsave_time_sec = 0L; while (checkTimes > 0){ checkTimes--; String info = jedis.info(RedisConstant.Persistence.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Persistence); if (map == null) { return false; } Integer inProgress = MapUtils.getInteger(map, RedisInfoEnum.rdb_bgsave_in_progress.getValue(), null); long lastSaveTime = MapUtils.getLong(map, RedisInfoEnum.rdb_last_save_time.getValue(), 0L); rdb_last_bgsave_time_sec = MapUtils.getLong(map, RedisInfoEnum.rdb_last_bgsave_time_sec.getValue(), 0L); String lastBgsaveStatus = MapUtils.getString(map, RedisInfoEnum.rdb_last_bgsave_status.getValue(), null); if(inProgress != null && inProgress == 0 && "ok".equals(lastBgsaveStatus) && System.currentTimeMillis()/1000 - lastSaveTime <= 300){ return true; } if(inProgress != null && inProgress == 1){ try{ TimeUnit.SECONDS.sleep(rdb_last_bgsave_time_sec > 10 ? rdb_last_bgsave_time_sec : 5); }catch (Exception e){ logger.error(String.format("%s:%s checkBgsaveFinish sleep failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } } } } catch (Exception e) { logger.error(String.format("%s:%s checkBgsaveFinish failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } return false; } /** * 检测load rdb/aof是否完成 * @param jedis * @return */ @Override public boolean checkLoadFinish(Jedis jedis, int checkTimes) { try { long sleepTime = 0L; while (checkTimes-- > 0){ String info = jedis.info(RedisConstant.Persistence.getValue()); Map> infoMap = processRedisStats(info); Map map = infoMap.get(RedisConstant.Persistence); if (map == null) { logger.error("{}:{} checkLoadFinish info persistence null, infoMap: {}", jedis.getClient().getHost(), jedis.getClient().getPort(), infoMap); continue; } Integer inProgress = MapUtils.getInteger(map, RedisInfoEnum.loading.getValue(), null); Integer etaSeconds = MapUtils.getInteger(map, RedisInfoEnum.loading_eta_seconds.getValue(), null); logger.error("{}:{} checkLoadFinish inProgress: {}, etaSeconds: {}", jedis.getClient().getHost(), jedis.getClient().getPort(), inProgress, etaSeconds); if(inProgress != null && inProgress == 0){ return true; } if(inProgress != null && inProgress == 1){ if(etaSeconds != null && etaSeconds > 0){ sleepTime = etaSeconds; }else { sleepTime = 5; } try{ TimeUnit.SECONDS.sleep(sleepTime); }catch (Exception e){ logger.error(String.format("%s:%s checkLoadFinish sleep failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } } } } catch (Exception e) { logger.error(String.format("%s:%s checkLoadFinish failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } return false; } /** * 获取rdb文件名 * @param jedis * @return */ @Override public String getRdbFileName(Jedis jedis) { try { List list = jedis.configGet("dbfilename"); if (CollectionUtils.isNotEmpty(list) && list.size() >= 2) { return list.get(1); } }catch (Exception e){ logger.error(String.format("%s:%s getRdbFileName failed %s", jedis.getClient().getHost(), jedis.getClient().getPort(), e.getMessage()), e); } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/impl/RedisConfigTemplateServiceImpl.java ================================================ package com.sohu.cache.redis.impl; import com.sohu.cache.constant.BaseConstant; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.InstanceConfigDao; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.redis.enums.RedisClusterConfigEnum; import com.sohu.cache.redis.enums.RedisConfigEnum; import com.sohu.cache.redis.enums.RedisSentinelConfigEnum; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.RedisConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * redis配置模板服务 * * @author leifu * @Date 2016年6月23日 * @Time 下午2:08:03 */ @Service("redisConfigTemplateService") public class RedisConfigTemplateServiceImpl implements RedisConfigTemplateService { private Logger logger = LoggerFactory.getLogger(RedisConfigTemplateServiceImpl.class); private final static String SPECIAL_EMPTY_STR = "\"\""; @Autowired private InstanceConfigDao instanceConfigDao; @Autowired private ResourceService resourceService; @Autowired private ResourceDao resourceDao; @Autowired private MachineDao machineDao; @Autowired private AppService appService; @Autowired @Lazy private RedisCenter redisCenter; @Autowired private RedisDeployCenter redisDeployCenter; @Autowired private InstanceDeployCenter instanceDeployCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired SSHService sshService; private static int RETRY_TIMES = 30; private static long SLEEP_MILLS = 2000; private static int WAITING_RESOURCE_SECOND = 5; private static int WAITING_RETRY_TIMES = 10; private static int DOWNLOAD_SECONDS = 60 * 5 * 1000; private static String DOWNLOAD_CMD = "cd %s && wget %s && tar -xvf %s && rm -rf %s "; @Override public List getAllInstanceConfig() { try { return instanceConfigDao.getAllInstanceConfig(); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getByType(int type) { try { return instanceConfigDao.getByType(type); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public List getByVesionAndType(int type, int versionId) { try { return instanceConfigDao.getByVersionAndType(type, versionId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public List getByVesion(int versionId) { try { return instanceConfigDao.getByVersion(versionId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public int saveOrUpdate(InstanceConfig instanceConfig) { return instanceConfigDao.saveOrUpdate(instanceConfig); } @Override public InstanceConfig getById(long id) { try { return instanceConfigDao.getById(id); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public InstanceConfig getByConfigKeyAndType(String configKey, int type) { try { return instanceConfigDao.getByConfigKeyAndType(configKey, type); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public int remove(long id) { return instanceConfigDao.remove(id); } @Override public int updateStatus(long id, int status) { return instanceConfigDao.updateStatus(id, status); } @Override public List handleCommonConfig(String host, int port, int maxMemory, String maxMemoryPolicy, int versionId) { //2018-08-24 List instanceConfigList = getByVesionAndType(ConstUtils.CACHE_REDIS_STANDALONE, versionId); if (CollectionUtils.isEmpty(instanceConfigList)) { return Collections.emptyList(); } List configs = new ArrayList(); for (InstanceConfig instanceConfig : instanceConfigList) { // 无效配置过滤 if (!instanceConfig.isEffective()) { continue; } String configKey = instanceConfig.getConfigKey(); String configValue = instanceConfig.getConfigValue(); if (StringUtils.isBlank(configValue)) { configValue = SPECIAL_EMPTY_STR; } if (RedisConfigEnum.MAXMEMORY.getKey().equals(configKey)) { configValue = String.format(configValue, maxMemory); } else if (RedisConfigEnum.DBFILENAME.getKey().equals(configKey) || RedisConfigEnum.APPENDFILENAME.getKey().equals(configKey) || RedisConfigEnum.PORT.getKey().equals(configKey)) { configValue = String.format(configValue, port); } else if (RedisConfigEnum.DIR.getKey().equals(configKey)) { configValue = machineCenter.getMachineRelativeDir(host, DirEnum.DATA_DIR.getValue()); } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getKey().equals(configKey)) { //随机比例 auto-aof-rewrite-percentage int percent = 69 + new Random().nextInt(30); configValue = String.format(configValue, percent); } else if (RedisConfigEnum.BIND.getKey().equals(configKey)) { configValue = String.format(configValue, host); } else if (RedisConfigEnum.MAXMEMORY_POLICY.getKey().equals(configKey)) { if (StringUtils.isNotEmpty(maxMemoryPolicy)) { configValue = maxMemoryPolicy; } } configs.add(combineConfigKeyValue(configKey, configValue)); } return configs; } @Override public List handleSentinelConfig(String masterName, String host, int port, String sentinelHost, int sentinelPort, int versionId, List> customConfigs) { List instanceConfigList = getByVesionAndType(ConstUtils.CACHE_REDIS_SENTINEL, versionId); instanceConfigList = instanceConfigList.stream().filter(InstanceConfig::isEffective).collect(Collectors.toList()); if (CollectionUtils.isEmpty(instanceConfigList)) { return Collections.emptyList(); } Map> notExistConfigMap = new HashMap<>(); Map> customConfigMap = new HashMap<>(); this.getCustomMapParam(instanceConfigList, customConfigs, customConfigMap, notExistConfigMap); List configs = new ArrayList(); for (InstanceConfig instanceConfig : instanceConfigList) { String configKey = instanceConfig.getConfigKey(); String configValue = instanceConfig.getConfigValue(); if (StringUtils.isBlank(configValue)) { configValue = SPECIAL_EMPTY_STR; } if (RedisSentinelConfigEnum.PORT.getKey().equals(configKey)) { configValue = String.format(configValue, sentinelPort); } else if (RedisSentinelConfigEnum.MONITOR.getKey().equals(configKey)) { configValue = String.format(configValue, masterName, host, port); } else if (RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getKey().equals(configKey) || RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getKey().equals(configKey) || RedisSentinelConfigEnum.PARALLEL_SYNCS.getKey().equals(configKey)) { configValue = String.format(configValue, masterName); } else if (RedisConfigEnum.DIR.getKey().equals(configKey)) { configValue = machineCenter.getMachineRelativeDir(sentinelHost, DirEnum.DATA_DIR.getValue()); } else { if(customConfigMap.containsKey(configKey)){ configValue = this.setCustomConfigs(configKey, configValue, configs, customConfigMap); } } configs.add(combineConfigKeyValue(configKey, configValue)); } this.setNewConfigDirectly(configs, notExistConfigMap); return configs; } private void getCustomMapParam(List instanceConfigList, List> customConfigs, Map> customConfigMap, Map> notExistConfigMap){ Map instanceConfigMap = instanceConfigList.stream().collect(Collectors.toMap(InstanceConfig::getConfigKey, InstanceConfig::getConfigValue)); if(CollectionUtils.isNotEmpty(customConfigs)){ customConfigs.forEach(customConfig -> { if(customConfigMap.containsKey(customConfig.getKey())){ customConfigMap.get(customConfig.getKey()).add(customConfig.getValue()); }else{ List confiValues = new ArrayList<>(); confiValues.add(customConfig.getValue()); customConfigMap.put(customConfig.getKey(), confiValues); } }); } customConfigMap.keySet().forEach(key -> { if (!instanceConfigMap.containsKey(key)) { notExistConfigMap.put(key, customConfigMap.get(key)); } }); } private String setCustomConfigs(String configKey, String configValue, List configs, Map> customConfigMap){ List configValues = customConfigMap.get(configKey); if(configValues.size() == 1){ configValue = configValues.get(0); } else { IntStream.range(0, configValues.size() - 1).forEach(i -> configs.add(combineConfigKeyValue(configKey, configValues.get(i))) ); configValue = configValues.get(configValues.size() - 1); } return configValue; } private void setNewConfigDirectly(List configs, Map> notExistConfigMap){ notExistConfigMap.forEach((configKey, configValues) -> configValues.forEach(configValue -> configs.add(combineConfigKeyValue(configKey, configValue)) ) ); } @Override public List handleClusterConfig(int port, int versionId) { List instanceConfigList = getByVesionAndType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER, versionId); if (CollectionUtils.isEmpty(instanceConfigList)) { return Collections.emptyList(); } List configs = new ArrayList(); for (InstanceConfig instanceConfig : instanceConfigList) { if (!instanceConfig.isEffective()) { continue; } String configKey = instanceConfig.getConfigKey(); String configValue = instanceConfig.getConfigValue(); if (StringUtils.isBlank(configValue)) { configValue = SPECIAL_EMPTY_STR; } if (RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey().equals(configKey)) { configValue = String.format(configValue, port); } configs.add(combineConfigKeyValue(configKey, configValue)); } return configs; } // @Override // public List handleCommonDefaultConfig(int port, int maxMemory) { // List configs = new ArrayList(); // for (RedisConfigEnum config : RedisConfigEnum.values()) { // if (RedisConfigEnum.MAXMEMORY.equals(config)) { // configs.add(config.getKey() + " " + String.format(config.getValue(), maxMemory)); // } else if (RedisConfigEnum.DBFILENAME.equals(config) || // RedisConfigEnum.APPENDFILENAME.equals(config) || RedisConfigEnum.PORT.equals(config)) { // configs.add(config.getKey() + " " + String.format(config.getValue(), port)); // } else if (RedisConfigEnum.DIR.equals(config)) { // configs.add(config.getKey() + " " + MachineProtocol.DATA_DIR); // } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.equals(config)) { // //随机比例 auto-aof-rewrite-percentage // int percent = 69 + new Random().nextInt(30); // configs.add(config.getKey() + " " + String.format(RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getValue(), percent)); // } else { // configs.add(config.getKey() + " " + config.getValue()); // } // } // return configs; // } @Override public List handleSentinelDefaultConfig(String masterName, String host, int port, int sentinelPort) { List configs = new ArrayList(); configs.add(RedisSentinelConfigEnum.PORT.getKey() + " " + String.format(RedisSentinelConfigEnum.PORT.getValue(), sentinelPort)); configs.add(RedisSentinelConfigEnum.DIR.getKey() + " " + RedisSentinelConfigEnum.DIR.getValue()); configs.add(RedisSentinelConfigEnum.MONITOR.getKey() + " " + String.format(RedisSentinelConfigEnum.MONITOR.getValue(), masterName, host, port, 1)); configs.add(RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getKey() + " " + String .format(RedisSentinelConfigEnum.DOWN_AFTER_MILLISECONDS.getValue(), masterName)); configs.add(RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getKey() + " " + String .format(RedisSentinelConfigEnum.FAILOVER_TIMEOUT.getValue(), masterName)); configs.add(RedisSentinelConfigEnum.PARALLEL_SYNCS.getKey() + " " + String .format(RedisSentinelConfigEnum.PARALLEL_SYNCS.getValue(), masterName)); return configs; } // @Override // public List handleClusterDefaultConfig(int port) { // List configs = new ArrayList(); // for (RedisClusterConfigEnum config : RedisClusterConfigEnum.values()) { // if (config.equals(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE)) { // configs.add(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey() + " " // + String.format(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getValue(), port)); // } else { // configs.add(config.getKey() + " " // + config.getValue()); // } // } // return configs; // } public SystemResource getRedisVersionByName(String versionName) { return resourceDao.getResourceByName(versionName); } public String copyRedisConfig(int versionCopyId, SystemResource resource) { SuccessEnum successEnum = null; try { //1.获取拷贝redis所有配置项 List configByRedisVersionId = instanceConfigDao.getConfigByRedisVersionId(versionCopyId); int index = 1; for (InstanceConfig instanceConfig : configByRedisVersionId) { logger.info("[" + (index++) + "] key :" + instanceConfig.getConfigKey() + " , value :" + instanceConfig.getConfigValue()); //2.插入到新的redis版本模板中 instanceConfig.setId(0); instanceConfig.setVersionId(resource.getId()); instanceConfigDao.saveOrUpdate(instanceConfig); } successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; // 需要当前清除状态 logger.info(e.getMessage(), e); } return successEnum.info(); } public String updateMachineInstallRedis(String host) { // 1.获取所有Redis有效版本 List resourceList = resourceDao.getResourceList(ResourceEnum.REDIS.getValue()); // 2.拼装命令cmd String cmds = ""; // 执行命令 String versions = "";//版本信息 String result = ""; // ssh结果 StringBuilder versionsBuilder = new StringBuilder(); StringBuilder cmdsBuilder = new StringBuilder(); if (resourceList != null && resourceList.size() > 0) { for (SystemResource redisVersion : resourceList) { versionsBuilder.append(redisVersion.getName()).append(";"); cmdsBuilder.append("cat ").append(redisVersion.getDir()).append("/src/redis-server | wc -l ").append(";"); } versions = versionsBuilder.toString(); cmds = cmdsBuilder.toString(); versions = versions.substring(0, versions.lastIndexOf(";")); } // 3.执行ssh命令 try { result = SSHUtil.execute(host, cmds); logger.info("execute cmd result:" + result); } catch (SSHException e) { e.printStackTrace(); logger.error("check redis-server machine ip:{} execute cmds:{} error", host, cmds); return SuccessEnum.FAIL.info(); } // 4.更新机器版本状态 MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo != null) { StringBuilder versionStrBuilder = new StringBuilder(); // 版本#flag; String[] versionRes = result.split("\n"); for (int index = 0; index < versionRes.length; index++) { try { // 0:未安装 1:安装成功 -1:安装过程中异常 int flag = NumberUtils.toInt(versionRes[index]) > 0 ? 1 : 0; versionStrBuilder.append(versions.split(";")[index]) .append("#") .append(flag) .append(";"); } catch (Exception e) { versionStrBuilder.append(versions.split(";")[index]) .append("#-1;"); } } machineInfo.setVersionInstall(versionStrBuilder.toString()); // 更新机器的版本情况 machineDao.saveMachineInfo(machineInfo); } else { logger.error("machine ip:{} is not exist", host); return SuccessEnum.FAIL.info(); } return SuccessEnum.SUCCESS.info(); } /** * 检查redis编译版本 * * @param host * @param redisDir */ public Boolean checkMachineRedisVersion(String host, String redisDir) { // 1.param check if (StringUtils.isEmpty(redisDir)) { logger.warn("redisDir is empty :{}", redisDir); return false; } String cmds = "cat " + redisDir + "/src/redis-server | wc -l "; // 2.执行ssh命令 try { String result = SSHUtil.execute(host, cmds); logger.info("execute cmds:{} result:{}", cmds, result); return NumberUtils.toInt(result) > 0 ? true : false; } catch (SSHException e) { e.printStackTrace(); logger.error("check redis-server machine ip:{} execute cmds:{} error", host, cmds); return false; } } public Boolean checkMachineRedisTool(String host, String redisDir) { // 1.param check if (StringUtils.isEmpty(redisDir)) { logger.warn("redisDir is empty :{}", redisDir); return false; } String cmds = "ls -l " + redisDir + "/redis-shake.linux | wc -l "; // 2.执行ssh命令 try { String result = SSHUtil.execute(host, cmds); logger.info("execute cmds:{} result:{}", cmds, result); return NumberUtils.toInt(result) > 0 ? true : false; } catch (SSHException e) { e.printStackTrace(); logger.error("check checkMachineRedisTool machine ip:{} execute cmds:{} error", host, cmds); return false; } } @Override public Boolean checkAndInstallRedisResource(String host, SystemResource redisResource) { Boolean redisInstallFlag = true; // 检测是否安装需要redis版本 String redisDir = ConstUtils.getRedisDir(redisResource.getName()); if (!checkMachineRedisVersion(host, redisDir)) { installRedisOnMachine(host, redisResource); // 验证安装是否成功,最多重试10次 for (int retry = 1; retry <= WAITING_RETRY_TIMES; retry++) { if (checkMachineRedisVersion(host, redisDir)) { logger.info("checkAndInstallRedisResource machine:{} install {} ok!", host, redisResource.getName()); redisInstallFlag = true; break; } redisInstallFlag = false; logger.info("checkAndInstallRedisResource machine:{} install {} fail status:{} ,retry times :{} !", host, redisResource.getName(), redisInstallFlag, retry); try { TimeUnit.SECONDS.sleep(WAITING_RESOURCE_SECOND); } catch (InterruptedException e) { e.printStackTrace(); } } } return redisInstallFlag; } public Boolean checkAndInstallRedisTool(String host, SystemResource redisResource) { Boolean redisInstallFlag = true; // 检测是否安装需要redis版本 String redisDir = ConstUtils.getRedisDir(redisResource.getName()); if (!checkMachineRedisTool(host, redisDir)) { installRedisOnMachine(host, redisResource); // 验证安装是否成功,最多重试10次 for (int retry = 1; retry <= WAITING_RETRY_TIMES; retry++) { if (checkMachineRedisTool(host, redisDir)) { logger.info("checkAndInstallRedisResource machine:{} install {} ok!", host, redisResource.getName()); redisInstallFlag = true; break; } redisInstallFlag = false; logger.info("checkAndInstallRedisResource machine:{} install {} fail status:{} ,retry times :{} !", host, redisResource.getName(), redisInstallFlag, retry); try { TimeUnit.SECONDS.sleep(WAITING_RESOURCE_SECOND); } catch (InterruptedException e) { e.printStackTrace(); } } } return redisInstallFlag; } /** * @param host * @param systemResource * @return */ public String installRedisOnMachine(String host, SystemResource systemResource) { // 1.远程仓库获取资源 SystemResource repository = resourceService.getRepository(); if (repository == null) { logger.error("repository is empty :{} ", repository); return SuccessEnum.FAIL.info(); } // 2.资源信息拼接 String fileName = systemResource.getName() + RedisConstUtils.REDIS_INSTALL_MAKE_PACKAGE_SUFFIX; String downloadurl = repository.getUrl() + systemResource.getDir() + "/" + fileName; String makeFilePath = ConstUtils.REDIS_INSTALL_BASE_DIR + "/" + fileName; String download_cmd = String.format(DOWNLOAD_CMD, ConstUtils.REDIS_INSTALL_BASE_DIR, downloadurl, makeFilePath, makeFilePath); String temp_file = RedisConstUtils.REDIS_SHELL_DIR + "execute.sh"; String execute_cmd = "mkdir -p " + RedisConstUtils.REDIS_SHELL_DIR + " && echo \"" + download_cmd + "\" > " + temp_file + " && sh " + temp_file + "> " + String.format(RedisConstUtils.REDIS_INSTALL_LOG, DateUtil.formatYYYYMMddHHMMss(new Date())) + " 2>&1 &"; // 3.执行ssh try { SSHTemplate.Result result = sshService.executeWithResult(host, execute_cmd, DOWNLOAD_SECONDS); logger.info("execute_cmd :{} result:{}", execute_cmd, result); } catch (SSHException e) { logger.info(e.getMessage(), e); logger.error("install redis machine ip:{} execute cmd:{} error", host, download_cmd); return SuccessEnum.FAIL.info(); } return SuccessEnum.SUCCESS.info(); } public Map slaveUpdateConfig(long appId, Integer upgradeVersionId, String upgradeVersionName) { Map resultMap = new HashMap(); SuccessEnum successEnum = null; // 1.获取所有配置项 AppDesc appDesc = appService.getByAppId(appId); /** * 2.配置更新步骤 * 2.1 备份slave配置 -> 2.2 slave shutdown -> 2.3 替换slave配置 -> 2.4 slave start */ List instanceList = appService.getAppInstanceInfo(appId); // 2.1 备份配置 String instanceInfo = ""; String instanceLog = ""; StringBuilder instanceInfoBuilder = new StringBuilder(); StringBuilder instanceLogBuilder = new StringBuilder(); if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("slave")) { // slave节点 & instanceId String ip = instance.getIp(); int port = instance.getPort(); int mem = instance.getMem(); int instanceId = instance.getId(); String bakTime = DateUtil.formatYYYYMMddHHMMss(new Date()); // redis实例版本检查,比较版本号 String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); int versionTag = Integer.parseInt(redisVersion.substring(redisVersion.lastIndexOf(".") + 1)); int targetVersionTag = Integer.parseInt(upgradeVersionName.substring(upgradeVersionName.lastIndexOf(".") + 1)); logger.info("current redis version:{} , target redis version:{}", versionTag, targetVersionTag); if (versionTag == targetVersionTag) { instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(" ") .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append(" 等于当前版本,不需升级\n"); //instanceLog += "
"; instanceLogBuilder.append("
"); continue; } else if (versionTag > targetVersionTag) { instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(" ") .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append(" 高于当前版本,不需升级\n"); //instanceLog += "
"; instanceLogBuilder.append("
"); continue; } // 1).备份配置 String bakCommonConfig = ""; Boolean isCluster = true; try { //1.1) 备份配置 String confDir = machineCenter.getMachineRelativeDir(instance.getIp(), DirEnum.CONF_DIR.getValue()); String confPath = ""; if (TypeUtil.isRedisCluster(instance.getType())) { bakCommonConfig = "cp -rf " + confDir + RedisProtocol.getConfig(port, true) + " " + confDir + RedisProtocol.getConfig(port, true) + ".bak" + bakTime; confPath = confDir + RedisProtocol.getConfig(port, true); } else { bakCommonConfig = "cp -rf " + confDir + RedisProtocol.getConfig(port, false) + " " + ".conf " + confDir + RedisProtocol.getConfig(port, false) + ".bak" + bakTime; confPath = confDir + RedisProtocol.getConfig(port, false); isCluster = false; } SSHUtil.execute(ip, bakCommonConfig); } catch (SSHException e) { logger.error(String.format("ip:%s bak config error:%s", ip, e.getMessage())); resultMap.put("message", "备份配置异常,请查看日志!"); break; } // 2).关闭redis boolean closeOp = instanceDeployCenter.shutdownExistInstance(appId, instanceId); // 3).生成新配置 & 4).启动redis try { appDesc.setVersionId(upgradeVersionId); boolean bornConf = redisDeployCenter.bornConfigAndRunNode(appDesc, instance, ip, port, mem, isCluster); if (bornConf == false) { resultMap.put("message", "启动失败,查看日志!"); break; } } catch (Exception e) { resultMap.put("message", "启动失败,查看日志!"); break; } // 5).记录日志 redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(" ") .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append(" 更新成功\n"); instanceInfo = instanceInfoBuilder.toString(); instanceLogBuilder.append("日志
"); instanceLog = instanceLogBuilder.toString(); } } successEnum = SuccessEnum.SUCCESS; } else { // return error! 实例无slave节 -1: slave节点不够 successEnum = SuccessEnum.ERROR; resultMap.put("message", "slave节点少于master节点数!"); } resultMap.put("status", successEnum.value()); resultMap.put("instanceInfo", instanceInfo); resultMap.put("instanceLog", instanceLog); // logger.info("result:{}", resultMap); return resultMap; } public Map slaveFailover(long appId) { Map resultMap = new HashMap(); SuccessEnum successEnum = null; /** * 2.配置更新步骤 * 2.1 备份slave配置 -> 2.2 slave shutdown -> 2.3 替换slave配置 -> 2.4 slave start */ AppDesc appDesc = appService.getByAppId(appId); List instanceList = appService.getAppInstanceInfo(appId); // 2.1 备份配置 if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("slave")) { // slave节点 & instanceId String ip = instance.getIp(); int port = instance.getPort(); int times = 0; //最多重试15次 boolean checkFailover = false;//检测是否failover成功 false:轮询检测 true:检测完毕 try { boolean failoverStatus = false; if (appDesc.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { failoverStatus = redisDeployCenter.clusterFailover(appId, instance.getId(), "force"); } else if (appDesc.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { failoverStatus = redisDeployCenter.sentinelFailover(appId); } logger.info("type:{},{} {} slave execute failover, execute {}", appDesc.getTypeDesc(), ip, port, failoverStatus); if (!failoverStatus) { // failover 失败 resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "failover失败,请查看日志!"); return resultMap; } // 根据主从偏移量 & 新slave节点状态 & 重试次数30次 判断是否failover完成。 while (!checkFailover && times++ <= RETRY_TIMES) { Boolean status = redisCenter.getRedisReplicationStatus(appId, ip, port); if (status) { checkFailover = status; } else { TimeUnit.MILLISECONDS.sleep(SLEEP_MILLS); logger.info(" check slave replication status ,waiting 2s ...."); } } } catch (Exception e) { e.printStackTrace(); logger.error(e.getMessage(), e); resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "从节点" + ip + ":" + port + " failover异常!"); return resultMap; } } } } resultMap.put("status", SuccessEnum.SUCCESS.value()); return resultMap; } /** *

* Description: 从节点发起psync之后是否load data *

* * @author chenshi * @version 1.0 * @date 2018/11/29 */ public Boolean slaveIsPsync(long appId, String ip, int port) { Boolean psyncFlag = false;// 未开始load data int times = 0; //最多重试15次 // 根据主从偏移量 & 新slave节点状态 & 重试次数30次 判断是否failover完成。 while (!psyncFlag && times++ <= RETRY_TIMES) { try { Boolean status = redisCenter.getRedisReplicationStatus(appId, ip, port); if (status) { psyncFlag = status; } else { TimeUnit.MILLISECONDS.sleep(SLEEP_MILLS); logger.info(" check slave psync replication status ,waiting 2s ...."); } } catch (Exception e) { e.printStackTrace(); logger.error(e.getMessage(), e); } } return psyncFlag; } /** * 组合 * * @param configKey * @param configValue * @return */ private String combineConfigKeyValue(String configKey, String configValue) { return configKey + ConstUtils.SPACE + configValue; } /** * * @param host 新加节点ip * @param port 新加节点port * @param versionId 部署实例版本 * @param maxMemory 最大内存 * @param maxMemoryPolicy 内存淘汰策略 * @param isCluster 是否集群 * @param customConfigs 自定义配置 * @param copyFromConfigMap 主节点实例配置(从主节点拷贝配置值) * @return */ @Override public List handleRedisConfig(String host, int port, int versionId, int maxMemory, String maxMemoryPolicy, boolean isCluster, List> customConfigs, Map copyFromConfigMap) { List instanceConfigList = getByVesionAndType(ConstUtils.CACHE_REDIS_STANDALONE, versionId); if (CollectionUtils.isEmpty(instanceConfigList)) { instanceConfigList = handleRedisCommonDefaultConfig(port, maxMemory); } if(isCluster){ List instanceClusterConfigs = getByVesionAndType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER, versionId); if (CollectionUtils.isEmpty(instanceClusterConfigs)) { instanceClusterConfigs = handleRedisClusterDefaultConfig(port); } instanceConfigList.addAll(instanceClusterConfigs); } Map> notExistConfigMap = new HashMap<>(); Map instanceConfigMap = instanceConfigList.stream().filter(instanceConfig -> instanceConfig.isEffective()) .collect(Collectors.toMap(instanceConfig -> instanceConfig.getConfigKey(), instanceConfig -> instanceConfig.getConfigValue())); Map> customConfigMap = new HashMap<>(); if(CollectionUtils.isNotEmpty(customConfigs)){ customConfigs.forEach(customConfig -> { if(customConfigMap.containsKey(customConfig.getKey())){ customConfigMap.get(customConfig.getKey()).add(customConfig.getValue()); }else{ List confiValues = new ArrayList<>(); confiValues.add(customConfig.getValue()); customConfigMap.put(customConfig.getKey(), confiValues); } }); } customConfigMap.keySet().forEach(key -> { if (!instanceConfigMap.containsKey(key)) { notExistConfigMap.put(key, customConfigMap.get(key)); } }); //是否有源节点的配置map boolean isCopy = MapUtils.isNotEmpty(copyFromConfigMap); List configs = new ArrayList(); for (InstanceConfig instanceConfig : instanceConfigList) { // 无效配置过滤 if (!instanceConfig.isEffective()) { continue; } String configKey = instanceConfig.getConfigKey(); String configValue = instanceConfig.getConfigValue(); if (StringUtils.isBlank(configValue)) { configValue = SPECIAL_EMPTY_STR; } if (RedisConfigEnum.MAXMEMORY.getKey().equals(configKey)) { configValue = String.format(configValue, maxMemory); } else if (RedisConfigEnum.DBFILENAME.getKey().equals(configKey) || RedisConfigEnum.APPENDFILENAME.getKey().equals(configKey) || RedisConfigEnum.PORT.getKey().equals(configKey)) { configValue = String.format(configValue, port); } else if (RedisConfigEnum.DIR.getKey().equals(configKey)) { configValue = machineCenter.getMachineRelativeDir(host, DirEnum.DATA_DIR.getValue()); } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getKey().equals(configKey)) { //随机比例 auto-aof-rewrite-percentage int percent = 69 + new Random().nextInt(30); configValue = String.format(configValue, percent); } else if (RedisConfigEnum.BIND.getKey().equals(configKey)) { configValue = String.format(configValue, host); } else if (RedisConfigEnum.MAXMEMORY_POLICY.getKey().equals(configKey)) { if (StringUtils.isNotEmpty(maxMemoryPolicy)) { configValue = maxMemoryPolicy; } } else if (RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey().equals(configKey)) { configValue = String.format(configValue, port); } else { if(customConfigMap.containsKey(configKey)){ List configValues = customConfigMap.get(configKey); if(configValues.size() == 1){ configValue = configValues.get(0); } else { IntStream.range(0, configValues.size() - 1).forEach(i -> { configs.add(combineConfigKeyValue(configKey, configValues.get(i))); }); configValue = configValues.get(configValues.size() - 1); } } else { if(isCopy){ if(instanceConfig.getValueType() == BaseConstant.ONE){ String copyValue = copyFromConfigMap.get(configKey); if(StringUtils.isNotBlank(copyValue)){ configValue = copyValue; } } } } } configs.add(combineConfigKeyValue(configKey, configValue)); } notExistConfigMap.forEach((configKey, configValues) -> configValues.forEach(configValue -> { configs.add(combineConfigKeyValue(configKey, configValue)); }) ); return configs; } private List handleRedisCommonDefaultConfig(int port, int maxMemory) { List configs = new ArrayList<>(); for (RedisConfigEnum config : RedisConfigEnum.values()) { if (RedisConfigEnum.MAXMEMORY.equals(config)) { configs.add(new InstanceConfig(config.getKey(), String.format(config.getValue(), maxMemory))); } else if (RedisConfigEnum.DBFILENAME.equals(config) || RedisConfigEnum.APPENDFILENAME.equals(config) || RedisConfigEnum.PORT.equals(config)) { configs.add(new InstanceConfig(config.getKey(), String.format(config.getValue(), port))); } else if (RedisConfigEnum.DIR.equals(config)) { configs.add(new InstanceConfig(config.getKey(), MachineProtocol.DATA_DIR)); } else if (RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.equals(config)) { //随机比例 auto-aof-rewrite-percentage int percent = 69 + new Random().nextInt(30); configs.add(new InstanceConfig(config.getKey(), String.format(RedisConfigEnum.AUTO_AOF_REWRITE_PERCENTAGE.getValue(), percent))); } else { configs.add(new InstanceConfig(config.getKey(), config.getValue())); } } return configs; } private List handleRedisClusterDefaultConfig(int port) { List configs = new ArrayList<>(); for (RedisClusterConfigEnum config : RedisClusterConfigEnum.values()) { if (config.equals(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE)) { configs.add(new InstanceConfig(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getKey(), String.format(RedisClusterConfigEnum.CLUSTER_CONFIG_FILE.getValue(), port))); } else { configs.add(new InstanceConfig(config.getKey(), config.getValue())); } } return configs; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/impl/RedisDeployCenterImpl.java ================================================ package com.sohu.cache.redis.impl; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.collect.UnmodifiableIterator; import com.sohu.cache.constant.AppDescEnum; import com.sohu.cache.constant.ClusterOperateResult; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisClusterNode; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.redis.enums.RedisConfigEnum; import com.sohu.cache.redis.util.AuthUtil; import com.sohu.cache.redis.util.JedisUtil; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.IdempotentConfirmer; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AppTypeEnum; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.RedisOperateEnum; import com.sohu.cache.web.enums.UseTypeEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import redis.clients.jedis.*; import redis.clients.jedis.args.ClusterFailoverOption; import redis.clients.jedis.exceptions.JedisDataException; import javax.annotation.Nullable; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Created by yijunzhang on 14-8-25. */ @Service("redisDeployCenter") public class RedisDeployCenterImpl implements RedisDeployCenter { // 重试次数 private static int RETRY_TIMES = 10; private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private InstanceDao instanceDao; @Autowired private MachineDao machineDao; @Autowired @Lazy private MachineCenter machineCenter; @Autowired @Lazy private RedisCenter redisCenter; @Autowired private AppDao appDao; @Autowired private RedisConfigTemplateService redisConfigTemplateService; @Autowired private InstanceDeployCenter instanceDeployCenter; @Resource(name = "appService") private AppService appService; @Autowired private ResourceService resourceService; @Autowired private SSHService sshService; @Override public boolean deployClusterInstance(long appId, List clusterNodes, int maxMemory) { if (!isExist(appId)) { return false; } AppDesc appDesc = appDao.getAppDescById(appId); String host = null; Integer port = null; Map clusterMap = new LinkedHashMap(); for (RedisClusterNode node : clusterNodes) { String masterHost = node.getMasterHost(); String slaveHost = node.getSlaveHost(); Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); if (masterPort == null) { logger.error("masterHost={} getAvailablePort is null", masterHost); return false; } if (host == null || port == null) { host = masterHost; port = masterPort; } boolean isMasterRun = runInstance(appDesc, masterHost, masterPort, maxMemory, true); if (!isMasterRun) { return false; } if (StringUtils.isNotBlank(slaveHost)) { Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); if (slavePort == null) { logger.error("slaveHost={} getAvailablePort is null", slaveHost); return false; } boolean isSlaveRun = runInstance(appDesc, slaveHost, slavePort, maxMemory, true); if (!isSlaveRun) { return false; } clusterMap.put(redisCenter.getJedis(appId, masterHost, masterPort), redisCenter.getJedis(appId, slaveHost, slavePort)); } else { clusterMap.put(redisCenter.getJedis(appId, masterHost, masterPort), null); } } boolean isCluster; try { isCluster = startCluster(appId, clusterMap); if (!isCluster) { logger.error("startCluster create error!"); return false; } for (Map.Entry entry : clusterMap.entrySet()) { Jedis master = entry.getKey(); Jedis slave = entry.getValue(); //保存实例信息 & 触发收集 saveInstance(appId, master.getClient().getHost(), master.getClient().getPort(), maxMemory, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); if (slave != null) { saveInstance(appId, slave.getClient().getHost(), slave.getClient().getPort(), maxMemory, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); } } } finally { //关闭jedis连接 for (Map.Entry entry : clusterMap.entrySet()) { entry.getKey().close(); if (entry.getValue() != null) { entry.getValue().close(); } } } return true; } private boolean clusterMeet(Jedis jedis, long appId, String host, int port) { boolean isSingleNode = redisCenter.isSingleClusterNode(appId, host, port); if (!isSingleNode) { logger.error("{}:{} isNotSingleNode", host, port); return false; } else { logger.warn("{}:{} isSingleNode", host, port); } String response = jedis.clusterMeet(host, port); boolean isMeet = response != null && response.equalsIgnoreCase("OK"); if (!isMeet) { logger.error("{}:{} meet error", host, port); return false; } return true; } public boolean startCluster(final long appId, Map clusterMap) { final Jedis jedis = new ArrayList(clusterMap.keySet()).get(0); //meet集群节点 for (final Map.Entry entry : clusterMap.entrySet()) { final Jedis master = entry.getKey(); boolean isMeet = new IdempotentConfirmer() { @Override public boolean execute() { boolean isMeet = clusterMeet(jedis, appId, master.getClient().getHost(), master.getClient().getPort()); if (!isMeet) { return false; } return true; } }.run(); if (!isMeet) { return false; } final Jedis slave = entry.getValue(); if (slave != null) { isMeet = new IdempotentConfirmer() { @Override public boolean execute() { boolean isMeet = clusterMeet(jedis, appId, slave.getClient().getHost(), slave.getClient().getPort()); if (!isMeet) { return false; } return true; } }.run(); if (!isMeet) { return false; } } } int masterSize = clusterMap.size(); int perSize = (int) Math.ceil(16384 * 1.0D / masterSize); int index = 0; int masterIndex = 0; final ArrayList slots = new ArrayList(); List masters = new ArrayList(clusterMap.keySet()); //分配slot for (int slot = 0; slot <= 16383; slot++) { slots.add(slot); if (index++ >= perSize || slot == 16383) { final int[] slotArr = new int[slots.size()]; for (int i = 0; i < slotArr.length; i++) { slotArr[i] = slots.get(i); } final Jedis masterJedis = masters.get(masterIndex++); boolean isSlot = new IdempotentConfirmer() { @Override public boolean execute() { String response = masterJedis.clusterAddSlots(slotArr); boolean isSlot = response != null && response.equalsIgnoreCase("OK"); if (!isSlot) { return false; } return true; } }.run(); if (!isSlot) { logger.error("{}:{} set slots:{}", masterJedis.getClient().getHost(), masterJedis.getClient().getPort(), slots); return false; } slots.clear(); index = 0; } } //设置从节点 for (Map.Entry entry : clusterMap.entrySet()) { final Jedis masterJedis = entry.getKey(); final Jedis slaveJedis = entry.getValue(); if (slaveJedis == null) { continue; } final String nodeId = getClusterNodeId(masterJedis); boolean isReplicate = new IdempotentConfirmer() { @Override public boolean execute() { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } String response = null; try { response = slaveJedis.clusterReplicate(nodeId); } catch (Exception e) { logger.error(e.getMessage(), e); } boolean isReplicate = response != null && response.equalsIgnoreCase("OK"); if (!isReplicate) { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } return false; } return true; } }.run(); if (!isReplicate) { logger.error("{}:{} set replicate:{}", slaveJedis.getClient().getHost(), slaveJedis.getClient().getPort(), isReplicate); return false; } } return true; } public boolean startClusterMaster(final long appId, Map clusterMap) { final Jedis jedis = new ArrayList(clusterMap.keySet()).get(0); //meet集群节点 for (final Map.Entry entry : clusterMap.entrySet()) { final Jedis master = entry.getKey(); boolean isMeet = new IdempotentConfirmer() { @Override public boolean execute() { boolean isMeet = clusterMeet(jedis, appId, master.getClient().getHost(), master.getClient().getPort()); if (!isMeet) { return false; } return true; } }.run(); if (!isMeet) { return false; } } int masterSize = clusterMap.size(); int perSize = (int) Math.ceil(16384 * 1.0D / masterSize); int index = 0; int masterIndex = 0; final ArrayList slots = new ArrayList(); List masters = new ArrayList(clusterMap.keySet()); //分配slot for (int slot = 0; slot <= 16383; slot++) { slots.add(slot); if (index++ >= perSize || slot == 16383) { final int[] slotArr = new int[slots.size()]; for (int i = 0; i < slotArr.length; i++) { slotArr[i] = slots.get(i); } final Jedis masterJedis = masters.get(masterIndex++); boolean isSlot = new IdempotentConfirmer() { @Override public boolean execute() { String response = masterJedis.clusterAddSlots(slotArr); boolean isSlot = response != null && response.equalsIgnoreCase("OK"); if (!isSlot) { return false; } return true; } }.run(); if (!isSlot) { logger.error("{}:{} set slots:{}", masterJedis.getClient().getHost(), masterJedis.getClient().getPort(), slots); return false; } slots.clear(); index = 0; } } return true; } public boolean startClusterSlave(final long appId, Map clusterMap) { final Jedis jedis = new ArrayList(clusterMap.keySet()).get(0); //meet集群节点 for (final Map.Entry entry : clusterMap.entrySet()) { final Jedis slave = entry.getValue(); if (slave != null) { boolean isMeet = new IdempotentConfirmer() { @Override public boolean execute() { boolean isMeet = clusterMeet(jedis, appId, slave.getClient().getHost(), slave.getClient().getPort()); if (!isMeet) { return false; } return true; } }.run(); if (!isMeet) { return false; } } } //设置从节点 for (Map.Entry entry : clusterMap.entrySet()) { final Jedis masterJedis = entry.getKey(); final Jedis slaveJedis = entry.getValue(); if (slaveJedis == null) { continue; } final String nodeId = getClusterNodeId(masterJedis); boolean isReplicate = new IdempotentConfirmer() { @Override public boolean execute() { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } String response = null; try { response = slaveJedis.clusterReplicate(nodeId); } catch (Exception e) { logger.error(e.getMessage(), e); } boolean isReplicate = response != null && response.equalsIgnoreCase("OK"); if (!isReplicate) { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } return false; } return true; } }.run(); if (!isReplicate) { logger.error("{}:{} set replicate:{}", slaveJedis.getClient().getHost(), slaveJedis.getClient().getPort(), isReplicate); return false; } } return true; } private String getClusterNodeId(Jedis jedis) { try { String infoOutput = jedis.clusterNodes(); for (String infoLine : infoOutput.split("\n")) { if (infoLine.contains("myself")) { return infoLine.split(" ")[0]; } } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } @Override public boolean deploySentinelInstance(long appId, String masterHost, String slaveHost, int maxMemory, List sentinelList) { if (!isExist(appId)) { return false; } AppDesc appDesc = appDao.getAppDescById(appId); //获取端口 Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_REDIS_STANDALONE); if (masterPort == null) { logger.error("masterHost={} getAvailablePort is null", masterHost); return false; } Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_REDIS_STANDALONE); if (slavePort == null) { logger.error("slaveHost={} getAvailablePort is null", slaveHost); return false; } //运行实例 boolean isMasterRun = runInstance(appDesc, masterHost, masterPort, maxMemory, false); if (!isMasterRun) { return false; } boolean isSlaveRun = runInstance(appDesc, slaveHost, slavePort, maxMemory, false); if (!isSlaveRun) { return false; } //添加slaveof配置 boolean isSlave = slaveOf(appDesc.getAppId(), masterHost, masterPort, slaveHost, slavePort); if (!isSlave) { return false; } //运行sentinel实例组 boolean isRunSentinel = runSentinelGroup(appDesc, sentinelList, masterHost, masterPort, appId, appDesc.getAppPassword()); if (!isRunSentinel) { return false; } //写入instanceInfo 信息 saveInstance(appId, masterHost, masterPort, maxMemory, ConstUtils.CACHE_REDIS_STANDALONE, ""); saveInstance(appId, slaveHost, slavePort, maxMemory, ConstUtils.CACHE_REDIS_STANDALONE, ""); return true; } @Override public boolean deployStandaloneInstance(long appId, String host, int maxMemory) { if (!isExist(appId)) { return false; } AppDesc appDesc = appDao.getAppDescById(appId); //获取端口 Integer port = machineCenter.getAvailablePort(host, ConstUtils.CACHE_REDIS_STANDALONE); if (port == null) { logger.error("masterHost={} getAvailablePort is null", host); return false; } //运行实例 boolean isMasterRun = runInstance(appDesc, host, port, maxMemory, false); if (!isMasterRun) { return false; } //写入instanceInfo 信息 saveInstance(appId, host, port, maxMemory, ConstUtils.CACHE_REDIS_STANDALONE, ""); return true; } private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory, int type, String cmd) { InstanceInfo instanceInfo = new InstanceInfo(); instanceInfo.setAppId(appId); MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); instanceInfo.setHostId(machineInfo.getId()); instanceInfo.setConn(0); instanceInfo.setMem(maxMemory); instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceInfo.setPort(port); instanceInfo.setType(type); instanceInfo.setCmd(cmd); instanceInfo.setIp(host); instanceDao.saveInstance(instanceInfo); return instanceInfo; } private boolean runSentinelGroup(AppDesc appDesc, List sentinelList, String masterHost, int masterPort, long appId, String password) { for (String sentinelHost : sentinelList) { boolean isRun = runSentinel(appDesc, sentinelHost, getMasterName(masterHost, masterPort), masterHost, masterPort); if (!isRun) { return false; } } return true; } @Override public boolean createRunNode(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster) { return runInstance(appDesc, host, port, maxMemory, isCluster); } @Override public String getRedisRunShell(boolean isCluster, String host, int port, String redisDir) { String runShell = machineCenter.isK8sMachine(host) == true ? RedisProtocol.getK8sRunShellByVersion(host, port, isCluster, redisDir) : RedisProtocol.getRunShellByVersion(port, isCluster, redisDir); return runShell; } @Override public String getSentinelRunShell(String host, int port, String redisDir) { String runShell = machineCenter.isK8sMachine(host) == true ? RedisProtocol.getK8sSentinelShellByVersion(host, port, redisDir) : RedisProtocol.getSentinelShellByVersion(port, redisDir); return runShell; } private boolean runInstance(AppDesc appDesc, String host, Integer port, int maxMemory, boolean isCluster) { return this.runInstance(appDesc, host, port, null, null, maxMemory, isCluster, null); } private boolean runInstance(AppDesc appDesc, String host, Integer port, @Nullable String masterHost, @Nullable Integer masterPort, int maxMemory, boolean isCluster, List> customConfigs) { long appId = appDesc.getAppId(); String password = appDesc.getAppPassword(); // 获取redis路径 SystemResource redisResource = resourceService.getResourceById(appDesc.getVersionId()); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); // Redis资源校验&推包 Boolean installStatus = redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); if (!installStatus) { throw new RuntimeException(String.format("machine: %s version :%s is installed %s", host, redisResource, installStatus)); } // 生成配置(获取配置,拷贝配置,定制化配置) List configs = handleInstanceConfig(appId, host, port, appDesc.getVersionId(), isCluster, maxMemory, appDesc.getMaxmemoryPolicy(), masterHost, masterPort, customConfigs); if (StringUtils.isNotBlank(password)) { //加两个选项 configs.add(RedisConfigEnum.REQUIREPASS.getKey() + ConstUtils.SPACE + password); configs.add(RedisConfigEnum.MASTERAUTH.getKey() + ConstUtils.SPACE + password); } printConfig(configs); String fileName; String runShell; if (isCluster) { runShell = getRedisRunShell(true, host, port, redisDir); fileName = RedisProtocol.getConfig(port, true); } else { runShell = getRedisRunShell(false, host, port, redisDir); fileName = RedisProtocol.getConfig(port, false); } String pathFile = machineCenter.createRemoteFile(host, fileName, configs); if (StringUtils.isBlank(pathFile)) { logger.error("createFile={} error", pathFile); return false; } if (isCluster) { //删除cluster节点配置 String deleteNodeShell = String.format("rm -rf %s/nodes-%s.conf", machineCenter.getMachineRelativeDir(host, DirEnum.DATA_DIR.getValue()), port); String deleteNodeResult = machineCenter.executeShell(host, deleteNodeShell); if (!ConstUtils.INNER_ERROR.equals(deleteNodeResult)) { logger.warn("runDeleteNodeShell={} at host {}", deleteNodeShell, host); } } //启动实例 logger.info("masterShell:host={};shell={}", host, runShell); boolean isMasterShell = machineCenter.startProcessAtPort(host, port, runShell); if (!isMasterShell) { logger.error("runShell={} error,{}:{}", runShell, host, port); return false; } //验证实例 if (!redisCenter.isRun(appId, host, port)) { logger.error("host:{};port:{} not run", host, port); return false; } else { logger.warn("runInstance-fallback : redis-cli -h {} -p {} shutdown", host, port); } return true; } public boolean bornConfigAndRunNode(AppDesc appDesc, InstanceInfo instanceInfo, String host, Integer port, int maxMemory, boolean isCluster) { long appId = appDesc.getAppId(); String password = appDesc.getAppPassword(); // 获取redis路径 SystemResource redisResource = resourceService.getResourceById(appDesc.getVersionId()); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); // 生成配置 List configs = handleInstanceConfig(appId, host, port, appDesc.getVersionId(), isCluster, maxMemory, appDesc.getMaxmemoryPolicy(), null, null, null); if (StringUtils.isNotBlank(password)) { //加两个选项 configs.add(RedisConfigEnum.REQUIREPASS.getKey() + ConstUtils.SPACE + password); configs.add(RedisConfigEnum.MASTERAUTH.getKey() + ConstUtils.SPACE + password); } printConfig(configs); String fileName; String runShell; if (isCluster) { runShell = getRedisRunShell(true, host, port, redisDir); fileName = RedisProtocol.getConfig(port, true); } else { runShell = getRedisRunShell(false, host, port, redisDir); fileName = RedisProtocol.getConfig(port, false); } // 删除redis配置 String deleteConfShell = String.format("rm -rf %sredis-cluster-%s.conf", MachineProtocol.CONF_DIR, port); String deleteConfResult = machineCenter.executeShell(host, deleteConfShell); if (!ConstUtils.INNER_ERROR.equals(deleteConfResult)) { logger.warn("runDeleteConfShell={} at host {}", deleteConfResult, host); } // 写入新的配置文件 String pathFile = machineCenter.createRemoteFile(host, fileName, configs); if (StringUtils.isBlank(pathFile)) { logger.error("createFile={} error", pathFile); return false; } //启动实例 logger.info("masterShell:host={};shell={}", host, runShell); boolean isMasterShell = machineCenter.startProcessAtPort(host, port, runShell); if (!isMasterShell) { logger.error("runShell={} error,{}:{}", runShell, host, port); return false; } //验证实例 if (!redisCenter.isRun(appId, host, port)) { logger.error("host:{};port:{} not run", host, port); return false; } else { logger.warn("runInstance-restart success : redis-cli -h {} -p {} ", host, port); instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceDao.update(instanceInfo); } return true; } private boolean runSentinel(AppDesc appDesc, String sentinelHost, String masterName, String masterHost, Integer masterPort) { //应用信息 long appId = appDesc.getAppId(); String password = appDesc.getAppPassword(); // 获取redis路径 // RedisVersion redisVersion = redisConfigTemplateService.getRedisVersionById(appDesc.getVersionId()); // String redisDir = redisVersion == null ? ConstUtils.REDIS_DEFAULT_DIR : redisVersion.getDir(); SystemResource redisResource = resourceService.getResourceById(appDesc.getVersionId()); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); // Redis资源校验&推包 Boolean installStatus = redisConfigTemplateService.checkAndInstallRedisResource(sentinelHost, redisResource); if (!installStatus) { throw new RuntimeException(String.format("machine: %s version :%s is installed %s", sentinelHost, redisResource, installStatus)); } //启动sentinel实例 Integer sentinelPort = machineCenter.getAvailablePort(sentinelHost, ConstUtils.CACHE_REDIS_SENTINEL); if (sentinelPort == null) { logger.error("host={} getAvailablePort is null", sentinelHost); return false; } List masterSentinelConfigs = handleSentinelConfig(masterName, masterHost, masterPort, sentinelHost, sentinelPort, appDesc.getVersionId()); if (StringUtils.isNotBlank(password)) { masterSentinelConfigs.add("sentinel " + RedisConfigEnum.AUTH_PASS.getKey() + ConstUtils.SPACE + masterName + ConstUtils.SPACE + password); } printConfig(masterSentinelConfigs); String masterSentinelFileName = RedisProtocol.getConfig(sentinelPort, false); String sentinelPathFile = machineCenter .createRemoteFile(sentinelHost, masterSentinelFileName, masterSentinelConfigs); if (StringUtils.isBlank(sentinelPathFile)) { return false; } String sentinelShell = getSentinelRunShell(sentinelHost, sentinelPort, redisDir); logger.info("sentinelMasterShell:{}", sentinelShell); boolean isSentinelMasterShell = machineCenter.startProcessAtPort(sentinelHost, sentinelPort, sentinelShell); if (!isSentinelMasterShell) { logger.error("sentinelMasterShell={} error", sentinelShell); return false; } //验证实例 if (!redisCenter.isRun(sentinelHost, sentinelPort)) { logger.error("host:{};port:{} not run", sentinelHost, sentinelPort); return false; } else { logger.warn("runSentinel-fallback : redis-cli -h {} -p {} shutdown", sentinelHost, sentinelPort); } //save sentinel /** * getMasterName(masterHost, masterPort) 存在问题:(instance_info表cmd 集群名称不一致问题) * 1).如果已经存在一个sentinel集群,masterName:master-node1(主节点node1,从节点node2), * 2).当主从节点failover(主节点为node2),再添加新的sentinel节点:master-node2 */ String sentinelMasterName = StringUtils.isEmpty(masterName) ? getMasterName(masterHost, masterPort) : masterName; saveInstance(appId, sentinelHost, sentinelPort, 0, ConstUtils.CACHE_REDIS_SENTINEL, sentinelMasterName); return true; } // /** // * 获取redis 基础配置 // * // * @param port // * @param maxMemory // * @return // */ // public List handleCommonConfig(String host, int port, int maxMemory, Integer maxMemoryPolicyType, int versionId) { // List configs = null; // try { // String maxMemoryPolicy = null; // if(maxMemoryPolicyType != null){ // AppDescEnum.MaxmemoryPolicyType policyType = AppDescEnum.MaxmemoryPolicyType.getByType(maxMemoryPolicyType); // if(policyType != null){ // maxMemoryPolicy = policyType.getName(); // } // } // configs = redisConfigTemplateService.handleCommonConfig(host, port, maxMemory, maxMemoryPolicy, versionId); // } catch (Exception e) { // logger.error(e.getMessage(), e); // } // if (CollectionUtils.isEmpty(configs)) { // configs = redisConfigTemplateService.handleCommonDefaultConfig(port, maxMemory); // } // return configs; // } private List handleSentinelConfig(String masterName, String host, int port, String sentinelHost, int sentinelPort, int versionId) { List configs = null; try { configs = redisConfigTemplateService.handleSentinelConfig(masterName, host, port, sentinelHost, sentinelPort, versionId, null); } catch (Exception e) { logger.error(e.getMessage(), e); } if (CollectionUtils.isEmpty(configs)) { configs = redisConfigTemplateService.handleSentinelDefaultConfig(masterName, host, port, sentinelPort); } return configs; } // private List handleClusterConfig(int port, int versionId) { // List configs = null; // try { // configs = redisConfigTemplateService.handleClusterConfig(port, versionId); // } catch (Exception e) { // logger.error(e.getMessage(), e); // } // if (CollectionUtils.isEmpty(configs)) { // configs = redisConfigTemplateService.handleClusterDefaultConfig(port); // } // return configs; // } /** * * @param appId 应用id * @param host 节点ip * @param port 节点port * @param versionId 部署实例版本 * @param isCluster 是否集群 * @param maxMemory 最大内存 * @param maxMemoryPolicyType 内存淘汰策略 * @param masterHost 主节点ip * @param masterPort 主节点port * @param customConfigs 自定义配置 * @return */ private List handleInstanceConfig(long appId, String host, int port, int versionId, boolean isCluster, int maxMemory, Integer maxMemoryPolicyType, @Nullable String masterHost, @Nullable Integer masterPort, List> customConfigs) { //获取主节点的配置 Map configInfoMap = new HashMap<>(); if(StringUtils.isNotBlank(masterHost) && masterPort != null && masterPort > 0){ configInfoMap = this.getConfigInfo(appId, masterHost, masterPort); } String maxMemoryPolicy = null; if(maxMemoryPolicyType != null){ AppDescEnum.MaxmemoryPolicyType policyType = AppDescEnum.MaxmemoryPolicyType.getByType(maxMemoryPolicyType); if(policyType != null){ maxMemoryPolicy = policyType.getName(); } } //获取模板配置 try { return redisConfigTemplateService.handleRedisConfig(host, port, versionId, maxMemory, maxMemoryPolicy, isCluster, customConfigs, configInfoMap); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } private Map getConfigInfo(long appId, String host, int port) { Map configInfo = new HashMap<>(); Jedis jedis = redisCenter .getAdminJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { List values = jedis.configGet("*"); if (values == null || values.size() < 1) { return configInfo; } for (int i = 0; i < values.size(); i += 2) { configInfo.put(values.get(i), values.get(i + 1)); } return configInfo; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } finally { jedis.close(); } } private String getMasterName(String host, int port) { String masterSentinelName = String.format("sentinel-%s-%s", host, port); return masterSentinelName; } private void printConfig(List masterConfigs) { logger.info("==================redis-{}-config==================", masterConfigs); for (String line : masterConfigs) { logger.info(line); } } private boolean isExist(long appId) { List instanceInfos = instanceDao.getInstListByAppId(appId); if (instanceInfos != null && instanceInfos.size() > 0) { logger.error("appId={} instances is exist , instanceInfos={}", appId, instanceInfos); return false; } return true; } @Override public boolean modifyAppConfig(long appId, String parameter, String value) { List list = instanceDao.getInstListByAppId(appId); if (list == null || list.isEmpty()) { logger.error(String.format("appId=%s no instances", appId)); return false; } for (InstanceInfo instance : list) { int type = instance.getType(); if (!TypeUtil.isRedisType(type)) { logger.error("appId={};type={};is not redisType", appId, type); return false; } //忽略sentinel if (TypeUtil.isRedisSentinel(type)) { continue; } //忽略下线 if (instance.isOffline()) { continue; } String host = instance.getIp(); int port = instance.getPort(); if (!modifyInstanceConfig(appId, host, port, parameter, value)) { return false; } } return true; } @Override public boolean modifyInstanceConfig(final long appId, final String host, final int port, final String parameter, final String value) { final Jedis jedis = redisCenter.getAdminJedis(appId, host, port, 5000, 5000); try { boolean isConfig = new IdempotentConfirmer() { @Override public boolean execute() { boolean isRun = redisCenter.isRun(appId, host, port); if (!isRun) { logger.warn("modifyInstanceConfig{}:{} is shutdown", host, port); return true; } String result = jedis.configSet(parameter, value); boolean isConfig = result != null && result.equalsIgnoreCase("OK"); if (!isConfig) { logger.error(String.format("modifyConfigError:ip=%s,port=%s,result=%s", host, port, result)); return false; } return isConfig; } }.run(); boolean isRewrite = redisCenter.configRewrite(appId, host, port); if (!isRewrite) { logger.error("configRewrite={}:{} failed", host, port); } return isConfig; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } finally { if (jedis != null) jedis.close(); } } @Override public String getInstanceConfig(final long appId, final String host, final int port, final String parameter) { try (Jedis jedis = redisCenter.getAdminJedis(appId, host, port, 5000, 5000);){ List values = jedis.configGet(parameter); if (values == null || values.size() < 1) { return null; } return values.get(1); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public boolean addSentinel(long appId, String sentinelHost) { AppDesc appDesc = appDao.getAppDescById(appId); JedisSentinelPool jedisSentinelPool = redisCenter.getJedisSentinelPool(appDesc); if (jedisSentinelPool == null) { return false; } List instanceInfos = instanceDao.getInstListByAppId(appId); String masterName = null; for (Iterator i = instanceInfos.iterator(); i.hasNext(); ) { InstanceInfo instanceInfo = i.next(); if (instanceInfo.getType() != ConstUtils.CACHE_REDIS_SENTINEL) { i.remove(); continue; } if (masterName == null && StringUtils.isNotBlank(instanceInfo.getCmd())) { masterName = instanceInfo.getCmd(); } } Jedis jedis = null; String masterHost = null; Integer masterPort = null; try { jedis = jedisSentinelPool.getResource(); masterHost = jedis.getClient().getHost(); masterPort = jedis.getClient().getPort(); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); jedisSentinelPool.destroy(); } } boolean isRun = runSentinel(appDesc, sentinelHost, masterName, masterHost, masterPort); if (!isRun) { return false; } return true; } @Override public RedisOperateEnum addSlotsFailMaster(final long appId, int lossSlotsInstanceId, final String newMasterHost) throws Exception { // 1.参数、应用、实例信息确认 Assert.isTrue(appId > 0); Assert.isTrue(lossSlotsInstanceId > 0); Assert.isTrue(StringUtils.isNotBlank(newMasterHost)); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisCluster(type)) { logger.error("{} is not redis cluster type", appDesc); return RedisOperateEnum.FAIL; } //获取失联slots的实例信息 InstanceInfo lossSlotsInstanceInfo = instanceDao.getInstanceInfoById(lossSlotsInstanceId); Assert.isTrue(lossSlotsInstanceInfo != null); // 2.获取集群中一个健康的master作为clusterInfo Nodes的数据源 List allInstanceInfo = redisCenter.getAllHealthyInstanceInfo(appId); //InstanceInfo sourceMasterInstance = redisCenter.getHealthyInstanceInfo(appId); if (allInstanceInfo == null || allInstanceInfo.size() == 0) { logger.warn("appId {} get all instance is zero", appId); return RedisOperateEnum.FAIL; } //默认获取第一个master节点 InstanceInfo sourceMasterInstance = allInstanceInfo.get(0); // 并未找到一个合适的实例可以 if (sourceMasterInstance == null) { logger.warn("appId {} does not have right instance", appId); return RedisOperateEnum.FAIL; } // 3. 找到丢失的slots,如果没找到就说明集群正常,直接返回 String healthyMasterHost = sourceMasterInstance.getIp(); int healthyMasterPort = sourceMasterInstance.getPort(); int healthyMasterMem = sourceMasterInstance.getMem(); // 3.1 查看整个集群中是否有丢失的slots List allLossSlots = redisCenter.getClusterLossSlots(appId, healthyMasterHost, healthyMasterPort); if (CollectionUtils.isEmpty(allLossSlots)) { logger.warn("appId {} all slots is regular and assigned", appId); return RedisOperateEnum.ALREADY_SUCCESS; } // 3.2 查看目标实例丢失slots final List clusterLossSlots = redisCenter .getInstanceSlots(appId, healthyMasterHost, healthyMasterPort, lossSlotsInstanceInfo.getIp(), lossSlotsInstanceInfo.getPort()); // 4.开启新的节点 // 4.1 从newMasterHost找到可用的端口newMasterPort final Integer newMasterPort = machineCenter .getAvailablePort(newMasterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); if (newMasterPort == null) { logger.error("host={} getAvailablePort is null", newMasterHost); return RedisOperateEnum.FAIL; } // 4.2 按照sourceMasterInstance的内存启动 boolean isRun = runInstance(appDesc, newMasterHost, newMasterPort, healthyMasterMem, true); if (!isRun) { logger.error("{}:{} is not run", newMasterHost, newMasterPort); return RedisOperateEnum.FAIL; } // 4.3 拷贝配置 boolean isCopy = copyCommonConfig(appId, healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort); if (!isCopy) { logger.error("{}:{} copy config {}:{} is error", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort); return RedisOperateEnum.FAIL; } // 5. meet boolean isClusterMeet = false; try (Jedis sourceMasterJedis = redisCenter.getAdminJedis(appId, healthyMasterHost, healthyMasterPort);){ isClusterMeet = clusterMeet(sourceMasterJedis, appId, newMasterHost, newMasterPort); if (!isClusterMeet) { logger.error("{}:{} cluster is failed", newMasterHost, newMasterPort); return RedisOperateEnum.FAIL; } } catch (Exception e) { logger.error(e.getMessage(), e); } if (!isClusterMeet) { logger.warn("{}:{} meet {}:{} is fail", healthyMasterHost, healthyMasterPort, newMasterHost, newMasterPort); return RedisOperateEnum.FAIL; } // 6. 分配slots //String addSlotsResult = ""; Jedis newMasterJedis = null; //Jedis healthyMasterJedis = null; try { newMasterJedis = redisCenter.getJedis(appId, newMasterHost, newMasterPort, 5000, 5000); //获取新的补救节点的nodeid final String nodeId = getClusterNodeId(newMasterJedis); //healthyMasterJedis = redisCenter.getJedis(appId, healthyMasterHost, healthyMasterPort, 5000, 5000); // 新加节点也需要addsolts InstanceInfo addInstance = new InstanceInfo(); addInstance.setIp(newMasterHost); addInstance.setPort(newMasterPort); allInstanceInfo.add(addInstance); for (InstanceInfo instance : allInstanceInfo) { final Jedis masterJedis = redisCenter.getJedis(appId, instance.getIp(), instance.getPort(), 5000, 5000); logger.warn("{}:{} set {}:{} slots start", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort); // 1. nodes meet 2. nodes set boolean setSlotStatus = true; try { setSlotStatus = new IdempotentConfirmer() { @Override public boolean execute() { String setSlotsResult = null; try { for (final Integer slot : clusterLossSlots) { setSlotsResult = masterJedis.clusterSetSlotNode(slot, nodeId); logger.warn("set slot {}, result is {}", slot, setSlotsResult); } } catch (JedisDataException exception) { logger.warn(exception.getMessage()); // unkown jedis node try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } } // result boolean nodeSetStatus = setSlotsResult != null && setSlotsResult.equalsIgnoreCase("OK"); return nodeSetStatus; } }.run(); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { //close jedis if (masterJedis != null) { masterJedis.close(); } } // set slots result if (setSlotStatus) { logger.warn("{}:{} set {}:{} slots success", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort); } else { logger.warn("{}:{} set {}:{} slots faily", instance.getIp(), instance.getPort(), newMasterHost, newMasterPort); return RedisOperateEnum.FAIL; } } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (newMasterJedis != null) { newMasterJedis.close(); } } // 7.保存实例信息、并开启收集信息 saveInstance(appId, newMasterHost, newMasterPort, healthyMasterMem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); // 休息一段时间,同步clusterNodes信息 TimeUnit.SECONDS.sleep(2); // 8.最终打印出当前还没有补充的slots List currentLossSlots = redisCenter.getClusterLossSlots(appId, newMasterHost, newMasterPort); logger.warn("appId {} failslots assigned unsuccessfully, lossslots is {}", appId, currentLossSlots); return RedisOperateEnum.OP_SUCCESS; } @Override public boolean addSlave(long appId, int instanceId, final String slaveHost) { Assert.isTrue(appId > 0); Assert.isTrue(instanceId > 0); Assert.isTrue(StringUtils.isNotBlank(slaveHost)); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisType(type)) { logger.error("{} is not redis type", appDesc); return false; } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); String masterHost = instanceInfo.getIp(); int masterPort = instanceInfo.getPort(); final Integer slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_REDIS_STANDALONE); if (slavePort == null) { logger.error("host={} getAvailablePort is null", slaveHost); return false; } List> customConfigs = new ArrayList<>(); boolean isRun; if (TypeUtil.isRedisCluster(type)) { isRun = runInstance(appDesc, slaveHost, slavePort, masterHost, masterPort, instanceInfo.getMem(), true, customConfigs); } else { isRun = runInstance(appDesc, slaveHost, slavePort, masterHost, masterPort, instanceInfo.getMem(), false, customConfigs); } if (!isRun) { logger.error("{}:{} is not run", slaveHost, slavePort); return false; } // 注意redis高低版本复制config的问题 boolean isCopy = copyCommonConfig(appId, masterHost, masterPort, slaveHost, slavePort); if (!isCopy) { logger.error("{}:{} copy config {}:{} is error", masterHost, masterPort, slaveHost, slavePort); return false; } if (TypeUtil.isRedisCluster(type)) { final Jedis masterJedis = redisCenter .getJedis(appId, masterHost, masterPort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); final Jedis slaveJedis = redisCenter .getJedis(appId, slaveHost, slavePort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); try { boolean isClusterMeet = clusterMeet(masterJedis, appId, slaveHost, slavePort); if (!isClusterMeet) { logger.error("{}:{} cluster is failed", slaveHost, slaveHost); return isClusterMeet; } final String nodeId = redisCenter.getNodeId(appId, masterHost, masterPort); if (StringUtils.isBlank(nodeId)) { logger.error("{}:{} getNodeId failed", masterHost, masterPort); return false; } boolean isClusterReplicate = new IdempotentConfirmer() { @Override public boolean execute() { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } String response = slaveJedis.clusterReplicate(nodeId); logger.info("clusterReplicate-{}:{}={}", slaveHost, slavePort, response); return response != null && response.equalsIgnoreCase("OK"); } }.run(); if (!isClusterReplicate) { logger.error("{}:{} clusterReplicate {} is failed ", slaveHost, slavePort, nodeId); return false; } // 工具迁移添加slave节点时 master可能出现阻塞 int times = 1; //最多重试10次 boolean blockingFlag = true;//检测master节点是否阻塞 true:阻塞 false:不阻塞 while (blockingFlag && times++ <= RETRY_TIMES) { try { String masterPong = masterJedis.ping(); String slavePong = slaveJedis.ping(); logger.info("master ping :{}", masterPong); logger.info("slave ping :{}", slavePong); blockingFlag = false; } catch (Exception e) { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e1) { e1.printStackTrace(); } logger.error(" waiting master/slave blocking status ,waiting 2s .... exception:{}", e.getMessage()); } } //保存配置 masterJedis.clusterSaveConfig(); slaveJedis.clusterSaveConfig(); redisCenter.configRewrite(appId, masterHost, masterPort); redisCenter.configRewrite(appId, slaveHost, slavePort); } finally { masterJedis.close(); slaveJedis.close(); } } else { boolean isSlave = slaveOf(appId, masterHost, masterPort, slaveHost, slavePort); if (!isSlave) { logger.error("{}:{} sync {}:{} is error", slaveHost, slavePort, masterHost, masterPort); return false; } } //写入instanceInfo 信息 if (TypeUtil.isRedisCluster(type)) { saveInstance(appId, slaveHost, slavePort, instanceInfo.getMem(), ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); } else { saveInstance(appId, slaveHost, slavePort, instanceInfo.getMem(), ConstUtils.CACHE_REDIS_STANDALONE, ""); } return true; } /** * 为主节点添加从节点 * * @param appDesc * @param masterHost * @param masterPort * @param mem 单位Mb * @param slaveInstance 配置有slaveHost,添加成功,将设置slavePort * @return */ public boolean addSlave(AppDesc appDesc, String masterHost, int masterPort, int mem, InstanceInfo slaveInstance) throws Exception{ Assert.isTrue(appDesc != null); Assert.isTrue(StringUtils.isNotBlank(masterHost)); Assert.isTrue(masterPort > 0); Assert.isTrue(mem > 0); Assert.isTrue(StringUtils.isNotBlank(slaveInstance.getIp())); int type = appDesc.getType(); if (!TypeUtil.isRedisType(type)) { logger.error("{} is not redis type", appDesc); return false; } final Integer slavePort = machineCenter.getAvailablePort(slaveInstance.getIp(), ConstUtils.CACHE_REDIS_STANDALONE); if (slavePort == null) { logger.error("host={} getAvailablePort is null", slaveInstance.getIp()); return false; } List> customConfigs = new ArrayList<>(); boolean isRun; if (TypeUtil.isRedisCluster(type)) { isRun = runInstance(appDesc, slaveInstance.getIp(), slavePort, masterHost, masterPort, mem, true, customConfigs); } else { isRun = runInstance(appDesc, slaveInstance.getIp(), slavePort, masterHost, masterPort, mem, false, customConfigs); } if (!isRun) { logger.error("{}:{} is not run", slaveInstance.getIp(), slavePort); return false; } // // 注意redis高低版本复制config的问题 // boolean isCopy = copyCommonConfig(appId, masterHost, masterPort, slaveHost, slavePort); // if (!isCopy) { // logger.error("{}:{} copy config {}:{} is error", masterHost, masterPort, slaveHost, slavePort); // return false; // } if (TypeUtil.isRedisCluster(type)) { final Jedis masterJedis = redisCenter .getAdminJedis(appDesc.getAppId(), masterHost, masterPort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); final Jedis slaveJedis = redisCenter .getAdminJedis(appDesc.getAppId(), slaveInstance.getIp(), slavePort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT); try { boolean isClusterMeet = clusterMeet(masterJedis, appDesc.getAppId(), slaveInstance.getIp(), slavePort); if (!isClusterMeet) { logger.error("{}:{} cluster is failed", slaveInstance.getIp(), slavePort); return isClusterMeet; } final String nodeId = redisCenter.getNodeId(appDesc.getAppId(), masterHost, masterPort); if (StringUtils.isBlank(nodeId)) { logger.error("{}:{} getNodeId failed", masterHost, masterPort); return false; } boolean isClusterReplicate = new IdempotentConfirmer() { @Override public boolean execute() { try { //等待广播节点 TimeUnit.SECONDS.sleep(2); } catch (Exception e) { logger.error(e.getMessage(), e); } String response = slaveJedis.clusterReplicate(nodeId); logger.info("clusterReplicate-{}:{}={}", slaveInstance.getIp(), slavePort, response); return response != null && response.equalsIgnoreCase("OK"); } }.run(); if (!isClusterReplicate) { logger.error("{}:{} clusterReplicate {} is failed ", slaveInstance.getIp(), slavePort, nodeId); return false; } // 工具迁移添加slave节点时 master可能出现阻塞 int times = 1; //最多重试10次 boolean blockingFlag = true;//检测master节点是否阻塞 true:阻塞 false:不阻塞 while (blockingFlag && times++ <= RETRY_TIMES) { try { String masterPong = masterJedis.ping(); String slavePong = slaveJedis.ping(); logger.info("master ping :{}", masterPong); logger.info("slave ping :{}", slavePong); blockingFlag = false; } catch (Exception e) { try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e1) { e1.printStackTrace(); } logger.error(" waiting master/slave blocking status ,waiting 2s .... exception:{}", e.getMessage()); } } //保存配置 masterJedis.clusterSaveConfig(); slaveJedis.clusterSaveConfig(); redisCenter.configRewrite(appDesc.getAppId(), masterHost, masterPort); redisCenter.configRewrite(appDesc.getAppId(), slaveInstance.getIp(), slavePort); } finally { masterJedis.close(); slaveJedis.close(); } } else { boolean isSlave = slaveOf(appDesc.getAppId(), masterHost, masterPort, slaveInstance.getIp(), slavePort); if (!isSlave) { logger.error("{}:{} sync {}:{} is error", slaveInstance.getIp(), slavePort, masterHost, masterPort); return false; } } slaveInstance.setPort(slavePort); //写入instanceInfo 信息 if (TypeUtil.isRedisCluster(type)) { saveInstance(appDesc.getAppId(), slaveInstance.getIp(), slavePort, mem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); } else { saveInstance(appDesc.getAppId(), slaveInstance.getIp(), slavePort, mem, ConstUtils.CACHE_REDIS_STANDALONE, ""); } return true; } @Override public String genSlaveIp(long appId, int instanceId) throws Exception { InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); String ip = instanceInfo.getIp(); MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip); //先从混合部署机器进行选择 List machineMixCandiList = machineCenter.getAllValidMachineMem(Arrays.asList(ip), machineInfo.getRoom(), UseTypeEnum.Machine_mix.getValue()); String slaveIp = this.getSlaveIp(machineMixCandiList, ip, machineInfo, instanceInfo); if(StringUtils.isEmpty(slaveIp)){ //再从专用部署机器进行选择 List machineSpecialCandiList = machineCenter.getAllValidMachineMem(Arrays.asList(ip), machineInfo.getRoom(), UseTypeEnum.Machine_special.getValue()); slaveIp = this.getSlaveIp(machineSpecialCandiList, ip, machineInfo, instanceInfo); } if(StringUtils.isEmpty(slaveIp)){ //再从测试部署机器进行选择 List machineTestCandiList = machineCenter.getAllValidMachineMem(Arrays.asList(ip), machineInfo.getRoom(), UseTypeEnum.Machine_test.getValue()); slaveIp = this.getSlaveIp(machineTestCandiList, ip, machineInfo, instanceInfo); } //若该应用下的机器没有满足条件的,选择其他机器 return slaveIp; } private String getSlaveIp(List machineList, String ip, MachineInfo machineInfo, InstanceInfo instanceInfo){ if (CollectionUtils.isNotEmpty(machineList)) { List machineResList = getMachineCandi(machineList, ip, instanceInfo.getMem(), machineInfo.getRack()); if (CollectionUtils.isNotEmpty(machineResList)) { int random = new Random().nextInt(machineResList.size()); return machineResList.get(random); } } return ""; } private boolean isSameRealMachine(String ip1, String ip2) { if (ip1.equals(ip2)) return true; MachineInfo machine1 = machineDao.getMachineInfoByIp(ip1); MachineInfo machine2 = machineDao.getMachineInfoByIp(ip2); String realIp1 = machine1.getVirtual() == 1 ? machine1.getRealIp() : machine1.getIp(); String realIp2 = machine2.getVirtual() == 1 ? machine2.getRealIp() : machine2.getIp(); return realIp1.equals(realIp2); } private List getMachineCandi(List machineCandiList, String ip, int reqMem, String rack) { return machineCandiList.stream() .filter(machineCandi -> !isSameRealMachine(ip, machineCandi.getIp())) .filter(machineCandi -> StringUtils.isEmpty(rack) || StringUtils.isEmpty(machineCandi.getRack()) || !rack.equals(machineCandi.getRack())) .filter(machineCandi -> (machineCandi.getMem() * 1024 - machineCandi.getUsedMem() / 1024 / 1024) > reqMem) .map(MachineMemStatInfo::getIp) .collect(Collectors.toList()); } @Override public boolean sentinelFailover(final long appId) throws Exception { Assert.isTrue(appId > 0); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisSentinel(type)) { logger.warn("app={} is not sentinel", appDesc); return false; } final List instanceList = instanceDao.getEffectiveInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { logger.warn("app={} instances is empty", appId); return false; } for (InstanceInfo instanceInfo : instanceList) { int instanceType = instanceInfo.getType(); if (TypeUtil.isRedisSentinel(instanceType)) { final String host = instanceInfo.getIp(); final int port = instanceInfo.getPort(); final String masterName = instanceInfo.getCmd(); if (StringUtils.isBlank(masterName)) { logger.warn("{} cmd is null", instanceInfo); continue; } boolean isRun = redisCenter.isRun(host, port); if (!isRun) { logger.warn("{}:{} is not run", host, port); continue; } boolean isSentinelFailOver = new IdempotentConfirmer() { @Override public boolean execute() { Jedis jedis = redisCenter.getJedis(host, port); try { String response = jedis.sentinelFailover(masterName); return response != null && response.equalsIgnoreCase("OK"); } finally { jedis.close(); } } }.run(); if (!isSentinelFailOver) { logger.warn("{}:{} sentienl isSentinelFailOver error", host, port); return false; } else { logger.warn("SentinelFailOver done! "); break; } } } return true; } public boolean sentinelReset(long app_id) throws Exception { AppDesc appDesc = appService.getByAppId(app_id); int type = appDesc.getType(); if (!TypeUtil.isRedisSentinel(type)) { logger.warn("app={} is not sentinel", appDesc); return false; } final List instanceList = instanceDao.getInstancesByType(app_id, ConstUtils.CACHE_REDIS_SENTINEL); if (instanceList == null || instanceList.isEmpty()) { logger.warn("app={} instances is empty", app_id); return false; } for (InstanceInfo instanceInfo : instanceList) { int instanceType = instanceInfo.getType(); if (TypeUtil.isRedisSentinel(instanceType)) { final String host = instanceInfo.getIp(); final int port = instanceInfo.getPort(); final String masterName = instanceInfo.getCmd(); if (StringUtils.isBlank(masterName)) { logger.warn("{} sentinel masterName is null", instanceInfo); continue; } boolean isRun = redisCenter.isRun(host, port); if (!isRun) { logger.warn("{}:{} is not run", host, port); continue; } boolean isSentinelReset = new IdempotentConfirmer() { @Override public boolean execute() { Jedis jedis = redisCenter.getJedis(host, port); try { Long response = jedis.sentinelReset("*"); if (response == 1) { return true; } } finally { jedis.close(); } return false; } }.run(); if (!isSentinelReset) { logger.warn("{}:{} sentinel isSentinelReset error", host, port); return false; } else { logger.warn("{}:{} SentinelReset done! ", host, port); } } } return true; } public boolean clusterFailover(long appId, HostAndPort hostAndPort, String failoverParam) throws Exception { InstanceInfo inst = instanceDao.getInstByIpAndPort(hostAndPort.getHost(), hostAndPort.getPort()); if (inst != null && inst.getId() > 0) { return clusterFailover(appId, inst.getId(), failoverParam); } else { logger.warn("appid:{} clusterFailover error : {} get instanceinfo is empty,inst:{} ", appId, hostAndPort, inst); return false; } } @Override public boolean clusterFailover(final long appId, int slaveInstanceId, final String failoverParam) throws Exception { Assert.isTrue(appId > 0); Assert.isTrue(slaveInstanceId > 0); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisCluster(type)) { logger.error("{} is not redis cluster type", appDesc); return false; } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(slaveInstanceId); Assert.isTrue(instanceInfo != null); String slaveHost = instanceInfo.getIp(); int slavePort = instanceInfo.getPort(); final Jedis slaveJedis = redisCenter.getJedis(appId, slaveHost, slavePort); boolean isClusterFailOver = new IdempotentConfirmer() { @Override public boolean execute() { String response = null; if (StringUtils.isBlank(failoverParam)) { response = slaveJedis.clusterFailover(); } else if ("force".equals(failoverParam)) { response = slaveJedis.clusterFailover(ClusterFailoverOption.FORCE); } else if ("takeover".equals(failoverParam)) { response = slaveJedis.clusterFailover(ClusterFailoverOption.TAKEOVER); } else { logger.error("appId {} failoverParam {} is wrong", appId, failoverParam); } return response != null && response.equalsIgnoreCase("OK"); } }.run(); if (!isClusterFailOver) { logger.error("{}:{} clusterFailover {} failed", slaveHost, slavePort, failoverParam); return false; } else { logger.warn("{}:{} clusterFailover {} Done! ", slaveHost, slavePort, failoverParam); } return true; } @Override public ClusterOperateResult delNode(final Long appId, int delNodeInstanceId) { final InstanceInfo forgetInstanceInfo = instanceDao.getInstanceInfoById(delNodeInstanceId); final String forgetNodeId = redisCenter.getNodeId(appId, forgetInstanceInfo.getIp(), forgetInstanceInfo.getPort()); if (StringUtils.isBlank(forgetNodeId)) { logger.warn("{} nodeId is null", forgetInstanceInfo.getHostPort()); return ClusterOperateResult.fail(String.format("%s nodeId is null", forgetInstanceInfo.getHostPort())); } List instanceInfos = instanceDao.getInstListByAppId(appId); for (InstanceInfo instanceInfo : instanceInfos) { if (instanceInfo == null) { continue; } if (instanceInfo.isOffline()) { continue; } // 过滤当前节点 if (forgetInstanceInfo.getHostPort().equals(instanceInfo.getHostPort())) { continue; } final String instanceHost = instanceInfo.getIp(); final int instancePort = instanceInfo.getPort(); boolean isForget = new IdempotentConfirmer() { @Override public boolean execute() { String response = null; Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, instanceHost, instancePort); logger.warn("{}:{} is forgetting {}", instanceHost, instancePort, forgetNodeId); response = jedis.clusterForget(forgetNodeId); boolean success = response != null && response.equalsIgnoreCase("OK"); logger.warn("{}:{} is forgetting {} result is {}", instanceHost, instancePort, forgetNodeId, success); return success; } catch (Exception e) { logger.error(e.getMessage()); } finally { if (jedis != null) { jedis.close(); } } return response != null && response.equalsIgnoreCase("OK"); } }.run(); if (!isForget) { logger.warn("{}:{} forget {} failed", instanceHost, instancePort, forgetNodeId); return ClusterOperateResult .fail(String.format("%s:%s forget %s failed", instanceHost, instancePort, forgetNodeId)); } } // shutdown boolean isShutdown = instanceDeployCenter.shutdownExistInstance(appId, delNodeInstanceId); if (!isShutdown) { logger.warn("{} shutdown failed", forgetInstanceInfo.getHostPort()); return ClusterOperateResult.fail(String.format("%s shutdown failed", forgetInstanceInfo.getHostPort())); } return ClusterOperateResult.success(); } /** * 1. 被forget的节点必须在线(这个条件有待验证) * 2. 被forget的节点不能有从节点 * 3. 被forget的节点不能有slots */ @Override public ClusterOperateResult checkClusterForget(Long appId, int forgetInstanceId) { // 0.各种验证 Assert.isTrue(appId > 0); Assert.isTrue(forgetInstanceId > 0); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisCluster(type)) { logger.error("{} is not redis cluster type", appDesc); return ClusterOperateResult.fail(String.format("instanceId: %s must be cluster type", forgetInstanceId)); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(forgetInstanceId); Assert.isTrue(instanceInfo != null); String forgetHost = instanceInfo.getIp(); int forgetPort = instanceInfo.getPort(); // 1.是否在线 boolean isRun = redisCenter.isRun(appId, forgetHost, forgetPort); if (!isRun) { logger.warn("{}:{} is not run", forgetHost, forgetPort); return ClusterOperateResult.fail(String.format("被forget的节点(%s:%s)必须在线", forgetHost, forgetPort)); } // 2.被forget的节点不能有从节点 BooleanEnum hasSlaves = redisCenter.hasSlaves(appId, forgetHost, forgetPort); // if (hasSlaves == null || hasSlaves) { // logger.warn("{}:{} has slave", forgetHost, forgetPort); // return ClusterOperateResult.fail(String.format("被forget的节点(%s:%s)不能有从节点", forgetHost, forgetPort)); // } if (hasSlaves == BooleanEnum.OTHER || hasSlaves == BooleanEnum.TRUE) { logger.warn("{}:{} has slave", forgetHost, forgetPort); return ClusterOperateResult.fail(String.format("被forget的节点(%s:%s)不能有从节点", forgetHost, forgetPort)); } // 3.被forget的节点不能有slots Map clusterSlotsMap = redisCenter.getClusterSlotsMap(appId); InstanceSlotModel instanceSlotModel = clusterSlotsMap.get(instanceInfo.getHostPort()); if (instanceSlotModel != null && instanceSlotModel.getSlotList() != null && instanceSlotModel.getSlotList().size() > 0) { logger.warn("{}:{} has slots", forgetHost, forgetPort); return ClusterOperateResult.fail(String.format("被forget的节点(%s:%s)不能持有slot", forgetHost, forgetPort)); } return ClusterOperateResult.success(); } /** * 拷贝redis配置 * * @param sourceHost * @param sourcePort * @param targetHost * @param targetPort * @return */ private boolean copyCommonConfig(long appId, String sourceHost, int sourcePort, String targetHost, int targetPort) { String[] compareConfigs = new String[]{"maxmemory-policy", "maxmemory", "cluster-node-timeout", "cluster-require-full-coverage", "repl-backlog-size", "appendonly", "hash-max-ziplist-entries", "hash-max-ziplist-value", "list-max-ziplist-entries", "list-max-ziplist-value", "set-max-intset-entries", "zset-max-ziplist-entries", "zset-max-ziplist-value", "timeout", "tcp-keepalive"}; try { for (String config : compareConfigs) { String sourceValue = getConfigValue(appId, sourceHost, sourcePort, config); if (StringUtils.isBlank(sourceValue)) { continue; } String targetValue = getConfigValue(appId, targetHost, targetPort, config); /** * todo chenshi * 上面参数配置是按照redis3.0版本配置,高版本redis 3.2的参数配置有变化(需要做映射或默认配置) * 3.0.7 : list-max-ziplist-entries list-max-ziplist-value * 3.2.10: 无上面两个参数配置list-max-ziplist-size list-compress-depth */ if (StringUtils.isNotBlank(targetValue)) { if (!targetValue.equals(sourceValue)) { this.modifyInstanceConfig(appId, targetHost, targetPort, config, sourceValue); } } } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } private String getConfigValue(long appId, String host, int port, String key) { Jedis jedis = redisCenter .getAdminJedis(appId, host, port, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { List values = jedis.configGet(key); if (values == null || values.size() < 1) { return null; } return values.get(1); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } finally { jedis.close(); } } @Override public boolean fixPassword(Long appId, String newPkey) { if (appId == null) { logger.warn("appId is null"); return false; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error("appId = {} not exist", appId); return false; } if (StringUtils.isBlank(newPkey)) { logger.warn("newPkey is null, fix empty password"); } String newPasswordMD5 = ""; if (StringUtils.isNotBlank(newPkey)) { newPasswordMD5 = AuthUtil.getAppIdMD5(newPkey); } String oldPasswordMD5 = appDesc.getAppPassword(); List instanceInfos = instanceDao.getInstListByAppId(appId); boolean isSuccess = batchFixPasswordByAdmin(instanceInfos, oldPasswordMD5, newPasswordMD5, AuthUtil.getAppIdMD5(StringUtils.isNotEmpty(newPkey) ? newPkey : String.valueOf(appId)), appDesc.getVersionId()); if (isSuccess) { appDesc.setPkey(newPkey); appDao.update(appDesc); } return isSuccess; } @Override public boolean fixPassword(Long appId, String password, Boolean customPwdFlag, boolean initRedisFlag) { if (appId == null) { logger.warn("appId is null"); return false; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error("appId = {} not exist", appId); return false; } if(customPwdFlag == null){ if(initRedisFlag){ customPwdFlag = appDesc.isSetCustomPassword(); }else{ customPwdFlag = false; } } String newPassword = null; String newPkey = null; if(customPwdFlag){ if(StringUtils.isBlank(password)){ if(initRedisFlag){ newPassword = appDesc.getCustomPassword(); }else{ newPassword = password; } }else{ newPassword = password; } }else{ if(StringUtils.isBlank(password)){ if(initRedisFlag){ newPkey = String.valueOf(appId); newPassword = AuthUtil.getAppIdMD5(newPkey); }else{ newPkey = null; newPassword = null; } }else{ newPkey = password; newPassword = AuthUtil.getAppIdMD5(password); } } if(newPassword == null){ newPassword = ""; } String oldPassword = appDesc.getAppPassword(); List instanceInfos = instanceDao.getInstListByAppId(appId); boolean isSuccess = false; if(!initRedisFlag){ isSuccess = batchFixPasswordByAdmin(instanceInfos, oldPassword, newPassword, AuthUtil.getAppIdMD5(StringUtils.isNotEmpty(newPkey) ? newPkey : String.valueOf(appId)), appDesc.getVersionId()); }else{ isSuccess = batchFixPassword(instanceInfos, oldPassword, newPassword, AuthUtil.getAppIdMD5(StringUtils.isNotEmpty(newPkey) ? newPkey : String.valueOf(appId)), appDesc.getVersionId()); } if(!customPwdFlag){ if (isSuccess) { appDesc.setPkey(newPkey); appDesc.setCustomPassword(null); appDao.updateWithCustomPwd(appDesc); } }else{ if (isSuccess) { newPkey = String.valueOf(appId); appDesc.setPkey(newPkey); appDesc.setCustomPassword(newPassword); appDao.updateWithCustomPwd(appDesc); } } return isSuccess; } @Override public boolean checkAuths(Long appId) { if (appId == null) { logger.warn("appId is null"); return false; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error("appId = {} not exist", appId); return false; } String password = appDesc.getAppPassword(); List instanceInfos = instanceDao.getInstListByAppId(appId); List nodeList = Lists.newArrayList(); try{ for (InstanceInfo instanceInfo : instanceInfos) { String host = instanceInfo.getIp(); try { int port = instanceInfo.getPort(); int type = instanceInfo.getType(); if (instanceInfo.isOffline()) { logger.info("instanceInfo {}:{} is offline", host, port); continue; } if (TypeUtil.isRedisCluster(type) || TypeUtil.isRedisStandalone(type)) { Jedis jedis = redisCenter.getJedis(host, port, password); nodeList.add(jedis); } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } return checkAuthNodes(nodeList, password); }finally { nodeList.forEach(jedis -> { try{ jedis.close(); }catch (Exception e){ } }); } } private boolean batchFixPasswordByAdmin(List instanceInfos, String oldPasswordMD5, String passwordMD5, String adminPwd, Integer versionId) { if (CollectionUtils.isEmpty(instanceInfos)) { return false; } //修改密码之前,提取所有存活节点。 List nodeList = Lists.newArrayList(); List rollbackNodeList = Lists.newArrayList(); String masterName = null; List sentinelList = Lists.newArrayList(); List rollbackSentinelList = Lists.newArrayList(); try{ for (InstanceInfo instanceInfo : instanceInfos) { String host = instanceInfo.getIp(); try { int port = instanceInfo.getPort(); int type = instanceInfo.getType(); if (instanceInfo.isOffline()) { logger.info("instanceInfo {}:{} is offline", host, port); continue; } if (TypeUtil.isRedisCluster(type) || TypeUtil.isRedisStandalone(type)) { Jedis jedis = redisCenter.getAdminJedis(host, port, adminPwd); nodeList.add(jedis); } else if (TypeUtil.isRedisSentinel(type)) { if (StringUtils.isNotBlank(instanceInfo.getCmd())) { masterName = instanceInfo.getCmd(); } Jedis jedis = redisCenter.getJedis(host, port); sentinelList.add(jedis); } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } logger.warn("collect nodes done,list:"); return this.doBatchFixPassword(nodeList, sentinelList, rollbackNodeList, rollbackSentinelList, masterName, oldPasswordMD5, passwordMD5, adminPwd, versionId, true); } finally { close(nodeList); close(sentinelList); } } private boolean batchFixPassword(List instanceInfos, String oldPasswordMD5, String passwordMD5, String adminPwd, Integer versionId) { if (CollectionUtils.isEmpty(instanceInfos)) { return false; } //修改密码之前,提取所有存活节点。 List nodeList = Lists.newArrayList(); List rollbackNodeList = Lists.newArrayList(); String masterName = null; List sentinelList = Lists.newArrayList(); List rollbackSentinelList = Lists.newArrayList(); try{ for (InstanceInfo instanceInfo : instanceInfos) { String host = instanceInfo.getIp(); try { int port = instanceInfo.getPort(); int type = instanceInfo.getType(); if (instanceInfo.isOffline()) { logger.info("instanceInfo {}:{} is offline", host, port); continue; } if (TypeUtil.isRedisCluster(type) || TypeUtil.isRedisStandalone(type)) { Jedis jedis = redisCenter.getJedis(host, port, oldPasswordMD5); nodeList.add(jedis); } else if (TypeUtil.isRedisSentinel(type)) { if (StringUtils.isNotBlank(instanceInfo.getCmd())) { masterName = instanceInfo.getCmd(); } Jedis jedis = redisCenter.getJedis(host, port); sentinelList.add(jedis); } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } //打印需要配置密码的节点信息 logger.warn("collect nodes done,list:"); return this.doBatchFixPassword(nodeList, sentinelList, rollbackNodeList, rollbackSentinelList, masterName, oldPasswordMD5, passwordMD5, adminPwd, versionId, false); } finally { close(nodeList); close(sentinelList); } } private boolean doBatchFixPassword(List nodeList, List sentinelList, List rollbackNodeList, List rollbackSentinelList, String masterName, String oldPasswordMD5, String passwordMD5, String adminPwd, Integer versionId, boolean doByAdmin) { //打印需要配置密码的节点信息 for (Jedis jedis : nodeList) { logger.warn("fix-password-node:" + JedisUtil.getHostPort(jedis) + " isRun:" + redisCenter.isRun(jedis.getClient().getHost(), jedis.getClient().getPort())); } for (Jedis jedis : sentinelList) { logger.warn("fix-sentinel-password-node:" + JedisUtil.getHostPort(jedis) + " isRun:" + redisCenter.isRun(jedis.getClient().getHost(), jedis.getClient().getPort())); } for (Jedis jedis : nodeList) { boolean isFix = false; if(doByAdmin){ isFix = fixNodeDefaultPasswordByAdmin(jedis, passwordMD5); }else{ isFix = fixNodePassword(jedis, passwordMD5); } if (isFix) { //加入待回滚列表 rollbackNodeList.add(jedis); } else { //设置node密码错误回滚node rollbackNodes(rollbackNodeList, oldPasswordMD5); return false; } } if (StringUtils.isNotBlank(masterName)) { for (Jedis jedis : sentinelList) { boolean isFix = fixSentinelPassword(jedis, masterName, passwordMD5); if (isFix) { //加入待回滚列表 rollbackSentinelList.add(jedis); } else { //设置sentinel密码错误回滚node+sentinel rollbackNodes(rollbackNodeList, oldPasswordMD5); rollbackSentinels(rollbackSentinelList, masterName, oldPasswordMD5); return false; } } } //检测所有节点密码发是否生效 boolean allAuth = checkAuthNodes(nodeList, passwordMD5); if (!allAuth) { logger.warn("base-auth-error: batch-rollback={}", passwordMD5); //设置sentinel密码错误回滚node+sentinel rollbackNodes(rollbackNodeList, oldPasswordMD5); rollbackSentinels(rollbackSentinelList, masterName, oldPasswordMD5); } return allAuth; } private boolean fixSentinelPassword(Jedis jedis, String masterName, String passwordMD5) { String hostPort = JedisUtil.getHostPort(jedis); /** * sentinel set {masterName} auth-pass {passwordMD5} * sentinel flushconfig */ try { Map params = new HashMap(); params.put("auth-pass", passwordMD5); String setResult = jedis.sentinelSet(masterName, params); if (setResult.equals("OK")) { logger.warn("config-pass sentinel success: sentinel={} master={} , auth-pass={}", hostPort, masterName, passwordMD5); String flushResult = JedisUtil.sentinelFlushConfig(jedis); if (flushResult.equals("OK")) { logger.warn("config rewrite success,sentinel={}", hostPort); } else { logger.error("config rewrite success sentinel={}", hostPort); return false; } } else { logger.error("sentinel-config-error:sentinel={} result={}", JedisUtil.getHostPort(jedis), setResult); return false; } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } private void rollbackNodes(List rollbackNodeList, String oldPasswordMD5) { //设置密码错误回滚 // rollback-nodes for (Jedis rollbackJedis : rollbackNodeList) { boolean rollback = fixNodePassword(rollbackJedis, oldPasswordMD5); logger.warn("node-rollback: node={} rollback={}", JedisUtil.getHostPort(rollbackJedis), rollback); } } private void rollbackSentinels(List rollbackSentinelList, String masterName, String oldPasswordMD5) { // rollback-sentinels for (Jedis rollbackJedis : rollbackSentinelList) { boolean rollback = fixSentinelPassword(rollbackJedis, masterName, oldPasswordMD5); logger.warn("sentinel-rollback: node={} rollback={}", JedisUtil.getHostPort(rollbackJedis), rollback); } } private boolean fixNodePassword(Jedis jedis, String passwordMD5) { String hostPort = JedisUtil.getHostPort(jedis); try { List results = Lists.newArrayList(); results.add(jedis.configSet("requirepass", passwordMD5)); //密码设置后,无密码连接需要重新认证 if (StringUtils.isNotBlank(passwordMD5)) { jedis.auth(passwordMD5); } results.add(jedis.configSet("masterauth", passwordMD5)); if (results.get(0).equals("OK") && results.get(1).equals("OK")) { logger.warn("config-pass success: node={} results={}", hostPort, results); String rewrite = jedis.configRewrite(); if (rewrite.equals("OK")) { logger.warn("node-rewrite success: node={} result={}", hostPort, rewrite); } else { logger.error("config rewrite error node={}", hostPort); } } else { logger.error("config-pass error: node={} results={}", hostPort, results); return false; } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } private boolean fixNodeDefaultPasswordByAdmin(Jedis jedis, String passwordMD5) { String hostPort = JedisUtil.getHostPort(jedis); try { List results = Lists.newArrayList(); results.add(jedis.configSet("requirepass", passwordMD5)); //管理员用户修改默认用户密码,无需要重新密码认证 results.add(jedis.configSet("masterauth", passwordMD5)); if (results.get(0).equals("OK") && results.get(1).equals("OK")) { logger.warn("config-pass success: node={} results={}", hostPort, results); String rewrite = jedis.configRewrite(); if (rewrite.equals("OK")) { logger.warn("node-rewrite success: node={} result={}", hostPort, rewrite); } else { logger.error("config rewrite error node={}", hostPort); } } else { logger.error("config-pass error: node={} results={}", hostPort, results); return false; } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } // 判断密码是否匹配 private boolean checkAuthNodes(List nodes, String passwordMD5) { for (Jedis jedis : nodes) { try { String auth = jedis.auth(passwordMD5); if (!auth.equals("OK")) { return false; } } catch (JedisDataException e) { //忽略无密码设置异常 if (e.getMessage().contains("no password is set") || e.getMessage().contains("without any password configured for the default user")) { logger.info("ignore ERR Client sent AUTH, but no password is set"); } else { logger.error(e.getMessage(), e); return false; } } catch (Exception e) { logger.error("node-auth-failed: node={} password={} error={}", JedisUtil.getHostPort(jedis), passwordMD5, e.getMessage()); logger.error(e.getMessage(), e); return false; } } return true; } @Override public boolean slaveOf(final long appId, final String masterHost, final int masterPort, final String slaveHost, final int slavePort) { final Jedis slave = redisCenter.getAdminJedis(appId, slaveHost, slavePort, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { boolean isSlave = new IdempotentConfirmer() { @Override public boolean execute() { String result = slave.slaveof(masterHost, masterPort); //也有可能是OK Already connected to specified master return result != null && result.startsWith("OK"); } }.run(); if (!isSlave) { logger.error(String.format("modifyAppConfig:ip=%s,port=%s failed", slaveHost, slavePort)); return false; } redisCenter.configRewrite(appId, slaveHost, slavePort); } catch (Exception e) { logger.error(e.getMessage(), e); return false; } finally { if (slave != null) slave.close(); } return true; } @Override public boolean slaveOfByDefaultUser(final long appId, final String masterHost, final int masterPort, final String slaveHost, final int slavePort) { final Jedis slave = redisCenter.getJedis(appId, slaveHost, slavePort, Protocol.DEFAULT_TIMEOUT * 3, Protocol.DEFAULT_TIMEOUT * 3); try { boolean isSlave = new IdempotentConfirmer() { @Override public boolean execute() { String result = slave.slaveof(masterHost, masterPort); //也有可能是OK Already connected to specified master return result != null && result.startsWith("OK"); } }.run(); if (!isSlave) { logger.error(String.format("modifyAppConfig:ip=%s,port=%s failed", slaveHost, slavePort)); return false; } redisCenter.configRewrite(slave); } catch (Exception e) { logger.error(e.getMessage(), e); return false; } finally { if (slave != null) slave.close(); } return true; } private void close(List list) { for (Jedis jedis : list) { if (jedis != null) jedis.close(); } } /** * * @param appId * @param newInstHost * @param newInstPort * @param pointedRdb 是否已在目录下导入了rdb * @param mem 实例最大内存(与runInstId 必须至少一个不为空) * @param runInstId 运行实例信息 * @param slots * @return */ @Override public boolean addInstanceToUnhealthyApp(long appId, final String newInstHost, final Integer newInstPort, final boolean pointedRdb, Integer mem, int[] slots, Integer runInstId) { Assert.isTrue(appId > 0 && StringUtils.isNotBlank(newInstHost) && newInstPort != null); AppDesc appDesc = appDao.getAppDescById(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisType(type)) { logger.error("{} is not redis type", appDesc); return false; } List> customConfigs = new ArrayList<>(); //启动实例,用默认配置文件 boolean isRun; //如果有已有实例,则复制其指定配置 InstanceInfo existInstanceInfo = null; String existInstanceHost = null; Integer existInstancePort = null; if(runInstId != null){ existInstanceInfo = instanceDao.getInstanceInfoById(runInstId); Assert.isTrue(existInstanceInfo != null); existInstanceHost = existInstanceInfo.getIp(); existInstancePort = existInstanceInfo.getPort(); // 注意redis高低版本复制config的问题 // Map configMap = copyCommonConfig(appId, existInstanceInfo.getIp(), existInstanceInfo.getPort()); // customConfigMap.putAll(configMap); if(mem == null){ mem = existInstanceInfo.getMem(); } } customConfigs.add(Pair.of(RedisConfigEnum.APPENDONLY.getKey(), "no")); logger.info("to do run {}:{} with custom config {}", newInstHost, newInstPort, customConfigs); if (TypeUtil.isRedisCluster(type)) { isRun = runInstance(appDesc, newInstHost, newInstPort, existInstanceHost, existInstancePort, mem, true, customConfigs); } else { isRun = runInstance(appDesc, newInstHost, newInstPort, existInstanceHost, existInstancePort, mem, false, customConfigs); } if (!isRun) { logger.error("{}:{} is not run", newInstHost, newInstPort); return false; } Set existsSlotSet = new HashSet<>(); try(Jedis jedis = redisCenter .getJedis(appId, newInstHost, newInstPort, Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT);) { //加载rdb,并等等rdb加载完成,然后确认节点 slot分配 if (pointedRdb) { boolean loadFinish = redisCenter.checkLoadFinish(jedis, RETRY_TIMES); if (!loadFinish) { return false; } else { if(appDesc.getType() == AppTypeEnum.REDIS_CLUSTER.getType()){ //获取当前实例分配节点 InstanceInfo instanceInfo = new InstanceInfo(); instanceInfo.setIp(newInstHost); instanceInfo.setPort(newInstPort); Map> clusterSlotMap = redisCenter.getClusterSlotMap(appId, instanceInfo); logger.info("instance {}:{} cluster slot info is {}", newInstHost, newInstPort, clusterSlotMap); clusterSlotMap.keySet().forEach(key -> { List hostAndPorts = clusterSlotMap.get(key); if (hostAndPorts.contains(new HostAndPort(newInstHost, newInstPort)) || hostAndPorts.contains(new HostAndPort("", newInstPort))) { String[] split = key.split("-"); if (split != null && split.length == 2) { for (int i = Integer.valueOf(split[0]); i <= Integer.valueOf(split[1]); i++) { existsSlotSet.add(i); } } } }); } } logger.info("{}:{} load rdb finish", newInstHost, newInstPort); } // 集群分配slot if(appDesc.getType() == AppTypeEnum.REDIS_CLUSTER.getType()){ logger.info("exists slots is {} due to load rdb", existsSlotSet); //计算需添加的slot if(CollectionUtils.isNotEmpty(existsSlotSet)){ Set originalToAddSlot = Arrays.stream(slots).boxed().collect(Collectors.toSet()); Sets.SetView setView = Sets.difference(originalToAddSlot, existsSlotSet); if(setView != null && setView.size() > 0){ int[] toAddSlots = new int[setView.size()]; int i = 0; UnmodifiableIterator iterator = setView.iterator(); while(iterator.hasNext()){ toAddSlots[i++] = iterator.next(); } slots = toAddSlots; } } logger.info("to add slots is {}", slots); //添加slot if(slots != null && slots.length > 0){ final int[] toAddSlots = slots; // 添加slots boolean isSlot = new IdempotentConfirmer() { @Override public boolean execute() { String response = jedis.clusterAddSlots(toAddSlots); boolean isSlot = response != null && response.equalsIgnoreCase("OK"); if (!isSlot) { logger.error("add slot {} to node {}:{} failed", toAddSlots, newInstHost, newInstPort); return false; } logger.info("add slot {} to node {}:{} success", toAddSlots, newInstHost, newInstPort); return true; } }.run(); if(!isSlot){ return false; } logger.info("add slots {} success", slots); } } } // 开启aof boolean configSetAndRewrite = redisCenter.configSetAndRewrite(appId, newInstHost, newInstPort, RedisConfigEnum.APPENDONLY.getKey(), "yes"); if (!configSetAndRewrite) { logger.error("appId {} instanceInfo {}:{} enable aof fail", appId, newInstHost, newInstPort); return configSetAndRewrite; } logger.info("enable {}:{} appendonly config to yes success", newInstHost, newInstPort); //判断是否指定链接实例,并meet到集群 if(existInstanceInfo != null){ if (TypeUtil.isRedisCluster(type)) { try (Jedis existJedis = redisCenter .getJedis(appId, existInstanceInfo.getIp(), existInstanceInfo.getPort(), Protocol.DEFAULT_TIMEOUT, Protocol.DEFAULT_TIMEOUT);) { boolean isClusterMeet = clusterMeet(existJedis, appId, newInstHost, newInstPort); if (!isClusterMeet) { logger.error("meet node {}:{} to cluster failed", newInstHost, newInstPort); return isClusterMeet; } logger.info("meet node {}:{} to cluster success", newInstHost, newInstPort); } } } //写入instanceInfo 信息 if (TypeUtil.isRedisCluster(type)) { saveInstance(appId, newInstHost, newInstPort, mem, ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); } else { saveInstance(appId, newInstHost, newInstPort, mem, ConstUtils.CACHE_REDIS_STANDALONE, ""); } return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/AuthUtil.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import java.security.MessageDigest; /** * Created by zhangyijun on 2017/7/31. */ public class AuthUtil { //客户端埋点SECRET_KEY,如果使用动态密码,建议客户端自行修改 public final static String SECRET_KEY = "asdfjlajrl2k3jflsdafjal$$$asfdf"; public final static String SPLIT_KEY = ":cc:"; /** * 密码判定 * 初始化用例: * 1:redis未设置密码,未设置password参数 * 2:redis未设置密码,设置password参数:原文 * 3:redis未设置密码,设置password参数:appId * 4:redis未设置密码,设置password参数:appId+MD5 * 5:redis设置密码, 设置password参数:原文 * 6:redis设置密码, 设置password参数:appId * 7:redis设置密码, 设置password参数:appId+MD5 * 运行期修改密码用例: * 1:redis无密码状态,后端设置原文密码后,连接报错重连通信正常 * 2:redis无密码状态,后端设置appId+MD5密码后,连接报错重连通信正常 * 3:redis存在appId密码,后端修改为md5密码后通信正常 * 期望结果: * 1:验证通过 * 2:原文密码,appId,MD5匹配一个,验证通过。 * 3:密码错误,抛出异常。 * tip: update this method without reset isbroken to true and it will fail when previous condition * @param jedis * @return */ public static void auth(Jedis jedis, String password) { if (password == null || password.trim().length() == 0) { //password为空,认为通过 return; } boolean isAuth = authForPassword(jedis, password); if (isAuth) { if (jedis.getClient().isBroken()) { jedis.close(); } } else { throw new JedisConnectionException("invalid password"); } } private static boolean authForPassword(Jedis jedis, String password) { if (password.contains(SPLIT_KEY)) { //password layout: appId+SPLIT_KEY+MD5 String[] split = password.split(SPLIT_KEY); String appId; String md5 = null; if (split.length == 1) { appId = split[0]; } else { appId = split[0]; md5 = split[1]; } // 如果存在md5,优先使用md5验证 if (md5 != null && md5.length() > 0) { boolean auth = checkAuth(jedis, md5, true); if (auth) { return true; } } md5 = getAppIdMD5(appId); return checkAuth(jedis, md5, false); } else { //不包含{SPLIT_KEY},直接认为是密码。 return "OK".equals(jedis.auth(password)); } } public static boolean checkAuth(Jedis jedis, String pass, boolean check) throws JedisDataException { try { jedis.auth(pass); return true; } catch (JedisDataException e) { if (check && e.getMessage() != null && e.getMessage().contains("invalid password")) { // 密码错误,重新验证 return false; } throw e; } } public static String getAppIdMD5(String appId) { String key = SECRET_KEY + ":" + appId; try { //确定计算方法 MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] md5Bytes = md5.digest(key.getBytes("UTF-8")); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) { hexValue.append("0"); } hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/ClusterNodeInformation.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.HostAndPort; import java.util.ArrayList; import java.util.List; public class ClusterNodeInformation { private HostAndPort node; private List availableSlots; private List slotsBeingImported; private List slotsBeingMigrated; public ClusterNodeInformation(HostAndPort node) { this.node = node; this.availableSlots = new ArrayList(); this.slotsBeingImported = new ArrayList(); this.slotsBeingMigrated = new ArrayList(); } public void addAvailableSlot(int slot) { availableSlots.add(slot); } public void addSlotBeingImported(int slot) { slotsBeingImported.add(slot); } public void addSlotBeingMigrated(int slot) { slotsBeingMigrated.add(slot); } public HostAndPort getNode() { return node; } public List getAvailableSlots() { return availableSlots; } public List getSlotsBeingImported() { return slotsBeingImported; } public List getSlotsBeingMigrated() { return slotsBeingMigrated; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/ClusterNodeInformationParser.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.HostAndPort; public class ClusterNodeInformationParser { private static final String SLOT_IMPORT_IDENTIFIER = "-<-"; private static final String SLOT_IN_TRANSITION_IDENTIFIER = "["; public static final int SLOT_INFORMATIONS_START_INDEX = 8; public static final int HOST_AND_PORT_INDEX = 1; public ClusterNodeInformation parse(String nodeInfo, HostAndPort current) { String[] nodeInfoPartArray = nodeInfo.split(" "); HostAndPort node = getHostAndPortFromNodeLine(nodeInfoPartArray, current); ClusterNodeInformation info = new ClusterNodeInformation(node); if (nodeInfoPartArray.length >= SLOT_INFORMATIONS_START_INDEX) { String[] slotInfoPartArray = extractSlotParts(nodeInfoPartArray); fillSlotInformation(slotInfoPartArray, info); } return info; } private String[] extractSlotParts(String[] nodeInfoPartArray) { String[] slotInfoPartArray = new String[nodeInfoPartArray.length - SLOT_INFORMATIONS_START_INDEX]; for (int i = SLOT_INFORMATIONS_START_INDEX; i < nodeInfoPartArray.length; i++) { slotInfoPartArray[i - SLOT_INFORMATIONS_START_INDEX] = nodeInfoPartArray[i]; } return slotInfoPartArray; } public HostAndPort getHostAndPortFromNodeLine(String[] nodeInfoPartArray, HostAndPort current) { String stringHostAndPort = nodeInfoPartArray[HOST_AND_PORT_INDEX]; String[] arrayHostAndPort = stringHostAndPort.split(":"); return new HostAndPort(arrayHostAndPort[0].isEmpty() ? current.getHost() : arrayHostAndPort[0], arrayHostAndPort[1].isEmpty() ? current.getPort() : Integer.parseInt(arrayHostAndPort[1])); } private void fillSlotInformation(String[] slotInfoPartArray, ClusterNodeInformation info) { for (String slotRange : slotInfoPartArray) { fillSlotInformationFromSlotRange(slotRange, info); } } private void fillSlotInformationFromSlotRange(String slotRange, ClusterNodeInformation info) { if (slotRange.startsWith(SLOT_IN_TRANSITION_IDENTIFIER)) { // slot is in transition int slot = Integer.parseInt(slotRange.substring(1).split("-")[0]); if (slotRange.contains(SLOT_IMPORT_IDENTIFIER)) { // import info.addSlotBeingImported(slot); } else { // migrate (->-) info.addSlotBeingMigrated(slot); } } else if (slotRange.contains("-")) { // slot range String[] slotRangePart = slotRange.split("-"); for (int slot = Integer.parseInt(slotRangePart[0]); slot <= Integer.parseInt(slotRangePart[1]); slot++) { info.addAvailableSlot(slot); } } else { // single slot info.addAvailableSlot(Integer.parseInt(slotRange)); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/Command.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.util.SafeEncoder; public enum Command implements ProtocolCommand { PING, SET, GET, QUIT, EXISTS, DEL, UNLINK, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZCARD, ZSCORE, ZPOPMAX, ZPOPMIN, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, ZCOUNT, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, ZLEXCOUNT, ZRANGEBYLEX, ZREVRANGEBYLEX, ZREMRANGEBYLEX, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, PFADD, PFCOUNT, PFMERGE, READONLY, GEOADD, GEODIST, GEOHASH, GEOPOS, GEORADIUS, GEORADIUS_RO, GEORADIUSBYMEMBER, GEORADIUSBYMEMBER_RO, MODULE, BITFIELD, HSTRLEN, TOUCH, SWAPDB, MEMORY, XADD, XLEN, XDEL, XTRIM, XRANGE, XREVRANGE, XREAD, XACK, XGROUP, XREADGROUP, XPENDING, XCLAIM, LATENCY, ACL, XINFO, BITFIELD_RO, COMMAND; private final byte[] raw; Command() { raw = SafeEncoder.encode(this.name()); } @Override public byte[] getRaw() { return raw; } public enum SearchCommand implements ProtocolCommand { CREATE("FT.CREATE"), ALTER("FT.ALTER"), INFO("FT.INFO"), SEARCH("FT.SEARCH"), EXPLAIN("FT.EXPLAIN"), EXPLAINCLI("FT.EXPLAINCLI"), AGGREGATE("FT.AGGREGATE"), CURSOR("FT.CURSOR"), CONFIG("FT.CONFIG"), CLUSTER_CONFIG("_FT.CONFIG"), ALIASADD("FT.ALIASADD"), ALIASUPDATE("FT.ALIASUPDATE"), ALIASDEL("FT.ALIASDEL"), SYNUPDATE("FT.SYNUPDATE"), SYNDUMP("FT.SYNDUMP"), SUGADD("FT.SUGADD"), SUGGET("FT.SUGGET"), SUGDEL("FT.SUGDEL"), SUGLEN("FT.SUGLEN"), DROPINDEX("FT.DROPINDEX"), LIST("FT._LIST"); private final byte[] raw; private SearchCommand(String alt) { raw = SafeEncoder.encode(alt); } @Override public byte[] getRaw() { return raw; } } public enum JSONCommand implements ProtocolCommand { OBJLEN("JSON.OBJLEN"), JSONGET("JSON.GET"); private final byte[] raw; private JSONCommand(String alt) { raw = SafeEncoder.encode(alt); } @Override public byte[] getRaw() { return raw; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/JedisUtil.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.Client; import redis.clients.jedis.Jedis; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/11/25 17:43 * @Description: */ public class JedisUtil { public static final String SENTINEL_FLUSH_CONFIG = "flushconfig"; public static List latencyLatest(Jedis jedis){ Client client = jedis.getClient(); client.sendCommand(Command.LATENCY, Keyword.LATEST.raw); List latencyItems = LatencyItem.from(client.getObjectMultiBulkReply()); return latencyItems; } public static String sentinelFlushConfig(Jedis jedis){ Client client = jedis.getClient(); client.sentinel(SENTINEL_FLUSH_CONFIG); return client.getStatusCodeReply(); } public static String getHostPort(Jedis jedis){ Client client = jedis.getClient(); return client.getHost() + ":" + client.getPort(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/Keyword.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.util.SafeEncoder; import java.util.Locale; public enum Keyword { AGGREGATE, ALPHA, ASC, BY, DESC, GET, LIMIT, MESSAGE, NO, NOSORT, PMESSAGE, PSUBSCRIBE, PUNSUBSCRIBE, OK, ONE, QUEUED, SET, STORE, SUBSCRIBE, UNSUBSCRIBE, WEIGHTS, WITHSCORES, RESETSTAT, REWRITE, RESET, FLUSH, EXISTS, LOAD, KILL, LEN, REFCOUNT, ENCODING, IDLETIME, GETNAME, SETNAME, LIST, MATCH, COUNT, PING, PONG, UNLOAD, REPLACE, KEYS, PAUSE, DOCTOR, BLOCK, NOACK, STREAMS, KEY, CREATE, MKSTREAM, SETID, DESTROY, DELCONSUMER, MAXLEN, GROUP, IDLE, TIME, RETRYCOUNT, FORCE, LATEST, HISTORY, GRAPH, USAGE, STATS, PURGE, TRACKING, GETREDIR, ID, ON, OFF, STREAM, GROUPS, CONSUMERS, HELP, FREQ, SETUSER, GETUSER, DELUSER, WHOAMI, CAT, GENPASS, USERS; public final byte[] raw; Keyword() { raw = SafeEncoder.encode(this.name().toLowerCase(Locale.ENGLISH)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/LatencyHistoryItem.java ================================================ package com.sohu.cache.redis.util; import java.util.ArrayList; import java.util.List; /** * @author wenruiwu * @create 2020/5/6 10:25 * @description Latency history event */ public class LatencyHistoryItem { private final long timeStamp; private final long executionTime; private static final String COMMA = ","; @SuppressWarnings("unchecked") public LatencyHistoryItem(List properties) { super(); this.timeStamp = (Long) properties.get(0); this.executionTime = (Long) properties.get(1); } @SuppressWarnings("unchecked") public static List from(List nestedMultiBulkReply) { List items = new ArrayList<>(nestedMultiBulkReply.size()); for (Object obj : nestedMultiBulkReply) { List properties = (List) obj; items.add(new LatencyHistoryItem(properties)); } return items; } public long getTimeStamp() { return timeStamp; } public long getExecutionTime() { return executionTime; } @Override public String toString() { return new StringBuilder().append(timeStamp).append(COMMA).append(executionTime).toString(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/LatencyItem.java ================================================ package com.sohu.cache.redis.util; import java.util.ArrayList; import java.util.List; /** * @author wenruiwu * @create 2020/4/29 17:24 * @description */ public class LatencyItem { private final String event; private final long timeStamp; private final long latestExecutionTime; private final long maxExecutionTime; private static final String COMMA = ","; @SuppressWarnings("unchecked") private LatencyItem(List properties) { super(); this.event = new String((byte[])properties.get(0)); this.timeStamp = (Long) properties.get(1); this.latestExecutionTime = (Long) properties.get(2); this.maxExecutionTime = (Long) properties.get(3); } @SuppressWarnings("unchecked") public static List from(List nestedMultiBulkReply) { List items = new ArrayList<>(nestedMultiBulkReply.size()); for (Object obj : nestedMultiBulkReply) { List properties = (List) obj; items.add(new LatencyItem(properties)); } return items; } public String getEvent() { return event; } public long getTimeStamp() { return timeStamp; } public long getLatestExecutionTime() { return latestExecutionTime; } public long getMaxExecutionTime() { return maxExecutionTime; } @Override public String toString() { return new StringBuilder().append(event).append(COMMA).append(timeStamp).append(COMMA) .append(latestExecutionTime).append(COMMA).append(maxExecutionTime).toString(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/PipelineUtil.java ================================================ package com.sohu.cache.redis.util; import redis.clients.jedis.DebugParams; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Protocol; import redis.clients.jedis.Response; import redis.clients.jedis.util.SafeEncoder; /** * @Author: zengyizhao * @DateTime: 2021/11/25 17:45 * @Description: */ public class PipelineUtil { public static Response latencyHistory(Pipeline pipeline, String event){ return pipeline.sendCommand(Command.LATENCY, Keyword.HISTORY.raw, SafeEncoder.encode(event)); } public static Response latencyReset(Pipeline pipeline, String event){ return pipeline.sendCommand(Command.LATENCY, joinParameters(Keyword.RESET.raw, SafeEncoder.encodeMany(event))); } public static Response clusterCountKeysInSlot(Pipeline pipeline, int slot){ byte[][] args = new byte[2][]; args[0] = SafeEncoder.encode(Protocol.CLUSTER_COUNTKEYINSLOT); args[1] = SafeEncoder.encode(String.valueOf(slot)); return pipeline.sendCommand(Command.CLUSTER, args); } public static Response debug(Pipeline pipeline, DebugParams params){ return pipeline.sendCommand(Command.DEBUG, params.getCommand()); } public static Response objectIdletime(Pipeline pipeline, String key) { return pipeline.sendCommand(Command.OBJECT, Keyword.IDLETIME.raw, SafeEncoder.encode(key)); } public static Response memoryUsage(Pipeline pipeline, String key){ return pipeline.sendCommand(Command.MEMORY, Keyword.USAGE.raw, SafeEncoder.encode(key)); } private static byte[][] joinParameters(byte[] first, byte[][] rest) { byte[][] result = new byte[rest.length + 1][]; result[0] = first; System.arraycopy(rest, 0, result, 1, rest.length); return result; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/ProtostuffSerializer.java ================================================ package com.sohu.cache.redis.util; import com.dyuproject.protostuff.LinkedBuffer; import com.dyuproject.protostuff.ProtostuffIOUtil; import com.dyuproject.protostuff.Schema; import com.dyuproject.protostuff.runtime.RuntimeSchema; import java.util.concurrent.ConcurrentHashMap; /** * Created by yijunzhang on 14-4-10. */ public class ProtostuffSerializer { private static ConcurrentHashMap, Schema> cachedSchema = new ConcurrentHashMap, Schema>(); public byte[] serialize(final T source) { VO vo = new VO(source); final LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); try { final Schema schema = getSchema(VO.class); return serializeInternal(vo, schema, buffer); } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } finally { buffer.clear(); } } public T deserialize(final byte[] bytes) { try { Schema schema = getSchema(VO.class); VO vo = deserializeInternal(bytes, schema.newMessage(), schema); if (vo != null && vo.getValue() != null) { return (T) vo.getValue(); } } catch (final Exception e) { throw new IllegalStateException(e.getMessage(), e); } return null; } private byte[] serializeInternal(final T source, final Schema schema, final LinkedBuffer buffer) { return ProtostuffIOUtil.toByteArray(source, schema, buffer); } private T deserializeInternal(final byte[] bytes, final T result, final Schema schema) { ProtostuffIOUtil.mergeFrom(bytes, result, schema); return result; } private static Schema getSchema(Class clazz) { @SuppressWarnings("unchecked") Schema schema = (Schema) cachedSchema.get(clazz); if (schema == null) { schema = RuntimeSchema.createFrom(clazz); cachedSchema.put(clazz, schema); } return schema; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/redis/util/VO.java ================================================ package com.sohu.cache.redis.util; import java.io.Serializable; /** * Created by yijunzhang on 14-4-2. */ public class VO implements Serializable { private T value; public VO(T value) { this.value = value; } public VO() { } public T getValue() { return value; } @Override public String toString() { return "VO{" + "value=" + value + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof VO)) return false; VO vo = (VO) o; if (value != null ? !value.equals(vo.value) : vo.value != null) return false; return true; } @Override public int hashCode() { return value != null ? value.hashCode() : 0; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/SchedulerCenter.java ================================================ package com.sohu.cache.schedule; import com.sohu.cache.entity.TriggerInfo; import org.quartz.Trigger; import org.quartz.TriggerKey; import java.util.List; /** * 控制job、trigger和scheduler的基类 * User: lingguo */ public interface SchedulerCenter { public Trigger getTrigger(TriggerKey triggerKey); /** * @param triggerKey * @return */ public boolean unscheduleJob(TriggerKey triggerKey); /** * 获取所有trigger * * @return */ public List getAllTriggers(); /** * 模糊查询trigger * * @return */ public List getTriggersByNameOrGroup(String query); /** * 暂定trigger * * @param triggerKey * @return */ public boolean pauseTrigger(TriggerKey triggerKey); /** * 恢复trigger * * @param triggerKey * @return */ public boolean resumeTrigger(TriggerKey triggerKey); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/TriggerCenter.java ================================================ package com.sohu.cache.schedule; import com.sohu.cache.entity.TriggerInfo; import org.quartz.TriggerKey; import java.util.List; /** * trigger管理接口 * * @author: lingguo * @time: 2014/10/13 14:02 */ public interface TriggerCenter { /** * 暂停trigger * * @param triggerKey * @return */ public boolean pauseTrigger(TriggerKey triggerKey); /** * 恢复trigger * * @param triggerKey * @return */ public boolean resumeTrigger(TriggerKey triggerKey); /** * 删除trigger(从db中删除了) * * @param triggerKey * @return */ public boolean removeTrigger(TriggerKey triggerKey); /** * 查询某一job类型下的所有trigger * * @param jobGroup job类型:redis/machine/machineMonitor * @return */ public List getTriggersByJobGroup(String jobGroup); /** * 返回所有的trigger * * @return */ public List getAllTriggers(); /** * 查询trigger,模糊匹配trigger name或trigger group * * @param queryString trigger name或trigger group的关键字 * @return */ public List searchTriggerByNameOrGroup(String queryString); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/BrevityScheduleType.java ================================================ package com.sohu.cache.schedule.brevity; import java.util.HashMap; import java.util.Map; /** * 短频任务类型 * Created by yijunzhang */ public enum BrevityScheduleType { REDIS_INFO(10, 1, "redis基本信息采集"), REDIS_SLOWLOG(11, 20, "redis慢查询采集"), REDIS_LATENCY(12, 1, "redis延迟事件信息采集"), MACHINE_INFO(50, 1, "机器信息采集"), MACHINE_MONITOR(51, 20, "机器监控报警任务"), MACHINE_NMON(52, 5, "机器nmon数据采集"); private static Map MAP = new HashMap(); static { for (BrevityScheduleType scheduleType : BrevityScheduleType.values()) { MAP.put(scheduleType.type, scheduleType); } } BrevityScheduleType(int type, int minutes, String info) { this.type = type; this.minutes = minutes; this.info = info; } //类型 private int type; //分钟分段 private int minutes; //任务说明 private String info; public static BrevityScheduleType typeOf(int type) { return MAP.get(type); } public int getType() { return type; } public int getMinutes() { return minutes; } public String getInfo() { return info; } @Override public String toString() { return "BrevityScheduleType{" + "type=" + type + ", minutes=" + minutes + ", info='" + info + '\'' + '}'; }} ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/BrevityScheduler.java ================================================ package com.sohu.cache.schedule.brevity; /** * 短频任务调度 * Created by yijunzhang */ public interface BrevityScheduler { /** * 维护全量定时任务逻辑 */ void maintainTasks(); /** * 异步竞争执行短频任务 * * @return */ void dispatcherTasks(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/BrevitySchedulerJob.java ================================================ package com.sohu.cache.schedule.brevity; import com.sohu.cache.schedule.jobs.CacheBaseJob; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; /** * Created by yijunzhang */ public class BrevitySchedulerJob extends CacheBaseJob { private static final long serialVersionUID = 2626836144949582163L; /** * 维护短频任务 * * @param context */ @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); BrevityScheduler brevityScheduler = applicationContext.getBean(BrevityScheduler.class); brevityScheduler.maintainTasks(); } catch (Exception e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/DispatcherBrevityScheduleJob.java ================================================ package com.sohu.cache.schedule.brevity; import com.sohu.cache.schedule.jobs.CacheBaseJob; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; /** * Created by yijunzhang */ public class DispatcherBrevityScheduleJob extends CacheBaseJob { private static final long serialVersionUID = 2626836144949582163L; /** * 维护短频任务 * * @param context */ @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); BrevityScheduler brevityScheduler = applicationContext.getBean(BrevityScheduler.class); brevityScheduler.dispatcherTasks(); } catch (Exception e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/impl/BrevitySchedulerImpl.java ================================================ package com.sohu.cache.schedule.brevity.impl; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.entity.BrevityScheduleTask; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.schedule.brevity.BrevityScheduleType; import com.sohu.cache.schedule.brevity.BrevityScheduler; import com.sohu.cache.server.ServerStatusCollector; import com.sohu.cache.util.ScheduleUtil; import com.sohu.cache.web.util.DateUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Lazy; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Created by zengyizhao */ @ConditionalOnProperty(name = "cachecloud.redis.enable", havingValue = "true") @Component @Slf4j public class BrevitySchedulerImpl implements BrevityScheduler { private static final String _yyyyMMddHHmm = "yyyyMMddHHmm"; private static final int BATCH = 100; @Autowired private AsyncService asyncService; @Autowired private JdbcTemplate jdbcTemplate; @Lazy @Autowired private RedisCenter redisCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private ServerStatusCollector serverStatusCollector; @Autowired private AssistRedisService assistRedisService; public static final AtomicLongMap BREVITY_SCHEDULER_MAP = AtomicLongMap.create(); public static final String REDIS_KEY_PREFIX = "cc:brevity:schedule:"; public static final String REDIS_LOCK_KEY_PREFIX = "cc:brevity:schedule:lock:"; public static final int REDIS_LOCK_EXPIRE_SECONDS = 90; @PostConstruct private void init() { asyncService.assemblePool(AsyncThreadPoolFactory.BREVITY_SCHEDULER_POOL, AsyncThreadPoolFactory.BREVITY_SCHEDULER_ASYNC_THREAD_POOL); } @Override public void maintainTasks() { try { BrevityScheduleType redisInfoType = BrevityScheduleType.REDIS_INFO; maintainNodes(redisInfoType); BrevityScheduleType redisSlowlogType = BrevityScheduleType.REDIS_SLOWLOG; maintainNodes(redisSlowlogType); BrevityScheduleType redisLatencyType = BrevityScheduleType.REDIS_LATENCY; maintainNodes(redisLatencyType); BrevityScheduleType machineInfoType = BrevityScheduleType.MACHINE_INFO; maintainMachines(machineInfoType); BrevityScheduleType machineMonitorType = BrevityScheduleType.MACHINE_MONITOR; maintainMachines(machineMonitorType); BrevityScheduleType machineNmonType = BrevityScheduleType.MACHINE_NMON; maintainMachines(machineNmonType); } catch (Exception e) { log.error(e.getMessage(), e); } } private void maintainMachines(BrevityScheduleType scheduleType) { List originalNodes = this.getOriginalMachinesOfType(scheduleType.getType()); List latestNodes = this.getLatestMachinesOfType(scheduleType.getType()); List addList = this.shouldAddMachinesOfType(originalNodes, latestNodes); if (CollectionUtils.isNotEmpty(addList)) { long version = getVersion(); Date date = new Date(); for (BrevityScheduleTask scheduleTask : addList) { scheduleTask.setType(scheduleType.getType()); scheduleTask.setVersion(version); scheduleTask.setCreateTime(date); boolean insertRst = insertBrevityScheduler(scheduleTask); if (insertRst) { log.warn("shouldAddMachinesOfType: task={}", scheduleTask); } } } List removeList = this.shouldRemoveMachinesOfType(originalNodes, latestNodes); if (CollectionUtils.isNotEmpty(removeList)) { for (BrevityScheduleTask scheduleTask : removeList) { Long result = delBrevityScheduler(scheduleTask); if (result != null && result > 0) { log.warn("shouldRemoveMachinesOfType: type={} task={}", scheduleType, scheduleTask); } } } } private void maintainNodes(BrevityScheduleType scheduleType) { List originalNodes = this.getOriginalNodesOfType(scheduleType.getType()); List latestNodes = this.getLatestNodesOfType(scheduleType.getType()); List addList = this.shouldAddNodesOfType(originalNodes, latestNodes); if (CollectionUtils.isNotEmpty(addList)) { long version = getVersion(); Date date = new Date(); for (BrevityScheduleTask scheduleTask : addList) { scheduleTask.setType(scheduleType.getType()); scheduleTask.setVersion(version); scheduleTask.setCreateTime(date); boolean insertRst = insertBrevityScheduler(scheduleTask); if (insertRst) { log.warn("shouldAddNodesOfType: task={}", scheduleTask); } } } List removeList = this.shouldRemoveNodesOfType(originalNodes, latestNodes); if (CollectionUtils.isNotEmpty(removeList)) { for (BrevityScheduleTask scheduleTask : removeList) { Long result = delBrevityScheduler(scheduleTask); if (result != null && result > 0) { log.warn("shouldRemoveNodesOfType: type={} task={}", scheduleType, scheduleTask); } } } } private long getVersion() { long version = Long.parseLong(DateUtil.formatDate(new Date(), _yyyyMMddHHmm)); return ScheduleUtil.getLastCollectTime(version); } private boolean insertBrevityScheduler(BrevityScheduleTask task) { return assistRedisService.hset(REDIS_KEY_PREFIX + task.getType(), task.getKeyField(), JSONObject.toJSONString(task)); } private Long delBrevityScheduler(BrevityScheduleTask task) { return assistRedisService.hdel(REDIS_KEY_PREFIX + task.getType(), task.getKeyField()); } //查询原有节点 private List getOriginalNodesOfType(int type) { Map originalMap = assistRedisService.hgetAll(REDIS_KEY_PREFIX + type); Collection originalNodes = originalMap.values(); List originalNodeList = originalNodes.stream() .map(originalNode -> JSONObject.parseObject(originalNode, BrevityScheduleTask.class)) .collect(Collectors.toList()); return originalNodeList; } //查询最新的节点 private List getLatestNodesOfType(int type) { String sql = "select t1.ip host,t1.port port, t1.type instanceType" + " from instance_info t1" + " where t1.status != 2 and t1.type in (2,6,11,12)"; List list = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(BrevityScheduleTask.class)); return list; } //查询应该被添加的节点 private List shouldAddNodesOfType(List originalNodeList, List latestNodeList) { List shouldAdds = new ArrayList<>(); Set originals = originalNodeList.stream() .map(original -> original.getHostPort()).collect(Collectors.toSet()); latestNodeList.forEach(latest -> { if(!originals.contains(latest.getHostPort())){ shouldAdds.add(latest); } }); return shouldAdds; } //查询应该被删除的节点 private List shouldRemoveNodesOfType(List originalNodeList, List latestNodeList) { List shouldRemoves = new ArrayList<>(); Set latests = latestNodeList.stream() .map(latest -> latest.getHostPort()).collect(Collectors.toSet()); originalNodeList.forEach(original -> { if(!latests.contains(original.getHostPort())){ shouldRemoves.add(original); } }); return shouldRemoves; } //查询原有节点 private List getOriginalMachinesOfType(int type) { Map originalMap = assistRedisService.hgetAll(REDIS_KEY_PREFIX + type); Collection originalMachines = originalMap.values(); List originalMachineList = originalMachines.stream() .map(originalMachine -> JSONObject.parseObject(originalMachine, BrevityScheduleTask.class)) .collect(Collectors.toList()); return originalMachineList; } //查询最新的节点 private List getLatestMachinesOfType(int type) { String sql = "select t1.ip host" + " from machine_info t1" + " where t1.available = 1"; List list = jdbcTemplate.query(sql, BeanPropertyRowMapper.newInstance(BrevityScheduleTask.class)); return list; } //查询应该被添加的机器 private List shouldAddMachinesOfType( List originalMachineList, List latestMachineList) { List shouldAdds = new ArrayList<>(); Set originals = originalMachineList.stream() .map(original -> original.getHost()).collect(Collectors.toSet()); latestMachineList.forEach(latest -> { if(!originals.contains(latest.getHost())){ shouldAdds.add(latest); } }); return shouldAdds; } //查询应该被删除的机器 private List shouldRemoveMachinesOfType( List originalMachineList, List latestMachineList) { List shouldRemoves = new ArrayList<>(); Set latests = latestMachineList.stream() .map(latest -> latest.getHost()).collect(Collectors.toSet()); originalMachineList.forEach(original -> { if(!latests.contains(original.getHost())){ shouldRemoves.add(original); } }); return shouldRemoves; } private List getTasks(int type, long version) { Map originalMap = assistRedisService.hgetAll(REDIS_KEY_PREFIX + type); Collection tasks = originalMap.values(); List scheduleTasks = tasks.stream().map(task -> JSONObject.parseObject(task, BrevityScheduleTask.class)) .filter(brevityScheduleTask -> brevityScheduleTask.getVersion() < version) .collect(Collectors.toList()); return scheduleTasks; } private int[] batchUpdate(List ids, long version) { String sql = "update brevity_schedule_resources set version = ? where id = ? and version < ?"; List batchArgs = Lists.newArrayListWithCapacity(ids.size()); for (Integer id : ids) { Object[] args = new Object[3]; args[0] = version; args[1] = id; args[2] = version; batchArgs.add(args); } //primary-key+version 竞争 return jdbcTemplate.batchUpdate(sql, batchArgs); } @Override public void dispatcherTasks() { log.warn("dispatcherTasks:brevity_scheduler_map={}", BREVITY_SCHEDULER_MAP); BREVITY_SCHEDULER_MAP.clear(); long currentVersion = getVersion(); for (BrevityScheduleType scheduleType : BrevityScheduleType.values()) { int minutes = scheduleType.getMinutes(); int type = scheduleType.getType(); log.debug("dispatcherTasks: type={} version={}", type, currentVersion); // 以minutes作为分段,整除代表可以被执行 if (currentVersion % minutes == 0) { List tasks = getTasks(type, currentVersion); if (CollectionUtils.isEmpty(tasks)) { log.info("dispatcherTasks-empty: type={} version={}", type, currentVersion); continue; } //乱序 Collections.shuffle(tasks); long dispatcherSize = 0; List subTasks = new ArrayList<>(); for (int index = 0; index < tasks.size(); index++) { if (index > 0 && index % BATCH == 0) { log.debug("dispatcherTasks-subTaskIds: index={} size={}", index, subTasks.size()); // copy for async asyncSubTaskIds(Lists.newArrayList(subTasks), currentVersion, scheduleType); dispatcherSize += subTasks.size(); subTasks.clear(); // if machine collect ,per 100 task sleep serve times if (scheduleType.getType() == BrevityScheduleType.MACHINE_INFO.getType() || scheduleType.getType() == BrevityScheduleType.MACHINE_MONITOR.getType() || scheduleType.getType() == BrevityScheduleType.MACHINE_NMON.getType()) { try { TimeUnit.MILLISECONDS.sleep(5000l); log.warn("machine task sleep {} ms", 5000); } catch (InterruptedException e) { e.printStackTrace(); } } } subTasks.add(tasks.get(index)); } if (subTasks.size() > 0) { dispatcherSize += subTasks.size(); asyncSubTaskIds(Lists.newArrayList(subTasks), currentVersion, scheduleType); } log.warn("dispatcherTasks-dispatched: size={} type={} version={}", dispatcherSize, type, currentVersion); } } } public Map getNodeInfoByTask(BrevityScheduleTask task) { String sql = "select t2.app_id appId,t2.ip host,t2.port port" + " from instance_info t2 " + " where t2.status != 2 " + " and t2.ip = '" + task.getHost() + "' and t2.port = " + task.getPort(); return jdbcTemplate.queryForMap(sql); } public Map getMachineInfoByTask(BrevityScheduleTask task) { String sql = "select t2.id hostId,t2.ip host" + " from machine_info t2 " + " where t2.available = 1 " + " and t2.ip = '" + task.getHost() + "'"; return jdbcTemplate.queryForMap(sql); } private void asyncSubTaskIds(final List subTasks, final long currentVersion, final BrevityScheduleType scheduleType) { asyncService.submitFuture(AsyncThreadPoolFactory.BREVITY_SCHEDULER_POOL, new KeyCallable("version:" + currentVersion) { @Override public Integer execute() { //执行分组 List toUnlockTasks = Lists.newArrayList(); List lockTasks = Lists.newArrayList(); try{ for (int i = 0; i < subTasks.size(); i++) { boolean updated = assistRedisService .setNEX(REDIS_LOCK_KEY_PREFIX + subTasks.get(i).getKeyField(), String.valueOf(subTasks.get(i).getVersion()), REDIS_LOCK_EXPIRE_SECONDS); //获得行锁 if (updated) { toUnlockTasks.add(subTasks.get(i)); String latestTaskStr = assistRedisService.hget(REDIS_KEY_PREFIX + scheduleType.getType(), subTasks.get(i).getKeyField()); BrevityScheduleTask brevityScheduleTask = JSONObject.parseObject(latestTaskStr, BrevityScheduleTask.class); if (brevityScheduleTask.getVersion() != null && brevityScheduleTask.getVersion() >= currentVersion) { continue; } subTasks.get(i).setVersion(currentVersion); boolean hset = assistRedisService.hset(REDIS_KEY_PREFIX + scheduleType.getType(), subTasks.get(i).getKeyField(), JSONObject.toJSONString(subTasks.get(i))); if(hset){ lockTasks.add(subTasks.get(i)); BREVITY_SCHEDULER_MAP.incrementAndGet(scheduleType.getType() + "-" + currentVersion); } } } for (BrevityScheduleTask task : lockTasks) { if (scheduleType == BrevityScheduleType.REDIS_INFO) { Map map = getNodeInfoByTask(task); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); Integer instanceType = MapUtils.getInteger(map, "instanceType"); redisCenter.collectRedisInfo(appId, currentVersion, host, port); } else if (scheduleType == BrevityScheduleType.REDIS_SLOWLOG) { Map map = getNodeInfoByTask(task); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); Integer instanceType = MapUtils.getInteger(map, "instanceType"); redisCenter.collectRedisSlowLog(appId, currentVersion, host, port); } else if (scheduleType == BrevityScheduleType.MACHINE_INFO) { Map map = getMachineInfoByTask(task); long hostId = MapUtils.getLong(map, "hostId"); String host = MapUtils.getString(map, "host"); machineCenter.asyncCollectMachineInfo(hostId, currentVersion, host); } else if (scheduleType == BrevityScheduleType.MACHINE_MONITOR) { Map map = getMachineInfoByTask(task); long hostId = MapUtils.getLong(map, "hostId"); String host = MapUtils.getString(map, "host"); machineCenter.asyncMonitorMachineStats(hostId, host); } else if (scheduleType == BrevityScheduleType.MACHINE_NMON) { Map map = getMachineInfoByTask(task); String host = MapUtils.getString(map, "host"); serverStatusCollector.asyncFetchServerStatus(host); } else if (scheduleType == BrevityScheduleType.REDIS_LATENCY) { Map map = getNodeInfoByTask(task); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); Integer instanceType = MapUtils.getInteger(map, "instanceType"); redisCenter.collectRedisLatencyInfo(appId, currentVersion, host, port); } } } finally { List keys = new ArrayList<>(); toUnlockTasks.forEach(task -> keys.add(REDIS_LOCK_KEY_PREFIX + task.getKeyField())); String[] keyArray = new String[keys.size()]; assistRedisService.delMulti(keys.toArray(keyArray)); } log.warn("dispatcherTasks asyncSubTask this batch end time: {}, scheduleType:{}, provideSize:{}, handleSize:{}" , System.currentTimeMillis(), scheduleType.getInfo(), subTasks.size(), lockTasks.size()); return lockTasks.size(); } }); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/brevity/impl/BrevitySchedulerImpl_Original.java ================================================ package com.sohu.cache.schedule.brevity.impl; import com.google.common.collect.Lists; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.entity.BrevityScheduleTask; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.schedule.brevity.BrevityScheduleType; import com.sohu.cache.schedule.brevity.BrevityScheduler; import com.sohu.cache.server.ServerStatusCollector; import com.sohu.cache.util.ScheduleUtil; import com.sohu.cache.web.util.DateUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Lazy; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * Created by yijunzhang */ @ConditionalOnProperty(name = "cachecloud.redis.enable", havingValue = "false", matchIfMissing = true) @Component @Slf4j public class BrevitySchedulerImpl_Original implements BrevityScheduler { private static final String _yyyyMMddHHmm = "yyyyMMddHHmm"; private static final int BATCH = 100; @Autowired private AsyncService asyncService; @Autowired private JdbcTemplate jdbcTemplate; @Lazy @Autowired private RedisCenter redisCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private ServerStatusCollector serverStatusCollector; public static final AtomicLongMap BREVITY_SCHEDULER_MAP = AtomicLongMap.create(); @PostConstruct private void init() { asyncService.assemblePool(AsyncThreadPoolFactory.BREVITY_SCHEDULER_POOL, AsyncThreadPoolFactory.BREVITY_SCHEDULER_ASYNC_THREAD_POOL); } @Override public void maintainTasks() { try { BrevityScheduleType redisInfoType = BrevityScheduleType.REDIS_INFO; maintainNodes(redisInfoType); BrevityScheduleType redisSlowlogType = BrevityScheduleType.REDIS_SLOWLOG; maintainNodes(redisSlowlogType); BrevityScheduleType redisLatencyType = BrevityScheduleType.REDIS_LATENCY; maintainNodes(redisLatencyType); BrevityScheduleType machineInfoType = BrevityScheduleType.MACHINE_INFO; maintainMachines(machineInfoType); BrevityScheduleType machineMonitorType = BrevityScheduleType.MACHINE_MONITOR; maintainMachines(machineMonitorType); BrevityScheduleType machineNmonType = BrevityScheduleType.MACHINE_NMON; maintainMachines(machineNmonType); } catch (Exception e) { log.error(e.getMessage(), e); } } private void maintainMachines(BrevityScheduleType scheduleType) { List> addList = shouldAddMachinesOfType(scheduleType.getType()); if (CollectionUtils.isNotEmpty(addList)) { for (Map map : addList) { BrevityScheduleTask task = BrevityScheduleTask.builder() .type(scheduleType.getType()) .version(getVersion()) .host(MapUtils.getString(map, "host")) .port(MapUtils.getIntValue(map, "port", 0)) .createTime(new Date()) .build(); int result = insertBrevityScheduler(task); if (result > 0) { log.warn("shouldAddMachinesOfType: task={}", task); } } } List> removeList = shouldRemoveMachinesOfType(scheduleType.getType()); if (CollectionUtils.isNotEmpty(removeList)) { for (Map map : removeList) { int id = MapUtils.getIntValue(map, "id"); int result = delBrevityScheduler(id); if (result > 0) { log.warn("shouldRemoveMachinesOfType: type={} id={}", scheduleType, id); } } } } private void maintainNodes(BrevityScheduleType scheduleType) { List> addList = shouldAddNodesOfType(scheduleType.getType()); if (CollectionUtils.isNotEmpty(addList)) { for (Map map : addList) { BrevityScheduleTask task = BrevityScheduleTask.builder() .type(scheduleType.getType()) .version(getVersion()) .host(MapUtils.getString(map, "host")) .port(MapUtils.getIntValue(map, "port")) .createTime(new Date()) .build(); int result = insertBrevityScheduler(task); if (result > 0) { log.warn("shouldAddNodesOfType: task={}", task); } } } List> removeList = shouldRemoveNodesOfType(scheduleType.getType()); if (CollectionUtils.isNotEmpty(removeList)) { for (Map map : removeList) { int id = MapUtils.getIntValue(map, "id"); int result = delBrevityScheduler(id); if (result > 0) { log.warn("shouldRemoveNodesOfType: type={} id={}", scheduleType, id); } } } } private long getVersion() { long version = Long.parseLong(DateUtil.formatDate(new Date(), _yyyyMMddHHmm)); return ScheduleUtil.getLastCollectTime(version); } private int insertBrevityScheduler(BrevityScheduleTask task) { String sql = "insert into brevity_schedule_resources(type,version,host,port,create_time)" + " values(?,?,?,?,?)"; return jdbcTemplate.update(sql, task.getType(), task.getVersion(), task.getHost(), task.getPort(), task.getCreateTime()); } private int delBrevityScheduler(int id) { String sql = "delete from brevity_schedule_resources where id = ?"; return jdbcTemplate.update(sql, id); } //查询应该被添加的节点 private List> shouldAddNodesOfType(int type) { String sql = "select t1.ip host,t1.port port" + " from instance_info t1" + " left join brevity_schedule_resources t2 on (t2.type=? and t1.ip=t2.host and t1.port=t2.port)\n" + " where t1.status != 2 and t1.type in (2,6) and t2.id is null"; List> list = jdbcTemplate.queryForList(sql, type); return list; } //查询应该被删除的节点 private List> shouldRemoveNodesOfType(int type) { String sql = "select t2.id id" + " from brevity_schedule_resources t2" + " left join instance_info t1 on (t1.status != 2 and t1.ip=t2.host and t1.port=t2.port)" + " where t2.type=? and t1.ip is null"; List> list = jdbcTemplate.queryForList(sql, type); return list; } //查询应该被添加的机器 private List> shouldAddMachinesOfType(int type) { String sql = "select t1.ip host" + " from machine_info t1" + " left join brevity_schedule_resources t2 on (t2.type=? and t1.ip=t2.host)" + " where t1.available = 1 and t2.id is null"; List> list = jdbcTemplate.queryForList(sql, type); return list; } //查询应该被删除的机器 private List> shouldRemoveMachinesOfType(int type) { String sql = "select t2.id id" + " from brevity_schedule_resources t2" + " left join machine_info t1 on (t1.available = 1 and t1.ip=t2.host)" + " where t2.type=? and t1.ip is null"; List> list = jdbcTemplate.queryForList(sql, type); return list; } private List getTaskIds(int type, long version) { String sql = "select id from brevity_schedule_resources " + "where type=" + type + " and version < " + version; List ids = jdbcTemplate.queryForList(sql, Integer.class); return ids; } private int[] batchUpdate(List ids, long version) { String sql = "update brevity_schedule_resources set version = ? where id = ? and version < ?"; List batchArgs = Lists.newArrayListWithCapacity(ids.size()); for (Integer id : ids) { Object[] args = new Object[3]; args[0] = version; args[1] = id; args[2] = version; batchArgs.add(args); } //primary-key+version 竞争 return jdbcTemplate.batchUpdate(sql, batchArgs); } @Override public void dispatcherTasks() { log.warn("dispatcherTasks:brevity_scheduler_map={}", BREVITY_SCHEDULER_MAP); BREVITY_SCHEDULER_MAP.clear(); long currentVersion = getVersion(); for (BrevityScheduleType scheduleType : BrevityScheduleType.values()) { int minutes = scheduleType.getMinutes(); int type = scheduleType.getType(); log.debug("dispatcherTasks: type={} version={}", type, currentVersion); // 以minutes作为分段,整除代表可以被执行 if (currentVersion % minutes == 0) { List taskIds = getTaskIds(type, currentVersion); if (CollectionUtils.isEmpty(taskIds)) { log.info("dispatcherTasks-empty: type={} version={}", type, currentVersion); continue; } //乱序 Collections.shuffle(taskIds); long dispatcherSize = 0; List subTaskIds = new ArrayList<>(); for (int index = 0; index < taskIds.size(); index++) { if (index > 0 && index % BATCH == 0) { log.debug("dispatcherTasks-subTaskIds: index={} size={}", index, subTaskIds.size()); // copy for async asyncSubTaskIds(Lists.newArrayList(subTaskIds), currentVersion, scheduleType); dispatcherSize += subTaskIds.size(); subTaskIds.clear(); // if machine collect ,per 100 task sleep serve times if (scheduleType.getType() == BrevityScheduleType.MACHINE_INFO.getType() || scheduleType.getType() == BrevityScheduleType.MACHINE_MONITOR.getType() || scheduleType.getType() == BrevityScheduleType.MACHINE_NMON.getType()) { try { TimeUnit.MILLISECONDS.sleep(5000l); log.warn("machine task sleep {} ms", 5000); } catch (InterruptedException e) { e.printStackTrace(); } } } subTaskIds.add(taskIds.get(index)); } if (subTaskIds.size() > 0) { dispatcherSize += subTaskIds.size(); asyncSubTaskIds(Lists.newArrayList(subTaskIds), currentVersion, scheduleType); } log.warn("dispatcherTasks-dispatched: size={} type={} version={}", dispatcherSize, type, currentVersion); } } } public Map getNodeInfoByLockId(int lockId) { String sql = "select t2.app_id appId,t2.ip host,t2.port port" + " from brevity_schedule_resources t1" + " inner join instance_info t2 on (t1.host=t2.ip and t1.port=t2.port)" + " where t1.id = " + lockId; return jdbcTemplate.queryForMap(sql); } public Map getMachineInfoByLockId(int lockId) { String sql = "select t2.id hostId,t2.ip host" + " from brevity_schedule_resources t1" + " inner join machine_info t2 on t1.host=t2.ip" + " where t1.id = " + lockId; return jdbcTemplate.queryForMap(sql); } private void asyncSubTaskIds(final List subTaskIds, final long currentVersion, final BrevityScheduleType scheduleType) { asyncService.submitFuture(AsyncThreadPoolFactory.BREVITY_SCHEDULER_POOL, new KeyCallable("version:" + currentVersion) { @Override public Integer execute() { //执行分组 int[] batchUpdates = batchUpdate(subTaskIds, currentVersion); List lockIds = Lists.newArrayList(); for (int i = 0; i < subTaskIds.size(); i++) { int updated = batchUpdates[i]; //获得行锁 if (updated > 0) { lockIds.add(subTaskIds.get(i)); BREVITY_SCHEDULER_MAP.incrementAndGet(scheduleType.getType() + "-" + currentVersion); } } for (Integer lockId : lockIds) { if (scheduleType == BrevityScheduleType.REDIS_INFO) { Map map = getNodeInfoByLockId(lockId); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); redisCenter.collectRedisInfo(appId, currentVersion, host, port); } else if (scheduleType == BrevityScheduleType.REDIS_SLOWLOG) { Map map = getNodeInfoByLockId(lockId); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); redisCenter.collectRedisSlowLog(appId, currentVersion, host, port); } else if (scheduleType == BrevityScheduleType.MACHINE_INFO) { Map map = getMachineInfoByLockId(lockId); long hostId = MapUtils.getLong(map, "hostId"); String host = MapUtils.getString(map, "host"); machineCenter.asyncCollectMachineInfo(hostId, currentVersion, host); } else if (scheduleType == BrevityScheduleType.MACHINE_MONITOR) { Map map = getMachineInfoByLockId(lockId); long hostId = MapUtils.getLong(map, "hostId"); String host = MapUtils.getString(map, "host"); machineCenter.asyncMonitorMachineStats(hostId, host); } else if (scheduleType == BrevityScheduleType.MACHINE_NMON) { Map map = getMachineInfoByLockId(lockId); String host = MapUtils.getString(map, "host"); serverStatusCollector.asyncFetchServerStatus(host); } else if (scheduleType == BrevityScheduleType.REDIS_LATENCY) { Map map = getNodeInfoByLockId(lockId); long appId = MapUtils.getLong(map, "appId"); String host = MapUtils.getString(map, "host"); int port = MapUtils.getIntValue(map, "port"); redisCenter.collectRedisLatencyInfo(appId, currentVersion, host, port); } } return lockIds.size(); } }); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/impl/SchedulerCenterImpl.java ================================================ package com.sohu.cache.schedule.impl; import com.sohu.cache.dao.QuartzDao; import com.sohu.cache.entity.TriggerInfo; import com.sohu.cache.schedule.SchedulerCenter; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 根据scheduler控制job、trigger和scheduler的执行和状态 *

* User: lingguo */ @Service("schedulerCenter") public class SchedulerCenterImpl implements SchedulerCenter { private Logger logger = LoggerFactory.getLogger(this.getClass()); // 注入预定义的scheduler @Autowired private Scheduler clusterScheduler; @Autowired private QuartzDao quartzDao; /** * 删除trigger * * @param triggerKey * @return */ @Override public boolean unscheduleJob(TriggerKey triggerKey) { boolean opResult = true; try { opResult = clusterScheduler.checkExists(triggerKey); if (opResult) { opResult = clusterScheduler.unscheduleJob(triggerKey); } } catch (SchedulerException e) { logger.error(e.getMessage(), e); opResult = false; } return opResult; } @Override public Trigger getTrigger(TriggerKey triggerKey) { Trigger trigger = null; try { trigger = clusterScheduler.getTrigger(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } return trigger; } @Override public List getAllTriggers() { return quartzDao.getAllTriggers(); } @Override public List getTriggersByNameOrGroup(String query) { return quartzDao.searchTriggerByNameOrGroup(query); } @Override public boolean pauseTrigger(TriggerKey triggerKey) { try { boolean exists = clusterScheduler.checkExists(triggerKey); if (exists) { clusterScheduler.pauseTrigger(triggerKey); return true; } logger.error("triggerKey={} not exists", triggerKey); return false; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } @Override public boolean resumeTrigger(TriggerKey triggerKey) { try { boolean exists = clusterScheduler.checkExists(triggerKey); if (exists) { clusterScheduler.resumeTrigger(triggerKey); return true; } logger.error("triggerKey={} not exists", triggerKey); return false; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/impl/TriggerCenterImpl.java ================================================ package com.sohu.cache.schedule.impl; import com.sohu.cache.dao.QuartzDao; import com.sohu.cache.entity.TriggerInfo; import com.sohu.cache.schedule.TriggerCenter; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * trigger管理接口的实现 * * @author: lingguo * @time: 2014/10/13 14:03 */ @Service("triggerCenter") public class TriggerCenterImpl implements TriggerCenter { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private Scheduler clusterScheduler; @Autowired private QuartzDao quartzDao; /** * 暂停trigger * * @param triggerKey * @return 操作成功返回true,否则返回false; */ @Override public boolean pauseTrigger(TriggerKey triggerKey) { boolean opResult = true; try { clusterScheduler.pauseTrigger(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); opResult = false; } return opResult; } /** * 恢复暂停的trigger * * @param triggerKey */ @Override public boolean resumeTrigger(TriggerKey triggerKey) { boolean opResult = true; try { clusterScheduler.resumeTrigger(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); opResult = false; } return opResult; } /** * 删除一个trigger * * @param triggerKey * @return */ @Override public boolean removeTrigger(TriggerKey triggerKey) { boolean opResult = true; try { clusterScheduler.unscheduleJob(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); opResult = false; } return opResult; } /** * 查询特定job类型下的所有trigger * * @param jobGroup job类型:redis/machine/machineMonitor * @return */ @Override public List getTriggersByJobGroup(String jobGroup) { List triggersOfGroup = null; try { triggersOfGroup = quartzDao.getTriggersByJobGroup(jobGroup); } catch (Exception e) { logger.error("jobGroup: {}", jobGroup, e); } return triggersOfGroup; } /** * 返回所有的trigger * * @return */ @Override public List getAllTriggers() { List allTriggers = null; try { allTriggers = quartzDao.getAllTriggers(); } catch (Exception e) { logger.error(e.getMessage(), e); } return allTriggers; } /** * 查询trigger,模糊匹配trigger name或trigger group * * @param queryString trigger name或trigger group的关键字 * @return */ @Override public List searchTriggerByNameOrGroup(String queryString) { List matchTriggers = null; try { matchTriggers = quartzDao.searchTriggerByNameOrGroup(queryString); } catch (Exception e) { logger.error("queryString: {}", queryString, e); } return matchTriggers; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/AppCapacityMonitorJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.web.service.AppAutoCapacityService; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; /** * Description: 定时更新内存使用最大值 * @author zengyizhao * @version 1.0 * @date 2022/10/11 */ public class AppCapacityMonitorJob extends CacheBaseJob { @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); try { AppAutoCapacityService appAutoCapacityService = applicationContext.getBean("appAutoCapacityService", AppAutoCapacityService.class); appAutoCapacityService.updateAppMemUsedHistory(); } catch (Exception e) { logger.error("updateAppMemUsedHistory error {}", e.getMessage()); } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/AppDailyJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.stats.app.AppDailyDataCenter; import com.sohu.cache.util.EnvUtil; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; /** * 发送日报 * * @author leifu * @Date 2016年8月12日 * @Time 上午11:25:09 */ public class AppDailyJob extends CacheBaseJob { private static final long serialVersionUID = 7751425759758902400L; @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); Environment env = applicationContext.getBean(Environment.class); if (EnvUtil.isDev(env)) { logger.warn("environment is dev ignored"); return; } try { AppDailyDataCenter appDailyDataCenter = applicationContext.getBean("appDailyDataCenter", AppDailyDataCenter.class); appDailyDataCenter.sendAppDailyEmail(); } catch (Exception e) { logger.error("sendAppDailyEmail error", e.getMessage()); } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/AppPersistenceCheckJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.stats.app.AppPersistenceCheckCenter; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; /** * Description: 应用持久化配置检查修正 * @author zengyizhao * @version 1.0 * @date 2022/11/3 */ public class AppPersistenceCheckJob extends CacheBaseJob { private static final long serialVersionUID = 7751425759758902400L; @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); try { AppPersistenceCheckCenter appPersistenceCheckCenter = applicationContext.getBean("appPersistenceCheckCenter", AppPersistenceCheckCenter.class); appPersistenceCheckCenter.checkAndFixAppPersistence(); } catch (Exception e) { logger.error("checkAndFixAppPersistence error", e.getMessage()); } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/CacheBaseJob.java ================================================ package com.sohu.cache.schedule.jobs; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; /** * job父类,包含一个抽象函方法,将实现推迟到具体的子类 * User: lingguo */ public abstract class CacheBaseJob implements Job, Serializable { private static final long serialVersionUID = -6605766126594260961L; protected Logger logger = LoggerFactory.getLogger(this.getClass()); protected final static String APPLICATION_CONTEXT_KEY = "applicationContext"; // 抽象方法,由子类实现,即具体的业务逻辑 public abstract void action(JobExecutionContext context); /** * 统计时间 * * @param context * @throws JobExecutionException */ @Override public void execute(JobExecutionContext context) throws JobExecutionException { long start = System.currentTimeMillis(); this.action(context); long cost = System.currentTimeMillis() - start; if (cost > 2000) { logger.warn("slowJob: job: {}, trigger: {}, cost: {} ms", context.getJobDetail().getKey(), context.getTrigger().getKey(), cost); } else { logger.debug("job: {}, trigger: {}, cost: {} ms", context.getJobDetail().getKey(), context.getTrigger().getKey(), cost); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/CleanupDayAppClientStatJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang.math.NumberUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created by rucao on 2020/1/8 */ public class CleanupDayAppClientStatJob extends CacheBaseJob { private static final long serialVersionUID = 8815839394475276540L; /** * 清除命令统计&异常统计 */ private static int BATCH_SIZE = 1000; private static final String CLEAN_APP_CLIENT_COMMAND_MINUTE_STATISTICS = "delete from app_client_command_minute_statistics where current_min < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_CLIENT_EXCEPTION_MINUTE_STATISTICS = "delete from app_client_exception_minute_statistics where current_min < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_CLIENT_LATENCY_COMMAND = "delete from app_client_latency_command where create_time < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_CLIENT_STATISTIC_GATHER = "delete from app_client_statistic_gather where gather_time < ? limit " + BATCH_SIZE; private static final String CLEAN_INSTANCE_LATENCY_HISTORY = "delete from instance_latency_history where execute_date < ? limit " + BATCH_SIZE; JdbcTemplate jdbcTemplate = null; @Override public void action(JobExecutionContext context) { if (!ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA) { logger.warn("whether_schedule_clean_data is false , ignored"); return; } try { logger.warn("begin-CleanupDayAppClientStatJob"); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class); Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_MONTH, -14); long timeFormat = NumberUtils.toLong(new SimpleDateFormat("yyyyMMddHHmm00").format(calendar.getTime())); String date = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()); /** * 清除命令统计&异常统计(保存14天) */ long cleanCount = 0; try{ cleanCount = scrollDelete(CLEAN_APP_CLIENT_COMMAND_MINUTE_STATISTICS, timeFormat); logger.warn("clean_app_client_command_minute_statistics count={}", cleanCount); }catch (Exception e){ logger.error("clean_app_client_command_minute_statistics error, ", e); } try{ cleanCount = scrollDelete(CLEAN_APP_CLIENT_EXCEPTION_MINUTE_STATISTICS, timeFormat); logger.warn("clean_app_client_exception_minute_statistics count={}", cleanCount); }catch (Exception e){ logger.error("clean_app_client_exception_minute_statistics error, ", e); } try{ cleanCount = scrollDelete(CLEAN_APP_CLIENT_LATENCY_COMMAND, calendar.getTime()); logger.warn("clean_app_client_latency_command count={}", cleanCount); }catch (Exception e){ logger.error("clean_app_client_latency_command error, ", e); } try{ cleanCount = scrollDelete(CLEAN_APP_CLIENT_STATISTIC_GATHER, date); logger.warn("clean_app_client_statistic_gather count={}", cleanCount); }catch (Exception e){ logger.error("clean_app_client_statistic_gather error, ", e); } try{ cleanCount = scrollDelete(CLEAN_INSTANCE_LATENCY_HISTORY, timeFormat); logger.warn("clean_instance_latency_history count={}", cleanCount); }catch (Exception e){ logger.error("clean_instance_latency_history error, ", e); } logger.warn("end-CleanupDayAppClientStatJob"); } catch (Exception e) { logger.error("CleanupDayAppClientStatJob error, ", e); } } /** * 滚动删除表数据 */ private long scrollDelete(String sql, Object time) { long totalCount = 0; while (true) { int cleanCount = jdbcTemplate.update(sql, time); totalCount += cleanCount; if (cleanCount == 0) { break; } } return totalCount; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/CleanupDayDimensionalityJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * 清理天维度数据任务 * Created by yijunzhang */ public class CleanupDayDimensionalityJob extends CacheBaseJob { private static final long serialVersionUID = 8815839394475276540L; private static int BATCH_SIZE = 1000; private static final String CLEAN_APP_HOUR_COMMAND_STATISTICS = "delete from app_hour_command_statistics where create_time < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_MINUTE_COMMAND_STATISTICS = "delete from app_minute_command_statistics where create_time < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_HOUR_STATISTICS = "delete from app_hour_statistics where create_time < ? limit " + BATCH_SIZE; private static final String CLEAN_APP_MINUTE_STATISTICS = "delete from app_minute_statistics where create_time < ? limit " + BATCH_SIZE; /** * 清除客户端耗时汇总数据 */ private static final String CLEAN_APP_CLIENT_MINUTE_COST_TOTAL = "delete from app_client_costtime_minute_stat_total where collect_time < ? limit " + BATCH_SIZE; //清除服务器统计数据 private static final String CLEAN_SERVER_STAT_STATISTICS = "delete from server_stat where cdate < ? limit " + BATCH_SIZE; /** * 清除实例基础统计 */ private static final String CLEAN_INSTANCE_MINUTE_STATS = "delete from instance_minute_stats where collect_time < ? limit " + BATCH_SIZE; JdbcTemplate jdbcTemplate = null; @Override public void action(JobExecutionContext context) { if (!ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA) { logger.warn("whether_schedule_clean_data is false , ignored"); return; } try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class); Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); // 清除应用&命令统计数据(保存31天) calendar.add(Calendar.DAY_OF_MONTH, -31); Date time = calendar.getTime(); long cleanCount = 0; cleanCount = scrollDelete(CLEAN_APP_HOUR_COMMAND_STATISTICS, time); logger.warn("clean_app_hour_command_statistics count={}", cleanCount); cleanCount = scrollDelete(CLEAN_APP_MINUTE_COMMAND_STATISTICS, time); logger.warn("clean_app_minute_command_statistics count={}", cleanCount); cleanCount = scrollDelete(CLEAN_APP_HOUR_STATISTICS, time); logger.warn("clean_app_hour_statistics count={}", cleanCount); cleanCount = scrollDelete(CLEAN_APP_MINUTE_STATISTICS, time); logger.warn("clean_app_minute_statistics count={}", cleanCount); //清除服务器统计数据 calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_MONTH, -7); String date = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()); cleanCount = scrollDelete(CLEAN_SERVER_STAT_STATISTICS, date); logger.warn("clean_server_stat_total count={}", cleanCount); long timeFormat = NumberUtils.toLong(new SimpleDateFormat("yyyyMMddHHmm00").format(calendar.getTime())); //清除进程级别统计数据(保存5天) long start = System.currentTimeMillis(); timeFormat = NumberUtils.toLong(new SimpleDateFormat("yyyyMMddHHmm").format(DateUtils.addDays(new Date(), -5))); cleanCount = scrollDelete(CLEAN_INSTANCE_MINUTE_STATS, timeFormat); logger.warn("clean_instance_minute_stats timeFormat={} count={} cost={}s", timeFormat, cleanCount, (System.currentTimeMillis() - start) / 1000); //清除客户端耗时汇总数据(保存14天) calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_MONTH, -14); timeFormat = NumberUtils.toLong(new SimpleDateFormat("yyyyMMddHHmm00").format(calendar.getTime())); cleanCount = jdbcTemplate.update(CLEAN_APP_CLIENT_MINUTE_COST_TOTAL, timeFormat); logger.warn("clean_app_client_costtime_minute_stat_total count={}", cleanCount); } catch (Exception e) { logger.error(e.getMessage(), e); } } /** * 滚动删除表数据 */ private long scrollDelete(String sql, Object time) { long totalCount = 0; while (true) { int cleanCount = jdbcTemplate.update(sql, time); totalCount += cleanCount; if (cleanCount == 0) { break; } } return totalCount; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/CleanupMinuteDimensionalityJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import org.springframework.jdbc.core.JdbcTemplate; import java.text.SimpleDateFormat; import java.util.Date; /** * 清理分钟维度数据任务 * Created by yijunzhang */ public class CleanupMinuteDimensionalityJob extends CacheBaseJob { private static final long serialVersionUID = 8815839394475276540L; /** * 实例基准数据,主要用于报警 */ private static final String CLEAN_STANDARD_STATISTICS = "delete from standard_statistics where collect_time < ?"; @Override public void action(JobExecutionContext context) { if (!ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA) { logger.warn("whether_schedule_clean_data is false , ignored"); return; } try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); JdbcTemplate jdbcTemplate = applicationContext.getBean("jdbcTemplate", JdbcTemplate.class); //清除进程级别统计数据(保存最近10分钟) long start = System.currentTimeMillis(); Date date = DateUtils.addMinutes(new Date(), -10); long timeFormat = NumberUtils.toLong(new SimpleDateFormat("yyyyMMddHHmm").format(date)); int cleanCount = jdbcTemplate.update(CLEAN_STANDARD_STATISTICS, timeFormat); logger.warn("clean_standard_statistics timeFormat={} count={} cost:{} ms", timeFormat, cleanCount, (System.currentTimeMillis() - start)); } catch (Exception e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/ExpAppsDailyJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.stats.admin.CoreAppsStatCenter; import com.sohu.cache.util.EnvUtil; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; /** * 发送日报 * * @author leifu * @Date 2016年8月12日 * @Time 上午11:25:09 */ public class ExpAppsDailyJob extends CacheBaseJob { private static final long serialVersionUID = 8864245475347417291L; @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); Environment env = applicationContext.getBean(Environment.class); if (EnvUtil.isDev(env)) { logger.warn("environment is dev ignored"); return; } try { CoreAppsStatCenter coreAppsStatCenter = applicationContext.getBean("coreAppsStatCenter", CoreAppsStatCenter.class); coreAppsStatCenter.sendExpAppsStatDataEmail(null); logger.info("expAppsStatData daily email"); } catch (Exception e) { logger.error("expAppClientStat daily report error", e.getMessage()); } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/GatherAppClientStatisticsJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.client.service.AppClientStatisticGatherService; import com.sohu.cache.entity.TimeBetween; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import java.util.Date; /** * Created by rucao on 2019/12/30 */ public class GatherAppClientStatisticsJob extends CacheBaseJob { private static final long serialVersionUID = 8815839394475276540L; private final static String COLLECT_TIME_FORMAT = "yyyyMMddHHmm00"; @Override public void action(JobExecutionContext context) { try { logger.warn("begin-gatherAppClientStatisticsJob"); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); AppClientStatisticGatherService appClientStatisticGatherService = applicationContext.getBean("appClientStatisticGatherService", AppClientStatisticGatherService.class); //前5-10分钟 TimeBetween timeBetween = fillWithDateFormat(); long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); appClientStatisticGatherService.bathAdd(startTime, endTime); logger.warn("end-gatherAppClientStatisticsJob, startTime={} endTime:{}", startTime, endTime); } catch (Exception e) { logger.error(e.getMessage(), e); } } private TimeBetween fillWithDateFormat() { Date endDate = DateUtils.addMinutes(new Date(), -5); Date startDate = DateUtils.addMinutes(endDate, -5); long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/GatherAppClientStatisticsServerCmdCountJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.client.service.AppClientStatisticGatherService; import com.sohu.cache.entity.TimeBetween; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import java.util.Date; /** * Description: server端 命令调用次数统计 * @author zengyizhao * @version 1.0 * @date 2024/05/14 */ public class GatherAppClientStatisticsServerCmdCountJob extends CacheBaseJob { private final static String COLLECT_TIME_FORMAT = "yyyyMMddHH"; @Override public void action(JobExecutionContext context) { try { logger.warn("begin-gatherAppClientStatisticsServerCmdCountJob"); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); AppClientStatisticGatherService appClientStatisticGatherService = applicationContext.getBean("appClientStatisticGatherService", AppClientStatisticGatherService.class); //前5-10分钟 TimeBetween timeBetween = fillWithDateFormat(); long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); appClientStatisticGatherService.bathAddServerCmdCount(startTime, endTime); logger.warn("end-gatherAppClientStatisticsServerCmdCountJob, startTime={} endTime:{}", startTime, endTime); } catch (Exception e) { logger.error(e.getMessage(), e); } } private TimeBetween fillWithDateFormat() { Date endDate = DateUtils.addHours(new Date(), -1); Date startDate = endDate; long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = startTime; return new TimeBetween(startTime, endTime, startDate, endDate); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/InstanceAlertValueJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.util.EnvUtil; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import com.sohu.cache.schedule.jobs.CacheBaseJob; import com.sohu.cache.stats.instance.InstanceAlertConfigService; import org.springframework.core.env.Environment; /** * 实例分钟报警 * @author leifu * @Date 2016年9月13日 * @Time 下午3:53:04 */ public class InstanceAlertValueJob extends CacheBaseJob { private static final long serialVersionUID = 1035952011763660681L; @Override public void action(JobExecutionContext context) { try { long startTime = System.currentTimeMillis(); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); Environment env = applicationContext.getBean(Environment.class); if (EnvUtil.isDev(env)) { logger.warn("environment is dev ignored"); return; } InstanceAlertConfigService instanceAlertConfigService = applicationContext.getBean("instanceAlertConfigService", InstanceAlertConfigService.class); instanceAlertConfigService.monitorLastMinuteAllInstanceInfo(); logger.info("InstanceAlertValueJob cost time {} ms", (System.currentTimeMillis() - startTime)); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/InstanceStatJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.inspect.impl.InstanceStateInspector; import com.sohu.cache.util.EnvUtil; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import org.springframework.core.env.Environment; /** * Created by chenshi on 2020/5/27. */ public class InstanceStatJob extends CacheBaseJob{ @Override public void action(JobExecutionContext context) { try { long startTime = System.currentTimeMillis(); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); Environment env = applicationContext.getBean(Environment.class); if (EnvUtil.isDev(env)) { logger.warn("environment is dev ignored"); return; } InstanceStateInspector instanceStateInspector = applicationContext.getBean("instanceStateInspector", InstanceStateInspector.class); instanceStateInspector.inspect(); logger.info("InstanceAlertValueJob cost time {} ms", (System.currentTimeMillis() - startTime)); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/ReviseAppClientStatisGatherJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.client.service.AppClientStatisticGatherService; import com.sohu.cache.entity.TimeBetween; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; import java.util.Date; /** * Created by rucao on 2020/3/27 */ public class ReviseAppClientStatisGatherJob extends CacheBaseJob { private static final long serialVersionUID = -5968147536403452672L; private final static String COLLECT_TIME_FORMAT = "yyyyMMdd000000"; @Override public void action(JobExecutionContext context) { try { logger.warn("begin-reviseAppClientStatisGatherJob"); SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); AppClientStatisticGatherService appClientStatisticGatherService = applicationContext.getBean("appClientStatisticGatherService", AppClientStatisticGatherService.class); //前一天 TimeBetween timeBetween = fillWithDateFormat(); long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); appClientStatisticGatherService.bathSave(startTime, endTime); logger.warn("end-reviseAppClientStatisGatherJob, startTime={} endTime:{}", startTime, endTime); } catch (Exception e) { logger.error(e.getMessage(), e); } } private TimeBetween fillWithDateFormat() { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/SystemConfigRefreshJob.java ================================================ package com.sohu.cache.schedule.jobs; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import org.springframework.context.ApplicationContext; import com.sohu.cache.schedule.jobs.CacheBaseJob; import com.sohu.cache.web.service.ConfigService; /** * 刷新系统配置 * @author leifu * @Date 2016年6月30日 * @Time 下午5:30:42 */ public class SystemConfigRefreshJob extends CacheBaseJob { private static final long serialVersionUID = 7751425759758902400L; @Override public void action(JobExecutionContext context) { try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); ConfigService configService = applicationContext.getBean("configService", ConfigService.class); configService.reloadSystemConfig(); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/schedule/jobs/TaskExecuteJob.java ================================================ package com.sohu.cache.schedule.jobs; import com.sohu.cache.task.TaskService; import org.quartz.JobExecutionContext; import org.quartz.SchedulerContext; import org.springframework.context.ApplicationContext; /** * @author fulei */ public class TaskExecuteJob extends CacheBaseJob { private static final long serialVersionUID = -1697673324465500314L; @Override public void action(JobExecutionContext context) { long startTime = System.currentTimeMillis(); logger.warn("TaskExecuteJob start"); try { SchedulerContext schedulerContext = context.getScheduler().getContext(); ApplicationContext applicationContext = (ApplicationContext) schedulerContext.get(APPLICATION_CONTEXT_KEY); TaskService taskService = applicationContext.getBean(TaskService.class); taskService.executeNewTask(); } catch (Exception e) { logger.error(e.getMessage(), e); } logger.warn("TaskExecuteJob end, cost time is {} ms", (System.currentTimeMillis() - startTime)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/ServerStatusCollector.java ================================================ package com.sohu.cache.server; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.server.data.OSInfo; import com.sohu.cache.server.data.Server; import com.sohu.cache.server.nmon.NMONService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor; import com.sohu.cache.ssh.SSHTemplate.Result; import com.sohu.cache.ssh.SSHTemplate.SSHCallback; import com.sohu.cache.ssh.SSHTemplate.SSHSession; import com.sohu.cache.web.service.ServerDataService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** * 服务器状态监控服务 */ @Component public class ServerStatusCollector { private static final Logger logger = LoggerFactory.getLogger(ServerStatusCollector.class); //获取监控结果 public static final String COLLECT_SERVER_STATUS = "[ -e \"" + NMONService.SOCK_LOG + "\" ] && /bin/cat " + NMONService.SOCK_LOG + " >> " + NMONService.NMON_LOG + ";[ -e \"" + NMONService.ULIMIT_LOG + "\" ] && /bin/cat " + NMONService.ULIMIT_LOG + " >> " + NMONService.NMON_LOG + ";/bin/mv " + NMONService.NMON_LOG + " " + NMONService.NMON_OLD_LOG + ";[ $? -eq 0 ] && /bin/cat " + NMONService.NMON_OLD_LOG; //nmon服务 @Autowired private NMONService nmonService; //ssh 模板类 @Autowired private SSHTemplate sshTemplate; //持久化 @Autowired private ServerDataService serverDataService; @Autowired private AsyncService asyncService; @PostConstruct public void init() { asyncService.assemblePool(AsyncThreadPoolFactory.MACHINE_POOL, AsyncThreadPoolFactory.MACHINE_THREAD_POOL); } //异步执行任务 public void asyncFetchServerStatus(final String ip) { String key = "collect-server-" + ip; asyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable(key) { public Boolean execute() { try { fetchServerStatus(ip); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); } /** * 抓取服务器状态 * * @param ip */ public void fetchServerStatus(final String ip) { try { sshTemplate.execute(ip, new SSHCallback() { public Result call(SSHSession session) { //尝试收集服务器运行状况 collectServerStatus(ip, session); //启动nmon收集服务器运行状况 OSInfo info = nmonService.start(ip, session); saveServerStatus(ip, info); return null; } }); } catch (Exception e) { logger.error("fetchServerStatus " + ip + " err", e); } } /** * 收集系统状况 * * @param ip * @param session */ private void collectServerStatus(String ip, SSHSession session) { final Server server = new Server(); server.setIp(ip); Result result = session.executeCommand(COLLECT_SERVER_STATUS, new DefaultLineProcessor() { public void process(String line, int lineNum) throws Exception { server.parse(line, null); } }); if (!result.isSuccess()) { logger.error("collect " + ip + " err:" + result.getResult(), result.getExcetion()); } //保存服务器静态信息 serverDataService.saveAndUpdateServerInfo(server); //保存服务器状况信息 serverDataService.saveServerStat(server); } /** * 保存服务器dist信息 * * @param ip * @param osInfo */ private void saveServerStatus(String ip, OSInfo osInfo) { if (osInfo == null) { return; } serverDataService.saveServerInfo(ip, osInfo.getIssue()); } public void setNmonService(NMONService nmonService) { this.nmonService = nmonService; } public void setSshTemplate(SSHTemplate sshTemplate) { this.sshTemplate = sshTemplate; } public void setServerDataService(ServerDataService serverDataService) { this.serverDataService = serverDataService; } public void setAsyncService(AsyncService asyncService) { this.asyncService = asyncService; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/CPU.java ================================================ package com.sohu.cache.server.data; import org.apache.commons.lang.math.NumberUtils; import java.util.ArrayList; import java.util.List; /** * cpu状况 */ public class CPU implements LineParser{ public static final String FLAG = "CPU"; public static final String CPU_ALL = "CPU_ALL"; private Usage allUsage; //包含各个虚拟cpu的情况 private List cpuList = new ArrayList(); /** * line format: * CPU001,CPU 1 bx-50-13,User%,Sys%,Wait%,Idle% * CPU002,CPU 2 bx-50-13,User%,Sys%,Wait%,Idle% * CPU_ALL,CPU Total bx-50-13,User%,Sys%,Wait%,Idle%,Busy,CPUs * CPU001,T0001,1.8,0.9,4.5,92.9 * CPU002,T0001,3.6,1.8,0.0,94.6 * CPU_ALL,T0001,2.1,1.3,0.6,95.9,,16 */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split(",", 6); if(items.length != 6) { return; } if(!items[1].equals(timeKey)) { return; } Usage usage = new Usage(); usage.setUser(NumberUtils.toFloat(items[2])); usage.setSys(NumberUtils.toFloat(items[3])); usage.setWait(NumberUtils.toFloat(items[4])); if(CPU_ALL.equals(items[0])) { allUsage = usage; } else { usage.setName(items[0]); cpuList.add(usage); } } } public List getCpuList() { return cpuList; } public Usage getAllUsage() { return allUsage; } public float getUser() { return allUsage == null ? 0 : allUsage.getUser(); } public float getSys() { return allUsage == null ? 0 : allUsage.getSys(); } public float getWait() { return allUsage == null ? 0 : allUsage.getWait(); } public String getExt(){ StringBuilder sb = new StringBuilder(); for(Usage usage : cpuList) { sb.append(usage.getName()); sb.append(","); sb.append(usage.getUser()); sb.append(","); sb.append(usage.getSys()); sb.append(","); sb.append(usage.getWait()); sb.append(";"); } return sb.toString(); } public String toString() { return "CPU [cpuList=" + cpuList + "]"; } /** * cpu使用率 */ static class Usage{ //代表那个cpu private String name; //用户空间使用率 private float user; //内核空间使用率 private float sys; //wio private float wait; public float getUser() { return user; } public void setUser(float user) { this.user = user; } public float getSys() { return sys; } public void setSys(float sys) { this.sys = sys; } public float getWait() { return wait; } public void setWait(float wait) { this.wait = wait; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Usage [name=" + name + ", user=" + user + ", sys=" + sys + ", wait=" + wait + "]"; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Connection.java ================================================ package com.sohu.cache.server.data; import org.apache.commons.lang.math.NumberUtils; /** * tcp连接 */ public class Connection implements LineParser{ public static final String FLAG = "TCP"; private int established; private int timeWait; private int orphan; /** * line format: * TCP: inuse 454 orphan 0 tw 159620 alloc 454 mem 79 */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split("\\s+"); for(int i = 0; i < items.length; ++i) { if(items[i].equals("inuse")) { established = NumberUtils.toInt(items[i+1]); } else if(items[i].equals("orphan")) { orphan = NumberUtils.toInt(items[i+1]); } else if(items[i].equals("tw")) { timeWait = NumberUtils.toInt(items[i+1]); } } } } public int getEstablished() { return established; } public int getTimeWait() { return timeWait; } public int getOrphan() { return orphan; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Disk.java ================================================ package com.sohu.cache.server.data; import org.apache.commons.lang.math.NumberUtils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; /** * io读写情况 */ public class Disk implements LineParser{ public static final String FLAG = "DISK"; public static final Pattern PATTERN = Pattern.compile("^BBBP,[0-9]+,/bin/df-m,"); public static final Pattern SUBPARTITION_PATTERN = Pattern.compile("[0-9]+$"); //包括总的状况及各个分区的状况 private Map> diskMap = new HashMap>(); /** * line format: * DISKBUSY,Disk %Busy iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKREAD,Disk Read KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKWRITE,Disk Write KB/s iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKXFER,Disk transfers per second iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKBSIZE,Disk Block Size iZ256oe4w5bZ,xvda,xvda1,xvdb,xvdb1 * DISKBUSY,T0001,0.0,0.0,0.0,0.0 * DISKREAD,T0001,0.0,0.0,0.0,0.0 * DISKWRITE,T0001,0.0,0.0,0.0,0.0 * DISKXFER,T0001,0.0,0.0,0.0,0.0 * DISKBSIZE,T0001,0.0,0.0,0.0,0.0 * BBBP,173,/bin/df-m,"ddev/xvda1 20158 16018 3117 84% /" */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split(","); if(!items[1].equals(timeKey)) { DiskUsageType type = DiskUsageType.getType(items[0]); if(type == null) { return; } List list = diskMap.get(type); if(list == null) { list = new ArrayList(); diskMap.put(type, list); } for(int i = 2; i < items.length; ++i) { Usage usage = new Usage(); usage.setDiskUsageTyp(type); usage.setName(items[i]); list.add(usage); } } else { DiskUsageType type = DiskUsageType.getType(items[0]); if(type == null) { return; } List list = diskMap.get(type); if(list == null) { return; } for(int i = 2; i < items.length; ++i) { float value = NumberUtils.toFloat(items[i]); if(value > 0) { list.get(i-2).setValue(value); } } } } else if(PATTERN.matcher(line).find()) { String[] tmp = line.split(",\""); if(tmp.length > 0) { String[] item = tmp[tmp.length - 1].split("\\s+"); if(item.length != 6 || !item[4].contains("%")) { return; } List list = diskMap.get(DiskUsageType.busy); String[] tp = item[0].split("/"); String mount = tp[tp.length - 1]; for(Usage usage : list) { if(usage.getName().equals(mount)) { Usage spaceUsage = new Usage(); spaceUsage.setDiskUsageTyp(DiskUsageType.space); spaceUsage.setName(usage.getName()); spaceUsage.setValue(NumberUtils.toFloat(item[4].split("%")[0])); diskMap.computeIfAbsent(DiskUsageType.space, k -> new ArrayList<>()).add(spaceUsage); } } } } } public Map> getDiskMap() { return diskMap; } public float getRead() { List usageList = diskMap.get(DiskUsageType.read); return getUsage(usageList); } public float getWrite() { List usageList = diskMap.get(DiskUsageType.write); return getUsage(usageList); } public float getIops() { List usageList = diskMap.get(DiskUsageType.transfer); return getUsage(usageList); } public float getBusy() { List usageList = diskMap.get(DiskUsageType.busy); return getUsage(usageList); } public String getExt() { StringBuilder sb = new StringBuilder(); for(Map.Entry> entry: diskMap.entrySet()) { DiskUsageType type = entry.getKey(); if(DiskUsageType.space == type) { continue; } sb.append(type.getValue()); sb.append("="); List usageList = entry.getValue(); for(Usage use : usageList) { sb.append(use.getName()); sb.append(":"); sb.append(use.getValue()); sb.append(","); } sb.append(";"); } return sb.toString(); } public String getSpace() { StringBuilder sb = new StringBuilder(); List usageList = diskMap.get(DiskUsageType.space); if(usageList == null) { return sb.toString(); } for(Usage use : usageList) { sb.append(use.getName()); sb.append(":"); sb.append(use.getValue()); sb.append(","); } return sb.toString(); } private float getUsage(List usageList) { float usage = 0; if(usageList != null) { for(Usage u : usageList) { if(!SUBPARTITION_PATTERN.matcher(u.getName()).find()) { usage += u.getValue(); } } } return usage; } @Override public String toString() { return "Disk [diskMap=" + diskMap + "]"; } /** * 使用率 */ static class Usage{ //分区名字 private String name; //使用率类型 private DiskUsageType diskUsageType; //使用率 private float value; public DiskUsageType getDiskUsageType() { return diskUsageType; } public void setDiskUsageTyp(DiskUsageType diskUsageType) { this.diskUsageType = diskUsageType; } public float getValue() { return value; } public void setValue(float value) { this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Usage [name=" + name + ", diskUsageType=" + diskUsageType + ", value=" + value + "]"; } } /** * 使用率类型 */ enum DiskUsageType{ //繁忙程度 busy("DISKBUSY"), //读 read("DISKREAD"), //写 write("DISKWRITE"), //io次数 transfer("DISKXFER"), //空间使用率 space("df"), ; private String value; private DiskUsageType(String value) { this.value = value; } public String getValue() { return value; } public static DiskUsageType getType(String type) { for(DiskUsageType dut : DiskUsageType.values()) { if(dut.getValue().equals(type)) { return dut; } } return null; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/LineParser.java ================================================ package com.sohu.cache.server.data; /** * 行解析器 */ public interface LineParser { /** * 解析nmon行 * @param line nmon行内容 * @param timeKey 时间戳 * @throws Exception */ void parse(String line, String timeKey) throws Exception; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Load.java ================================================ package com.sohu.cache.server.data; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.math.NumberUtils; /** * 系统负载 */ public class Load implements LineParser{ public static final Pattern PATTERN = Pattern.compile( "^BBBP,[0-9]+,uptime,.*(\\d+\\.\\d+), (\\d+\\.\\d+), (\\d+\\.\\d+)"); //1分钟负载 private float load1; //5分钟负载 private float load5; //15分钟负载 private float load15; /** * line format: * BBBP,585,uptime," 09:35:00 up 567 days, 15:07, 0 users, load average: 0.60, 0.63, 0.67" */ public void parse(String line, String timeKey) throws Exception{ Matcher matcher = PATTERN.matcher(line); if(matcher.find()) { load1 = NumberUtils.toFloat(matcher.group(1)); load5 = NumberUtils.toFloat(matcher.group(2)); load15 = NumberUtils.toFloat(matcher.group(3)); } } public float getLoad1() { return load1; } public float getLoad5() { return load5; } public float getLoad15() { return load15; } @Override public String toString() { return "Load [load1=" + load1 + ", load5=" + load5 + ", load15=" + load15 + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Memory.java ================================================ package com.sohu.cache.server.data; import org.apache.commons.lang.math.NumberUtils; /** * 内存使用情况 */ public class Memory implements LineParser{ public static final String FLAG = "MEM"; //总内存,单位M private float total; //总空闲内存,单位M private float totalFree; //buffer,单位M private float buffer; //cache,单位M private float cache; //swap,单位M private float swap; //swap空闲内存,单位M private float swapFree; /** * line format: * MEM,Memory MB bx-50-13,memtotal,hightotal,lowtotal,swaptotal,memfree,highfree,lowfree,swapfree,memshared,cached,active,bigfree,buffers,swapcached,inactive * MEM,T0001,48288.7,0.0,48288.7,8189.4,132.6,0.0,132.6,8189.1,-0.0,24210.6,30819.7,-1.0,153.9,0.0,16451.1 */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split(","); if(!items[1].equals(timeKey)) { return; } total = NumberUtils.toFloat(items[2]); swap = NumberUtils.toFloat(items[5]); totalFree = NumberUtils.toFloat(items[6]); swapFree = NumberUtils.toFloat(items[9]); cache = NumberUtils.toFloat(items[11]); buffer = NumberUtils.toFloat(items[14]); } } public float getTotal() { return total; } public float getTotalFree() { return totalFree; } public float getBuffer() { return buffer; } public float getCache() { return cache; } public float getSwap() { return swap; } public float getSwapFree() { return swapFree; } @Override public String toString() { return "Memory [total=" + total + ", totalFree=" + totalFree + ", buffer=" + buffer + ", cache=" + cache + ", swap=" + swap + ", swapFree=" + swapFree + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Net.java ================================================ package com.sohu.cache.server.data; import org.apache.commons.lang.math.NumberUtils; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; /** * 网络流量 */ public class Net implements LineParser{ public static final String FLAG = "NET,"; private float nin; private float nout; private StringBuilder ninDetail = new StringBuilder(); private StringBuilder noutDetail = new StringBuilder(); private List ncList = new ArrayList(); /** * line format: * NET,Network I/O bx-50-13,lo-read-KB/s,eth0-read-KB/s,eth1-read-KB/s,eth2-read-KB/s,eth3-read-KB/s,lo-write-KB/s,eth0-write-KB/s,eth1-write-KB/s,eth2-write-KB/s,eth3-write-KB/s, * NET,T0001,190.3,3317.8,0.0,0.0,0.0,190.3,3377.7,0.0,0.0,0.0, */ public void parse(String line, String timeKey) throws Exception{ if(line.startsWith(FLAG)) { String[] items = line.split(","); if(items[1].startsWith("Network")) { for(int i = 0; i < items.length; ++i) { if(items[i].startsWith("eth")) { NetworkInterfaceCard nic = new NetworkInterfaceCard(); nic.setName(items[i]); nic.setIdx(i); ncList.add(nic); } } } else { for(NetworkInterfaceCard nic : ncList) { nic.setValue(NumberUtils.toFloat(items[nic.getIdx()])); } caculate(); } } } private void caculate() { float totalIn = 0; float totalOut = 0; for(NetworkInterfaceCard nic : ncList) { String[] array = nic.getName().split("-"); if("read".equals(array[1])) { ninDetail.append(array[0]); ninDetail.append(","); ninDetail.append(nic.getValue()); ninDetail.append(";"); totalIn += nic.getValue(); } else if("write".equals(array[1])) { noutDetail.append(array[0]); noutDetail.append(","); noutDetail.append(nic.getValue()); noutDetail.append(";"); totalOut += nic.getValue(); } } nin = BigDecimal.valueOf(totalIn).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); nout = BigDecimal.valueOf(totalOut).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); } public float getNin() { return nin; } public float getNout() { return nout; } public String getNinDetail() { return ninDetail.toString(); } public String getNoutDetail() { return noutDetail.toString(); } static class NetworkInterfaceCard{ private String name; private float value; private int idx; public String getName() { return name; } public void setName(String name) { this.name = name; } public float getValue() { return value; } public void setValue(float value) { this.value = value; } public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/OS.java ================================================ package com.sohu.cache.server.data; import com.sohu.cache.server.data.OSInfo.DistributionType; import com.sohu.cache.server.data.OSInfo.DistributionVersion; import com.sohu.cache.server.data.OSInfo.OSType; import com.sohu.cache.server.data.OSInfo.ProcessorArchitecture; /** * 从OSInfo解析后的OS */ public class OS { //操作系统类型 private OSType osType; //发行版本 private DistributionType distributionType; //发行版本号 private DistributionVersion distributionVersion; //处理器架构 private ProcessorArchitecture processorArchitecture; public OS(OSType osType, DistributionType distributionType, DistributionVersion distributionVersion, ProcessorArchitecture processorArchitecture) { this.osType = osType; this.distributionType = distributionType; this.distributionVersion = distributionVersion; this.processorArchitecture = processorArchitecture; } public OSType getOsType() { return osType; } public void setOsType(OSType osType) { this.osType = osType; } public DistributionType getDistributionType() { return distributionType; } public void setDistributionType(DistributionType distributionType) { this.distributionType = distributionType; } public DistributionVersion getDistributionVersion() { return distributionVersion; } public void setDistributionVersion(DistributionVersion distributionVersion) { this.distributionVersion = distributionVersion; } public ProcessorArchitecture getProcessorArchitecture() { return processorArchitecture; } public void setProcessorArchitecture(ProcessorArchitecture processorArchitecture) { this.processorArchitecture = processorArchitecture; } @Override public String toString() { return "OS [osType=" + osType + ", dist=" + distributionType + ", version=" + distributionVersion + ", bit=" + processorArchitecture + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/OSInfo.java ================================================ package com.sohu.cache.server.data; /** * 代表操作系统的原始信息 * 及一些类型定义 */ public class OSInfo { //操作系统信息 uname -a private String uname; //发布版本 - /etc/issue private String issue; public String getUname() { return uname; } public void setUname(String uname) { this.uname = uname; } public String getIssue() { return issue; } public void setIssue(String issue) { this.issue = issue; } public String toString() { return "OSInfo [uname=" + uname + ", issue=" + issue + "]"; } /** * 操作系统类型 */ public enum OSType{ LINUX("linux"), ; private String value; private OSType(String value) { this.value = value; } public String getValue() { return value; } public static OSType findByValue(String value) { for(OSType os : values()) { if(os.getValue().equals(value)) { return os; } } return null; } } /** * 操作系统的发行版本 */ public enum DistributionType{ //通用系列 LINUX("linux", "@@linux@@", new DistributionVersion[]{DistributionVersion.DEFAULT}), LINUX_OLD("linux_old", "@@linux_old@@", new DistributionVersion[]{DistributionVersion.DEFAULT}), //红帽系列 REDHAT("rhel", "red hat", new DistributionVersion[]{ DistributionVersion.REDHAT_4, DistributionVersion.REDHAT_45, DistributionVersion.REDHAT_5, DistributionVersion.REDHAT_52, DistributionVersion.REDHAT_54, DistributionVersion.REDHAT_6, DistributionVersion.REDHAT_65, DistributionVersion.REDHAT_7, DistributionVersion.REDHAT_71, DistributionVersion.REDHAT_72, }), //centos系列 CENTOS("centos", "centos", new DistributionVersion[]{ DistributionVersion.CENTOS_6, DistributionVersion.CENTOS_7, }), //ubuntu系列 UBUNTU("ubuntu", "ubuntu", new DistributionVersion[]{ DistributionVersion.UBUNTU_6, DistributionVersion.UBUNTU_7, DistributionVersion.UBUNTU_8, DistributionVersion.UBUNTU_810, DistributionVersion.UBUNTU_9, DistributionVersion.UBUNTU_910, DistributionVersion.UBUNTU_10, DistributionVersion.UBUNTU_1004, DistributionVersion.UBUNTU_1010, DistributionVersion.UBUNTU_1104, DistributionVersion.UBUNTU_1110, DistributionVersion.UBUNTU_13, DistributionVersion.UBUNTU_14, DistributionVersion.UBUNTU_1404, DistributionVersion.UBUNTU_1410, DistributionVersion.UBUNTU_15, DistributionVersion.UBUNTU_1504, DistributionVersion.UBUNTU_1510, }), //debian系列 DEBIAN("debian", "debian", new DistributionVersion[]{ DistributionVersion.DEBIAN_5, DistributionVersion.DEBIAN_50, DistributionVersion.DEBIAN_6, DistributionVersion.DEBIAN_60, DistributionVersion.DEBIAN_7, DistributionVersion.DEBIAN_8, }), //fedora系列 FEDORA("fedora", "fedora", new DistributionVersion[]{ DistributionVersion.FEDORA_14, DistributionVersion.FEDORA_15, DistributionVersion.FEDORA_16, DistributionVersion.FEDORA_17, DistributionVersion.FEDORA_18, DistributionVersion.FEDORA_19, DistributionVersion.FEDORA_20, DistributionVersion.FEDORA_21, DistributionVersion.FEDORA_22, }), //mint系列 MINT("mint", "mint", new DistributionVersion[]{ DistributionVersion.MINT_7, DistributionVersion.MINT_8, DistributionVersion.MINT_12, DistributionVersion.MINT_14, DistributionVersion.MINT_15, DistributionVersion.MINT_16, DistributionVersion.MINT_17, }), //opensuse系列 OPENSUSE("opensuse", "opensuse", new DistributionVersion[]{ DistributionVersion.OPENSUSE_11, DistributionVersion.OPENSUSE_12, DistributionVersion.OPENSUSE_13, }), //sles系列(SuSE Linux Enterprise Server) SLES("sles", "sles", new DistributionVersion[]{ DistributionVersion.SLES_11, DistributionVersion.SLES_12, DistributionVersion.SLES_13, }), //knoppix KNOPPIX("knoppix", "knoppix", new DistributionVersion[]{ DistributionVersion.KNOPPIX_4, DistributionVersion.KNOPPIX_5, DistributionVersion.KNOPPIX_6, DistributionVersion.KNOPPIX_7, }), ; //nmon文件对应的名字 private String nmonName; //发行版本对应的标志 private String distSign; private DistributionVersion[] versions; private DistributionType(String nmonName, String distSign, DistributionVersion[] versions) { this.nmonName = nmonName; this.distSign = distSign; this.versions = versions; } public String getNmonName() { return nmonName; } public String getDistSign() { return distSign; } public DistributionVersion[] getVersions() { return versions; } public static DistributionType findByContains(String value) { for(DistributionType type : values()) { if(value.contains(type.getDistSign())) { return type; } } return null; } } /** * 操作系统的发行版本号 */ public enum DistributionVersion{ //通用系列无版本 DEFAULT(""), //红帽系列 REDHAT_4("4"), REDHAT_45("45"), REDHAT_5("5"), REDHAT_52("52"), REDHAT_54("54"), REDHAT_6("6"), REDHAT_65("65"), REDHAT_7("7"), REDHAT_71("71"), REDHAT_72("72"), //centos系列 CENTOS_6("6"), CENTOS_7("7"), //ubuntu系列 UBUNTU_6("6"), UBUNTU_7("7"), UBUNTU_8("8"), UBUNTU_810("810"), UBUNTU_9("9"), UBUNTU_910("910"), UBUNTU_10("10"), UBUNTU_1004("1004"), UBUNTU_1010("1010"), UBUNTU_1104("1104"), UBUNTU_1110("1110"), UBUNTU_13("13"), UBUNTU_14("14"), UBUNTU_1404("1404"), UBUNTU_1410("1410"), UBUNTU_15("15"), UBUNTU_1504("1504"), UBUNTU_1510("1510"), //debian系列 DEBIAN_5("5"), DEBIAN_50("50"), DEBIAN_6("6"), DEBIAN_60("60"), DEBIAN_7("7"), DEBIAN_8("8"), //fedora系列 FEDORA_14("14"), FEDORA_15("15"), FEDORA_16("16"), FEDORA_17("17"), FEDORA_18("18"), FEDORA_19("19"), FEDORA_20("20"), FEDORA_21("21"), FEDORA_22("22"), //mint系列 MINT_7("7"), MINT_8("8"), MINT_12("12"), MINT_14("14"), MINT_15("15"), MINT_16("16"), MINT_17("17"), //opensuse系列 OPENSUSE_11("11"), OPENSUSE_12("12"), OPENSUSE_13("13"), //sles系列(SuSE Linux Enterprise Server) SLES_11("11"), SLES_12("12"), SLES_13("13"), //knoppix KNOPPIX_4("4"), KNOPPIX_5("5"), KNOPPIX_6("6"), KNOPPIX_7("7"), ; private String value; private DistributionVersion(String value) { this.value = value; } public String getValue() { return value; } } /** * 处理器架构 */ public enum ProcessorArchitecture{ X86_64("x86_64"), X86("x86"), UNKONW(""), ; private String value; private ProcessorArchitecture(String value) { this.value = value; } public String getValue() { return value; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/data/Server.java ================================================ package com.sohu.cache.server.data; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.regex.Pattern; import org.apache.commons.lang.math.NumberUtils; /** * 服务器基本状态 */ public class Server implements LineParser{ public static final String TIME_FLAG = "ZZZZ"; public static final String FLAG = "AAA"; public static final Pattern pattern = Pattern.compile("^BBBP,[0-9]+,/proc/cpuinfo,\"model name"); public static final String OPEN_FILES = "open files"; public static final String MX_PROCESS = "max user processes"; //标志时间的字段 private String timeKey; //收集日期 类似18:49:21,31-MAY-2016格式 private String dateTime; private Date collectTime; private String ip; //host private String host; //逻辑cpu个数 private int cpus; //nmon版本 private String nmon; //cpu型号 private String cpuModel; //内核版本 private String kernel; //发行版本 private String dist; //ulimit private String ulimit = ""; private CPU cpu; private Memory mem; private Load load; private Disk disk; private Net net; private Connection connection; public Server() { cpu = new CPU(); mem = new Memory(); load = new Load(); disk = new Disk(); net = new Net(); connection = new Connection(); } public static void main(String[] args) throws ParseException { String s = "18:49:21,31-MAY-2016"; SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss,dd-MMM-yyyy", Locale.ENGLISH); System.out.println(sdf.parse(s)); } /** * line format: * ZZZZ,T0001,09:50:01,01-JUL-2016 * AAA,host,localhost * AAA,version,14g * AAA,cpus,16 * AAA,OS,Linux,2.6.18-348.el5,#1 SMP Wed Nov 28 21:22:00 EST 2012,x86_64 * BBBP,374,/proc/cpuinfo,"stat name : Intel(R) Xeon(R) CPU E5620 @ 2.40GHz" * open files (-n) 65535 * max user processes (-u) 65535 */ public void parse(String line, String key) throws Exception { if(line.startsWith(TIME_FLAG)) { String[] items = line.split(",", 3); if(items.length == 3) { this.timeKey = items[1]; this.dateTime = items[2]; SimpleDateFormat sdf = new SimpleDateFormat( "HH:mm:ss,dd-MMM-yyyy", Locale.ENGLISH); this.collectTime = sdf.parse(dateTime); } } else if(line.startsWith(FLAG)) { String[] items = line.split(",", 3); if(items.length > 2) { if("host".equals(items[1])) { host = items[2]; } else if("version".equals(items[1])) { nmon = items[2]; } else if("cpus".equals(items[1])) { cpus = NumberUtils.toInt(items[2]); } else if("OS".equals(items[1])) { kernel = items[2]; } } } else if(cpuModel == null && pattern.matcher(line).find()) { String[] tmp = line.split("model name"); if(tmp.length == 2) { cpuModel = tmp[1].trim(); cpuModel = cpuModel.substring(1, cpuModel.length() - 1); } } String mxFile = parseULimit(line, OPEN_FILES, "f"); if(mxFile != null) { ulimit += mxFile; } String mxProcess = parseULimit(line, MX_PROCESS, "p"); if(mxProcess != null) { ulimit += mxProcess; } load.parse(line, timeKey); cpu.parse(line, timeKey); mem.parse(line, timeKey); net.parse(line, timeKey); disk.parse(line, timeKey); connection.parse(line, timeKey); } private String parseULimit(String line, String prefix, String flag) { String result = null; if(line.startsWith(prefix)) { String[] tmp = line.split("\\s+"); if(tmp.length > 0) { int v = NumberUtils.toInt(tmp[tmp.length - 1]); if(v > 0) { result = flag + "," + v +";"; } } } return result; } public String getDateTime() { return dateTime; } public Date getCollectTime() { return (Date) collectTime.clone(); } public Connection getConnection() { return connection; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getHost() { return host; } public int getCpus() { return cpus; } public String getUlimit() { return ulimit; } public String getNmon() { return nmon; } public String getCpuModel() { return cpuModel; } public String getKernel() { return kernel; } public String getDist() { return dist; } public CPU getCpu() { return cpu; } public Memory getMem() { return mem; } public String getTime() { return new SimpleDateFormat("HHmm").format(collectTime); } public Load getLoad() { return load; } public Disk getDisk() { return disk; } public Net getNet() { return net; } public void setHost(String host) { this.host = host; } public void setCpus(int cpus) { this.cpus = cpus; } public void setNmon(String nmon) { this.nmon = nmon; } public void setCpuModel(String cpuModel) { this.cpuModel = cpuModel; } public void setDist(String dist) { this.dist = dist; } public void setKernel(String kernel) { this.kernel = kernel; } public void setUlimit(String ulimit) { this.ulimit = ulimit; } @Override public String toString() { return "Server [timeKey=" + timeKey + ", dateTime=" + dateTime + ", collectTime=" + collectTime + ", ip=" + ip + ", host=" + host + ", cpus=" + cpus + ", nmon=" + nmon + ", cpuModel=" + cpuModel + ", kernel=" + kernel + ", dist=" + dist + ", ulimit=" + ulimit + ", cpu=" + cpu + ", mem=" + mem + ", load=" + load + ", disk=" + disk + ", net=" + net + ", connection=" + connection + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/server/nmon/NMONService.java ================================================ package com.sohu.cache.server.nmon; import com.sohu.cache.server.data.OS; import com.sohu.cache.server.data.OSInfo; import com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor; import com.sohu.cache.ssh.SSHTemplate.Result; import com.sohu.cache.ssh.SSHTemplate.SSHSession; import com.sohu.cache.util.NMONFileFactory; import com.sohu.cache.util.OSFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.io.File; /** * 服务器监控脚本服务(nmon识别和监控) */ @Component public class NMONService { private static final Logger logger = LoggerFactory.getLogger(NMONService.class); //获取系统版本位数命令 public static final String OS_INFO_CMD = "/bin/uname -a; /bin/cat /etc/issue"; //nmon路径 public static final String NMON_DIR = "/opt/cachecloud/soft/"; //nmon文件名 public static final String NMON = "nmon"; //nmon完整路径 public static final String NMON_FILE = NMON_DIR + NMON; //获取nmon版本 public static final String NMON_VERSION = "[ -e \"" + NMON_FILE + "\" ] && " + NMON_FILE + " -V"; //nmon输出的结果文件 public static final String NMON_LOG = "/tmp/nmon.log"; //nmon输出的老结果文件 public static final String NMON_OLD_LOG = "/tmp/nmon.old.log"; //tcp输出的结果文件 public static final String SOCK_LOG = "/tmp/sock.log"; //ulimit输出的结果文件 public static final String ULIMIT_LOG = "/tmp/ulimit.log"; //nmon监控启动 public static final String START_SERVER_COLLECT = NMON_FILE + " -F " + NMON_LOG + " -s0 -c1;" + "/bin/grep TCP /proc/net/sockstat > " + SOCK_LOG + ";ulimit -n -u > " + ULIMIT_LOG ; //创建nmon路径 public static final String MK_NMON_DIR = "/bin/mkdir -p /opt/cachecloud/soft/"; /** * 启动nmon收集系统状况 * * @param ip * @param session * @return @OSInfo 收集到的操作系统信息 */ public OSInfo start(String ip, SSHSession session) { Result startCollectResult = session.executeCommand(START_SERVER_COLLECT); if (!startCollectResult.isSuccess()) { logger.error("start nmon " + ip + " err:" + startCollectResult.getResult(), startCollectResult.getExcetion()); //执行命令没有发生异常,则nmon可能不存在或有问题 if (startCollectResult.getExcetion() == null) { //尝试处理出错信息 return initNmon(ip, session); } } return null; } /** * 尝试修复启动失败的错误 * * @param ip * @param session */ private OSInfo initNmon(String ip, SSHSession session) { //获取nmon版本 String version = getNMONVersion(ip, session); //获取操作系统原始信息 OSInfo osInfo = getOSInfo(ip, session); OS os = null; //nmon文件不存在,需要根据操作系统识别是否支持 if (null == version) { logger.warn("{} not exist {}", ip, NMON_FILE); //将原始信息转换为可识别的操作系统 os = OSFactory.getOS(osInfo); } else { //nmon存在,但是版本有问题,此时不应该再判断系统信息了,直接用默认的 logger.warn("{} {} version err:" + version, ip, NMON_FILE); os = OSFactory.getDefaultOS(osInfo); } if (os == null) { logger.error("unkonw os info={}", osInfo); return null; } //获取nmon文件 File nmonFile = NMONFileFactory.getNMONFile(os); if (nmonFile == null) { logger.warn("{} no corresponding nmon file", os); nmonFile = NMONFileFactory.getNMONFile(OSFactory.getDefaultOS(osInfo)); } //将nmon文件传输至服务器 sendNMONToServer(ip, session, nmonFile); return osInfo; } /** * 获取nmon文件版本 * * @param ip * @param session * @return 存在返回版本,不存在返回null, 执行错误返回异常 */ private String getNMONVersion(String ip, SSHSession session) { Result nmonVersionResult = session.executeCommand(NMON_VERSION); if (nmonVersionResult.isSuccess()) { return nmonVersionResult.getResult(); } else { logger.error(NMON_VERSION + " err:" + nmonVersionResult.getResult(), nmonVersionResult.getExcetion()); } return null; } /** * 获取操作系统信息 * * @param ip * @param session * @return OSInfo */ private OSInfo getOSInfo(String ip, SSHSession session) { final OSInfo osInfo = new OSInfo(); session.executeCommand(OS_INFO_CMD, new DefaultLineProcessor() { public void process(String line, int lineNum) throws Exception { switch (lineNum) { case 1: osInfo.setUname(line); break; case 2: osInfo.setIssue(line); break; default: break; } } }); return osInfo; } /** * 将nmon文件scp到服务器上 * * @param ip * @param session * @param nmonFile */ private void sendNMONToServer(String ip, SSHSession session, File nmonFile) { Result mkResult = session.executeCommand(MK_NMON_DIR); if (!mkResult.isSuccess()) { logger.error("mkdir err:" + mkResult.getResult(), mkResult.getExcetion()); return; } Result scpRst = session.scpToFile(nmonFile.getAbsolutePath(), NMON, NMON_DIR); if (scpRst.isSuccess()) { logger.info("scp {} to {} success", nmonFile.getAbsolutePath(), ip); } else { logger.error("scp to " + ip + " err", scpRst.getExcetion()); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHClient.java ================================================ package com.sohu.cache.ssh; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.auth.password.PasswordIdentityProvider; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader; import org.apache.sshd.common.keyprovider.KeyIdentityProvider; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.security.SecurityUtils; import java.io.IOException; import java.nio.file.FileSystemException; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.util.Collection; import java.util.concurrent.TimeUnit; /** * ssh client * * @Auther: yongfeigao * @Date: 2023/10/23 */ @Slf4j @Data public class SSHClient { // 服务器 ssh 用户 private String serverUser; // 服务器 ssh 密码 private String serverPassword; // 服务器 ssh 端口 private Integer serverPort; // 服务器 ssh 链接建立超时时间 private Integer serverConnectTimeout; // 服务器 ssh 操作超时时间 private Integer serverOPTimeout; // 服务器 ssh 私钥 private String privateKeyPath; private SshClient client; public void init() throws GeneralSecurityException, IOException { client = buildSshClient(); if (StringUtils.isNotEmpty(privateKeyPath)) { setAuthByKey(client); } client.setPasswordIdentityProvider(PasswordIdentityProvider.wrapPasswords(getServerPassword())); client.start(); } private SshClient buildSshClient() { SshClient client = SshClient.setUpDefaultClient(); client.setSessionHeartbeat(Session.HeartbeatType.IGNORE, TimeUnit.SECONDS, 10); return client; } private void setAuthByKey(SshClient client) throws GeneralSecurityException, IOException { try{ KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser(); Collection keys = loader.loadKeyPairs(null, Paths.get(privateKeyPath), null); client.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keys)); }catch (FileSystemException e){ log.error("setAuthByKey error, please check ssh type and key path and key. ", e); } } /** * 连接服务器 * * @param ip * @return * @throws IOException */ public ClientSession connect(String ip) throws IOException { ClientSession session = getClient().connect(getServerUser(), ip, getServerPort()).verify(getServerConnectTimeout(), TimeUnit.MILLISECONDS).getSession(); session.auth().verify(getServerConnectTimeout(), TimeUnit.MILLISECONDS); return session; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHMachineInfo.java ================================================ package com.sohu.cache.ssh; import lombok.Builder; import lombok.Data; import java.util.Objects; /** * @Author: zengyizhao * @CreateTime: 2024/4/3 12:38 * @Description: ssh session key * @Version: 1.0 */ @Data @Builder public class SSHMachineInfo { /** * ip */ private String ip; /** * 用户名 */ private String username; /** * 登录方式 */ private int authType; /** * 密码 */ private String password; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SSHMachineInfo that = (SSHMachineInfo) o; return authType == that.authType && Objects.equals(ip, that.ip) && Objects.equals(password, that.password) && Objects.equals(username, that.username); } @Override public int hashCode() { return Objects.hash(ip, username, authType, password); } @Override public String toString() { return "SSHMachineInfo{" + "ip='" + ip + '\'' + ", authType=" + authType + '}'; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHService.java ================================================ package com.sohu.cache.ssh; import com.sohu.cache.exception.SSHException; /** * @author leifu */ public interface SSHService { /** * 执行ssh命令 * @param ip * @param port * @param username * @param password * @param command * @return * @throws SSHException */ String execute(String ip, int port, String username, String password, final String command) throws SSHException; /** * 执行ssh命令 * @param ip * @param port * @param username * @param password * @param command * @return * @throws SSHException */ SSHTemplate.Result executeWithResult(String ip, int port, String username, String password, final String command) throws SSHException; /** * 执行ssh命令,可设置超时时间 * @param ip * @param port * @param username * @param password * @param command * @param timeoutMills * @return * @throws SSHException */ SSHTemplate.Result executeWithResult(String ip, int port, String username, String password, final String command, int timeoutMills) throws SSHException; /** * 拷贝文件到远程目录 * @param ip * @param port * @param username * @param password * @param localPath * @param remoteDir * @return * @throws SSHException */ SSHTemplate.Result scpFileToRemote(String ip, int port, String username, String password, final String localPath, final String remoteDir) throws SSHException; /** * 拷贝文件到远程目录 * @param ip * @param localPath * @param remoteDir * @return * @throws SSHException */ SSHTemplate.Result scpFileToRemote(String ip, String localPath, String remoteDir) throws SSHException; /** * 执行命令 * @param ip * @param cmd * @return * @throws SSHException */ String execute(String ip, String cmd) throws SSHException; /** * 执行命令 * @param ip * @param cmd * @return * @throws SSHException */ SSHTemplate.Result executeWithResult(String ip, String cmd) throws SSHException; /** * 执行命令,可设置超时时间 * @param ip * @param cmd * @return * @throws SSHException */ SSHTemplate.Result executeWithResult(String ip, String cmd, int millsSecond) throws SSHException; /** * 查看机器ip上的端口port是否已被占用; * @param ip * @param port * @return * @throws SSHException */ boolean isPortUsed(String ip, int port) throws SSHException; /** * 通过ip来判断ssh端口 * @param ip * @return */ int getSshPort(String ip); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHServiceImpl.java ================================================ package com.sohu.cache.ssh; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.exception.SSHException; import com.sohu.cache.ssh.SSHTemplate.Result; import com.sohu.cache.ssh.SSHTemplate.SSHCallback; import com.sohu.cache.ssh.SSHTemplate.SSHSession; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.sohu.cache.constant.EmptyObjectConstant.EMPTY_STRING; import static com.sohu.cache.constant.SymbolConstant.COMMA; /** * @author fulei * @date 2018年6月25日 */ @Service public class SSHServiceImpl implements SSHService { private Logger logger = LoggerFactory.getLogger(SSHServiceImpl.class); @Autowired private MachineDao machineDao; private Map machineIpInfoMap = new ConcurrentHashMap(); private Map appNameIdMap = new ConcurrentHashMap(); @Autowired(required = false) private SSHTemplate sshTemplate; @Override public String execute(String ip, int port, String username, String password, final String command) throws SSHException { Result rst = executeWithResult(ip, port, username, password, command); if (rst.isSuccess()) { return rst.getResult(); } return ""; } @Override public Result executeWithResult(String ip, int port, String username, String password, final String command) throws SSHException { return sshTemplate.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.executeCommand(command); } }); } @Override public Result executeWithResult(String ip, int port, String username, String password, final String command, int timeoutMills) throws SSHException { return sshTemplate.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.executeCommand(command, timeoutMills); } }); } @Override public Result executeWithResult(String ip, String cmd) throws SSHException { return executeWithResult(ip, getSshPort(ip), ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd); } public Result executeWithResult(String ip, String cmd, int millsSecond) throws SSHException { return executeWithResult(ip, getSshPort(ip), ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd, millsSecond); } @Override public Result scpFileToRemote(String ip, int port, String username, String password, final String localPath, final String remoteDir) throws SSHException { return sshTemplate.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.scpToDir(localPath, remoteDir, "0644"); } }); } @Override public Result scpFileToRemote(String ip, String localPath, String remoteDir) throws SSHException { return scpFileToRemote(ip, getSshPort(ip), ConstUtils.USERNAME, ConstUtils.PASSWORD, localPath, remoteDir); } @Override public String execute(String ip, String cmd) throws SSHException { return execute(ip, getSshPort(ip), ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd); } @Override public boolean isPortUsed(String ip, int port) throws SSHException { /** * 执行ps命令,查看端口,以确认刚才执行的shell命令是否成功,返回一般是这样的: * root 12510 12368 0 14:34 pts/0 00:00:00 redis-server *:6379 */ String psCmd = "/bin/ps -ef | grep %s | grep -v grep"; psCmd = String.format(psCmd, port); String psResponse = execute(ip, psCmd); boolean isUsed = false; if (StringUtils.isNotBlank(psResponse)) { String[] resultArr = psResponse.split(System.lineSeparator()); for (String resultLine : resultArr) { if (resultLine.contains(String.valueOf(port))) { isUsed = true; break; } } } return isUsed; } @Override public int getSshPort(String ip) { /** * 如果ssh默认端口不是22,请自行实现该逻辑 */ return ConstUtils.SSH_PORT_DEFAULT; } /** * 匹配字符串中的数字 * * @param content * @return */ private static String matchMemLineNumber(String content) { String result = EMPTY_STRING; if (content == null || EMPTY_STRING.equals(content.trim())) { return result; } Pattern pattern = Pattern.compile("(\\d+)"); Matcher matcher = pattern.matcher(content); if (matcher.find()) { result = matcher.group(1); } return result; } /** * 从top的cpuLine解析出us * * @param cpuLine * @return */ private static double getUsCpu(String cpuLine) { if (cpuLine == null || EMPTY_STRING.equals(cpuLine.trim())) { return 0; } String[] items = cpuLine.split(COMMA); if (items.length < 1) { return 0; } String usCpuStr = items[0]; return NumberUtils.toDouble(matchCpuLine(usCpuStr)); } private static String matchCpuLine(String content) { String result = EMPTY_STRING; if (content == null || EMPTY_STRING.equals(content.trim())) { return result; } Pattern pattern = Pattern.compile("(\\d+).(\\d+)"); Matcher matcher = pattern.matcher(content); if (matcher.find()) { result = matcher.group(); } return result; } public MachineInfo getMachineInfo(String ip) { MachineInfo machineInfo = machineIpInfoMap.get(ip); if (machineInfo == null) { machineInfo = machineDao.getMachineInfoByIp(ip); machineIpInfoMap.put(ip, machineInfo); } return machineInfo; } public Long getAppId(String name) { Long appId = appNameIdMap.get(name); return appId; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHSessionPooledObjectFactory.java ================================================ package com.sohu.cache.ssh; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SshAuthTypeEnum; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.config.keys.loader.KeyPairResourceLoader; import org.apache.sshd.common.util.security.SecurityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.util.Collection; import java.util.concurrent.TimeUnit; /** * ssh session链接池工厂 * * @Auther: yongfeigao * @Date: 2023/10/20 */ public class SSHSessionPooledObjectFactory implements KeyedPooledObjectFactory { private final Logger logger = LoggerFactory.getLogger(getClass()); private SSHClient sshClient; public SSHSessionPooledObjectFactory() throws GeneralSecurityException, IOException { sshClient = new SSHClient(); sshClient.setServerUser(ConstUtils.USERNAME); sshClient.setServerPassword(ConstUtils.PASSWORD); sshClient.setServerPort(ConstUtils.SSH_PORT_DEFAULT); sshClient.setServerConnectTimeout(ConstUtils.SSH_CONNECTION_TIMEOUT); if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PUBLIC_KEY.getValue()) { sshClient.setPrivateKeyPath(ConstUtils.PUBLIC_KEY_PEM); } sshClient.init(); } @Override public PooledObject makeObject(SSHMachineInfo sshMachineInfo) throws Exception { int port = ConstUtils.SSH_PORT_DEFAULT; ClientSession session = sshClient.getClient().connect(ConstUtils.USERNAME, sshMachineInfo.getIp(), port).verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS).getSession(); session.setUsername(sshMachineInfo.getUsername()); if(sshMachineInfo.getAuthType() == SshAuthTypeEnum.PASSWORD.getValue()){ session.addPasswordIdentity(sshMachineInfo.getPassword()); }else if(sshMachineInfo.getAuthType() == SshAuthTypeEnum.PUBLIC_KEY.getValue()){ KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser(); Collection keys = loader.loadKeyPairs(null, Paths.get(ConstUtils.PUBLIC_KEY_PEM), null); session.addPublicKeyIdentity(keys.iterator().next()); } session.auth().verify(ConstUtils.SSH_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); logger.info("create object, key:{}", sshMachineInfo.getIp()); return new DefaultPooledObject<>(session); } @Override public void destroyObject(SSHMachineInfo sshMachineInfo, PooledObject pooledObject) throws Exception { ClientSession clientSession = pooledObject.getObject(); if (clientSession != null) { try { clientSession.close(); } catch (Exception e) { logger.warn("close err, key:{}", sshMachineInfo.getIp(), e); } } logger.info("destroy object {}", sshMachineInfo.getIp()); } @Override public boolean validateObject(SSHMachineInfo sshMachineInfo, PooledObject pooledObject) { boolean closed = pooledObject.getObject().isClosed(); if (closed) { logger.warn("{} session closed", sshMachineInfo.getIp()); return false; } return true; } @Override public void activateObject(SSHMachineInfo sshMachineInfo, PooledObject pooledObject) throws Exception { } @Override public void passivateObject(SSHMachineInfo sshMachineInfo, PooledObject pooledObject) throws Exception { } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHTemplate.java ================================================ package com.sohu.cache.ssh; import com.sohu.cache.exception.SSHException; import com.sohu.cache.util.ConstUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.pool2.impl.GenericKeyedObjectPool; import org.apache.sshd.client.channel.ClientChannel; import org.apache.sshd.client.channel.ClientChannelEvent; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.scp.client.ScpClient; import org.apache.sshd.scp.client.ScpClientCreator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.*; import java.nio.file.FileSystems; import java.nio.file.attribute.PosixFilePermission; import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.stream.Collectors; /** * SSH操作模板类 */ @Component public class SSHTemplate { private static final Logger logger = LoggerFactory.getLogger(SSHTemplate.class); public static final List PERMS = Arrays.asList(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.GROUP_READ, PosixFilePermission.OTHERS_READ); @Autowired private GenericKeyedObjectPool clientSessionPool; private static final int CONNCET_TIMEOUT = 5000; private static final int OP_TIMEOUT = 10000; public Result execute(String ip, SSHCallback callback) throws SSHException{ return execute(ip,ConstUtils.SSH_PORT_DEFAULT, ConstUtils.USERNAME, ConstUtils.PASSWORD, callback); } /** * 通过回调执行命令 * @param ip * @param port * @param username * @param password * @param callback 可以使用Session执行多个命令 * @throws SSHException */ public Result execute(String ip, int port, String username, String password, SSHCallback callback) throws SSHException{ ClientSession session = null; SSHMachineInfo sshMachineInfo = SSHMachineInfo.builder().ip(ip).username(username) .authType(ConstUtils.SSH_AUTH_TYPE).password(password).build(); try { session = clientSessionPool.borrowObject(sshMachineInfo); return callback.call(new SSHSession(session, ip)); } catch (Exception e) { throw new SSHException("SSH exception: " + e.getMessage(), e); } finally { close(sshMachineInfo, session); } } private DefaultLineProcessor generateDefaultLineProcessor(StringBuilder buffer) { return new DefaultLineProcessor() { public void process(String line, int lineNum) throws Exception { if (lineNum > 1) { buffer.append(System.lineSeparator()); } buffer.append(line); } }; } /** * 获取调用命令后的返回结果 * @param is 输入流 * @return 如果获取结果有异常或者无结果,那么返回null */ private String getResult(InputStream is) { final StringBuilder buffer = new StringBuilder(); LineProcessor lp = new DefaultLineProcessor() { public void process(String line, int lineNum) throws Exception { if(lineNum > 1) { buffer.append(System.lineSeparator()); } buffer.append(line); } }; processStream(is, lp); return buffer.length() > 0 ? buffer.toString() : null; } /** * 从流中获取内容 * @param is */ private void processStream(InputStream is, LineProcessor lineProcessor) { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(is)); String line = null; int lineNum = 1; while ((line = reader.readLine()) != null) { try { lineProcessor.process(line, lineNum); } catch (Exception e) { logger.error("err line:" + line, e); } if (lineProcessor instanceof DefaultLineProcessor) { ((DefaultLineProcessor) lineProcessor).setLineNum(lineNum); } lineNum++; } lineProcessor.finish(); } catch (IOException e) { logger.error(e.getMessage(), e); } finally { close(reader); } } private void close(BufferedReader read) { if (read != null) { try { read.close(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } private void close(SSHMachineInfo sshMachineInfo, ClientSession session) { if (session != null) { try { clientSessionPool.returnObject(sshMachineInfo, session); } catch (Exception e) { logger.error(e.getMessage(), e); } } } /** * 可以调用多次executeCommand, 并返回结果 */ public class SSHSession { private String address; private ClientSession clientSession; private SSHSession(ClientSession clientSession, String address) { this.clientSession = clientSession; this.address = address; } /** * 执行命令并返回结果,可以执行多次 * @param cmd * @return 执行成功Result为true,并携带返回信息,返回信息可能为null * 执行失败Result为false,并携带失败信息 * 执行异常Result为false,并携带异常 */ public Result executeCommand(String cmd) { return executeCommand(cmd, OP_TIMEOUT); } public Result executeCommand(String cmd, int timoutMillis) { return executeCommand(cmd, null, timoutMillis); } public Result executeCommand(String cmd, LineProcessor lineProcessor) { return executeCommand(cmd, lineProcessor, OP_TIMEOUT); } /** * 执行命令并返回结果,可以执行多次 * @param cmd * @param lineProcessor 回调处理行 * @return 如果lineProcessor不为null,那么永远返回Result.true */ public Result executeCommand(String cmd, LineProcessor lineProcessor, int timoutMillis) { try (ByteArrayOutputStream stdout = new ByteArrayOutputStream(); ByteArrayOutputStream stderr = new ByteArrayOutputStream(); ClientChannel channel = clientSession.createExecChannel(cmd)) { channel.setOut(stdout); channel.setErr(stderr); channel.open().verify(timoutMillis); // Wait (forever) for the channel to close - signalling command finished channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); LineProcessor tmpLP = lineProcessor; // 如果客户端需要进行行处理,则直接进行回调 if (tmpLP != null) { processStream(new ByteArrayInputStream(stdout.toByteArray()), tmpLP); } else { StringBuilder buffer = new StringBuilder(); tmpLP = generateDefaultLineProcessor(buffer); processStream(new ByteArrayInputStream(stdout.toByteArray()), tmpLP); if (buffer.length() > 0) { return new Result(true, buffer.toString()); } } if(tmpLP.lineNum() == 0) { // 返回为null代表可能有异常,需要检测标准错误输出,以便记录日志 Result errResult = tryLogError(new ByteArrayInputStream(stderr.toByteArray()), cmd); if (errResult != null) { return errResult; } } return new Result(true, null); } catch (Exception e) { logger.error("execute ip:{} cmd:{}", address, cmd, e); return new Result(e); } } private Result tryLogError(InputStream is, String cmd) { StringBuilder buffer = new StringBuilder(); LineProcessor lp = generateDefaultLineProcessor(buffer); processStream(is, lp); String errInfo = buffer.length() > 0 ? buffer.toString() : null; if (errInfo != null) { logger.error("address " + address + " execute cmd:({}), err:{}", cmd, errInfo); return new Result(false, errInfo); } return null; } /** * Copy a set of local files to a remote directory, uses the specified mode when * creating the file on the remote side. * @param localFiles * Path and name of local file. * @param remoteFile * name of remote file. * @param remoteTargetDirectory * Remote target directory. Use an empty string to specify the default directory. * @param mode * a four digit string (e.g., 0644, see "man chmod", "man open") * @throws IOException */ public Result scp(String[] localFiles, String remoteFile, String remoteTargetDirectory, String mode) { try { ScpClient client = ScpClientCreator.instance().createScpClient(clientSession); String separator = FileSystems.getDefault().getSeparator(); if(localFiles.length == 1){ if(StringUtils.isBlank(remoteFile)){ client.upload(localFiles, remoteTargetDirectory, ScpClient.Option.TargetIsDirectory); int index = localFiles[0].lastIndexOf(separator); if(index <= 0){ index = 0; }else{ index = index + 1; } String fileName = localFiles[0].substring(index); clientSession.executeRemoteCommand("chmod " + mode + " \"" + remoteTargetDirectory + "/" + fileName + "\""); } else { client.upload(localFiles, remoteTargetDirectory + "/" + remoteFile); clientSession.executeRemoteCommand("chmod " + mode + " \"" + remoteTargetDirectory + "/" + remoteFile + "\""); } } else { client.upload(localFiles, remoteTargetDirectory, ScpClient.Option.TargetIsDirectory); StringBuffer sb = new StringBuffer(); List files = Arrays.asList(localFiles); String remoteFiles = files.stream().map(file -> { int index = file.lastIndexOf(separator); if(index <= 0){ index = 0; }else{ index = index + 1; } return " \"" + remoteTargetDirectory + "/" + file.substring(index) + "\""; }).collect(Collectors.joining(" ")); clientSession.executeRemoteCommand("chmod " + mode + " " + remoteFiles); } return new Result(true); } catch (Exception e) { logger.error("scp local="+Arrays.toString(localFiles) + " to " + remoteTargetDirectory + " remote=" + remoteFile + " err", e); return new Result(e); } } public Result scpToDir(String localFile, String remoteTargetDirectory) { return scpToDir(localFile, remoteTargetDirectory, "0744"); } public Result scpToDir(String localFile, String remoteTargetDirectory, String mode) { return scp(new String[] { localFile }, null, remoteTargetDirectory, mode); } public Result scpToDir(String[] localFile, String remoteTargetDirectory) { return scp(localFile, null, remoteTargetDirectory, "0744"); } public Result scpToFile(String localFile, String remoteFile, String remoteTargetDirectory) { return scpToFile(localFile, remoteFile, remoteTargetDirectory, "0744"); } public Result scpToFile(String localFile, String remoteFile, String remoteTargetDirectory, String mode) { return scp(new String[] { localFile }, remoteFile, remoteTargetDirectory, "0744"); } } /** * 结果封装 */ public static class Result{ private boolean success; private String result; private Exception excetion; public Result(boolean success) { this.success = success; } public Result(boolean success, String result) { this.success = success; this.result = result; } public Result(Exception excetion) { this.success = false; this.excetion = excetion; } public Exception getExcetion() { return excetion; } public void setExcetion(Exception excetion) { this.excetion = excetion; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } @Override public String toString() { return "Result [success=" + success + ", result=" + result + ", excetion=" + excetion + "]"; } } /** * 执行命令回调 */ public interface SSHCallback{ /** * 执行回调 * @param session */ Result call(SSHSession session); } /** * 从流中直接解析数据 */ public static interface LineProcessor { /** * 处理行 * @param line 内容 * @param lineNum 行号,从1开始 * @throws Exception */ void process(String line, int lineNum) throws Exception; /** * 返回内容的行数,如果为0需要检测错误流 * @return */ int lineNum(); /** * 所有的行处理完毕回调该方法 */ void finish(); } public static abstract class DefaultLineProcessor implements LineProcessor { protected int lineNum; @Override public int lineNum() { return lineNum; } public void setLineNum(int lineNum) { this.lineNum = lineNum; } public void finish() {} } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/ssh/SSHUtil.java ================================================ package com.sohu.cache.ssh; import com.google.common.collect.Maps; import com.sohu.cache.entity.MachineStats; import com.sohu.cache.exception.IllegalParamException; import com.sohu.cache.exception.SSHException; import com.sohu.cache.ssh.SSHTemplate.DefaultLineProcessor; import com.sohu.cache.ssh.SSHTemplate.Result; import com.sohu.cache.ssh.SSHTemplate.SSHCallback; import com.sohu.cache.ssh.SSHTemplate.SSHSession; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.IntegerUtil; import com.sohu.cache.util.StringUtil; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.text.DecimalFormat; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.sohu.cache.constant.BaseConstant.WORD_SEPARATOR; import static com.sohu.cache.constant.EmptyObjectConstant.EMPTY_STRING; import static com.sohu.cache.constant.SymbolConstant.COMMA; import static com.sohu.cache.constant.SymbolConstant.PERCENT; import static com.sohu.cache.constant.SymbolConstant.SPACE; /** * Created by yijunzhang on 14-6-20. */ @Component public class SSHUtil { private static final Logger logger = LoggerFactory.getLogger(SSHUtil.class); private final static String COMMAND_TOP = "top -b -n 1 | head -5"; private final static String COMMAND_DF_LH = "df -lh"; private final static String LOAD_AVERAGE_STRING = "load average: "; private final static String COMMAND_MEM = "cat /proc/meminfo | grep -E -w 'MemTotal|MemFree|Buffers|Cached'"; private final static String COMMAND_CPU_MEM_DF = "(top -b -n 1 | head -5) && (cat /proc/meminfo | grep -E -w 'MemTotal|MemFree|Buffers|Cached') && ((mount | grep '/opt/cachecloud/data');(df -aBM | grep -v '-'))"; private final static String MEM_TOTAL = "MemTotal"; private final static String MEM_FREE = "MemFree"; private final static String MEM_BUFFERS = "Buffers"; private final static String MEM_CACHED = "Cached"; private final static String MOUNT_CACHECLOUD_PATH = "/opt/cachecloud/data"; private final static String M_SIZE = "M"; @Autowired private SSHTemplate sshTemplate; //使用 @SSHTemplate 重构SSHUtil private static SSHTemplate sshTemplateNew; @PostConstruct private void initSSHTemplate(){ sshTemplateNew = sshTemplate; } /** * Get HostPerformanceEntity[cpuUsage, memUsage, load] by ssh.
* 方法返回前已经释放了所有资源,调用方不需要关心 * * @param ip * @param userName * @param password * @throws Exception * @since 1.0.0 */ public static MachineStats getMachineInfo(String ip, int port, String userName, String password) throws SSHException { if (StringUtil.isBlank(ip)) { try { throw new IllegalParamException("Param ip is empty!"); } catch (IllegalParamException e) { throw new SSHException(e.getMessage(), e); } } port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT); final MachineStats machineStats = new MachineStats(); machineStats.setIp(ip); sshTemplateNew.execute(ip, port, userName, password, session -> { //解析top命令 session.executeCommand(COMMAND_CPU_MEM_DF, new DefaultLineProcessor() { private String totalMem; private String freeMem; private String buffersMem; private String cachedMem; private String totalDisk; private String availableDisk; private String usedDiskRatio; private String mountDisk; private Map diskUsageMap = Maps.newHashMap(); public void process(String line, int lineNum) throws Exception { if (1 == lineNum) { // 第一行,通常是这样: // top - 19:58:52 up 416 days, 30 min, 1 user, load average: // 0.00, 0.00, 0.00 int loadAverageIndex = line.indexOf(LOAD_AVERAGE_STRING); String loadAverages = line.substring(loadAverageIndex) .replace(LOAD_AVERAGE_STRING, EMPTY_STRING); String[] loadAverageArray = loadAverages.split(","); if (3 == loadAverageArray.length) { machineStats.setLoad(StringUtil.trimToEmpty(loadAverageArray[0])); } } else if (3 == lineNum) { // 第三行通常是这样: // , 0.0% sy, 0.0% ni, 100.0% id, 0.0% wa, // 0.0% hi, 0.0% si // redhat:%Cpu(s): 0.0 us // centos7:Cpu(s): 0.0% us double cpuUs = getUsCpu(line); machineStats.setCpuUsage(String.valueOf(cpuUs)); } else if (lineNum > 5 && lineNum < 10) { if (line.contains(MEM_TOTAL)) { totalMem = matchMemLineNumber(line).trim(); } else if (line.contains(MEM_FREE)) { freeMem = matchMemLineNumber(line).trim(); } else if (line.contains(MEM_BUFFERS)) { buffersMem = matchMemLineNumber(line).trim(); } else if (line.contains(MEM_CACHED)) { cachedMem = matchMemLineNumber(line).trim(); } } else if (lineNum >= 10) { if(lineNum == 10){ if(line.contains(MOUNT_CACHECLOUD_PATH)){ String[] mountArray = line.split(SPACE); if(mountArray != null && mountArray.length > 1){ mountDisk = mountArray[0]; } return; } } /** * 内容通常是这样: Filesystem 容量 已用 可用 已用% 挂载点 /dev/xvda2 5.8G 3.2G 2.4G * 57% / /dev/xvda1 99M 8.0M 86M 9% /boot none 769M 0 769M 0% * /dev/shm /dev/xvda7 68G 7.1G 57G 12% /home /dev/xvda6 2.0G 36M * 1.8G 2% /tmp /dev/xvda5 2.0G 199M 1.7G 11% /var **/ line = line.replaceAll(" {1,}", WORD_SEPARATOR); String[] lineArray = line.split(WORD_SEPARATOR); if (6 == lineArray.length) { String diskUsage = lineArray[4]; String mountedOn = lineArray[5]; diskUsageMap.put(mountedOn, diskUsage); if(StringUtils.isNotEmpty(mountDisk) && totalDisk == null){ String fileDisk = lineArray[0]; if(mountDisk.equals(fileDisk)){ totalDisk = lineArray[1]; if(totalDisk != null){ totalDisk = totalDisk.replace(M_SIZE, EMPTY_STRING); } availableDisk = lineArray[3]; if(availableDisk != null){ availableDisk = availableDisk.replace(M_SIZE, EMPTY_STRING); } usedDiskRatio = lineArray[4]; if(usedDiskRatio != null){ usedDiskRatio = usedDiskRatio.replace(PERCENT, EMPTY_STRING); } } } } } } public void finish() { if (!StringUtil.isBlank(totalMem, freeMem, buffersMem)) { Long totalMemLong = NumberUtils.toLong(totalMem); Long freeMemLong = NumberUtils.toLong(freeMem); Long buffersMemLong = NumberUtils.toLong(buffersMem); Long cachedMemLong = NumberUtils.toLong(cachedMem); Long usedMemFree = freeMemLong + buffersMemLong + cachedMemLong; Double memoryUsage = 1 - (NumberUtils.toDouble(usedMemFree.toString()) / NumberUtils .toDouble(totalMemLong.toString()) / 1.0); machineStats.setMemoryTotal(String.valueOf(totalMemLong)); machineStats.setMemoryFree(String.valueOf(usedMemFree)); DecimalFormat df = new DecimalFormat("0.00"); machineStats.setMemoryUsageRatio(df.format(memoryUsage * 100)); machineStats.setDiskTotal(totalDisk); machineStats.setDiskAvailable(availableDisk); machineStats.setDiskUsageRatio(usedDiskRatio); } machineStats.setDiskUsageMap(diskUsageMap); } }); return null; }); // 统计当前网络流量 @TODO Double traffic = 0.0; machineStats.setTraffic(traffic.toString()); return machineStats; } /** * SSH 方式登录远程主机,执行命令,方法内部会关闭所有资源,调用方无须关心。 * * @param ip 主机ip * @param username 用户名 * @param password 密码 * @param command 要执行的命令 */ public static String execute(String ip, int port, String username, String password, final String command) throws SSHException { if (StringUtil.isBlank(command)) { return EMPTY_STRING; } port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT); Result rst = sshTemplateNew.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.executeCommand(command); } }); if (rst.isSuccess()) { return rst.getResult(); } return ""; } public static String execute(String ip, int port, String username, String password, final String command, int timeout) throws SSHException { if (StringUtil.isBlank(command)) { return EMPTY_STRING; } port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT); Result rst = sshTemplateNew.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.executeCommand(command, timeout); } }); if (rst != null) { return rst.getResult(); } return ""; } /** * @param ip * @param port * @param username * @param password * @param localPath * @param remoteDir * @return * @throws SSHException */ public static boolean scpFileToRemote(String ip, int port, String username, String password, final String localPath, final String remoteDir) throws SSHException { Result rst = sshTemplateNew.execute(ip, port, username, password, new SSHCallback() { public Result call(SSHSession session) { return session.scpToDir(localPath, remoteDir); } }); if (rst.isSuccess()) { return true; } if (rst.getExcetion() != null) { throw new SSHException(rst.getExcetion()); } return false; } /** * 重载,使用默认端口、用户名和密码 * * @param ip * @param localPath * @param remoteDir * @return * @throws SSHException */ public static boolean scpFileToRemote(String ip, String localPath, String remoteDir) throws SSHException { int sshPort = SSHUtil.getSshPort(ip); return scpFileToRemote(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, localPath, remoteDir); } /** * 重载,使用默认端口、用户名和密码 * * @param ip * @param cmd * @return * @throws SSHException */ public static String execute(String ip, String cmd) throws SSHException { int sshPort = SSHUtil.getSshPort(ip); return execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd); } public static String execute(String ip, String cmd, Integer timeout) throws SSHException { int sshPort = SSHUtil.getSshPort(ip); if (timeout == null) { return execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd, 30000); } else { return execute(ip, sshPort, ConstUtils.USERNAME, ConstUtils.PASSWORD, cmd, timeout); } } /** * 查看机器ip上的端口port是否已被占用; * * @param ip 机器ip * @param port 要检查的端口 * @return 如果被占用返回true,否则返回false; * @throws SSHException */ public static boolean isPortUsed(String ip, int port) throws SSHException { /** * 执行ps命令,查看端口,以确认刚才执行的shell命令是否成功,返回一般是这样的: * root 12510 12368 0 14:34 pts/0 00:00:00 redis-server *:6379 */ String psCmd = "/bin/ps -ef | grep %s | grep -v grep"; psCmd = String.format(psCmd, port); String psResponse = execute(ip, psCmd); boolean isUsed = false; if (StringUtils.isNotBlank(psResponse)) { String[] resultArr = psResponse.split(System.lineSeparator()); for (String resultLine : resultArr) { if (resultLine.contains(String.valueOf(port))) { isUsed = true; break; } } } return isUsed; } /** * 通过ip来判断ssh端口 * * @param ip * @return */ public static int getSshPort(String ip) { /** * 如果ssh默认端口不是22,请自行实现该逻辑 */ return ConstUtils.SSH_PORT_DEFAULT; } /** * 匹配字符串中的数字 * * @param content * @return */ private static String matchMemLineNumber(String content) { String result = EMPTY_STRING; if (content == null || EMPTY_STRING.equals(content.trim())) { return result; } Pattern pattern = Pattern.compile("(\\d+)"); Matcher matcher = pattern.matcher(content); if (matcher.find()) { result = matcher.group(1); } return result; } /** * 从top的cpuLine解析出us * * @param cpuLine * @return */ public static double getUsCpu(String cpuLine) { if (cpuLine == null || EMPTY_STRING.equals(cpuLine.trim())) { return 0; } String[] items = cpuLine.split(COMMA); if (items.length < 1) { return 0; } String usCpuStr = items[0]; return NumberUtils.toDouble(matchCpuLine(usCpuStr)); } private static String matchCpuLine(String content) { String result = EMPTY_STRING; if (content == null || EMPTY_STRING.equals(content.trim())) { return result; } Pattern pattern = Pattern.compile("(\\d+).(\\d+)"); Matcher matcher = pattern.matcher(content); if (matcher.find()) { result = matcher.group(); } return result; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/admin/CoreAppsStatCenter.java ================================================ package com.sohu.cache.stats.admin; /** * Created by rucao on 2020/3/25 */ public interface CoreAppsStatCenter { boolean sendExpAppsStatDataEmail(String searchDate); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/admin/impl/CoreAppsStatCenterImpl.java ================================================ package com.sohu.cache.stats.admin.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.alert.utils.AlertUtils; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.stats.admin.CoreAppsStatCenter; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.FreemakerUtils; import freemarker.template.Configuration; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * Created by rucao on 2020/3/25 */ @Service("coreAppsStatCenter") @Slf4j public class CoreAppsStatCenterImpl implements CoreAppsStatCenter { @Autowired private AppService appService; @Autowired private AppDao appDao; @Autowired private UserService userService; @Autowired private ResourceDao resourceDao; @Autowired private EmailComponent emailComponent; @Autowired private Configuration configuration; @Autowired private MachineCenter machineCenter; @Override public boolean sendExpAppsStatDataEmail(String searchDate) { try { log.info("sendExpAppsStatDataEmail"); if (StringUtil.isBlank(searchDate)) { //默认发送前一天的日报 Date startDate = DateUtils.addDays(new Date(), -1); searchDate = DateUtil.formatDate(startDate, "yyyy-MM-dd"); } List appDescList = appDao.getOnlineAppsNonTest(); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceDao.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(appDesc -> String.valueOf(appDesc.getAppId()), Function.identity())); Map>> appClientGatherStatGroup = appService.getFilterAppClientStatGather(-1, searchDate); // 获取异常的宿主或容器信息 Map exceptionMachineEnv = machineCenter.getExceptionMachineEnv(DateUtils.addDays(new Date(), -1)); noticeExpAppsDaily(searchDate, appDescMap, appClientGatherStatGroup,exceptionMachineEnv); return true; } catch (Exception e) { log.error(e.getMessage(), e); return false; } } public void noticeExpAppsDaily(String searchDate, Map appDescMap, Map>> appClientGatherStatGroup,Map exceptionMachineEnv) { String title = String.format("【CacheCloud】%s应用日报", searchDate); Map context = new HashMap<>(); context.put("appDescMap", appDescMap); context.put("appClientGatherStatGroup", appClientGatherStatGroup); context.put("exceptionMachineEnv", exceptionMachineEnv); context.put("searchDate", searchDate); String mailContent = FreemakerUtils.createText("expAppsDaily.ftl", configuration, context); log.info("noticeExpAppsDaily sendMailToAdmin, title:{}, mailContent:{}", title, mailContent); // 发送管理员 emailComponent.sendDailyMail(title, mailContent, Arrays.asList(AlertUtils.EMAILS.split(",")), null); log.info("noticeExpAppsDaily success"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/AppDailyDataCenter.java ================================================ package com.sohu.cache.stats.app; import java.util.Date; import com.sohu.cache.entity.AppDailyData; /** * 应用日数据统计 * @author leifu * @Date 2016年8月10日 * @Time 下午5:11:03 */ public interface AppDailyDataCenter { /** * 发送所有应用日报 */ int sendAppDailyEmail(); /** * 发送单个应用日报 */ boolean sendAppDailyEmail(long appId, Date startDate, Date endDate); /** * 获取单天应用日报 */ AppDailyData getAppDailyData(long appId, Date date); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/AppDataMigrateCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.RedisMigrateToolConstant; import com.sohu.cache.entity.AppDataMigrateSearch; import com.sohu.cache.entity.AppDataMigrateStatus; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/10/24 */ public interface AppDataMigrateCenter { /** * 查看日志 * * @param id * @param pageSize * @return */ String showDataMigrateLog(long id, int pageSize); /** * 查看校验日志 * * @param id * @param pageSize * @return */ String showCheckDataLog(long id, int pageSize); /** * 查看配置 * * @param id * @return */ String showDataMigrateConf(long id); /** * 查询迁移工具的实时状态 * * @param id * @return */ Map> showMiragteToolProcess(long id); /** * 搜索列表 * * @param appDataMigrateSearch * @return */ List search(AppDataMigrateSearch appDataMigrateSearch); int getMigrateTaskCount(AppDataMigrateSearch appDataMigrateSearch); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/AppDeployCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.DataFormatCheckResult; import com.sohu.cache.constant.HorizontalResult; import com.sohu.cache.entity.*; import java.util.List; /** * app相关发布操作 * Created by yijunzhang on 14-10-20. */ public interface AppDeployCenter { /** * 新建应用 * * @param appDesc * @param appUser * @param memSize */ public boolean createApp(AppDesc appDesc, AppUser appUser, String memSize); /** * 为应用分配资源 * * @param appAuditId * @param nodeInfoList
格式=masterIp:空间:slaveIp * @param auditUser * @return */ public boolean allocateResourceApp(Long appAuditId, List nodeInfoList, AppUser auditUser); /** * 为API应用分配的资源格式检测 * * @param appDeployText * @return */ public DataFormatCheckResult checkAppDeployDetail4Api(AppInfoApi appInfoApi, String appDeployText, RedisVersion redisVersion); /** * 下线应用 * * @param appId * @return */ public long offLineApp(Long appId, AppUser userInfo, Long auditId); /** * 修改应用下节点配置 * * @param appId * @param appAuditId * @param key * @param value * @return */ public boolean modifyAppConfig(Long appId, Long appAuditId, String key, String value); /** * 垂直扩展 * * @param appId * @param appAuditId * @param memory 单位MB * @return */ public boolean verticalExpansion(Long appId, Long appAuditId, long operateId, int memory); /** * 检测水平扩容节点 * * @param appAuditId * @param masterSizeSlave * @return */ public DataFormatCheckResult checkHorizontalNodes(Long appAuditId, String masterSizeSlave); /** * 检查水平扩容的格式 * * @param appId * @param appAuditId * @param sourceId * @param targetId * @param startSlot * @param endSlot * @param migrateType * @return */ public HorizontalResult checkHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot, int endSlot, int migrateType); /** * 开始水平扩容 * * @param appId * @param appAuditId * @param sourceId * @param targetId * @param startSlot * @param endSlot * @param migrateType * @return */ public HorizontalResult startHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot, int endSlot, int migrateType); /** * 重试水平扩容 * * @param instanceReshardProcessId * @return */ public HorizontalResult retryHorizontal(final int instanceReshardProcessId); /** * 添加cluster一个主(从)节点 * * @param appId * @param masterHost * @param slaveHost 从节点可为空 * @param memory * @return */ public boolean addHorizontalNodes(Long appId, String masterHost, String slaveHost, int memory); /** * 获取当前水平扩展进度列表 * * @return */ public List getHorizontalProcess(long auditId); /** * 清理应用数据 * * @param appId * @param appUser * @return */ public boolean cleanAppData(long appId, AppUser appUser); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/AppPersistenceCheckCenter.java ================================================ package com.sohu.cache.stats.app; /** * Description: 应用持久化配置检查修正 * @author zengyizhao * @version 1.0 * @date 2022/11/3 */ public interface AppPersistenceCheckCenter { /** * 发送所有应用日报 */ void checkAndFixAppPersistence(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/AppStatsCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.AppTopology; import com.sohu.cache.constant.TimeDimensionalityEnum; import com.sohu.cache.entity.*; import com.sohu.cache.web.vo.AppDetailVO; import java.util.Date; import java.util.List; import java.util.Map; /** * app级别的查询、统计和汇总 *

* Created by lingguo on 14-6-26. */ public interface AppStatsCenter { /** * 通过时间区间查询app的分钟统计数据 * * @param appId * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ public List getAppStatsListByMinuteTime(final long appId, long beginTime, long endTime); /** * 通过时间区间查询app的分钟统计数据 * * @param appId * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ public List getAppStatsList(final long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum); /** * 通过时间区间查询app的每日日报数据 * * @param appId * @param beginDate 时间,格式:yyyyMMdd * @param endDate 时间,格式:yyyyMMdd * @return */ public List getAppHitRatioList(final long appId, long beginDate, long endDate); /** * 按照分钟查询应用历史最大使用内存 * @param appId * @param beginTime * @param endTime * @return */ public Long getUsedMemoryMaxByTimeBetween(final long appId, long beginTime, long endTime); /** * 通过时间区间查询一条app的分钟统计数据 * * @param appId * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ AppStats getOneAppStats(long appId, long beginTime, long endTime); /** * 查询一天中应用的命令执行次数的top5 * * @param appId 应用id * @param begin 日期格式:yyyyMMddHHmm * @param end 日期格式:yyyyMMddHHmm * @return */ public List getTop5AppCommandStatsList(final long appId, long begin, long end); /** * 查询一天中应用的命令执行次数的top5 * * @param appId 应用id * @param begin 日期格式:yyyyMMddHHmm * @param end 日期格式:yyyyMMddHHmm * @return */ public List getTopLimitAppCommandStatsList(final long appId, long begin, long end, int limit); /** * 查询应用的配置和节点信息 * * @param appId * @return */ public Map queryAppTopology(final long appId); /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @param commandName 命令名 * @return */ public List getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum, String commandName); /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @param commandName 命令名 * @return */ public List getCommandStatsList(long appId, long beginTime, long endTime, String commandName); /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ public List getCommandStatsList(long appId, long beginTime, long endTime); /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ public List getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum); /** * 查询应用指定命令的峰值 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @param commandName 命令名 * @return */ public AppCommandStats getCommandClimax(long appId, Long beginTime, Long endTime, String commandName); /** * 获取应用详细信息 * * @param appId * @return */ public AppDetailVO getAppDetail(long appId); /** * 通过所有在线的应用详细信息 * @return */ Map getOnlineAppDetails(); /** * 获取所有在线应用的应用客户端连接总数 * @return */ List getOnlineAppConnClients(); /** * 获取应用命令调用次数分布 * * @param appId * @param beginTime * @param endTime * @return */ public List getAppCommandGroup(long appId, Long beginTime, Long endTime); /** * 获取应用命令调用总次数 * * @param appId * @param beginTime * @param endTime * @return */ public Long getAppCommandCount(long appId, long beginTime, long endTime); /** * 在appId级别执行命令 * * @param appId * @param command * @param userName * @return */ public String executeCommand(long appId, String command, String userName); /** * 按照appId获取实例所有慢查询日志 * * @param appId * @param startDate * @param endDate * @return */ public List getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate); Map>> getAppLatencyStats(long appId, long startTime, long endTime); Map getAppLatencyStatsGroupByInstance(long appId, long startTime, long endTime); Map>> getAppLatencyInfo(long appId, long startTime, long endTime); List getByInstanceExecuteTime(long instanceId, String executeDate); /** * 按照appId获取每个实例慢查询个数 * * @param appId * @param startDate * @param endDate * @return */ public Map getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate); /** *

* Description:获取总览相关统计数 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/8/14 */ public Map getAppTotalStat(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/ImportAppCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.ImportAppResult; import com.sohu.cache.entity.AppDesc; /** * 导入应用 * * @author leifu * @Date 2016-4-16 * @Time 下午3:42:49 */ public interface ImportAppCenter { /** * 检查应用和实例 * * @param appInstanceInfo * @return */ ImportAppResult check(int type, String appInstanceInfo, String password); /** * 导入应用和相关实例 * * @param appDesc * @param appInstanceInfo * @return */ boolean importAppAndInstance(AppDesc appDesc, String appInstanceInfo); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/RedisMigrateToolCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.AppDataMigrateEnum; import com.sohu.cache.constant.AppDataMigrateResult; import com.sohu.cache.constant.CommandResult; import com.sohu.cache.entity.AppDataMigrateStatus; import com.sohu.cache.entity.SystemResource; /** * 数据迁移 * * @author leifu * @Date 2016-6-8 * @Time 下午2:54:33 */ public interface RedisMigrateToolCenter { /** * 检查配置 * * @param migrateMachineIp * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @param redisSourcePass * @param redisTargetPass * @return */ AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass,SystemResource resource); /** * 开始迁移 * * @param migrateMachineIp * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @param redisSourcePass * @param targetSourcePass * @return */ AppDataMigrateStatus migrate(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId, String redisSourcePass, String targetSourcePass, long userId, SystemResource resource); /** * 比较源和目标的样本数据 * * @param id * @param nums * @return */ CommandResult sampleCheckData(long id, int nums); /** * 关闭迁移 * * @param id * @return */ AppDataMigrateResult stopMigrate(long id); /** * @param appId * @return */ String getAppInstanceListForRedisMigrateTool(long appId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/RedisShakeCenter.java ================================================ package com.sohu.cache.stats.app; import com.sohu.cache.constant.AppDataMigrateEnum; import com.sohu.cache.constant.AppDataMigrateResult; import com.sohu.cache.constant.CommandResult; import com.sohu.cache.entity.AppDataMigrateStatus; import com.sohu.cache.entity.SystemResource; /** * 数据迁移工具 redis-shake * Created by rucao on 2019/10/23 */ public interface RedisShakeCenter { /** * 检查配置 * * @param migrateMachineIp * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @param redisSourcePass * @param redisTargetPass * @return */ AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass,SystemResource resource); /** * 开始迁移 * * @param migrateMachineIp * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @param sourceAppId * @param targetAppId * @param redisSourcePass * @param redisTargetPass * @param userId * @return */ AppDataMigrateStatus migrate(String migrateMachineIp, int source_rdb_parallel, int parallel, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId, String redisSourcePass, String redisTargetPass, String redisSourceVersion, String redisTargetVersion, long userId, SystemResource resource); /** * 关闭迁移 * * @param id * @return */ AppDataMigrateResult stopMigrate(long id); /** * 比较源和目标的样本数据 * * @param id * @param batchcount * @return */ CommandResult checkData(long id, int batchcount, int comparemode); /** * @param appId * @return */ String getAppInstanceListForRedisShake(long appId); /** * 显示迁移进度 * * @param id * @return */ String showProcess(long id); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/AppDailyDataCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.alert.utils.AlertUtils; import com.sohu.cache.dao.*; import com.sohu.cache.entity.AppDailyData; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.stats.app.AppDailyDataCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.FreemakerUtils; import com.sohu.cache.web.vo.AppDetailVO; import freemarker.template.Configuration; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import javax.annotation.Resource; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; /** * 应用日报 * * @author leifu * @Date 2016年8月10日 * @Time 下午5:17:02 */ @Service("appDailyDataCenter") public class AppDailyDataCenterImpl implements AppDailyDataCenter { private final static int STAT_ERROR = 0; @Resource UserService userService; private Logger logger = LoggerFactory.getLogger(AppDailyDataCenterImpl.class); @Autowired private EmailComponent emailComponent; @Autowired private AppStatsCenter appStatsCenter; @Autowired private Configuration configuration; @Autowired private InstanceSlowLogDao instanceSlowLogDao; @Autowired private AppClientExceptionStatDao appClientExceptionStatDao; @Autowired private AppStatsDao appStatsDao; @Autowired private AppDailyDao appDailyDao; @Autowired private AppService appService; @Override public int sendAppDailyEmail() { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); int successCount = 0; List appDescList = appService.getAllAppDesc(); for (AppDesc appDesc : appDescList) { try { boolean result = sendAppDailyEmail(appDesc.getAppId(), startDate, endDate); if (result) { successCount++; } } catch (Exception e) { logger.error(e.getMessage(), e); } } return successCount; } @Override public boolean sendAppDailyEmail(long appId, Date startDate, Date endDate) { try { AppDailyData appDailyData = generateAppDaily(appId, startDate, endDate); if (appDailyData == null) { return false; } fillAppDailyData(appDailyData); //保存每天的日报,后期查询和分析 appDailyDao.save(appDailyData); AppDetailVO appDetailVO = appDailyData.getAppDetailVO(); noticeAppDaily(startDate, appDetailVO, appDailyData); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } /** * 填充信息 * * @param appDailyData */ private void fillAppDailyData(AppDailyData appDailyData) { appDailyData.setAppId(appDailyData.getAppDetailVO().getAppDesc().getAppId()); appDailyData.setDate(appDailyData.getStartDate()); Map valueSizeDistributeCountMap = appDailyData.getValueSizeDistributeCountMap(); //@TODO 暂时不计数 long bigKeyTimes = 0; StringBuffer bigKeyInfo = new StringBuffer(); for (Entry entry : valueSizeDistributeCountMap.entrySet()) { String key = entry.getKey(); long times = entry.getValue(); bigKeyInfo.append(key + ":" + times + "\n"); } appDailyData.setBigKeyInfo(bigKeyInfo.toString()); appDailyData.setBigKeyTimes(bigKeyTimes); } public AppDailyData generateAppDaily(long appId, Date startDate, Date endDate) { Assert.isTrue(appId > 0L); AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId); if (appDetailVO == null) { logger.error("appId={} not exist", appId); return null; } AppDesc appDesc = appDetailVO.getAppDesc(); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); if (appDesc.isOffline()) { return null; } if (appDesc.isTestOk()) { return null; } AppDailyData appDailyData = new AppDailyData(); appDailyData.setStartDate(startDate); appDailyData.setEndDate(endDate); // 应用详情 appDailyData.setAppDetailVO(appDetailVO); // 慢查询 int slowLogCount = getSlowLogCount(appId, startDate, endDate); appDailyData.setSlowLogCount(slowLogCount); String searchDate = DateUtil.formatDate(startDate, "yyyy-MM-dd"); Map> appClientGatherStatMap = appService.getAppClientStatGather(appId, searchDate); Map appClientGatherStat = MapUtils.getMap(appClientGatherStatMap, appId); if (MapUtils.isNotEmpty(appClientGatherStat)) { appDailyData.setClientCmdCount(MapUtils.getLongValue(appClientGatherStat, "cmd_count", -0l)); appDailyData.setClientAvgCmdCost(MapUtils.getDoubleValue(appClientGatherStat, "avg_cmd_cost", -0)); appDailyData.setClientConnExpCount(MapUtils.getLongValue(appClientGatherStat, "conn_exp_count", -0l)); appDailyData.setClientAvgConnExpCost(MapUtils.getDoubleValue(appClientGatherStat, "avg_conn_exp_cost", -0)); appDailyData.setClientCmdExpCount(MapUtils.getLongValue(appClientGatherStat, "cmd_exp_count", -0l)); appDailyData.setClientAvgCmdExpCost(MapUtils.getDoubleValue(appClientGatherStat, "avg_cmd_exp_cost", -0)); appDailyData.setLatencyCount(MapUtils.getLongValue(appClientGatherStat, "latency_count", -0l)); } // 客户端值分布 Map valueSizeDistributeCountMap = new HashMap<>(); appDailyData.setValueSizeDistributeCountMap(valueSizeDistributeCountMap); // 应用相关统计 Map appMinuteStatMap = getAppMinuteStat(appId, startDate, endDate); appDailyData.setMaxMinuteClientCount(MapUtils.getIntValue(appMinuteStatMap, "maxClientCount")); appDailyData.setAvgMinuteClientCount(MapUtils.getIntValue(appMinuteStatMap, "avgClientCount")); appDailyData.setMaxMinuteCommandCount(MapUtils.getIntValue(appMinuteStatMap, "maxCommandCount")); appDailyData.setAvgMinuteCommandCount(MapUtils.getIntValue(appMinuteStatMap, "avgCommandCount")); appDailyData.setMaxMinuteHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "maxHitRatio") * 100.0)); appDailyData.setMinMinuteHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "minHitRatio") * 100.0)); appDailyData.setAvgHitRatio(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "avgHitRatio") * 100.0)); appDailyData.setAvgUsedMemory(MapUtils.getLongValue(appMinuteStatMap, "avgUsedMemory") / 1024 / 1024); appDailyData.setMaxUsedMemory(MapUtils.getLongValue(appMinuteStatMap, "maxUsedMemory") / 1024 / 1024); appDailyData.setAvgUsedDisk(MapUtils.getLongValue(appMinuteStatMap, "avgUsedDisk") / 1024 / 1024); appDailyData.setMaxUsedDisk(MapUtils.getLongValue(appMinuteStatMap, "maxUsedDisk") / 1024 / 1024); appDailyData.setExpiredKeysCount(MapUtils.getIntValue(appMinuteStatMap, "expiredKeys")); appDailyData.setEvictedKeysCount(MapUtils.getIntValue(appMinuteStatMap, "evictedKeys")); appDailyData.setAvgMinuteNetOutputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "avgNetOutputByte") / 1024.0 / 1024.0)); appDailyData.setMaxMinuteNetOutputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "maxNetOutputByte") / 1024.0 / 1024.0)); appDailyData.setAvgMinuteNetInputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "avgNetInputByte") / 1024.0 / 1024.0)); appDailyData.setMaxMinuteNetInputByte(remainNumberTwoPoint(MapUtils.getDoubleValue(appMinuteStatMap, "maxNetInputByte") / 1024.0 / 1024.0)); appDailyData.setAvgObjectSize(MapUtils.getIntValue(appMinuteStatMap, "avgObjectSize")); appDailyData.setMaxObjectSize(MapUtils.getIntValue(appMinuteStatMap, "maxObjectSize")); return appDailyData; } /** * 保留两位 * * @param num * @return */ private double remainNumberTwoPoint(double num) { DecimalFormat df = new DecimalFormat("0.00"); return NumberUtils.toDouble(df.format(num)); } /** * 获取客户端连接数统计 * * @param appId * @param startDate * @param endDate * @return */ private Map getAppMinuteStat(long appId, Date startDate, Date endDate) { try { String COLLECT_TIME_FORMAT = "yyyyMMddHHmm"; long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return appStatsDao.getAppMinuteStat(appId, startTime, endTime); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyMap(); } } /** * 获取应用在指定日期内慢查询次数 * * @param appId * @param startDate * @param endDate * @return */ private int getSlowLogCount(long appId, Date startDate, Date endDate) { try { return instanceSlowLogDao.getAppSlowLogCount(appId, startDate, endDate); } catch (Exception e) { logger.error(e.getMessage(), e); return STAT_ERROR; } } /** * 日报通知 * * @param startDate * @param appDetailVO * @param appDailyData */ public void noticeAppDaily(Date startDate, AppDetailVO appDetailVO, AppDailyData appDailyData) { List ccEmailList = getCCEmailList(appDetailVO.getAppDesc()); String startDateFormat = DateUtil.formatYYYYMMdd(startDate); String title = String.format("【CacheCloud】%s日报(appId=%s)", startDateFormat, appDetailVO.getAppDesc().getAppId()); AppDesc appDesc = appDetailVO.getAppDesc(); Map context = new HashMap<>(); context.put("appDesc", appDesc); context.put("appDailyData", appDailyData); String mailContent = FreemakerUtils.createText("appDaily.ftl", configuration, context); // 发送日报 emailComponent.sendDailyMail(title, mailContent, appDetailVO.getEmailList(), ccEmailList); } public void noteAppTopologyDaily(Date startDate, List topologyExamResult) { String startDateFormat = DateUtil.formatYYYYMMdd(startDate); String title = String.format("【CacheCloud】应用拓扑结构检查结果%s日报", startDateFormat); Map context = new HashMap<>(); context.put("examResult", topologyExamResult); String mailContent = FreemakerUtils.createText("topologyExam.ftl", configuration, context); emailComponent.sendDailyMail(title, mailContent, Arrays.asList(AlertUtils.EMAILS.split(",")), null); } /** * A级以上抄送管理员,S级抄送领导 * * @param appDesc * @return */ private List getCCEmailList(AppDesc appDesc) { Set ccEmailSet = new LinkedHashSet(); //A级 if (appDesc.isVeryImportant()) { for (String email : emailComponent.getAdminEmail().split(ConstUtils.COMMA)) { ccEmailSet.add(email); } } //S级 if (appDesc.isSuperImportant()) { ccEmailSet.addAll(ConstUtils.LEADER_EMAIL_LIST); } return new ArrayList(ccEmailSet); } @Override public AppDailyData getAppDailyData(long appId, Date date) { try { return appDailyDao.getAppDaily(appId, new SimpleDateFormat("yyyy-MM-dd").format(date)); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/AppDataMigrateCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.sohu.cache.constant.AppDataMigrateStatusEnum; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.constant.RedisMigrateToolConstant; import com.sohu.cache.constant.RedisShakeEnum; import com.sohu.cache.dao.AppDataMigrateStatusDao; import com.sohu.cache.entity.AppDataMigrateSearch; import com.sohu.cache.entity.AppDataMigrateStatus; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.app.AppDataMigrateCenter; import com.sohu.cache.util.ConstUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import java.util.*; import java.util.stream.Collectors; /** * Created by rucao on 2019/10/24[] */ @Slf4j @Service public class AppDataMigrateCenterImpl implements AppDataMigrateCenter { @Autowired private AppDataMigrateStatusDao appDataMigrateStatusDao; @Autowired private MachineCenter machineCenter; @Override public String showDataMigrateLog(long id, int pageSize) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return ""; } try { int migrateStatus = appDataMigrateStatus.getStatus(); String logPath = appDataMigrateStatus.getLogPath(); String host = appDataMigrateStatus.getMigrateMachineIp(); MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host); if (machineInfo != null && machineInfo.getAvailable() == MachineInfoEnum.AvailableEnum.YES.getValue()) { StringBuilder command = new StringBuilder(); command.append("tail -n").append(pageSize).append(" ").append(logPath); String result = SSHUtil.execute(host, command.toString()); int logStatus = migrateStatus; if (StringUtils.isNotEmpty(result) && result.contains(RedisShakeEnum.LOG_ERROR.getKeyword())) { logStatus = AppDataMigrateStatusEnum.ERROR.getStatus(); } else if (StringUtils.isNotEmpty(result) && (result.contains(RedisShakeEnum.LOG_SYNC_RDB_DONE.getKeyword()) || result.contains(RedisShakeEnum.LOG_FORWARD_COMMANDS.getKeyword()))) { logStatus = AppDataMigrateStatusEnum.FULL_END.getStatus(); } else if (StringUtils.isNotEmpty(result) && result.contains(RedisShakeEnum.LOG_SYNCING.getKeyword())) { logStatus = AppDataMigrateStatusEnum.START.getStatus(); } else if (StringUtils.isNotEmpty(result) && result.contains(RedisShakeEnum.LOG_WAITING_SOURCE_RDB.getKeyword())) { logStatus = AppDataMigrateStatusEnum.PREPARE.getStatus(); } if (migrateStatus != logStatus) { appDataMigrateStatusDao.updateStatus(id, logStatus); } return result; } else { log.warn("machine ip:{} is offline", host); return ""; } } catch (SSHException e) { log.error(e.getMessage(), e); return ""; } } @Override public String showCheckDataLog(long id, int pageSize) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return ""; } String migrateId = appDataMigrateStatus.getMigrateId(); String logPath = ConstUtils.getRedisFullCheckResultDir() + "log-" + migrateId + ".log"; String host = appDataMigrateStatus.getMigrateMachineIp(); StringBuilder command = new StringBuilder(); command.append("tail -n").append(pageSize).append(" ").append(logPath); try { return SSHUtil.execute(host, command.toString()); } catch (SSHException e) { log.error(e.getMessage(), e); return ""; } } @Override public String showDataMigrateConf(long id) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return ""; } String configPath = appDataMigrateStatus.getConfigPath(); String host = appDataMigrateStatus.getMigrateMachineIp(); String command = "cat " + configPath; try { return SSHUtil.execute(host, command); } catch (SSHException e) { log.error(e.getMessage(), e); return ""; } } @Override public Map> showMiragteToolProcess(long id) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return Collections.emptyMap(); } String info = ""; String host = appDataMigrateStatus.getMigrateMachineIp(); int port = appDataMigrateStatus.getMigrateMachinePort(); Jedis jedis = null; try { jedis = new Jedis(host, port, 5000); info = jedis.info(); } catch (Exception e) { log.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } if (StringUtils.isBlank(info)) { return Collections.emptyMap(); } return processRedisMigrateToolStats(info); } @Override public List search(AppDataMigrateSearch appDataMigrateSearch) { try { // List onMigrateIds = appDataMigrateStatusDao.getAllOnMigrateId(); // onMigrateIds.parallelStream().map(migrateId -> showDataMigrateLog(migrateId, 100)).collect(Collectors.toList()); return appDataMigrateStatusDao.search(appDataMigrateSearch); } catch (Exception e) { log.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public int getMigrateTaskCount(AppDataMigrateSearch appDataMigrateSearch) { try { return appDataMigrateStatusDao.getMigrateTaskCount(appDataMigrateSearch); } catch (Exception e) { log.error(e.getMessage(), e); return 0; } } /** * 处理迁移工具状态 * * @param statResult * @return */ private Map> processRedisMigrateToolStats(String statResult) { Map> redisStatMap = new HashMap>(); String[] data = statResult.split("\r\n"); String key; int i = 0; int length = data.length; while (i < length) { if (data[i].contains("#")) { int index = data[i].indexOf('#'); key = data[i].substring(index + 1); ++i; RedisMigrateToolConstant redisMigrateToolConstant = RedisMigrateToolConstant.value(key.trim()); if (redisMigrateToolConstant == null) { continue; } Map sectionMap = new LinkedHashMap(); while (i < length && data[i].contains(":")) { String[] pair = data[i].split(":"); sectionMap.put(pair[0], pair[1]); i++; } redisStatMap.put(redisMigrateToolConstant, sectionMap); } else { i++; } } return redisStatMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/AppDeployCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.constant.*; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.*; import com.sohu.cache.stats.app.AppDeployCenter; import com.sohu.cache.task.TaskService; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.AppEmailUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import redis.clients.jedis.HostAndPort; import java.util.*; /** * Created by yijunzhang on 14-10-20. */ @Service("appDeployCenter") public class AppDeployCenterImpl implements AppDeployCenter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private AppService appService; @Autowired private RedisDeployCenter redisDeployCenter; @Autowired private RedisCenter redisCenter; @Autowired private AppEmailUtil appEmailUtil; @Autowired private AppAuditDao appAuditDao; @Autowired private MachineCenter machineCenter; @Autowired private InstanceDao instanceDao; @Autowired private AppAuditLogDao appAuditLogDao; @Autowired private AppDao appDao; @Autowired private InstanceReshardProcessDao instanceReshardProcessDao; @Autowired private ResourceDao resourceDao; @Autowired private TaskService taskService; @Autowired private RedisConfigTemplateService redisConfigTemplateService; @Override public boolean createApp(AppDesc appDesc, AppUser appUser, String memSize) { try { appService.save(appDesc); // 保存应用和用户的关系 String officers = appDesc.getOfficer(); if (!StringUtils.isEmpty(officers)) { for (String officerId : officers.split(",")) { if (!StringUtils.isEmpty(officerId)) { appService.saveAppToUser(appDesc.getAppId(), Long.parseLong(officerId)); } } } // 更新appKey long appId = appDesc.getAppId(); appService.updateAppKey(appId); //处理memSize memSize = memSize.replaceAll("\\s*", ""); memSize += "G"; // 保存应用审批信息 AppAudit appAudit = new AppAudit(); appAudit.setAppId(appId); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setCreateTime(new Date()); appAudit.setModifyTime(new Date()); appAudit.setParam1(memSize); appAudit.setParam2(appDesc.getTypeDesc()); appAudit.setInfo("类型:" + appDesc.getTypeDesc() + ";初始申请空间:" + memSize); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(AppAuditType.APP_AUDIT.getValue()); appAuditDao.insertAppAudit(appAudit); // 发邮件 appEmailUtil.noticeAppResult(appDesc, appAudit); // 保存申请日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_DESC_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } public DataFormatCheckResult checkAppDeployDetail4Api(AppInfoApi appInfoApi, String appDeployText, com.sohu.cache.entity.RedisVersion redisVersion) { if (StringUtils.isBlank(appDeployText)) { logger.error("appDeployText is null"); return DataFormatCheckResult.fail("部署节点列表不能为空!"); } String[] nodeInfoList = appDeployText.split(ConstUtils.NEXT_LINE); if (nodeInfoList == null || nodeInfoList.length == 0) { logger.error("nodeInfoList is null"); return DataFormatCheckResult.fail("部署节点列表不能为空!"); } int type = appInfoApi.getType(); //检查每一行 for (String nodeInfo : nodeInfoList) { nodeInfo = StringUtils.trim(nodeInfo); if (StringUtils.isBlank(nodeInfo)) { return DataFormatCheckResult.fail(String.format("部署列表%s中存在空行!", appDeployText)); } String[] array = nodeInfo.split(ConstUtils.COLON); if (array == null || array.length == 0) { return DataFormatCheckResult.fail(String.format("部署列表%s中存在空行!", appDeployText)); } String masterHost = null; String memSize = null; String slaveHost = null; if (TypeUtil.isRedisCluster(type)) { if (array.length == 2) { masterHost = array[0]; memSize = array[1]; } else if (array.length == 3) { masterHost = array[0]; memSize = array[1]; slaveHost = array[2]; } else { return DataFormatCheckResult.fail(String.format("部署列表中%s,格式错误!", nodeInfo)); } } else if (TypeUtil.isRedisSentinel(type)) { if (array.length == 3) { masterHost = array[0]; memSize = array[1]; slaveHost = array[2]; } else if (array.length == 1) { masterHost = array[0]; } else { return DataFormatCheckResult.fail(String.format("部署列表中%s,格式错误!", nodeInfo)); } } else if (TypeUtil.isRedisStandalone(type)) { if (array.length == 2) { masterHost = array[0]; memSize = array[1]; } else { return DataFormatCheckResult.fail(String.format("部署列表中%s,格式错误!", nodeInfo)); } } if (!checkHostExist(masterHost)) { return DataFormatCheckResult.fail(String.format("%s中的ip=%s不存在,请在机器管理中添加!", nodeInfo, masterHost)); } if (StringUtils.isNotBlank(memSize) && !NumberUtils.isDigits(memSize)) { return DataFormatCheckResult.fail(String.format("%s中的中的memSize=%s不是整数!", nodeInfo, memSize)); } if (StringUtils.isNotBlank(slaveHost) && !checkHostExist(slaveHost)) { return DataFormatCheckResult.fail(String.format("%s中的ip=%s不存在,请在机器管理中添加!", nodeInfo, slaveHost)); } // 20180828 检查机器的redis版本是否安装 if (redisVersion == null) { return DataFormatCheckResult.fail(String.format("redis版本不存在,请添加正确Redis版本!")); } } //检查sentinel类型:数据节点一行,sentinel节点多行 if (TypeUtil.isRedisSentinel(type)) { return checkSentinelAppDeploy(nodeInfoList); //检查单点类型:只能有一行数据节点 } else if (TypeUtil.isRedisStandalone(type)) { return checkStandaloneAppDeploy(nodeInfoList); } return DataFormatCheckResult.success("应用部署格式正确,可以开始部署了!"); } /** * 检查单点格式 * * @param nodeInfoList * @return */ private DataFormatCheckResult checkStandaloneAppDeploy(String[] nodeInfoList) { int redisLineNum = 0; for (String nodeInfo : nodeInfoList) { nodeInfo = StringUtils.trim(nodeInfo); String[] array = nodeInfo.split(ConstUtils.COLON); if (array.length == 2) { redisLineNum++; } } // redis节点只有一行 if (redisLineNum != 1) { return DataFormatCheckResult.fail("应用部署格式错误, Standalone格式必须是一行masterIp:memSize(M)"); } return DataFormatCheckResult.success("应用部署格式正确,可以开始部署了!"); } /** * 检查redis sentinel格式 * * @param nodeInfoList * @return */ private DataFormatCheckResult checkSentinelAppDeploy(String[] nodeInfoList) { int redisLineNum = 0; int sentinelLineNum = 0; for (String nodeInfo : nodeInfoList) { nodeInfo = StringUtils.trim(nodeInfo); String[] array = nodeInfo.split(ConstUtils.COLON); if (array.length == 3) { redisLineNum++; } else if (array.length == 1) { sentinelLineNum++; } } // redis节点只有redisLineMustNum行 final int redisLineMustNum = 1; if (redisLineNum < redisLineMustNum) { return DataFormatCheckResult.fail("应用部署格式错误, Sentinel应用中必须有Redis数据节点!"); } else if (redisLineNum > redisLineMustNum) { return DataFormatCheckResult.fail("应用部署格式错误, Sentinel应用中Redis数据节点只能有一行!"); } // sentinel节点至少有sentinelLessNum个 final int sentinelLessNum = 3; if (sentinelLineNum < sentinelLessNum) { return DataFormatCheckResult.fail("应用部署格式错误, Sentinel应用中Sentinel节点至少要有" + sentinelLessNum + "个!"); } return DataFormatCheckResult.success("应用部署格式正确,可以开始部署了!"); } /** * 查看host是否存在 * * @param host * @return */ private boolean checkHostExist(String host) { try { MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host); if (machineInfo == null) { return false; } if (machineInfo.isOffline()) { logger.warn("host {} is offline", host); return false; } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } return true; } @Override public boolean allocateResourceApp(Long appAuditId, List nodeInfoList, AppUser auditUser) { if (appAuditId == null || appAuditId <= 0L) { logger.error("appAuditId is null"); return false; } if (nodeInfoList == null || nodeInfoList.isEmpty()) { logger.error("nodeInfoList is null"); return false; } AppAudit appAudit = appAuditDao.getAppAudit(appAuditId); if (appAudit == null) { logger.error("appAudit:id={} is not exist", appAuditId); return false; } long appId = appAudit.getAppId(); AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { logger.error("appDesc:id={} is not exist", appId); return false; } int type = appDesc.getType(); List nodes = new ArrayList(); for (String nodeInfo : nodeInfoList) { nodeInfo = StringUtils.trim(nodeInfo); if (StringUtils.isBlank(nodeInfo)) { continue; } String[] array = nodeInfo.split(":"); nodes.add(array); } boolean isAudited = false; if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisCluster(type)) { isAudited = deployCluster(appId, nodes); } else if (nodes.size() > 0) { if (TypeUtil.isRedisSentinel(type)) { isAudited = deploySentinel(appId, nodes); } else { isAudited = deployStandalone(appId, nodes.get(0)); } } else { logger.error("nodeInfoList={} is error", nodeInfoList); } } else { logger.error("unknown type : {}", type); return false; } //审核通过 if (isAudited) { // 改变审核状态 appAuditDao.updateAppAudit(appAudit.getId(), AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return true; } @Override public long offLineApp(Long appId, AppUser userInfo, Long auditId) { Assert.isTrue(appId != null && appId > 0L); return taskService.addOffLineAppTask(appId, auditId, 0, userInfo); } @Override public boolean modifyAppConfig(Long appId, Long appAuditId, String key, String value) { Assert.isTrue(appId != null && appId > 0L); Assert.isTrue(appAuditId != null && appAuditId > 0L); Assert.isTrue(StringUtils.isNotBlank(key)); Assert.isTrue(StringUtils.isNotBlank(value)); boolean isModify = redisDeployCenter.modifyAppConfig(appId, key, value); if (isModify) { // 改变审核状态 appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return isModify; } private boolean deploySentinel(long appId, List nodes) { //数据节点 String[] dataNodeInfo = nodes.get(0); String master = dataNodeInfo[0]; int memory = NumberUtils.createInteger(dataNodeInfo[1]); String slave = dataNodeInfo[2]; // sentinel节点 List sentinelList = new ArrayList(); if (nodes.size() < 2) { logger.error("sentinelList is none,don't generate sentinel app!"); return false; } // sentinel节点 for (int i = 1; i < nodes.size(); i++) { String[] nodeInfo = nodes.get(i); if (nodeInfo.length == 0 || StringUtils.isBlank(nodeInfo[0])) { logger.error("sentinel line {} may be empty", i); return false; } sentinelList.add(nodeInfo[0]); } return redisDeployCenter.deploySentinelInstance(appId, master, slave, memory, sentinelList); } private boolean deployCluster(long appId, List nodes) { List clusterNodes = new ArrayList(); int maxMemory = 0; for (String[] array : nodes) { String master = array[0]; int memory = NumberUtils.createInteger(array[1]); String slave = null; if (array.length > 2) { slave = array[2]; } RedisClusterNode node = new RedisClusterNode(master, slave); maxMemory = memory; clusterNodes.add(node); } return redisDeployCenter.deployClusterInstance(appId, clusterNodes, maxMemory); } private boolean deployStandalone(long appId, String[] nodeInfo) { String host = nodeInfo[0]; int memory = NumberUtils.createInteger(nodeInfo[1]); return redisDeployCenter.deployStandaloneInstance(appId, host, memory); } @Override public boolean verticalExpansion(Long appId, Long appAuditId, long operateId, final int memory) { Assert.isTrue(appId != null && appId > 0L); Assert.isTrue(appAuditId != null && appAuditId > 0L); Assert.isTrue(memory > 0); AppDesc appDesc = appService.getByAppId(appId); Assert.isTrue(appDesc != null); int type = appDesc.getType(); if (!TypeUtil.isRedisType(type)) { logger.error("appId={};type={} is not redis!", appDesc, type); return false; } List instanceInfos = instanceDao.getInstListByAppId(appId); if (instanceInfos == null || instanceInfos.isEmpty()) { logger.error("instanceInfos is null"); return false; } for (InstanceInfo instanceInfo : instanceInfos) { int instanceType = instanceInfo.getType(); if (TypeUtil.isRedisSentinel(instanceType)) { continue; } // 下线实例不做操作 if (instanceInfo.isOffline()) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); final long maxMemoryBytes = Long.valueOf(memory) * 1024 * 1024; boolean isConfig = redisDeployCenter.modifyInstanceConfig(appId, host, port, "maxmemory", String.valueOf(maxMemoryBytes)); if (!isConfig) { logger.error("{}:{} set maxMemory error", host, port); return false; } //更新instanceInfo配置 instanceInfo.setMem(memory); instanceDao.update(instanceInfo); } // 改变审核状态 appAuditDao.updateAppAuditUser(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value(), operateId); return true; } @Override public boolean addHorizontalNodes(Long appId, String masterHost, String slaveHost, int memory) { AppDesc appDesc = appDao.getAppDescById(appId); //1. 寻找主从节点的可用端口 Integer masterPort = machineCenter.getAvailablePort(masterHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); if (masterPort == null) { logger.error("master host={} getAvailablePort is null", masterHost); return false; } Integer slavePort = 0; boolean hasSlave = StringUtils.isNotBlank(slaveHost); if (hasSlave) { slavePort = machineCenter.getAvailablePort(slaveHost, ConstUtils.CACHE_TYPE_REDIS_CLUSTER); if (slavePort == null) { logger.error("slave host={} getAvailablePort is null", slaveHost); return false; } } //2. 启动主从节点 boolean isMasterCreate = redisDeployCenter.createRunNode(appDesc, masterHost, masterPort, memory, true); if (!isMasterCreate) { logger.error("createRunNode master failed {}:{}", masterHost, masterPort); return false; } if (hasSlave) { //运行节点 boolean isSlaveCreate = redisDeployCenter.createRunNode(appDesc, slaveHost, slavePort, memory, true); if (!isSlaveCreate) { logger.error("createRunNode slave failed {}:{}", slaveHost, slavePort); return false; } } //3. 获取应用下有效节点 Set clusterHosts = getEffectiveInstanceList(appId); //4. 添加新节点: meet,复制,不做slot分配 // RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao); RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao, appDao, resourceDao); boolean joinCluster = clusterReshard.joinCluster(appId, masterHost, masterPort, slaveHost, slavePort); if (joinCluster) { //5. 保存实例,开启统计功能 saveInstance(appId, masterHost, masterPort, memory); if (hasSlave) { saveInstance(appId, slaveHost, slavePort, memory); } } return joinCluster; } @Override public boolean cleanAppData(long appId, AppUser appUser) { try { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return false; } if (TypeUtil.isRedisType(appDesc.getType())) { return redisCenter.cleanAppData(appDesc, appUser); } else { return false; } } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } /** * @param appId * @param appAuditId * @param startSlot * @param endSlot * @return */ private boolean isInProcess(Long appId, long appAuditId, int startSlot, int endSlot) { return false; } private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory) { InstanceInfo instanceInfo = new InstanceInfo(); instanceInfo.setAppId(appId); MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host); instanceInfo.setHostId(machineInfo.getId()); instanceInfo.setConn(0); instanceInfo.setMem(maxMemory); instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceInfo.setPort(port); instanceInfo.setType(ConstUtils.CACHE_TYPE_REDIS_CLUSTER); instanceInfo.setCmd(""); instanceInfo.setIp(host); instanceDao.saveInstance(instanceInfo); return instanceInfo; } @Override public HorizontalResult checkHorizontal(long appId, long appAuditId, long sourceId, long targetId, int startSlot, int endSlot, int migrateType) { boolean isInProcess = isInProcess(appId, appAuditId, startSlot, endSlot); if (isInProcess) { return HorizontalResult.fail(String.format("appId=%s %s:%s正在迁移!", appId, startSlot, endSlot)); } // 1.应用信息 AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { return HorizontalResult.fail("应用信息为空"); } // 2.0 源实例ID不能等于目标实例ID if (sourceId == targetId) { return HorizontalResult.fail(String.format("源实例ID=%s不能等于目标实例ID=%s", sourceId, targetId)); } // 2.1 源实例信息 InstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(sourceId); if (sourceInstanceInfo == null) { return HorizontalResult.fail(String.format("源实例id=%s为空", sourceId)); } // 2.2 对比源实例的appId是否正确 long sourceAppId = sourceInstanceInfo.getAppId(); if (sourceAppId != appId) { return HorizontalResult.fail(String.format("源实例id=%s不属于appId=%s", sourceId, appId)); } // 2.3 源实例是否在线 boolean sourceIsRun = redisCenter.isRun(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort()); if (!sourceIsRun) { return HorizontalResult.fail(String.format("源实例%s必须运行中", sourceInstanceInfo.getHostPort())); } // 2.4必须是master节点 BooleanEnum sourceIsMaster = redisCenter.isMaster(appId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort()); if (sourceIsMaster != BooleanEnum.TRUE) { return HorizontalResult.fail(String.format("源实例%s必须是主节点", sourceInstanceInfo.getHostPort())); } // 3.1 目标实例信息 InstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(targetId); if (targetInstanceInfo == null) { return HorizontalResult.fail(String.format("目标实例id=%s为空", targetId)); } // 3.2 对比目标实例的appId是否正确 long targetAppId = targetInstanceInfo.getAppId(); if (targetAppId != appId) { return HorizontalResult.fail(String.format("目标实例id=%s不属于appId=%s", targetId, appId)); } // 3.3 目标实例是否在线 boolean targetIsRun = redisCenter.isRun(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort()); if (!targetIsRun) { return HorizontalResult.fail(String.format("目标实例%s必须运行中", targetInstanceInfo.getHostPort())); } // 3.4 必须是master节点 BooleanEnum targetIsMaster = redisCenter.isMaster(appId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort()); if (targetIsMaster != BooleanEnum.TRUE) { return HorizontalResult.fail(String.format("目标实例%s必须是主节点", targetInstanceInfo.getHostPort())); } // 4.startSlot和endSlot是否在源实例中 // 4.1 判断数值 int maxSlot = 16383; if (startSlot < 0 || startSlot > maxSlot) { return HorizontalResult.fail(String.format("startSlot=%s必须在0-%s", startSlot, maxSlot)); } if (endSlot < 0 || endSlot > maxSlot) { return HorizontalResult.fail(String.format("endSlot=%s必须在0-%s", endSlot, maxSlot)); } if (startSlot > endSlot) { return HorizontalResult.fail("startSlot不能大于endSlot"); } // 4.2 判断startSlot和endSlot属于sourceId // 获取所有slot分布 Map clusterSlotsMap = redisCenter.getClusterSlotsMap(appId); if (MapUtils.isEmpty(clusterSlotsMap)) { return HorizontalResult.fail("无法获取slot分布!"); } // 获取源实例负责的slot String sourceHostPort = sourceInstanceInfo.getHostPort(); InstanceSlotModel instanceSlotModel = clusterSlotsMap.get(sourceHostPort); if (instanceSlotModel == null || CollectionUtils.isEmpty(instanceSlotModel.getSlotList())) { return HorizontalResult.fail("源实例上没有slot!"); } List slotList = instanceSlotModel.getSlotList(); for (int i = startSlot; i <= endSlot; i++) { if (!slotList.contains(i)) { return HorizontalResult.fail(String.format("源实例没有包含尽startSlot=%s到endSlot=%s", startSlot, endSlot)); } } //5.是否支持批量,版本要大于等于3.0.6 String sourceRedisVersion = redisCenter.getRedisVersion(sourceAppId, sourceInstanceInfo.getIp(), sourceInstanceInfo.getPort()); if (StringUtils.isBlank(sourceRedisVersion)) { return HorizontalResult.fail(String.format("源实例%s版本为空", sourceInstanceInfo.getHostPort())); } String targetRedisVersion = redisCenter.getRedisVersion(targetAppId, targetInstanceInfo.getIp(), targetInstanceInfo.getPort()); if (StringUtils.isBlank(targetRedisVersion)) { return HorizontalResult.fail(String.format("目标实例%s版本为空", targetInstanceInfo.getHostPort())); } RedisVersion sourceRedisVersionModel = getRedisVersion(sourceRedisVersion); //选择了批量,但是当前版本不支持pipeline if (migrateType == 1 && !sourceRedisVersionModel.isSupportPipelineMigrate()) { return HorizontalResult.fail(String.format("源实例%s版本为%s,不支持pipeline migrate!", sourceInstanceInfo.getHostPort(), sourceRedisVersion)); } RedisVersion targetRedisVersionModel = getRedisVersion(targetRedisVersion); //选择了批量,但是当前版本不支持pipeline if (migrateType == 1 && !targetRedisVersionModel.isSupportPipelineMigrate()) { return HorizontalResult.fail(String.format("目标实例%s版本为%s,不支持pipeline migrate!", targetInstanceInfo.getHostPort(), targetRedisVersion)); } return HorizontalResult.checkSuccess(); } private RedisVersion getRedisVersion(String redisVersion) { String[] versionArr = redisVersion.split("\\."); if (versionArr.length == 1) { return new RedisVersion(NumberUtils.toInt(versionArr[0]), 0, 0); } else if (versionArr.length == 2) { return new RedisVersion(NumberUtils.toInt(versionArr[0]), NumberUtils.toInt(versionArr[1]), 0); } else if (versionArr.length >= 3) { return new RedisVersion(NumberUtils.toInt(versionArr[0]), NumberUtils.toInt(versionArr[1]), NumberUtils.toInt(versionArr[2])); } return null; } /** * 获取应用下有效节点 * * @param appId * @return */ private Set getEffectiveInstanceList(long appId) { Set clusterHosts = new HashSet(); //全部节点 List instanceInfos = instanceDao.getInstListByAppId(appId); for (InstanceInfo instance : instanceInfos) { if (instance.isOffline()) { continue; } clusterHosts.add(new HostAndPort(instance.getIp(), instance.getPort())); } return clusterHosts; } @Override public HorizontalResult startHorizontal(final long appId, final long appAuditId, long sourceId, final long targetId, final int startSlot, final int endSlot, final int migrateType) { InstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(sourceId); InstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(targetId); InstanceReshardProcess instanceReshardProcess = saveInstanceReshardProcess(appId, appAuditId, sourceInstanceInfo, targetInstanceInfo, startSlot, endSlot, PipelineEnum.getPipelineEnum(migrateType)); instanceReshardProcess.setSourceInstanceInfo(sourceInstanceInfo); instanceReshardProcess.setTargetInstanceInfo(targetInstanceInfo); startMigrateSlot(instanceReshardProcess); logger.warn("start reshard appId={} instance={}:{} deploy done", instanceReshardProcess.getAppId(), targetInstanceInfo.getIp(), targetInstanceInfo.getPort()); return HorizontalResult.scaleSuccess(); } @Override public HorizontalResult retryHorizontal(final int instanceReshardProcessId) { InstanceReshardProcess instanceReshardProcess = instanceReshardProcessDao.get(instanceReshardProcessId); instanceReshardProcess.setStatus(ReshardStatusEnum.RUNNING.getValue()); instanceReshardProcessDao.updateStatus(instanceReshardProcess.getId(), ReshardStatusEnum.RUNNING.getValue()); InstanceInfo sourceInstanceInfo = instanceDao.getInstanceInfoById(instanceReshardProcess.getSourceInstanceId()); InstanceInfo targetInstanceInfo = instanceDao.getInstanceInfoById(instanceReshardProcess.getTargetInstanceId()); instanceReshardProcess.setSourceInstanceInfo(sourceInstanceInfo); instanceReshardProcess.setTargetInstanceInfo(targetInstanceInfo); startMigrateSlot(instanceReshardProcess); logger.warn("retry reshard appId={} instance={}:{} deploy done", instanceReshardProcess.getAppId(), targetInstanceInfo.getIp(), targetInstanceInfo.getPort()); return HorizontalResult.scaleSuccess(); } private void startMigrateSlot(final InstanceReshardProcess instanceReshardProcess) { final long appId = instanceReshardProcess.getAppId(); final long appAuditId = instanceReshardProcess.getAuditId(); final InstanceInfo targetInstanceInfo = instanceReshardProcess.getTargetInstanceInfo(); AsyncThreadPoolFactory.RESHARD_PROCESS_THREAD_POOL.execute(new Runnable() { @Override public void run() { //所有节点用户clustersetslot Set clusterHosts = getEffectiveInstanceList(appId); // RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao); RedisClusterReshard clusterReshard = new RedisClusterReshard(clusterHosts, redisCenter, instanceReshardProcessDao, appDao, resourceDao); //添加进度 boolean joinCluster = clusterReshard.migrateSlot(instanceReshardProcess); if (joinCluster) { // 改变审核状态 appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); if (targetInstanceInfo != null && targetInstanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { targetInstanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceDao.update(targetInstanceInfo); } } } }); } /** * 保存进度 * * @param appId * @param appAuditId * @param sourceInstanceInfo * @param targetInstanceInfo * @param startSlot * @param endSlot * @return */ private InstanceReshardProcess saveInstanceReshardProcess(long appId, long appAuditId, InstanceInfo sourceInstanceInfo, InstanceInfo targetInstanceInfo, int startSlot, int endSlot, PipelineEnum pipelineEnum) { Date now = new Date(); InstanceReshardProcess instanceReshardProcess = new InstanceReshardProcess(); instanceReshardProcess.setAppId(appId); instanceReshardProcess.setAuditId(appAuditId); instanceReshardProcess.setFinishSlotNum(0); instanceReshardProcess.setIsPipeline(pipelineEnum.getValue()); instanceReshardProcess.setSourceInstanceId(sourceInstanceInfo.getId()); instanceReshardProcess.setTargetInstanceId(targetInstanceInfo.getId()); instanceReshardProcess.setMigratingSlot(startSlot); instanceReshardProcess.setStartSlot(startSlot); instanceReshardProcess.setEndSlot(endSlot); instanceReshardProcess.setStatus(ReshardStatusEnum.RUNNING.getValue()); instanceReshardProcess.setStartTime(now); //用status控制显示结束时间 instanceReshardProcess.setEndTime(now); instanceReshardProcess.setCreateTime(now); instanceReshardProcess.setUpdateTime(now); instanceReshardProcessDao.save(instanceReshardProcess); return instanceReshardProcess; } @Override public DataFormatCheckResult checkHorizontalNodes(Long appAuditId, String masterSizeSlave) { if (appAuditId == null) { logger.error("appAuditId is null"); return DataFormatCheckResult.fail("审核id不能为空!"); } if (StringUtils.isBlank(masterSizeSlave)) { logger.error("masterSizeSlave is null"); return DataFormatCheckResult.fail("添加节点不能为空!"); } AppAudit appAudit = appAuditDao.getAppAudit(appAuditId); if (appAudit == null) { logger.error("appAudit:id={} is not exist", appAuditId); return DataFormatCheckResult.fail(String.format("审核id=%s不存在", appAuditId)); } long appId = appAudit.getAppId(); AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { logger.error("appDesc:id={} is not exist"); return DataFormatCheckResult.fail(String.format("appId=%s不存在", appId)); } // 多个节点 String[] nodes = masterSizeSlave.split(ConstUtils.NEXT_LINE); for (String node : nodes) { if (!StringUtils.isEmpty(node.trim())) { //节点数组 master:memSize:slave String[] array = node.trim().split(ConstUtils.COLON); if (array == null || array.length == 0) { return DataFormatCheckResult.fail(String.format("添加节点%s格式错误", masterSizeSlave)); } //检查格式 String masterHost; String memSize; String slaveHost = null; if (array.length == 2) { masterHost = array[0]; memSize = array[1]; } else if (array.length == 3) { masterHost = array[0]; memSize = array[1]; slaveHost = array[2]; } else { return DataFormatCheckResult.fail(String.format("添加节点%s, 格式错误!", masterSizeSlave)); } //检查主节点机器是否存在 if (!checkHostExist(masterHost)) { return DataFormatCheckResult.fail(String.format("%s中的ip=%s不存在,请在机器管理中添加!", masterSizeSlave, masterHost)); } //检查memSize格式 if (StringUtils.isNotBlank(memSize) && !NumberUtils.isDigits(memSize)) { return DataFormatCheckResult.fail(String.format("%s中的中的memSize=%s不是整数!", masterSizeSlave, memSize)); } //检查从节点格式 if (StringUtils.isNotBlank(slaveHost) && !checkHostExist(slaveHost)) { return DataFormatCheckResult.fail(String.format("%s中的ip=%s不存在,请在机器管理中添加!", masterSizeSlave, slaveHost)); } } } return DataFormatCheckResult.success("添加节点格式正确,可以开始部署了!"); } @Override public List getHorizontalProcess(long auditId) { try { return instanceReshardProcessDao.getByAuditId(auditId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } private static class RedisVersion { int majorVersion; int minorVersion; int patchVersion; public RedisVersion(int majorVersion, int minorVersion, int patchVersion) { super(); this.majorVersion = majorVersion; this.minorVersion = minorVersion; this.patchVersion = patchVersion; } /** * 大于等于3.0.6 * * @return */ public boolean isSupportPipelineMigrate() { if (majorVersion < 3) { return false; } else if (majorVersion == 3) { if (minorVersion > 0) { return true; } else { return patchVersion >= 6; } } else { return true; } } @Override public String toString() { return "RedisVersion [majorVersion=" + majorVersion + ", minorVersion=" + minorVersion + ", patchVersion=" + patchVersion + "]"; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/AppPersistenceCheckCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.constant.AppDescEnum; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.stats.app.AppPersistenceCheckCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.AppService; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** * Description: 应用持久化配置检查修正 * @author zengyizhao * @version 1.0 * @date 2022/11/3 */ @Slf4j @Service("appPersistenceCheckCenter") public class AppPersistenceCheckCenterImpl implements AppPersistenceCheckCenter { @Autowired private AppService appService; @Autowired private EmailComponent emailComponent; @Override public void checkAndFixAppPersistence() { List appDescList = appService.getAllAppDesc(); List onlineAppDescs = appDescList.stream() .filter(appDesc -> AppStatusEnum.STATUS_PUBLISHED.getStatus() == appDesc.getStatus() && appDesc.getPersistenceType() != AppDescEnum.AppPersistenceType.GENERAL.getValue()) .collect(Collectors.toList()); onlineAppDescs.forEach(appDesc -> { String failMessage = appService.checkAppPersistenceConfigAndFix(appDesc.getAppId(), getCurAppPersistenceMaps().get(0).getPersistenceMap().get(Integer.valueOf(appDesc.getPersistenceType())), getCurAppPersistenceMaps().get(1).getPersistenceMap().get(Integer.valueOf(appDesc.getPersistenceType()))); if(StringUtils.isNotEmpty(failMessage)){ log.error("checkAndFixAppPersistence job fail: {}", failMessage); emailComponent.sendMailToAdmin("【CacheCloud】持久化报警", this.generateAlertInfo(appDesc, failMessage)); } }); } private String generateAlertInfo(AppDesc appDesc, String failMessage){ return String.format("应用id:%s 应用名:%s 应用环境:%s 应用类型:%s 持久化类型:%s
持久化检测报警:%s
请及时关注。", appDesc.getAppId(), appDesc.getName(), (appDesc.getIsTest() == 0 ? "测试" : "正式"), appDesc.getTypeDesc(), AppDescEnum.AppPersistenceType.getByType(appDesc.getPersistenceType()).getInfo(), failMessage); } @Data @AllArgsConstructor @NoArgsConstructor class AppPersistenceTypeMap { private Boolean isMaster; private Map> persistenceMap; } public List getCurAppPersistenceMaps(){ List appPersistenceMaps = new ArrayList<>(); String configStr = ConstUtils.APP_PERSISTENCE_CONFIG_MAP; JSONArray objects = JSON.parseArray(configStr); JSONObject jsonObject = objects.getJSONObject(0); AppPersistenceTypeMap curPersistenceMap = getCurPersistenceMap(jsonObject); appPersistenceMaps.add(curPersistenceMap); jsonObject = objects.getJSONObject(1); curPersistenceMap = getCurPersistenceMap(jsonObject); if(curPersistenceMap.isMaster){ appPersistenceMaps.add(0, curPersistenceMap); }else{ appPersistenceMaps.add(curPersistenceMap); } return appPersistenceMaps; } private AppPersistenceTypeMap getCurPersistenceMap(JSONObject jsonObject){ Map> persistenceMap = new HashMap<>(); Set keySet = jsonObject.keySet(); boolean isMaster = jsonObject.getBoolean("isMaster"); JSONObject persistenceJson = jsonObject.getJSONObject("persistenceMap"); Set persisTypeSet = persistenceJson.keySet(); persisTypeSet.forEach(persisType -> { Map configMap = persistenceJson.getObject(persisType, Map.class); persistenceMap.put(Integer.valueOf(persisType), configMap); } ); return new AppPersistenceTypeMap(isMaster, persistenceMap); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/AppStatsCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Maps; import com.sohu.cache.constant.AppTopology; import com.sohu.cache.constant.TimeDimensionalityEnum; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.PandectUtil; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.MachineMemoryDistriEnum; import com.sohu.cache.web.enums.StatEnum; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang.StringUtils; import org.assertj.core.util.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import java.text.DecimalFormat; import java.util.*; import java.util.stream.Collectors; /** * 基于app的统计信息的接口:包括app详情、app配置以及基于app的统计 * * @author leifu * @Date 2015年3月2日 * @Time 下午1:50:09 */ @Service("appStatsCenter") public class AppStatsCenterImpl implements AppStatsCenter { private final static String COLLECT_DATE_FORMAT = "yyyyMMddHHmm"; private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private AppDao appDao; @Autowired private InstanceDao instanceDao; @Autowired private MachineDao machineDao; @Autowired private AppStatsDao appStatsDao; @Autowired private InstanceLatencyHistoryDao instanceLatencyHistoryDao; @Autowired private InstanceSlowLogDao instanceSlowLogDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired @Lazy private RedisCenter redisCenter; @Autowired private UserService userService; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private ResourceDao resourceDao; @Autowired private AppDailyDao appDailyDao; @Override public List getAppStatsListByMinuteTime(long appId, long beginTime, long endTime) { Assert.isTrue(appId > 0); Assert.isTrue(beginTime > 0 && endTime > 0); List appStatsList = null; try { appStatsList = appStatsDao.getAppStatsList(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT)); } catch (Exception e) { logger.error(e.getMessage(), e); } return appStatsList; } /** * 通过时间区间查询app的分钟统计数据 * * @param appId * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ @Override public List getAppStatsList(final long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum) { Assert.isTrue(appId > 0); Assert.isTrue(beginTime > 0 && endTime > 0); List appStatsList = null; try { if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) { appStatsList = appStatsDao.getAppStatsByMinute(appId, beginTime, endTime); } else if (TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) { appStatsList = appStatsDao.getAppStatsByHour(appId, beginTime, endTime); } } catch (Exception e) { logger.error(e.getMessage(), e); } return appStatsList; } /** * 通过时间区间查询app的每日日报数据 * * @param appId * @param beginDate 时间,格式:yyyyMMdd * @param endDate 时间,格式:yyyyMMdd * @return */ @Override public List getAppHitRatioList(final long appId, long beginDate, long endDate) { Assert.isTrue(appId > 0); Assert.isTrue(beginDate > 0 && endDate > 0); List appStatsList = null; try { appStatsList = appDailyDao.getAppDailyList(appId, beginDate, endDate); } catch (Exception e) { logger.error(e.getMessage(), e); } return appStatsList; } /** * 按照分钟查询应用历史最大使用内存,时间跨度不可过大,会有性能问题 * @param appId * @param beginTime * @param endTime * @return */ @Override public Long getUsedMemoryMaxByTimeBetween(final long appId, long beginTime, long endTime){ return appStatsDao.getUsedMemoryMaxByTimeBetween(appId, beginTime, endTime); } /** * 通过时间区间查询一条app的分钟统计数据 * * @param appId * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ @Override public AppStats getOneAppStats(final long appId, long beginTime, long endTime) { Assert.isTrue(appId > 0); Assert.isTrue(beginTime > 0 && endTime > 0); AppStats appStats = appStatsDao.getOneAppStatsByMinute(appId, beginTime, endTime); return appStats; } @Override public List getTop5AppCommandStatsList(final long appId, long begin, long end) { Assert.isTrue(appId > 0); Assert.isTrue(begin > 0L); Assert.isTrue(end > 0L); List topAppCmdList = null; try { topAppCmdList = appStatsDao.getTopAppCommandGroupSum(appId, new TimeDimensionality(begin, end, COLLECT_DATE_FORMAT), 5); } catch (Exception e) { logger.error(e.getMessage(), e); } return topAppCmdList; } @Override public List getTopLimitAppCommandStatsList(long appId, long begin, long end, int limit) { Assert.isTrue(appId > 0); Assert.isTrue(begin > 0L); Assert.isTrue(end > 0L); List topAppCmdList = null; try { topAppCmdList = appStatsDao.getTopAppCommandStatsList(appId, new TimeDimensionality(begin, end, COLLECT_DATE_FORMAT), limit); } catch (Exception e) { logger.error(e.getMessage(), e); } return topAppCmdList; } /** * 查询应用的配置和节点信息 * * @param appId * @return */ @Override public Map queryAppTopology(final long appId) { Assert.isTrue(appId > 0); Map appTopologyMap = new HashMap(); AppDesc appDesc = null; double totalMemory = 0.0; Set machineSet = new HashSet(); int masterCount = 0; int slaveCount = 0; List instanceInfoList = null; try { appDesc = appDao.getAppDescById(appId); instanceInfoList = instanceDao.getInstListByAppId(appId); if (appDesc == null || instanceInfoList == null || instanceInfoList.isEmpty()) { logger.error("get app and it's instances error, appId = {}", appId); return null; } if (appDesc.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { for (InstanceInfo instance : instanceInfoList) { machineSet.add(instance.getHostId()); totalMemory += instance.getMem(); BooleanEnum isMaster = redisCenter.isMaster(appId, instance.getIp(), instance.getPort()); if (isMaster == BooleanEnum.OTHER) { continue; } if (isMaster == BooleanEnum.TRUE) { masterCount++; } else { slaveCount++; } } } appTopologyMap.put(AppTopology.TOTAL_MEMORY, totalMemory / ConstUtils._1024); appTopologyMap.put(AppTopology.MACHINE_COUNT, machineSet.size()); appTopologyMap.put(AppTopology.MASTER_COUNT, masterCount); appTopologyMap.put(AppTopology.SLAVE_COUNT, slaveCount); } catch (Exception e) { logger.error(e.getMessage(), e); } return appTopologyMap; } /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @param commandName 命令名 * @return */ @Override public List getCommandStatsList(long appId, long beginTime, long endTime, String commandName) { return appStatsDao.getAppCommandStatsList(appId, commandName, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT)); } /** * 查询应用指定时间段,指定命令名的结果集合 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @return */ @Override public List getCommandStatsList(long appId, long beginTime, long endTime) { return appStatsDao.getAppAllCommandStatsList(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT)); } @Override public List getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum, String commandName) { if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) { return appStatsDao.getAppCommandStatsListByMinuteWithCommand(appId, beginTime, endTime, commandName); } else if (TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) { return appStatsDao.getAppCommandStatsListByHourWithCommand(appId, beginTime, endTime, commandName); } return Collections.emptyList(); } @Override public List getCommandStatsListV2(long appId, long beginTime, long endTime, TimeDimensionalityEnum timeDimensionalityEnum) { if (TimeDimensionalityEnum.MINUTE.equals(timeDimensionalityEnum)) { return appStatsDao.getAppAllCommandStatsListByMinute(appId, beginTime, endTime); } else if (TimeDimensionalityEnum.HOUR.equals(timeDimensionalityEnum)) { return appStatsDao.getAppAllCommandStatsListByHour(appId, beginTime, endTime); } return Collections.emptyList(); } /** * 查询应用指定命令的峰值 * * @param appId 应用id * @param beginTime 时间,格式:yyyyMMddHHmm * @param endTime 时间,格式:yyyyMMddHHmm * @param commandName 命令名 * @return */ @Override public AppCommandStats getCommandClimax(long appId, Long beginTime, Long endTime, String commandName) { TimeDimensionality td = new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT); AppCommandStats appCommandStats = appStatsDao.getCommandClimaxCount(appId, commandName, td); if (appCommandStats == null) { return null; } appCommandStats.setCommandName(commandName); AppCommandStats appCommandStatsTemp = appStatsDao.getCommandClimaxCreateTime(appId, commandName, appCommandStats.getCommandCount(), td); if (appCommandStatsTemp != null) { appCommandStats.setCreateTime(appCommandStatsTemp.getCreateTime()); } return appCommandStats; } /** * 获取应用命令调用次数分布 * * @param appId * @param beginTime * @param endTime * @return */ @Override public List getAppCommandGroup(long appId, Long beginTime, Long endTime) { return appStatsDao.getAppCommandGroup(appId, new TimeDimensionality(beginTime, endTime, COLLECT_DATE_FORMAT)); } /** * 获取应用命令调用次数分布 * * @param appId * @param beginTime * @param endTime * @return */ @Override public Long getAppCommandCount(long appId, long beginTime, long endTime) { Long count = appStatsDao.getAppCommandCount(appId, beginTime, endTime); return count == null ? 0L : count; } /** * 获取应用详细信息 */ @Override public AppDetailVO getAppDetail(long appId) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return null; } //1.获取Redis版本名称 SystemResource redisResource = resourceDao.getResourceById(appDesc.getVersionId()); if (redisResource != null) { appDesc.setVersionName(redisResource.getName()); //2.判断版本是否可以升级 List versionList = resourceDao.getResourceList(ResourceEnum.REDIS.getValue()); for (SystemResource version : versionList) { try { // 大版本同一版本且大于当前版本号 int versionTag = Integer.parseInt(version.getName().replaceAll("redis-","").replaceAll("\\.","")); int currentTag = Integer.parseInt(redisResource.getName().replaceAll("redis-","").replaceAll("\\.","")); // 支持小版本号升级 String versionStr = redisResource.getName().substring(0, redisResource.getName().lastIndexOf(".")); if (version.getName().indexOf(versionStr) > -1 && versionTag > currentTag) { appDesc.setIsVersionUpgrade(1); break; } } catch (Exception e) { logger.error("parse version:{} {} exception : {}", redisResource.getName(), version.getName(), e.getMessage(), e); appDesc.setIsVersionUpgrade(0); } } } else { appDesc.setIsVersionUpgrade(0); } AppDetailVO resultVO = new AppDetailVO(); resultVO.setAppDesc(appDesc); Set machines = new HashSet(); List instanceList = instanceDao.getInstListByAppId(appId); if (instanceList == null || instanceList.isEmpty()) { return resultVO; } long hits = 0L; long miss = 0L; long allUsedMemory = 0L; long allUsedDisk = 0L; long allMaxDisk = 0L; long allMaxMemory = 0L; double highestMemFragRatio = 0D; //碎片率最大值 long instId = 0L; //碎片率最大值的实例id List instanceStatsList = instanceStatsDao.getInstanceStatsByAppId(appId); if (instanceStatsList != null && instanceStatsList.size() > 0) { Map instanceStatMap = new HashMap(); for (InstanceStats stats : instanceStatsList) { instanceStatMap.put(stats.getInstId(), stats); } for (InstanceInfo instanceInfo : instanceList) { if (instanceInfo.isOffline()) { continue; } machines.add(instanceInfo.getIp()); InstanceStats instanceStats = instanceStatMap.get(Long.valueOf(instanceInfo.getId())); if (instanceStats == null) { continue; } boolean isMaster = isMaster(instanceStats); long usedMemory = instanceStats.getUsedMemory(); long usedMemoryMB = usedMemory / 1024 / 1024; long usedDisk = instanceStats.getUsedDisk(); long usedDiskMB = usedDisk / 1024 / 1024; allUsedDisk += usedDisk; allMaxDisk += instanceInfo.getMem() * 1024L * 1024; allUsedMemory += usedMemory; allMaxMemory += instanceStats.getMaxMemory(); hits += instanceStats.getHits(); miss += instanceStats.getMisses(); //碎片率最大值 double memFragRatio = instanceStats.getMemFragmentationRatio(); if (memFragRatio > highestMemFragRatio) { highestMemFragRatio = memFragRatio; instId = instanceStats.getInstId(); } if (isMaster) { resultVO.setMem(resultVO.getMem() + instanceInfo.getMem()); resultVO.setCurrentMem(resultVO.getCurrentMem() + usedMemoryMB); resultVO.setCurrentObjNum(resultVO.getCurrentObjNum() + instanceStats.getCurrItems()); resultVO.setMasterNum(resultVO.getMasterNum() + 1); resultVO.setCurrentDisk(resultVO.getCurrentDisk() + usedDiskMB); //按instanceStats计算conn resultVO.setConn(resultVO.getConn() + instanceStats.getCurrConnections()); } else { resultVO.setSlaveNum(resultVO.getSlaveNum() + 1); } } } // 授权用户 List userList = userService.getByAppId(appId); if (userList != null && userList.size() > 0) { resultVO.setAppUsers(userList); } // 报警用户 List alertUsedrList = userService.getAlertByAppId(appId); if (alertUsedrList != null && alertUsedrList.size() > 0) { resultVO.setAlertUsers(alertUsedrList); } resultVO.setMachineNum(machines.size()); if (allMaxMemory == 0L) { resultVO.setMemUsePercent(0.0D); } else { double percent = 100 * (double) allUsedMemory / (allMaxMemory); DecimalFormat df = new DecimalFormat("##.##"); resultVO.setMemUsePercent(Double.parseDouble(df.format(percent))); } if (allMaxDisk == 0L) { resultVO.setDiskUsePercent(0.0D); } else { double diskPercent = 100 * (double) allUsedDisk / (allMaxDisk); DecimalFormat df = new DecimalFormat("##.##"); resultVO.setDiskUsePercent(Double.parseDouble(df.format(diskPercent))); } //最大碎片率及对应实例Id resultVO.setHighestMemFragRatio(highestMemFragRatio); resultVO.setInstIdWithHighestMemFragRatio(instId); if (miss == 0L) { if (hits > 0) { resultVO.setHitPercent(100.0D); } else { resultVO.setHitPercent(0.0D); } } else { double percent = 100 * (double) hits / (hits + miss); DecimalFormat df = new DecimalFormat("##.##"); resultVO.setHitPercent(Double.parseDouble(df.format(percent))); } return resultVO; } @Override public Map getOnlineAppDetails() { List appDescList = appDao.getOnlineApps(); Map appDetailVOMap = appDescList.stream() .map(appDesc -> getAppDetail(appDesc.getAppId())) .collect(Collectors.toMap(appDetail -> appDetail.getAppDesc().getAppId(), appDetail -> appDetail)); return appDetailVOMap; } @Override public List getOnlineAppConnClients() { List result = new ArrayList<>(); List appDescList = appDao.getOnlineApps(); appDescList.forEach(appDesc -> { AppClientStatisticGather gather = new AppClientStatisticGather(); long appId = appDesc.getAppId(); List> addrInstanceList = redisCenter.getAppClientList(appId, 0); int totalConnectedClients = 0; for (Map addrInstance : addrInstanceList) { totalConnectedClients += MapUtils.getIntValue(addrInstance, "size", 0); } gather.setGatherTime(DateUtil.formatYYYY_MM_dd(new Date())); gather.setAppId(appId); gather.setConnectedClients(totalConnectedClients); result.add(gather); }); return result; } private boolean isMaster(InstanceStats instanceStats) { return instanceStats.getRole() == 1 ? true : false; } @Override public String executeCommand(long appId, String command, String userName) { if (StringUtils.isBlank(command)) { return "命令不能为空"; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return "app not found"; } if (TypeUtil.isRedisType(appDesc.getType())) { return redisCenter.executeCommand(appDesc, command, userName); } return "not support app"; } @Override public Map getInstanceSlowLogCountMapByAppId(Long appId, Date startDate, Date endDate) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return Collections.emptyMap(); } if (TypeUtil.isRedisType(appDesc.getType())) { return redisCenter.getInstanceSlowLogCountMapByAppId(appId, startDate, endDate); } return Collections.emptyMap(); } @Override public List getInstanceSlowLogByAppId(long appId, Date startDate, Date endDate) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return Collections.emptyList(); } if (TypeUtil.isRedisType(appDesc.getType())) { return redisCenter.getInstanceSlowLogByAppId(appId, startDate, endDate); } return Collections.emptyList(); } @Override public Map>> getAppLatencyStats(long appId, long startTime, long endTime) { try { List> appLatencyInfoList = instanceLatencyHistoryDao.getAppLatencyStats(appId, startTime, endTime); Map>> appLatencyInfoMap = Maps.newHashMap(); appLatencyInfoList.stream().forEach(appLatencyInfo -> { String event = MapUtils.getString(appLatencyInfo, "event"); ArrayList appEventLatency = (ArrayList) MapUtils.getObject(appLatencyInfoMap, event); if (CollectionUtils.isEmpty(appEventLatency)) { appEventLatency = Lists.newArrayList(); appLatencyInfoMap.put(event, appEventLatency); } appEventLatency.add(appLatencyInfo); }); return appLatencyInfoMap; } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public Map getAppLatencyStatsGroupByInstance(long appId, long startTime, long endTime) { try { List> appLatencyInfoList = instanceLatencyHistoryDao.getAppLatencyStatsGroupByInstance(appId, startTime, endTime); Map appInstanceLatencyStats = appLatencyInfoList.stream() .collect(Collectors.toMap(latencyInfo -> MapUtils.getString(latencyInfo, "host_port"), latencyInfo -> MapUtils.getLong(latencyInfo, "count"))); return appInstanceLatencyStats; } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public Map>> getAppLatencyInfo(long appId, long startTime, long endTime) { try { List> appLatencyInfoList = instanceLatencyHistoryDao.getAppLatencyInfo(appId, startTime, endTime, ""); Map>> appLatencyInfoMap = Maps.newHashMap(); appLatencyInfoList.stream().forEach(appLatencyInfo -> { String host_port = MapUtils.getString(appLatencyInfo, "host_port"); ArrayList appEventLatency = (ArrayList) MapUtils.getObject(appLatencyInfoMap, host_port); if (CollectionUtils.isEmpty(appEventLatency)) { appEventLatency = Lists.newArrayList(); appLatencyInfoMap.put(host_port, appEventLatency); } appEventLatency.add(appLatencyInfo); }); return appLatencyInfoMap; } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyMap(); } } @Override public List getByInstanceExecuteTime(long instanceId, String executeDate) { try { return instanceSlowLogDao.getByInstanceExecuteTime(instanceId, executeDate); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public Map getAppTotalStat() { Map totalMap = new HashMap(); /** * 1.从mysql获取 * 2.从jvm获取 */ if (PandectUtil.getFromMysql() || MapUtils.isEmpty(PandectUtil.getPandectMap())) { // 1.基础统计 // 1.1 在线应用数 int appCount = appDao.getAllAppCount(null); totalMap.put(StatEnum.TOTAL_EFFETIVE_APP.value(), appCount); // 1.2 机器数量 List machineInfoList = machineDao.getAllMachines(); totalMap.put(StatEnum.TOTAL_MACHINE_NUM.value(), machineInfoList.size()); //1.2.1 物理机数量,增加物理机数量 Set physicalMachineSet = machineInfoList.stream() .map(machineInfo -> machineInfo.getRealIp()) .filter(realIp -> StringUtils.isNotEmpty(realIp)) .collect(Collectors.toSet()); totalMap.put(StatEnum.TOTAL_PHYSICAL_MACHINE_NUM.value(), physicalMachineSet.size()); // 1.3 获取实例数量 List allInsts = instanceDao.getAllInsts(); totalMap.put(StatEnum.TOTAL_INSTANCE_NUM.value(), allInsts.size()); // 2.获取redis版本分布情况 List redisDistribute = new ArrayList(); List> appVersionStats = appDao.getVersionStat(); Map versionMap = new HashMap(); List versionList = resourceDao.getResourceList(ResourceEnum.REDIS.getValue()); if (!CollectionUtils.isEmpty(versionList)) { for (SystemResource version : versionList) { versionMap.put(version.getId(), version.getName()); } } if (!CollectionUtils.isEmpty(appVersionStats)) { for (Map appVersion : appVersionStats) { Integer version_id = MapUtils.getInteger(appVersion, "version_id"); Integer num = MapUtils.getInteger(appVersion, "num"); if (versionMap.containsKey(version_id)) { ParamCount paramCount = new ParamCount(versionMap.get(version_id), num, ""); redisDistribute.add(paramCount); } } } totalMap.put(StatEnum.REDIS_VERSION_DISTRIBUTE.value(), JSONObject.toJSONString(redisDistribute)); totalMap.put(StatEnum.REDIS_VERSION_COUNT.value(), versionList.size()); // 4.获取机器内存分配/机器内存使用分布 // 4.1 机器内存使用分布 Map machineMemoryDistributeMap = machineCenter.getUsedMemoryDistribute(); List machineMemoryDistributeList = new ArrayList(); for (Map.Entry entry : machineMemoryDistributeMap.entrySet()) { ParamCount paramCount = new ParamCount(entry.getKey().getInfo(), entry.getValue(), ""); machineMemoryDistributeList.add(paramCount); } totalMap.put(StatEnum.MACHINE_USEDMEMORY_DISTRIBUTE.value(), JSONObject.toJSONString(machineMemoryDistributeList)); // 4.2 机器内存分配分布 Map maxMemoryDistributeMap = machineCenter.getMaxMemoryDistribute(); List maxMemoryDistributeList = new ArrayList(); for (Map.Entry entry : maxMemoryDistributeMap.entrySet()) { ParamCount paramCount = new ParamCount(entry.getKey().getInfo(), entry.getValue(), ""); maxMemoryDistributeList.add(paramCount); } totalMap.put(StatEnum.MACHINE_MAXMEMORY_DISTRIBUTE.value(), JSONObject.toJSONString(maxMemoryDistributeList)); // 4.3 机房分布 List> roomStat = machineDao.getRoomStat(); List roomDistribute = new ArrayList(); if (roomStat != null && roomStat.size() > 0) { for (Map room : roomStat) { ParamCount paramCount = new ParamCount(MapUtils.getString(room, "name"), MapUtils.getInteger(room, "num"), ""); roomDistribute.add(paramCount); } } totalMap.put(StatEnum.MACHIEN_ROOM_DISTRIBUTE.value(), JSONObject.toJSONString(roomDistribute)); // 5.最后一次从数据库获取时间 totalMap.put(PandectUtil.KEY_LASTTIME, System.currentTimeMillis()); // 6.暂存到jvm PandectUtil.setPandectMap(totalMap); } else { totalMap.putAll(PandectUtil.getPandectMap()); } return totalMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/ImportAppCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.sohu.cache.constant.ImportAppResult; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.InstanceStatsDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.app.ImportAppCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.IdempotentConfirmer; import com.sohu.cache.web.service.AppService; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.Protocol; import java.util.List; import java.util.Map; /** * 导入应用 * * @author leifu * @Date 2016-4-16 * @Time 下午3:42:49 */ @Service("importAppCenter") public class ImportAppCenterImpl implements ImportAppCenter { private Logger logger = LoggerFactory.getLogger(ImportAppCenterImpl.class); @Autowired private AppService appService; @Autowired @Lazy private RedisCenter redisCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private InstanceDao instanceDao; @Autowired private InstanceStatsDao instanceStatsDao; @Override public ImportAppResult check(int type, String appInstanceInfo, String password) { // 1.实例信息是否为空 if (StringUtils.isBlank(appInstanceInfo)) { return ImportAppResult.fail("实例详情为空"); } String[] appInstanceDetails = appInstanceInfo.split("\n"); String masterNameInput = ""; // 2.检查实例信息格式是否正确 for (String appInstance : appInstanceDetails) { if (StringUtils.isBlank(appInstance)) { return ImportAppResult.fail("应用实例信息有空行"); } String[] instanceItems = appInstance.split(":"); if (instanceItems.length != 2) { return ImportAppResult.fail("应用实例信息" + appInstance + "格式错误,必须以冒号分隔"); } // 2.1检查端口是否为整数 String ip = instanceItems[0]; String portStr = instanceItems[1]; boolean portIsDigit = NumberUtils.isDigits(portStr); if ((!portIsDigit) && (type != ConstUtils.CACHE_REDIS_SENTINEL)) { return ImportAppResult.fail(appInstance + "中的port不是整数"); } else if ((!portIsDigit) && (type == ConstUtils.CACHE_REDIS_SENTINEL)) { masterNameInput = instanceItems[0]; continue; } int port = NumberUtils.toInt(portStr); // 2.2检查ip:port是否已经在instance_info表和instance_statistics中 int count = instanceDao.getCountByIpAndPort(ip, port); if (count > 0) { return ImportAppResult.fail(appInstance + "中ip:port已经在instance_info存在"); } InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByHost(ip, port); if (instanceStats != null) { return ImportAppResult.fail(appInstance + "中ip:port已经在instance_statistics存在"); } // 3.2检查Redis实例是否存活 boolean isRun; if (StringUtils.isNotEmpty(password)) { // 外部导入密码以外部密码为主(cc内部采用一定规则加密) isRun = redisCenter.isRun(ip, port, password); } else { isRun = redisCenter.isRun(ip, port); } if (!isRun) { return ImportAppResult.fail(appInstance + "中的节点不是存活的"); } //3.3判断sentinel模式下,masterName是否正确 if (StringUtils.isNotEmpty(masterNameInput) && (type == ConstUtils.CACHE_REDIS_SENTINEL)) { String masterName = getSentinelMasterName(ip, port); if (StringUtils.isEmpty(masterName) || !masterNameInput.equals(masterName)) { return ImportAppResult.fail(ip + ":" + port + ", masterName:" + masterName + "与所填" + masterNameInput + "不一致"); } } } return ImportAppResult.success(); } @Override public boolean importAppAndInstance(AppDesc appDesc, String appInstanceInfo) { boolean isSuccess = true; try { // 1.1 保存应用信息 appService.save(appDesc); long appId = appDesc.getAppId(); // 1.2 更新appKey appService.updateAppKey(appId); int type = appDesc.getType(); // 2.保存应用和用户的关系 appService.saveAppToUser(appId, appDesc.getUserId()); // 3.保存实例信息并开启统计 String[] appInstanceDetails = appInstanceInfo.split("\n"); // 4.检查实例信息格式是否正确 for (String appInstance : appInstanceDetails) { String[] instanceItems = appInstance.split(":"); String host = instanceItems[0]; int port = NumberUtils.toInt(instanceItems[1]); String memoryOrMasterName = instanceItems[2]; boolean isSentinelNode = NumberUtils.toInt(memoryOrMasterName) <= 0; if (isSentinelNode) { saveInstance(appId, host, port, 0, ConstUtils.CACHE_REDIS_SENTINEL, memoryOrMasterName); } else { if (ConstUtils.CACHE_REDIS_STANDALONE == type || ConstUtils.CACHE_REDIS_SENTINEL == type) { saveInstance(appId, host, port, NumberUtils.toInt(memoryOrMasterName), ConstUtils.CACHE_REDIS_STANDALONE, ""); } else if (ConstUtils.CACHE_TYPE_REDIS_CLUSTER == type) { saveInstance(appId, host, port, NumberUtils.toInt(memoryOrMasterName), ConstUtils.CACHE_TYPE_REDIS_CLUSTER, ""); } } } } catch (Exception e) { logger.error(e.getMessage(), e); isSuccess = false; } return isSuccess; } /** * 获取sentinel的masterName * * @param ip * @param port * @return */ private String getSentinelMasterName(final String ip, final int port) { final StringBuilder masterName = new StringBuilder(); new IdempotentConfirmer() { private int timeOutFactor = 1; @Override public boolean execute() { Jedis jedis = null; try { // 预留 String password = null; jedis = redisCenter.getJedis(ip, port, password); jedis.getClient().setConnectionTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); jedis.getClient().setSoTimeout(Protocol.DEFAULT_TIMEOUT * (timeOutFactor++)); List> mapList = jedis.sentinelMasters(); String targetKey = "name"; for (Map map : mapList) { if (map.containsKey(targetKey)) { masterName.append(MapUtils.getString(map, targetKey, "")); } } return true; } catch (Exception e) { logger.warn("{}:{} error message is {} ", ip, port, e.getMessage()); return false; } finally { if (jedis != null) { jedis.close(); } } } }.run(); return masterName.toString(); } /** * 保存实例信息 * * @param appId * @param host * @param port * @param maxMemory * @param type * @param cmd * @return */ private InstanceInfo saveInstance(long appId, String host, int port, int maxMemory, int type, String cmd) { InstanceInfo instanceInfo = new InstanceInfo(); instanceInfo.setAppId(appId); MachineInfo machineInfo = machineCenter.getMachineInfoByIp(host); instanceInfo.setHostId(machineInfo.getId()); instanceInfo.setConn(0); instanceInfo.setMem(maxMemory); instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceInfo.setPort(port); instanceInfo.setType(type); instanceInfo.setCmd(cmd); instanceInfo.setIp(host); instanceDao.saveInstance(instanceInfo); return instanceInfo; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/RedisMigrateToolCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.sohu.cache.constant.*; import com.sohu.cache.dao.AppDataMigrateStatusDao; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.app.AppDataMigrateCenter; import com.sohu.cache.stats.app.RedisMigrateToolCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.service.AppService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; /** * 数据迁移(使用唯品会的开源工具redis-migrate-tool进行迁移) * * @author leifu * @Date 2016-6-8 * @Time 下午2:54:33 */ @Service("redisMigrateToolCenter") public class RedisMigrateToolCenterImpl implements RedisMigrateToolCenter { private Logger logger = LoggerFactory.getLogger(RedisMigrateToolCenterImpl.class); @Autowired private AppService appService; @Autowired @Lazy private RedisCenter redisCenter; @Autowired private MachineCenter machineCenter; @Autowired private AppDataMigrateCenter appDataMigrateCenter; @Autowired private AppDataMigrateStatusDao appDataMigrateStatusDao; @Override public AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass,SystemResource resource) { // 1. 检查migrateMachineIp是否安装 AppDataMigrateResult migrateMachineResult = checkMigrateMachine(migrateMachineIp,resource); if (!migrateMachineResult.isSuccess()) { return migrateMachineResult; } // 2. 检查源配置 AppDataMigrateResult sourceResult = checkMigrateConfig(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, redisSourcePass, true); if (!sourceResult.isSuccess()) { return sourceResult; } // 3. 检查目标 AppDataMigrateResult targetResult = checkMigrateConfig(migrateMachineIp, targetRedisMigrateEnum, targetServers, redisTargetPass, false); if (!targetResult.isSuccess()) { return targetResult; } return AppDataMigrateResult.success(); } /** * 检查迁移的机器是否正常 * * @param migrateMachineIp * @return */ private AppDataMigrateResult checkMigrateMachine(String migrateMachineIp, SystemResource resource) { if (StringUtils.isBlank(migrateMachineIp)) { return AppDataMigrateResult.fail("redis-migrate-tool所在机器的IP不能为空"); } // 1. 检查机器是否存在在机器列表中 try { MachineInfo machineInfo = machineCenter.getMachineInfoByIp(migrateMachineIp); if (machineInfo == null) { return AppDataMigrateResult.fail(migrateMachineIp + "没有在机器管理列表中"); } else if (machineInfo.isOffline()) { return AppDataMigrateResult.fail(migrateMachineIp + ",该机器已经被删除"); } } catch (Exception e) { logger.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); } // 2. 检查是否安装redis-migrate-tool try { String cmd = ConstUtils.getRedisMigrateToolCmd(resource.getName()); String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isBlank(response) || !response.contains("source") || !response.contains("target")) { return AppDataMigrateResult.fail(migrateMachineIp + "下," + cmd + "执行失败,请确保redis-migrate-tool安装正确!"); } } catch (Exception e) { logger.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); } // 3. 检查是否有运行的redis-migrate-tool // 3.2 查看进程是否存在 try { String cmd = "/bin/ps -ef | grep redis-migrate-tool | grep -v grep | grep -v tail"; String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isNotBlank(response)) { return AppDataMigrateResult.fail(migrateMachineIp + "下有redis-migrate-tool进程,请确保只有一台机器只有一个迁移任务进行"); } } catch (Exception e) { logger.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); } return AppDataMigrateResult.success(); } /** * 检测配置 * * @param migrateMachineIp * @param redisMigrateEnum * @param servers * @return */ private AppDataMigrateResult checkMigrateConfig(String migrateMachineIp, AppDataMigrateEnum redisMigrateEnum, String servers, String redisPassword, boolean isSource) { //target如果是rdb是没有路径的,不需要检测 if (isSource || !AppDataMigrateEnum.isFileType(redisMigrateEnum)) { if (StringUtils.isBlank(servers)) { return AppDataMigrateResult.fail("服务器信息不能为空!"); } } List serverList = Arrays.asList(servers.split(ConstUtils.NEXT_LINE)); if (CollectionUtils.isEmpty(serverList)) { return AppDataMigrateResult.fail("服务器信息格式有问题!"); } for (String server : serverList) { if (AppDataMigrateEnum.isFileType(redisMigrateEnum)) { if (!isSource) { continue; } // 检查文件是否存在 String filePath = server; String cmd = "head " + filePath; try { String headResult = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isBlank(headResult)) { return AppDataMigrateResult.fail(migrateMachineIp + "上的rdb:" + filePath + "不存在或者为空!"); } } catch (Exception e) { logger.error(e.getMessage()); return AppDataMigrateResult.fail(migrateMachineIp + "上的rdb:" + filePath + "读取异常!"); } } else { // 1. 检查是否为ip:port格式(简单检查一下,无需正则表达式) // 2. 检查Redis节点是否存在 String[] instanceItems = server.split(":"); if (instanceItems.length != 2) { return AppDataMigrateResult.fail("实例信息" + server + "格式错误,必须为ip:port格式"); } String ip = instanceItems[0]; String portStr = instanceItems[1]; boolean portIsDigit = NumberUtils.isDigits(portStr); if (!portIsDigit) { return AppDataMigrateResult.fail(server + "中的port不是整数"); } int port = NumberUtils.toInt(portStr); boolean isRun = redisCenter.isRun(ip, port, redisPassword); if (!isRun) { return AppDataMigrateResult.fail(server + "不是存活的或者密码错误!"); } } } return AppDataMigrateResult.success(); } @Override public AppDataMigrateStatus migrate(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId, String redisSourcePass, String redisTargetPass, long userId, SystemResource resource) { // 1. 生成配置 int migrateMachinePort = ConstUtils.REDIS_MIGRATE_TOOL_PORT; String configContent = generateConfig(migrateMachinePort, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass); // 2. 上传配置 String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); String confileFileName = "rmt-" + timestamp + ".conf"; String logFileName = "rmt-" + timestamp + ".log"; boolean uploadConfig = createRemoteFile(migrateMachineIp, confileFileName, configContent); if (!uploadConfig) { return null; } // 3. 开始执行: 指定的配置名、目录、日志名 String cmd = ConstUtils.getRedisMigrateToolCmd(resource.getName()) + " -c " + ConstUtils.getRedisMigrateToolDir() + confileFileName + " -o " + ConstUtils.getRedisMigrateToolDir() + logFileName + " -d"; logger.warn(cmd); try { SSHUtil.execute(migrateMachineIp, cmd); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } // 4. 记录执行记录 AppDataMigrateStatus appDataMigrateStatus = new AppDataMigrateStatus(); appDataMigrateStatus.setMigrateId(timestamp); appDataMigrateStatus.setMigrateTool(1); appDataMigrateStatus.setMigrateMachineIp(migrateMachineIp); appDataMigrateStatus.setMigrateMachinePort(migrateMachinePort); appDataMigrateStatus.setStartTime(new Date()); appDataMigrateStatus.setSourceMigrateType(sourceRedisMigrateEnum.getIndex()); appDataMigrateStatus.setSourceServers(sourceServers); appDataMigrateStatus.setTargetMigrateType(targetRedisMigrateEnum.getIndex()); appDataMigrateStatus.setTargetServers(targetServers); appDataMigrateStatus.setLogPath(ConstUtils.getRedisMigrateToolDir() + logFileName); appDataMigrateStatus.setConfigPath(ConstUtils.getRedisMigrateToolDir() + confileFileName); appDataMigrateStatus.setUserId(userId); appDataMigrateStatus.setSourceAppId(sourceAppId); appDataMigrateStatus.setTargetAppId(targetAppId); appDataMigrateStatus.setStatus(AppDataMigrateStatusEnum.PREPARE.getStatus()); appDataMigrateStatusDao.save(appDataMigrateStatus); return appDataMigrateStatus; } /** * 生成配置 * * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @return */ public String generateConfig(int listenPort, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass) { // source StringBuffer config = new StringBuffer(); config.append("[source]" + ConstUtils.NEXT_LINE); config.append("type: " + sourceRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE); config.append("servers:" + ConstUtils.NEXT_LINE); List sourceServerList = Arrays.asList(sourceServers.split(ConstUtils.NEXT_LINE)); for (String server : sourceServerList) { config.append(" - " + server + ConstUtils.NEXT_LINE); } if (StringUtils.isNotBlank(redisSourcePass)) { config.append("redis_auth: " + redisSourcePass + ConstUtils.NEXT_LINE); } config.append(ConstUtils.NEXT_LINE); // target config.append("[target]" + ConstUtils.NEXT_LINE); config.append("type: " + targetRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE); if (!AppDataMigrateEnum.isFileType(targetRedisMigrateEnum)) { config.append("servers:" + ConstUtils.NEXT_LINE); List targetServerList = Arrays.asList(targetServers.split(ConstUtils.NEXT_LINE)); for (String server : targetServerList) { config.append(" - " + server + ConstUtils.NEXT_LINE); } if (StringUtils.isNotBlank(redisTargetPass)) { config.append("redis_auth: " + redisTargetPass + ConstUtils.NEXT_LINE); } config.append(ConstUtils.NEXT_LINE); } // common:使用最简配置 config.append("[common]" + ConstUtils.NEXT_LINE); config.append("listen: 0.0.0.0:" + listenPort + ConstUtils.NEXT_LINE); config.append("dir: " + ConstUtils.getRedisMigrateToolDir()); return config.toString(); } /** * 创建远程文件 * * @param host * @param fileName * @param content */ public boolean createRemoteFile(String host, String fileName, String content) { /** * 1. 创建本地文件 */ // 确认目录 String localAbsolutePath = MachineProtocol.TMP_DIR + fileName; File tmpDir = new File(MachineProtocol.TMP_DIR); if (!tmpDir.exists()) { if (!tmpDir.mkdirs()) { logger.error("cannot create /tmp/cachecloud directory."); } } Path path = Paths.get(MachineProtocol.TMP_DIR + fileName); // 将配置文件的内容写到本地 BufferedWriter bufferedWriter = null; try { bufferedWriter = Files.newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8)); bufferedWriter.write(content); } catch (IOException e) { logger.error("write rmt file error, ip: {}, filename: {}, content: {}", host, fileName, content, e); return false; } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } /** * 2. 将配置文件推送到目标机器上 */ try { SSHUtil.scpFileToRemote(host, localAbsolutePath, ConstUtils.getRedisMigrateToolDir()); } catch (SSHException e) { logger.error("scp rmt file to remote server error: ip: {}, fileName: {}", host, fileName, e); return false; } /** * 3. 删除临时文件 */ File file = new File(localAbsolutePath); if (file.exists()) { boolean del = file.delete(); if (!del) { logger.warn("file.delete:{}", del); } } return true; } @Override public CommandResult sampleCheckData(long id, int nums) { /*AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return null; } String ip = appDataMigrateStatus.getMigrateMachineIp(); String configPath = appDataMigrateStatus.getConfigPath(); String sampleCheckDataCmd = ConstUtils.getRedisMigrateToolCmd() + " -c " + configPath + " -C" + " 'redis_check " + nums + "'"; logger.warn("sampleCheckDataCmd: {}", sampleCheckDataCmd); try { return new CommandResult(sampleCheckDataCmd, SSHUtil.execute(ip, sampleCheckDataCmd)); } catch (Exception e) { logger.error(e.getMessage(), e); return new CommandResult(sampleCheckDataCmd, ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); }*/ return null; } @Override public AppDataMigrateResult stopMigrate(long id) { // 获取基本信息 AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return AppDataMigrateResult.fail("id=" + id + "迁移记录不存在!"); } // 获取进程号 String migrateMachineIp = appDataMigrateStatus.getMigrateMachineIp(); String migrateMachineHostPort = migrateMachineIp + ":" + appDataMigrateStatus.getMigrateMachinePort(); Map> redisMigrateToolStatMap = appDataMigrateCenter.showMiragteToolProcess(id); if (MapUtils.isEmpty(redisMigrateToolStatMap)) { return AppDataMigrateResult.fail("获取" + migrateMachineHostPort + "相关信息失败,可能是进程不存在或者客户端超时,请查找原因或重试!"); } Map serverMap = redisMigrateToolStatMap.get(RedisMigrateToolConstant.Server); int pid = MapUtils.getInteger(serverMap, "process_id", -1); if (pid <= 0) { return AppDataMigrateResult.fail("获取" + migrateMachineHostPort + "的进程号" + pid + "异常"); } // 确认进程号是redis-migrate-tool进程 BooleanEnum exist = checkPidWhetherIsRmt(migrateMachineIp, pid); if (exist == BooleanEnum.OTHER) { return AppDataMigrateResult.fail("执行过程中发生异常,请查看系统日志!"); } else if (exist == BooleanEnum.FALSE) { return AppDataMigrateResult.fail(migrateMachineIp + "进程号" + pid + "不存在,请确认!"); } // kill掉进程 try { String cmd = "kill " + pid; SSHUtil.execute(migrateMachineIp, cmd); exist = checkPidWhetherIsRmt(migrateMachineIp, pid); if (exist == BooleanEnum.OTHER) { return AppDataMigrateResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } else if (exist == BooleanEnum.FALSE) { // 更新记录完成更新 appDataMigrateStatusDao.updateStatus(id, AppDataMigrateStatusEnum.END.getStatus()); return AppDataMigrateResult.success("已经成功停止了id=" + id + "的迁移任务"); } else { return AppDataMigrateResult.fail(migrateMachineIp + "进程号" + pid + "仍然存在,没有kill掉,请确认!"); } } catch (Exception e) { logger.error(e.getMessage()); return AppDataMigrateResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } } @Override public String getAppInstanceListForRedisMigrateTool(long appId) { AppDesc appDesc = appService.getByAppId(appId); StringBuffer instances = new StringBuffer(); List instanceList = appService.getAppInstanceInfo(appId); if (CollectionUtils.isNotEmpty(instanceList)) { for (int i = 0; i < instanceList.size(); i++) { InstanceInfo instanceInfo = instanceList.get(i); if (instanceInfo == null) { continue; } if (instanceInfo.isOffline()) { continue; } // 如果是sentinel类型的应用只出master if (TypeUtil.isRedisSentinel(appDesc.getType())) { if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } if (redisCenter.isMaster(appId, instanceInfo.getIp(), instanceInfo.getPort()) != BooleanEnum.TRUE) { continue; } } instances.append(instanceInfo.getIp() + ":" + instanceInfo.getPort()); if (i != instanceList.size() - 1) { instances.append(ConstUtils.NEXT_LINE); } } } return instances.toString(); } /** * 检查pid是否是redis-migrate-tool进程 * * @param migrateMachineIp * @param pid * @return * @throws SSHException */ private BooleanEnum checkPidWhetherIsRmt(String migrateMachineIp, int pid) { try { String cmd = "/bin/ps -ef | grep redis-migrate-tool | grep -v grep | grep " + pid; String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isNotBlank(response)) { return BooleanEnum.TRUE; } else { return BooleanEnum.FALSE; } } catch (SSHException e) { logger.error(e.getMessage(), e); return BooleanEnum.OTHER; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/app/impl/RedisShakeCenterImpl.java ================================================ package com.sohu.cache.stats.app.impl; import com.google.common.base.Joiner; import com.sohu.cache.constant.*; import com.sohu.cache.dao.AppDataMigrateStatusDao; import com.sohu.cache.entity.AppDataMigrateStatus; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.exception.SSHException; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.app.RedisShakeCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.service.AppService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; /** * Created by rucao on 2019/10/23 */ @Slf4j @Service public class RedisShakeCenterImpl implements RedisShakeCenter { @Autowired private AppService appService; @Autowired private RedisCenter redisCenter; @Autowired private SSHService sshService; @Autowired private AppDataMigrateStatusDao appDataMigrateStatusDao; @Override public AppDataMigrateResult check(String migrateMachineIp, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass, SystemResource resource) { // 1. 检查migrateMachineIp是否安装 AppDataMigrateResult migrateMachineResult = checkRedisShakeMachine(migrateMachineIp, resource); if (!migrateMachineResult.isSuccess()) { return migrateMachineResult; } // 2. 检查源配置 AppDataMigrateResult sourceResult = checkMigrateConfigOfRedisShake(sourceRedisMigrateEnum, sourceServers, redisSourcePass); if (!sourceResult.isSuccess()) { return sourceResult; } // 3. 检查目标 AppDataMigrateResult targetResult = checkMigrateConfigOfRedisShake(targetRedisMigrateEnum, targetServers, redisTargetPass); if (!targetResult.isSuccess()) { return targetResult; } return AppDataMigrateResult.success(); } @Override public AppDataMigrateStatus migrate(String migrateMachineIp, int source_rdb_parallel, int parallel, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, long sourceAppId, long targetAppId, String redisSourcePass, String redisTargetPass, String redisSourceVersion, String redisTargetVersion, long userId, SystemResource resource) { String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); // 1. 生成配置 String configContent = generateRedisShakeConfig(timestamp, source_rdb_parallel, parallel, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass, resource); // 2. 上传配置 String fileName = "redis-shake-"; String confileFileName = fileName + timestamp + ".conf"; String logFileName = fileName + timestamp + ".log"; boolean uploadConfig = createRemoteFile(migrateMachineIp, confileFileName, configContent, resource); if (!uploadConfig) { return null; } // 3. 开始执行: 指定的配置名、目录、日志名 String cmd = "nohup " + ConstUtils.getRedisShakeLinuxCmd(resource.getName()) + " -conf=" + ConstUtils.getRedisShakeConfDir(resource.getName()) + confileFileName + " -type=sync > "+ConstUtils.REDIS_INSTALL_BASE_DIR+"/shake.out 2>&1 &"; log.warn(cmd); try { SSHTemplate.Result cmdResult = sshService.executeWithResult(migrateMachineIp, cmd); // 4. 记录执行记录 if (cmdResult.isSuccess()) { AppDataMigrateStatus appDataMigrateStatus = new AppDataMigrateStatus(); appDataMigrateStatus.setMigrateId(timestamp); appDataMigrateStatus.setMigrateTool(0); appDataMigrateStatus.setMigrateMachineIp(migrateMachineIp); appDataMigrateStatus.setStartTime(new Date()); appDataMigrateStatus.setSourceMigrateType(sourceRedisMigrateEnum.getIndex()); appDataMigrateStatus.setSourceServers(sourceServers); appDataMigrateStatus.setTargetMigrateType(targetRedisMigrateEnum.getIndex()); appDataMigrateStatus.setTargetServers(targetServers); appDataMigrateStatus.setLogPath(ConstUtils.getRedisShakeLogsDir(resource.getName()) + logFileName); appDataMigrateStatus.setConfigPath(ConstUtils.getRedisShakeConfDir(resource.getName()) + confileFileName); appDataMigrateStatus.setUserId(userId); appDataMigrateStatus.setSourceAppId(sourceAppId); appDataMigrateStatus.setTargetAppId(targetAppId); appDataMigrateStatus.setRedisSourceVersion(redisSourceVersion); appDataMigrateStatus.setRedisTargetVersion(redisTargetVersion); appDataMigrateStatus.setStatus(AppDataMigrateStatusEnum.PREPARE.getStatus()); appDataMigrateStatusDao.save(appDataMigrateStatus); return appDataMigrateStatus; } else { return null; } } catch (Exception e) { log.error(e.getMessage(), e); return null; } } @Override public AppDataMigrateResult stopMigrate(long id) { // 获取基本信息 AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return AppDataMigrateResult.fail("id=" + id + "迁移记录不存在!"); } String migrateMachineIp = appDataMigrateStatus.getMigrateMachineIp(); // redis-shake stop.sh try { String configPath = appDataMigrateStatus.getConfigPath(); ConstUtils.REDIS_SHAKE_HOME = configPath.substring(0, configPath.indexOf("conf")); String migrateId = appDataMigrateStatus.getMigrateId(); String stopCmd = ConstUtils.getRedisShakeStopCmd() + " " + String.format("%s/pid/redis-shake-%s.pid", ConstUtils.REDIS_SHAKE_HOME, migrateId); String stopResult = SSHUtil.execute(migrateMachineIp, stopCmd); if (StringUtils.isNotEmpty(stopResult) && stopResult.contains("Fail")) { if (stopResult.contains("No process number")) { String migrateLog = showProcess(id); if (StringUtils.isNotEmpty(migrateId) && migrateLog.contains(RedisShakeEnum.LOG_ERROR.getKeyword())) { appDataMigrateStatusDao.updateStatus(id, AppDataMigrateStatusEnum.ERROR.getStatus()); return AppDataMigrateResult.fail("迁移任务migrate id:" + migrateId + "异常,任务终止"); } else { appDataMigrateStatusDao.updateStatus(id, AppDataMigrateStatusEnum.END.getStatus()); return AppDataMigrateResult.fail("迁移任务migrate id:" + migrateId + "已经停止"); } } return AppDataMigrateResult.fail("迁移任务id:" + id + stopResult); } appDataMigrateStatusDao.updateStatus(id, AppDataMigrateStatusEnum.END.getStatus()); return AppDataMigrateResult.success("已经成功停止了id=" + id + "的迁移任务"); } catch (Exception e) { log.error(e.getMessage()); return AppDataMigrateResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } } @Override public CommandResult checkData(long id, int batchcount, int comparemode) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return null; } String ip = appDataMigrateStatus.getMigrateMachineIp(); String sampleCheckDataCmd = generateRedisFullCheckConfig(appDataMigrateStatus, batchcount, comparemode); log.warn("checkDataCmd: {}", sampleCheckDataCmd); try { String checkResult = SSHUtil.execute(ip, sampleCheckDataCmd); if (StringUtils.isNotEmpty(checkResult)) { return new CommandResult(sampleCheckDataCmd, ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } return new CommandResult(sampleCheckDataCmd, checkResult); } catch (Exception e) { log.error(e.getMessage(), e); return new CommandResult(sampleCheckDataCmd, ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } } @Override public String getAppInstanceListForRedisShake(long appId) { AppDesc appDesc = appService.getByAppId(appId); StringBuffer instances = new StringBuffer(); List instanceList = appService.getAppOnlineInstanceInfo(appId); int sentinelFlag = 0; if (CollectionUtils.isNotEmpty(instanceList)) { for (int i = 0; i < instanceList.size(); i++) { InstanceInfo instanceInfo = instanceList.get(i); if (instanceInfo == null) { continue; } if (instanceInfo.isOffline()) { continue; } // 如果是sentinel类型的应用 // master_name:master/slave // sentinelIp1:sentinelPort1 if (TypeUtil.isRedisSentinel(appDesc.getType())) { if ("slave".equals(instanceInfo.getRoleDesc())) { continue; } else if ("sentinel".equals(instanceInfo.getRoleDesc())) { if (sentinelFlag == 0) { String sentinel_master_name = instanceInfo.getCmd() + ":master" + ConstUtils.NEXT_LINE; instances.insert(0, sentinel_master_name); sentinelFlag = 1; } } else if ("master".equals(instanceInfo.getRoleDesc())) { continue; } } if (TypeUtil.isRedisCluster(appDesc.getType())) { if ("slave".equals(instanceInfo.getRoleDesc())) { continue; } } instances.append(instanceInfo.getIp() + ":" + instanceInfo.getPort()); if (i != instanceList.size() - 1) { instances.append(ConstUtils.NEXT_LINE); } } } return instances.toString(); } @Override public String showProcess(long id) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return ""; } String logPath = appDataMigrateStatus.getLogPath(); String host = appDataMigrateStatus.getMigrateMachineIp(); StringBuilder command = new StringBuilder(); String keyword; String result; try { keyword = RedisShakeEnum.LOG_ERROR.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { return RedisShakeEnum.LOG_ERROR.getDescription() + ConstUtils.NEXT_LINE + result; } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_FORWARD_COMMANDS.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { return RedisShakeEnum.LOG_FORWARD_COMMANDS.getDescription() + ConstUtils.NEXT_LINE + result; } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_SYNCING.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { return RedisShakeEnum.LOG_SYNCING.getDescription() + ConstUtils.NEXT_LINE + result; } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_WAITING_SOURCE_RDB.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { return RedisShakeEnum.LOG_WAITING_SOURCE_RDB.getDescription() + ConstUtils.NEXT_LINE + result; } } } } return result; } catch (SSHException e) { log.error(e.getMessage(), e); return ""; } } public int updateProcess(long id) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.get(id); if (appDataMigrateStatus == null) { return 0; } int migrateStatus = appDataMigrateStatus.getStatus(); String logPath = appDataMigrateStatus.getLogPath(); String host = appDataMigrateStatus.getMigrateMachineIp(); StringBuilder command = new StringBuilder(); String keyword; String result; try { int logStatus = migrateStatus; keyword = RedisShakeEnum.LOG_ERROR.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { logStatus = AppDataMigrateStatusEnum.ERROR.getStatus(); } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_FORWARD_COMMANDS.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { logStatus = AppDataMigrateStatusEnum.FULL_END.getStatus(); } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_SYNCING.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { logStatus = AppDataMigrateStatusEnum.START.getStatus(); } else { command.delete(0, command.length()); keyword = RedisShakeEnum.LOG_WAITING_SOURCE_RDB.getKeyword(); command.append("grep ").append(keyword).append(" ").append(logPath).append(" | tail -n 10").toString(); result = SSHUtil.execute(host, command.toString()); if (StringUtils.isNotEmpty(result)) { logStatus = AppDataMigrateStatusEnum.PREPARE.getStatus(); } } } } if (migrateStatus != logStatus) { return appDataMigrateStatusDao.updateStatus(id, logStatus); } } catch (SSHException e) { log.error(e.getMessage(), e); } return 0; } /** * 检查用redis-shake迁移的机器是否正常 * * @param migrateMachineIp * @return */ private AppDataMigrateResult checkRedisShakeMachine(String migrateMachineIp, SystemResource resource) { if (StringUtils.isBlank(migrateMachineIp)) { return AppDataMigrateResult.fail("redis-migrate-tool所在机器的IP不能为空"); } // 1. 检查机器是否存在在机器列表中 /*try { MachineInfo machineInfo = machineCenter.getMachineInfoByIp(migrateMachineIp); if (machineInfo == null) { return AppDataMigrateResult.fail(migrateMachineIp + "没有在机器管理列表中"); } else if (machineInfo.isOffline()) { return AppDataMigrateResult.fail(migrateMachineIp + ",该机器已经被删除"); } } catch (Exception e) { log.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); }*/ //2. 检查是否安装redis-shake /*try { String cmd = ConstUtils.getRedisShakeLinuxCmd(resource.getName()); String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isBlank(response) || !response.contains("start.sh") || !response.contains("conf")) { return AppDataMigrateResult.fail(migrateMachineIp + "下," + cmd + "执行失败,请确保redis-shake安装正确!"); } } catch (Exception e) { log.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); }*/ //3. 查看进程是数量 try { String cmd = "ps -ef | grep redis-shake | grep -v grep | grep -v tail"; String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isNotEmpty(response)) { String[] redis_shake_count = response.split(ConstUtils.NEXT_LINE); if (redis_shake_count.length >= 3) { return AppDataMigrateResult.fail(migrateMachineIp + "下有" + redis_shake_count.length + "个redis-shake进程," + "请切换迁移机器或等待其他迁移任务执行完毕后重试"); } } } catch (Exception e) { log.error(e.getMessage(), e); return AppDataMigrateResult.fail("检测发生异常,请观察日志"); } return AppDataMigrateResult.success(); } /** * redis-shake 检测配置 * * @param redisMigrateEnum * @param servers * @param redisPassword * @return */ private AppDataMigrateResult checkMigrateConfigOfRedisShake(AppDataMigrateEnum redisMigrateEnum, String servers, String redisPassword) { List serverList = Arrays.asList(servers.split(ConstUtils.NEXT_LINE)); if (CollectionUtils.isEmpty(serverList)) { return AppDataMigrateResult.fail("服务器信息格式有问题!"); } for (int i = 0; i < serverList.size(); i++) { // 1. 检查是否为ip:port格式(简单检查一下,无需正则表达式) // 2. 检查Redis节点是否存在 String server = serverList.get(i); String[] instanceItems = server.split(":"); if (instanceItems.length != 2) { return AppDataMigrateResult.fail("实例信息" + server + "格式错误,必须为ip:port格式"); } if (redisMigrateEnum == AppDataMigrateEnum.sentinel && i == 0) { String sentinel_master_name = instanceItems[0]; String master_or_slave = instanceItems[1]; if (!(master_or_slave.equalsIgnoreCase("master") || master_or_slave.equalsIgnoreCase("slave"))) { return AppDataMigrateResult.fail(server + "不是sentinel_master_name:master_or_slave格式"); } } else { String ip = instanceItems[0]; String portStr = instanceItems[1]; boolean portIsDigit = NumberUtils.isDigits(portStr); if (!portIsDigit) { return AppDataMigrateResult.fail(server + "中的port不是整数"); } int port = NumberUtils.toInt(portStr); boolean isRun = redisCenter.isRun(ip, port, redisPassword); if (!isRun) { return AppDataMigrateResult.fail(server + "不是存活的或者密码错误!"); } } } return AppDataMigrateResult.success(); } /** * 生成redis-shake配置 * * @param migrateId * @param sourceRedisMigrateEnum * @param sourceServers * @param targetRedisMigrateEnum * @param targetServers * @param redisSourcePass * @param redisTargetPass * @return */ private String generateRedisShakeConfig(String migrateId, int source_rdb_parallel, int parallel, AppDataMigrateEnum sourceRedisMigrateEnum, String sourceServers, AppDataMigrateEnum targetRedisMigrateEnum, String targetServers, String redisSourcePass, String redisTargetPass, SystemResource resource) { StringBuffer config = new StringBuffer(); config.append("id = redis-shake-" + migrateId + ConstUtils.NEXT_LINE); config.append("log.file = " + ConstUtils.getRedisShakeLogsDir(resource.getName()) + "redis-shake-" + migrateId + ".log" + ConstUtils.NEXT_LINE); config.append("pid_path = " + ConstUtils.getRedisShakePidDir(resource.getName()) + ConstUtils.NEXT_LINE); config.append("rewrite = true" + ConstUtils.NEXT_LINE); config.append("metric = false" + ConstUtils.NEXT_LINE); //config.append("http_profile = " + ConstUtils.getRedisShakeHttpPort() + ConstUtils.NEXT_LINE); config.append("http_profile = -1" + ConstUtils.NEXT_LINE); config.append("metric.print_log = false" + ConstUtils.NEXT_LINE); config.append("parallel = " + parallel + ConstUtils.NEXT_LINE); config.append("source.rdb.parallel = " + source_rdb_parallel + ConstUtils.NEXT_LINE); //source config.append("source.type = " + sourceRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE); config.append("source.address = " + formatAddress(sourceServers, sourceRedisMigrateEnum.getIndex()) + ConstUtils.NEXT_LINE); config.append("source.auth_type = auth" + ConstUtils.NEXT_LINE); config.append("source.password_raw = " + redisSourcePass + ConstUtils.NEXT_LINE); //target config.append("target.type = " + targetRedisMigrateEnum.getType() + ConstUtils.NEXT_LINE); config.append("target.address = " + formatAddress(targetServers, targetRedisMigrateEnum.getIndex()) + ConstUtils.NEXT_LINE); config.append("target.auth_type = auth" + ConstUtils.NEXT_LINE); config.append("target.password_raw = " + redisTargetPass + ConstUtils.NEXT_LINE); return config.toString(); } private String formatAddress(String servers, int migrateType) { List sourceServerList = Arrays.asList(servers.split(ConstUtils.NEXT_LINE)); String address = Joiner.on(ConstUtils.SEMICOLON).join(sourceServerList); if (migrateType == AppDataMigrateEnum.sentinel.getIndex()) { return address.replaceFirst(ConstUtils.SEMICOLON, ConstUtils.AT); } return address; } private String formatAddressForRedisFullCheck(long appId, String servers, int migrateType) { if (migrateType == AppDataMigrateEnum.sentinel.getIndex()) { List instanceList = appService.getAppInstanceInfo(appId); if (CollectionUtils.isNotEmpty(instanceList)) { for (int i = 0; i < instanceList.size(); i++) { InstanceInfo instanceInfo = instanceList.get(i); if ("master".equals(instanceInfo.getRoleDesc())) { return instanceInfo.getIp() + ":" + instanceInfo.getPort(); } } } return ""; } else { return formatAddress(servers, migrateType); } } private String generateRedisFullCheckConfig(AppDataMigrateStatus appDataMigrateStatus, int nums, int comparemode) { StringBuffer cmd = new StringBuffer(); String migrateId = appDataMigrateStatus.getMigrateId(); cmd.append(ConstUtils.getRedisFullCheckCmd() + ConstUtils.SPACE);// 异步命令 cmd.append("-s " + "\"" + formatAddressForRedisFullCheck(appDataMigrateStatus.getSourceAppId(), appDataMigrateStatus.getSourceServers(), appDataMigrateStatus.getSourceMigrateType()) + "\"" + ConstUtils.SPACE); cmd.append("-p " + appService.getByAppId(appDataMigrateStatus.getSourceAppId()).getAppPassword() + ConstUtils.SPACE); cmd.append("--sourcedbtype=" + getCompareType(appDataMigrateStatus.getSourceMigrateType()) + ConstUtils.SPACE);//源库的类别,0:db(standalone单节点、主从),1: cluster(集群版),2: 阿里云 cmd.append("-t " + "\"" + formatAddressForRedisFullCheck(appDataMigrateStatus.getTargetAppId(), appDataMigrateStatus.getTargetServers(), appDataMigrateStatus.getTargetMigrateType()) + "\"" + ConstUtils.SPACE); cmd.append("-a " + appService.getByAppId(appDataMigrateStatus.getTargetAppId()).getAppPassword() + ConstUtils.SPACE); cmd.append("--targetdbtype=" + getCompareType(appDataMigrateStatus.getTargetMigrateType()) + ConstUtils.SPACE); cmd.append("--comparetimes=1" + ConstUtils.SPACE);//比较轮数 cmd.append("-m " + comparemode + ConstUtils.SPACE);//比较模式,1表示全量比较,2表示只对比value的长度,3只对比key是否存在,4全量比较的情况下,忽略大key的比较 cmd.append("--batchcount=" + nums + ConstUtils.SPACE);//批量聚合的数量 cmd.append("--log=" + ConstUtils.getRedisFullCheckResultDir() + "log-" + migrateId + ".log" + ConstUtils.SPACE);//log文件 //cmd.append("--metric=" + ConstUtils.getRedisFullCheckResultDir() + "metric-" + migrateId + ConstUtils.SPACE); // todo metric文件,报错 cmd.append("-d " + ConstUtils.getRedisFullCheckResultDir() + "key-" + migrateId + ".db" + ConstUtils.SPACE); //异常数据列表保存的文件名称 cmd.append("--result=" + ConstUtils.getRedisFullCheckResultDir() + "result-" + migrateId + ".log" + ConstUtils.SPACE);//不一致结果记录到result文件中,格式:'db diff-type key field'; return cmd.toString(); } private int getCompareType(int migrateType) { if (migrateType == AppDataMigrateEnum.standalone.getIndex() || migrateType == AppDataMigrateEnum.sentinel.getIndex() || migrateType == AppDataMigrateEnum.REDIS_NODE.getIndex()) { return 0; } else if (migrateType == AppDataMigrateEnum.cluster.getIndex()) { return 1; } return -1; } /** * 创建远程文件 * * @param host * @param fileName * @param content */ public boolean createRemoteFile(String host, String fileName, String content, SystemResource resource) { /** * 1. 创建本地文件 */ // 确认目录 String localAbsolutePath = MachineProtocol.TMP_DIR + fileName; File tmpDir = new File(MachineProtocol.TMP_DIR); if (!tmpDir.exists()) { if (!tmpDir.mkdirs()) { log.error("cannot create /tmp/cachecloud directory."); } } Path path = Paths.get(MachineProtocol.TMP_DIR + fileName); // 将配置文件的内容写到本地 BufferedWriter bufferedWriter = null; try { bufferedWriter = Files.newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8)); bufferedWriter.write(content); } catch (IOException e) { log.error("write rmt file error, ip: {}, filename: {}, content: {}", host, fileName, content, e); return false; } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } } /** * 2. 将配置文件推送到目标机器上 */ try { String redisShakeConfDir = ConstUtils.getRedisShakeConfDir(resource.getName()); String redisShakeLogDir = ConstUtils.getRedisShakeLogsDir(resource.getName()); String redisShakePidDir = ConstUtils.getRedisShakePidDir(resource.getName()); SSHUtil.execute(host, String.format("mkdir -p %s %s %s", redisShakeConfDir, redisShakeLogDir, redisShakePidDir)); SSHUtil.scpFileToRemote(host, localAbsolutePath, redisShakeConfDir); } catch (SSHException e) { log.error("scp rmt file to remote server error: ip: {}, fileName: {}", host, fileName, e); return false; } /** * 3. 删除临时文件 */ File file = new File(localAbsolutePath); if (file.exists()) { boolean del = file.delete(); if (!del) { log.warn("file.delete:{}", del); } } return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/InstanceAlertConfigService.java ================================================ package com.sohu.cache.stats.instance; import java.util.Date; import java.util.List; import com.sohu.cache.entity.InstanceAlertConfig; /** * 实例报警阀值配置 * @author leifu * @Date 2017年5月19日 * @Time 下午2:12:29 */ public interface InstanceAlertConfigService { /** * 获取所有实例报警配置列表 * @return */ List getAll(); /** * 根据类型获取实例报警配置列表 * @param type * @return */ List getByType(int type); /** * 根据类型获取实例报警配置列表 * @param type 报警类型 * @param appType 应用类型 * @return */ List getByTypeAndAppType(int type, int appType); /** * 保存 * @param instanceAlertConfig 报警实例 * @return */ int save(InstanceAlertConfig instanceAlertConfig); /** * 保存 * @param instanceAlertConfigList 报警实例列表 * @return */ int batchSave(List instanceAlertConfigList); /** * 根据id获取 * @param id * @return */ InstanceAlertConfig get(int id); /** * 根据id删除 * @param id * @return */ int remove(int id); /** * 根据alertConfig 获取全局配置,并根据比较类型进行筛选出紧急程度 * @param alertConfig * @param compareType * @param appType * @return */ InstanceAlertConfig getGlobalAlertConfigByCondition(String alertConfig, int compareType, Integer appType); /** * 更新alertValue和checkCycle * @param id * @param alertValue * @param checkCycle * @param compareType * @param importantLevel */ void update(long id, String alertValue, int checkCycle, int compareType, int importantLevel); /** * 根据alertConfig和compareType更新所有报警配置的紧急程度 * @param alertConfig * @param compareType * @param importantLevel * @param appType */ void updateImportantLevel(String alertConfig, int compareType, int importantLevel, Integer appType); /** * 更新配置的最后检测时间 * @param id * @param lastCheckTime */ void updateLastCheckTime(long id, Date lastCheckTime); /** * 监控所有Redis上一分钟状态 */ void monitorLastMinuteAllInstanceInfo(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/InstanceDeployCenter.java ================================================ package com.sohu.cache.stats.instance; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.task.constant.MachineSyncEnum; import java.util.List; /** * Created by yijunzhang on 14-11-26. */ public interface InstanceDeployCenter { /** * 启动已经存在的实例 * @param appId * @param instanceId * @return */ boolean startExistInstance(long appId, int instanceId); /** * 启动已存在的实例,无需进行redis资源包校验 * @param appId * @param instanceId * @return */ boolean startExistInstanceWithoutResourceCheck(long appId, int instanceId); /** * 下线已经存在的实例 * @param appId * @param instanceId * @return */ boolean shutdownExistInstance(long appId, int instanceId); /** * cluster forget * @param appId * @param instanceId * @return */ boolean forgetInstance(long appId, int instanceId); /** * 清理(cluster forget)集群内所有fail节点 * @param appId * @param instanceId * @return */ boolean clearFailInstances(long appId); /** * 展示实例最近的日志 * @param instanceId * @param maxLineNum * @return */ String showInstanceRecentLog(int instanceId, int maxLineNum); /** * 修改实例配置 * @param appId * @param appAuditId * @param host * @param port * @param instanceConfigKey * @param instanceConfigValue * @return */ boolean modifyInstanceConfig(long appId, Long appAuditId, String host, int port, String instanceConfigKey, String instanceConfigValue); /** * 检测pod是否有被调度其他宿主机 * @param ip */ MachineSyncEnum podChangeStatus(String ip); /** * 检测pod是否有心跳停止实例&启动 * @return */ List checkAndStartExceptionInstance(String ip, Boolean isAlert); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/InstanceStatsCenter.java ================================================ package com.sohu.cache.stats.instance; import com.google.common.collect.Table; import com.sohu.cache.entity.InstanceCommandStats; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceMinuteStats; import com.sohu.cache.entity.InstanceStats; import java.util.List; import java.util.Map; /** * 实例统计方法 * Created by yijunzhang on 14-9-17. */ public interface InstanceStatsCenter { /** * 根据实例id获取实例的静态信息 * * @param instanceId 实例id * @return 实例信息对象 */ InstanceInfo getInstanceInfo(long instanceId); /** * 根据实例id获取实例的实施统计&是否在线&redis实时统计信息 * * @param instanceId 实例id * @return 实例实时状态信息 */ InstanceStats getInstanceStats(long instanceId); /** * 根据实例id,起止时间,命令名称获取实例对应命令的执行次数曲线 * * @param instanceId 实例id * @param beginTime 起始时间 闭区间 yyyyMMddHHmm * @param endTime 结束时间 闭区间 yyyyMMddHHmm * @param commandName 命令名称 * @return 实例命令执行对象的列表 */ List getCommandStatsList(Long instanceId, long beginTime, long endTime, String commandName); /** * 根据appId,起止时间,统计指标名称 获取实例对应指标统计列表 * * @param appId 实例id * @param beginTime 起始时间 闭区间 yyyyMMddHHmm * @param endTime 结束时间 闭区间 yyyyMMddHHmm * @param commands 命令名称 * @return 应用下 所有实例 命令执行对象的列表 *
* Map>> : Map>> */ Map>> getStandardStatsList(Long appId, long beginTime, long endTime, List commands); /** * 根据appId,起止时间,统计指标名称 获取实例对应指标统计列表 * * @param appId 实例id * @param beginTime 起始时间 闭区间 yyyyMMddHHmm * @param endTime 结束时间 闭区间 yyyyMMddHHmm * @param commands 命令名称 * @return 应用下 所有实例统计信息 *
* Table>> */ Table>> getInstanceMinuteStatsList(Long appId, long beginTime, long endTime, List commands); /** * 在实例上执行命令 * * @param host * @param port * @param command * @return */ public String executeCommand(String host, int port, String command); /** * 在实例上执行命令 * * @param instanceId * @param command * @return */ public String executeCommand(Long instanceId, String command); /** * 获取所有统计信息 * @return */ public List getInstanceStats(); /** * 按照机器获取实例列表 * @param ip * @return */ List getInstanceStats(String ip); /** * 将一个对象(如统计信息)保存到mysql里 * * @param infoMap 统计信息对象 * @param clusterInfoMap clusterinfo统计信息 * @param ip ip * @param port port * @param dbType * @return 成功保存返回true,否则返回false */ public boolean saveStandardStats(Map infoMap, Map clusterInfoMap, String ip, int port, String dbType); /** * 根据收集时间查询某一个实例或机器的统计信息 * * @param collectTime 时间点,格式:yyyyMMddHHmm * @param ip ip * @param port port * @param dbType * @return 该时间点对应的统计信息 */ public Map queryStandardInfoMap(long collectTime, String ip, int port, String dbType); /** * 查询一段时间内,实例或机器的统计信息的列表,如实例或机器一天中每分钟的统计数据 * * @param beginTime 起始时间,格式:yyyyMMddHHmm * @param endTime 结束时间,格式:yyyyMMddHHmm * @param ip ip * @param port port * @param dbType * @return 该时间区间内,对应的统计信息的列表 */ public List> queryDiffMapList(long beginTime, long endTime, String ip, int port, String dbType); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceAlertConfigServiceImpl.java ================================================ package com.sohu.cache.stats.instance.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.alert.bean.AlertConfigBaseData; import com.sohu.cache.alert.strategy.*; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceAlertConfigDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.StandardStatsDao; import com.sohu.cache.entity.*; import com.sohu.cache.redis.enums.AppTypeToAlertTypeEnum; import com.sohu.cache.redis.enums.InstanceAlertStatusEnum; import com.sohu.cache.redis.enums.InstanceAlertTypeEnum; import com.sohu.cache.redis.enums.RedisAlertConfigEnum; import com.sohu.cache.stats.instance.InstanceAlertConfigService; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.EnvUtil; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.enums.ImportantLevelTypeEnum; import com.sohu.cache.web.service.AppAlertRecordService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.FreemakerUtils; import freemarker.template.Configuration; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * @author leifu * @Date 2017年5月19日 * @Time 下午2:16:36 */ @Service("instanceAlertConfigService") public class InstanceAlertConfigServiceImpl implements InstanceAlertConfigService { private Logger logger = LoggerFactory.getLogger(InstanceAlertConfigServiceImpl.class); @Autowired private InstanceAlertConfigDao instanceAlertConfigDao; @Autowired private StandardStatsDao standardStatsDao; @Autowired private InstanceDao instanceDao; @Autowired private EmailComponent emailComponent; @Autowired private Configuration configuration; @Autowired private AppDao appDao; @Autowired private UserService userService; @Autowired private Environment environment; @Autowired private AppAlertRecordService appAlertRecordService; private static Map alertConfigStrategyMap = new HashMap(); static { alertConfigStrategyMap.put(RedisAlertConfigEnum.aof_current_size, new AofCurrentSizeAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.client_biggest_input_buf, new ClientBiggestInputBufAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.client_longest_output_list, new ClientLongestOutputListAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.instantaneous_ops_per_sec, new InstantaneousOpsPerSecAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.latest_fork_usec, new LatestForkUsecAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.mem_fragmentation_ratio, new MemFragmentationRatioAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.rdb_last_bgsave_status, new RdbLastBgsaveStatusAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_aof_delayed_fsync, new MinuteAofDelayedFsyncAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_rejected_connections, new RdbLastBgsaveStatusAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_partial_err, new MinuteSyncPartialErrAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_partial_ok, new MinuteSyncPartialOkAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_sync_full, new MinuteSyncFullAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_total_net_input_bytes, new MinuteTotalNetInputMBytesAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.minute_total_net_output_bytes, new MinuteTotalNetOutputMBytesAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.master_slave_offset_diff, new MasterSlaveOffsetAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.cluster_state, new ClusterStateAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.cluster_slots_ok, new ClusterSlotsOkAlertStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.used_cpu_sys, new MinuteUsedCpuSysStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.used_cpu_user, new MinuteUsedCpuUserStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.used_cpu_sys_children, new MinuteUsedCpuSysChStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.used_cpu_user_children, new MinuteUsedCpuUserChStrategy()); alertConfigStrategyMap.put(RedisAlertConfigEnum.other_default_common_config, new DefaultCommonAlertStrategy()); } @Override public List getAll() { try { return instanceAlertConfigDao.getAll(); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public int save(InstanceAlertConfig instanceAlertConfig) { try { return instanceAlertConfigDao.save(instanceAlertConfig); } catch (Exception e) { logger.error(e.getMessage(), e); return -1; } } @Override public int batchSave(List instanceAlertConfigList) { try { return instanceAlertConfigDao.batchSave(instanceAlertConfigList); } catch (Exception e) { logger.error(e.getMessage(), e); return -1; } } @Override public InstanceAlertConfig get(int id) { try { return instanceAlertConfigDao.get(id); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public int remove(int id) { try { return instanceAlertConfigDao.remove(id); } catch (Exception e) { logger.error(e.getMessage(), e); return -1; } } @Override public List getByType(int type) { try { return instanceAlertConfigDao.getByType(type); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getByTypeAndAppType(int type, int appType) { try { return instanceAlertConfigDao.getByTypeAndAppType(type, appType); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public InstanceAlertConfig getGlobalAlertConfigByCondition(String alertConfig, int compareType, Integer appType) { try { List configList = instanceAlertConfigDao.getByAlertConfigAndType(alertConfig, InstanceAlertTypeEnum.ALL_ALERT.getValue(), appType); for (InstanceAlertConfig instanceAlertConfig : configList) { if(instanceAlertConfig.getStatus() == InstanceAlertStatusEnum.YES.getValue() && compareType == instanceAlertConfig.getCompareType()){ return instanceAlertConfig; } } if(CollectionUtils.isNotEmpty(configList)){ return configList.get(0); } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } @Override public void update(long id, String alertValue, int checkCycle, int compareType, int importantLevel) { instanceAlertConfigDao.update(id, alertValue, checkCycle, compareType, importantLevel); } @Override public void updateImportantLevel(String alertConfig, int compareType, int importantLevel, Integer appType) { if(appType == null){ appType = AppTypeToAlertTypeEnum.REDIS_ALERT.getType(); } instanceAlertConfigDao.updateImportantLevel(alertConfig, compareType, importantLevel, appType); } @Override public void updateLastCheckTime(long id, Date lastCheckTime) { try { instanceAlertConfigDao.updateLastCheckTime(id, lastCheckTime); } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override public void monitorLastMinuteAllInstanceInfo() { long startTime = System.currentTimeMillis(); // 1.全部和特殊实例报警配置 List commonInstanceAlertConfigList = getByType(InstanceAlertTypeEnum.ALL_ALERT.getValue()); List specialInstanceAlertConfigList = getByType(InstanceAlertTypeEnum.INSTANCE_ALERT.getValue()); //1.2查询应用报警配置 List appInstanceAlertConfigList = getByType(InstanceAlertTypeEnum.APP_ALERT.getValue()); // 2.所有实例信息 List allInstanceInfoList = instanceDao.getAllInsts(); if (CollectionUtils.isEmpty(allInstanceInfoList)) { return; } List transferAppInstanceAlertConfigList = new ArrayList<>(); List appInstanceInfo = null; for (InstanceAlertConfig instanceAlertConfig: appInstanceAlertConfigList) { appInstanceInfo = allInstanceInfoList.stream().filter(instanceInfo -> instanceInfo.getAppId() == instanceAlertConfig.getInstanceId()).collect(Collectors.toList()); addAppInstanceToTransferList(transferAppInstanceAlertConfigList, instanceAlertConfig, appInstanceInfo); } if(CollectionUtils.isNotEmpty(transferAppInstanceAlertConfigList)){ specialInstanceAlertConfigList.addAll(transferAppInstanceAlertConfigList); } List allInstanceAlertConfigList = new ArrayList(); allInstanceAlertConfigList.addAll(commonInstanceAlertConfigList); allInstanceAlertConfigList.addAll(specialInstanceAlertConfigList); if (CollectionUtils.isEmpty(allInstanceAlertConfigList)) { return; } // 3. 取上1分钟Redis实例统计信息 Date currentTime = new Date(); Date beginTime = DateUtils.addMinutes(currentTime, -2); Date endTime = DateUtils.addMinutes(currentTime, -1); Map standardStatMap = getStandardStatsMap(beginTime, endTime); if (MapUtils.isEmpty(standardStatMap)) { logger.warn("standardStatMap is empty!"); return; } // 4.检测所有配置 List instanceAlertValueResultList = new ArrayList(); for (InstanceAlertConfig instanceAlertConfig : allInstanceAlertConfigList) { if (!checkInCycle(instanceAlertConfig)) { continue; } List tempInstanceInfoList = allInstanceInfoList; if (instanceAlertConfig.isSpecail()) { tempInstanceInfoList.clear(); InstanceInfo instanceInfo = null; if(instanceAlertConfig.getInstanceInfo() == null){ instanceInfo = instanceDao.getInstanceInfoById(instanceAlertConfig.getInstanceId()); }else{ instanceInfo = instanceAlertConfig.getInstanceInfo(); } if (instanceInfo == null) { continue; } tempInstanceInfoList.add(instanceInfo); } for (InstanceInfo instanceInfo : tempInstanceInfoList) { List InstanceAlertValueResultTempList = dealInstanceAlert(specialInstanceAlertConfigList, instanceAlertConfig, instanceInfo, standardStatMap, currentTime); if (CollectionUtils.isNotEmpty(InstanceAlertValueResultTempList)) { instanceAlertValueResultList.addAll(InstanceAlertValueResultTempList); } } // 更新配置最后检测时间 updateLastCheckTime(instanceAlertConfig.getId(), currentTime); } if (CollectionUtils.isNotEmpty(instanceAlertValueResultList)) { // 发送邮件 sendInstanceAlertEmail(beginTime, endTime, instanceAlertValueResultList); } long costTime = System.currentTimeMillis() - startTime; if (costTime > 20000) { logger.warn("monitorLastMinuteAllInstanceInfo cost {} ms", costTime); } } /** * 将应用报警转化为应用下实例报警 * @param transferAppInstanceAlertConfigList 转换后结果存储 * @param instanceAlertConfig 应用报警配置 * @param appInstanceInfo 应用下实例信息列表 */ private void addAppInstanceToTransferList(List transferAppInstanceAlertConfigList, InstanceAlertConfig instanceAlertConfig, List appInstanceInfo) { InstanceAlertConfig appInstanceAlertConfig = null; for (InstanceInfo instanceInfo : appInstanceInfo) { appInstanceAlertConfig = new InstanceAlertConfig(); try { BeanUtils.copyProperties(appInstanceAlertConfig, instanceAlertConfig); } catch (Exception e) { logger.error("addAppInstanceToTransferList error:", e); } appInstanceAlertConfig.setInstanceId(instanceInfo.getId()); appInstanceAlertConfig.setInstanceInfo(instanceInfo); transferAppInstanceAlertConfigList.add(appInstanceAlertConfig); } } /** * 处理实例 * * @param instanceAlertConfig * @param instanceInfo * @param standardStatMap * @param currentTime */ private List dealInstanceAlert(List specialInstanceAlertConfigList, InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo, Map standardStatMap, Date currentTime) { if (instanceInfo.isOffline()) { return null; } // 单个实例的统计信息 String hostPort = instanceInfo.getHostPort(); StandardStats standardStats = standardStatMap.get(hostPort); if (standardStats == null) { return null; } // 判断是不是特殊实例 InstanceAlertConfig finalInstanceConfig = filterSpecial(specialInstanceAlertConfigList, instanceAlertConfig, instanceInfo); // 普通配置,但finalInstanceConfig不等于instanceAlertConfig,跳过 if (!instanceAlertConfig.isSpecail() && finalInstanceConfig.getId() != instanceAlertConfig.getId()) { return null; } // 是否进入检测周期 boolean isInCycle = checkInCycle(finalInstanceConfig); if (!isInCycle) { return null; } // 枚举检测 String alertConfig = finalInstanceConfig.getAlertConfig(); RedisAlertConfigEnum redisAlertConfigEnum = RedisAlertConfigEnum.getRedisAlertConfig(alertConfig); if(redisAlertConfigEnum == null){ redisAlertConfigEnum = RedisAlertConfigEnum.other_default_common_config; } // 策略检测 AlertConfigStrategy alertConfigStrategy = alertConfigStrategyMap.get(redisAlertConfigEnum); if (alertConfigStrategy == null) { return null; } // 获取基准数据 AlertConfigBaseData alertConfigBaseData = new AlertConfigBaseData(); alertConfigBaseData.setInstanceInfo(instanceInfo); alertConfigBaseData.setStandardStats(standardStats); // 开始检测 try { return alertConfigStrategy.checkConfig(finalInstanceConfig, alertConfigBaseData); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } /** * 发送邮件 * * @param instanceAlertValueResultList */ private void sendInstanceAlertEmail(Date beginTime, Date endTime, List instanceAlertValueResultList) { if (CollectionUtils.isEmpty(instanceAlertValueResultList)) { return; } Collections.sort(instanceAlertValueResultList, new Comparator() { @Override public int compare(InstanceAlertValueResult o1, InstanceAlertValueResult o2) { return (int) (o1.getAppId() - o2.getAppId()); } }); // 1.客户端应用定制报警 Map> appAlertMap = new HashMap>(); Set appSets = new HashSet(); Map appDescMap = new HashMap(); // 2.遍历报警实例 for (InstanceAlertValueResult instanceAlertValueResult : instanceAlertValueResultList) { long appId = instanceAlertValueResult.getAppId(); AppDesc appDesc = null; if (appDescMap.containsKey(appId)) { appDesc = appDescMap.get(appId); } else { appDesc = appDao.getAppDescById(instanceAlertValueResult.getAppId()); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); appDescMap.put(appId, appDesc); } instanceAlertValueResult.setAppDesc(appDesc); // 找出定制报警的客户端 if (appDesc.getIsAccessMonitor() == 1) { appSets.add(appId); } } // 3.按客户端定制报警应用分组发送 for (Long appid : appSets) { List instanceAlertList = new ArrayList(); for (InstanceAlertValueResult instanceAlert : instanceAlertValueResultList) { if (appid == instanceAlert.getAppId()) { instanceAlertList.add(instanceAlert); } } if (instanceAlertList.size() > 0) { appAlertMap.put(appid, instanceAlertList); logger.warn("monitor alert appid:{},instance size ={}", appid, instanceAlertList.size()); } } // 4.发送给管理员报警 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); int importantLevel = this.getAlertImportantLevel(instanceAlertValueResultList); String emailTitle = String.format("Redis实例分钟报警(%s~%s)", sdf.format(beginTime), sdf.format(endTime)); if(importantLevel == ImportantLevelTypeEnum.URGENT.getType() || importantLevel == ImportantLevelTypeEnum.IMPORTANT.getType() || importantLevel == ImportantLevelTypeEnum.NORMAL.getType()){ emailTitle = String.format("[%s]Redis实例分钟报警(%s~%s)", ImportantLevelTypeEnum.getInfoByType(importantLevel), sdf.format(beginTime), sdf.format(endTime)); } Map context = new HashMap<>(); context.put("instanceAlertValueResultList", instanceAlertValueResultList); String emailContent = FreemakerUtils.createText("instanceAlert.ftl", configuration, context); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.INSTANCE_MINUTE_MONITOR, emailTitle, null, instanceAlertValueResultList); emailComponent.sendMailToAdmin(emailTitle, emailContent.replaceAll("\t","")); // 5.发送给客户端定制报警 for (Map.Entry> appAlert : appAlertMap.entrySet()) { Long appId = appAlert.getKey(); List instanceAlertList = appAlert.getValue(); emailTitle = String.format("应用Redis分钟报警(%s~%s)", sdf.format(beginTime), sdf.format(endTime)); Map context1 = new HashMap<>(); context1.put("instanceAlertValueResultList", instanceAlertList); emailContent = FreemakerUtils.createText("appAlert.ftl", configuration, context1); // 获取报警用户列表 List appUsers = userService.getAlertByAppId(appId); List emailList = getEmailList(appUsers); if (emailList != null && emailList.size() > 0) { emailComponent.sendMail(emailTitle, emailContent, emailList); } } } /** * 根据报警结果,获取报警重要程度 * @param instanceAlertValueResultList * @return */ private int getAlertImportantLevel(List instanceAlertValueResultList){ int importantLevel = ImportantLevelTypeEnum.NORMAL.getType(); for(InstanceAlertValueResult alertValueResult : instanceAlertValueResultList){ if(alertValueResult.getInstanceAlertConfig() != null && alertValueResult.getInstanceAlertConfig().getImportantLevel() != null){ if(importantLevel < alertValueResult.getInstanceAlertConfig().getImportantLevel()){ importantLevel = alertValueResult.getInstanceAlertConfig().getImportantLevel(); } } } return importantLevel; } /** *

* Description: 获取邮件列表 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/9/25 */ public List getEmailList(List appUsers) { List emailList = new ArrayList(); if (appUsers != null && appUsers.size() > 0) { for (AppUser appUser : appUsers) { String email = appUser.getEmail(); if (StringUtils.isNotBlank(email)) { emailList.add(appUser.getEmail()); } } } return emailList; } /** * 检测是否在周期内 * * @param finalInstanceConfig * @return */ private boolean checkInCycle(InstanceAlertConfig finalInstanceConfig) { if (EnvUtil.isLocal(environment)) { return true; } // 检测周期转换为毫秒 long checkCycleMillionTime = finalInstanceConfig.getCheckCycleMillionTime(); // 当前距离上一次检测过去的毫秒 long betweenTime = new Date().getTime() - finalInstanceConfig.getLastCheckTime().getTime(); // 超过说明需要进行再测检测了 if (betweenTime >= checkCycleMillionTime) { return true; } return false; } /** * 判断当前实例是否在特殊报警配置中 * * @param specialInstanceAlertConfigList * @param instanceAlertConfig * @param instanceInfo * @return */ private InstanceAlertConfig filterSpecial(List specialInstanceAlertConfigList, InstanceAlertConfig instanceAlertConfig, InstanceInfo instanceInfo) { // 如果没有则返回原来的配置 if (CollectionUtils.isEmpty(specialInstanceAlertConfigList)) { return instanceAlertConfig; } // 寻找特殊配置 for (InstanceAlertConfig specialInstanceAlertConfig : specialInstanceAlertConfigList) { String specialAlertConfig = specialInstanceAlertConfig.getAlertConfig(); long instanceId = specialInstanceAlertConfig.getInstanceId(); // 配置名和实例id对上 if (instanceAlertConfig.getAlertConfig().equals(specialAlertConfig) && instanceInfo.getId() == instanceId) { return specialInstanceAlertConfig; } } return instanceAlertConfig; } /** * 获取指定时间内的标准统计信息Map * * @param beginTime * @param endTime * @return */ private Map getStandardStatsMap(Date beginTime, Date endTime) { List standardStatsList = standardStatsDao.getStandardStatsByCreateTime(beginTime, endTime, ConstUtils.REDIS); // 按照host:port做分组 Map resultMap = new HashMap(); for (StandardStats standardStats : standardStatsList) { String hostPort = standardStats.getIp() + ":" + standardStats.getPort(); resultMap.put(hostPort, standardStats); } return resultMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceDeployCenterImpl.java ================================================ package com.sohu.cache.stats.instance.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.AppAuditDao; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.MachineRelationDao; import com.sohu.cache.entity.*; import com.sohu.cache.entity.InstanceAlertValueResult; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.MachineRelation; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.machine.MachineDeployCenter; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.constant.MachineSyncEnum; import com.sohu.cache.task.constant.TaskQueueEnum; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.enums.MachineTaskEnum; import com.sohu.cache.web.enums.PodStatusEnum; import com.sohu.cache.web.service.AppAlertRecordService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.FreemakerUtils; import freemarker.template.Configuration; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import org.springframework.web.client.RestTemplate; import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import java.util.*; import java.util.concurrent.TimeUnit; /** * Created by yijunzhang on 14-11-26. */ @Service("instanceDeployCenter") public class InstanceDeployCenterImpl implements InstanceDeployCenter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private InstanceDao instanceDao; @Autowired private MachineRelationDao machineRelationDao; @Autowired @Lazy private RedisCenter redisCenter; @Autowired private RedisDeployCenter redisDeployCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private AppAuditDao appAuditDao; @Autowired private AppDao appDao; @Autowired private RedisConfigTemplateService redisConfigTemplateService; @Autowired EmailComponent emailComponent; @Autowired(required = false) RestTemplate restTemplate; @Autowired MachineDeployCenter machineDeployCenter; @Autowired TaskService taskService; @Autowired AssistRedisService assistRedisService; @Autowired private Configuration configuration; @Autowired private AppService appService; @Autowired private ResourceService resourceService; @Autowired private AppAlertRecordService appAlertRecordService; private final static String LINE_SEP = "\\n"; private final static String FAIL = "fail"; @Override public boolean startExistInstance(long appId, int instanceId) { Assert.isTrue(instanceId > 0L); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); int type = instanceInfo.getType(); String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 获取redis路径 SystemResource redisResource = resourceService.getResourceById(appDao.getAppDescById(appId).getVersionId()); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); // Redis资源校验&推包 Boolean installStatus = redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); if (!installStatus) { logger.info("{} is install :{}", host, redisResource.getName()); return false; } boolean isRun; if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { isRun = redisCenter.isRun(host, port); } else { isRun = redisCenter.isRun(appId, host, port); } if (isRun) { logger.warn("{}:{} instance is Running", host, port); } else { String runShell = ""; if (TypeUtil.isRedisCluster(type)) { runShell = redisDeployCenter.getRedisRunShell(true, host, port, redisDir); } else if (TypeUtil.isRedisSentinel(type)) { runShell = redisDeployCenter.getSentinelRunShell(host, port, redisDir); } else { runShell = redisDeployCenter.getRedisRunShell(false, host, port, redisDir); } boolean isRunShell = machineCenter.startProcessAtPort(host, port, runShell); if (!isRunShell) { logger.error("startProcessAtPort-> {}:{} shell= {} failed", host, port, runShell); return false; } else { logger.warn("{}:{} instance has Run", host, port); } if (TypeUtil.isRedisSentinel(type)) { isRun = redisCenter.isRun(host, port); } else { isRun = redisCenter.isRun(appId, host, port); } } } else { logger.error("type={} not match!", type); isRun = false; } if (isRun) { instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceDao.update(instanceInfo); } // 重置所有sentinel实例状态 if (TypeUtil.isRedisSentinel(type)) { try { redisDeployCenter.sentinelReset(appId); } catch (Exception e) { logger.error("redis sentinel reset error :{}", e.getMessage(), e); } } return isRun; } @Override public boolean startExistInstanceWithoutResourceCheck(long appId, int instanceId) { Assert.isTrue(instanceId > 0L); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); int type = instanceInfo.getType(); String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 获取redis路径 SystemResource redisResource = resourceService.getResourceById(appDao.getAppDescById(appId).getVersionId()); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); boolean isRun; if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { isRun = redisCenter.isRun(host, port); } else { isRun = redisCenter.isRun(appId, host, port); } if (isRun) { logger.warn("{}:{} instance is Running", host, port); } else { String runShell = ""; if (TypeUtil.isRedisCluster(type)) { runShell = redisDeployCenter.getRedisRunShell(true, host, port, redisDir); } else if (TypeUtil.isRedisSentinel(type)) { runShell = redisDeployCenter.getSentinelRunShell(host, port, redisDir); } else { runShell = redisDeployCenter.getRedisRunShell(false, host, port, redisDir); } boolean isRunShell = machineCenter.startProcessAtPort(host, port, runShell); if (!isRunShell) { logger.error("startProcessAtPort-> {}:{} shell= {} failed", host, port, runShell); return false; } else { logger.warn("{}:{} instance has Run", host, port); } if (TypeUtil.isRedisSentinel(type)) { isRun = redisCenter.isRun(host, port); } else { isRun = redisCenter.isRun(appId, host, port); } } } else { logger.error("type={} not match!", type); isRun = false; } if (isRun) { instanceInfo.setStatus(InstanceStatusEnum.GOOD_STATUS.getStatus()); instanceDao.update(instanceInfo); } // 重置所有sentinel实例状态 if (TypeUtil.isRedisSentinel(type)) { try { redisDeployCenter.sentinelReset(appId); } catch (Exception e) { logger.error("redis sentinel reset error :{}", e.getMessage(), e); } } return isRun; } @Override public boolean shutdownExistInstance(long appId, int instanceId) { Assert.isTrue(instanceId > 0L); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); int type = instanceInfo.getType(); String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); boolean isShutdown; if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { isShutdown = redisCenter.shutdown(host, port); // 重置reset sentinel实例状态 try { redisDeployCenter.sentinelReset(appId); } catch (Exception e) { logger.error("redis sentinel reset error :{}", e.getMessage(), e); } } else { isShutdown = redisCenter.shutdown(appId, host, port); } if (isShutdown) { logger.warn("{}:{} redis is shutdown", host, port); } else { logger.error("{}:{} redis shutdown error", host, port); } } else { logger.error("type={} not match!", type); isShutdown = false; } //check shutdown success if(isShutdown){ isShutdown = redisCenter.checkShutdownSuccess(instanceInfo); } if (isShutdown) { instanceInfo.setStatus(InstanceStatusEnum.OFFLINE_STATUS.getStatus()); instanceDao.update(instanceInfo); } return isShutdown; } @Override public boolean forgetInstance(long appId, int instanceId) { Assert.isTrue(instanceId > 0L); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); String nodeId = null; //获取应用下所有在线实例 List instanceList = appService.getAppOnlineInstanceInfo(appId); //找到一个运行的节点用来执行cluster nodes InstanceInfo firstRunning = null; for (InstanceInfo instance : instanceList) { //todo: 节点cluster node不能包含handshake?否则nodeId一直在变 if (redisCenter.isRun(appId, instance.getIp(), instance.getPort())) { firstRunning = instance; break; } } //先获取被forget节点的node id(cluster myid) String clusterNodes = redisCenter.getClusterNodes(appId, firstRunning.getIp(), firstRunning.getPort()); //从其他在线节点拿到cluster nodes nodeId = getNodeIdFromClusterNodes(clusterNodes, host, port); logger.warn("app {} instance {}:{} instanceId {} cluster node id {} will be forgot. cluster nodes\n{}", appId, host, port, instanceId, nodeId, clusterNodes); if (StringUtils.isNotBlank(nodeId)) { int forgetCount = 0; String instanceIp; int instancePort; for (InstanceInfo instanceInfo1 : instanceList) { instanceIp = instanceInfo1.getIp(); instancePort = instanceInfo1.getPort(); if (redisCenter.forget(appId, instanceIp, instancePort, nodeId)) { forgetCount++; logger.warn("instance {}:{} in app {} forget instance {}:{}-{} successfully", instanceIp, instancePort, appId, host, port, nodeId); } else { logger.error("instance {}:{} in app {} forget instance {}:{}-{} failed", instanceIp, instancePort, appId, host, port, nodeId); } } if (forgetCount == instanceList.size()) { //所有在线节点forget成功 instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.FORGET_STATUS.getStatus()); logger.warn("app {} forget&update instance {}:{} successfully. current cluster nodes\n{}", appId, host, port, redisCenter.getClusterNodes(appId, firstRunning.getIp(), firstRunning.getPort())); return true; } } else { //cluster nodes已经没有该节点,则直接将数据库状态改为InstanceStatusEnum.FORGET_STATUS.getStatus() instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.FORGET_STATUS.getStatus()); logger.warn("app {} update instance(nodeId is null) {}:{} successfully. current cluster nodes\n{}", appId, host, port, redisCenter.getClusterNodes(appId, firstRunning.getIp(), firstRunning.getPort())); return true; } return false; } @Override public boolean clearFailInstances(long appId) { try { //验证app类型是cluster AppDesc appDesc = appService.getByAppId(appId); if (appDesc.getType() != ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { logger.warn("app {} is not cluster!", appId); return false; } //找到一个运行的节点用来执行cluster nodes List instanceList = appService.getAppOnlineInstanceInfo(appId); InstanceInfo firstRun = null; for (InstanceInfo instanceInfo : instanceList) { if (redisCenter.isRun(appId, instanceInfo.getIp(), instanceInfo.getPort())) { firstRun = instanceInfo; break; } } if (firstRun == null) { logger.warn("app {} can not find an running instance!", appId); return false; } String clusterNodes = redisCenter.getClusterNodes(appId, firstRun.getIp(), firstRun.getPort()); //拿到cluster nodes if (StringUtils.isNotBlank(clusterNodes)) { String nodeId, hostPort, host, role; int port, total = 0; //total统计该应用共forget的节点数 String[] lines = clusterNodes.split(LINE_SEP); if (lines != null && lines.length > 0) { for (String line : lines) { if (line.contains(FAIL)) { //todo:其他判断条件 int count = 0; String[] items = line.split(" "); if (items != null && items.length > 0) { nodeId = items[0]; hostPort = items[1].split("@")[0]; host = hostPort.split(":")[0]; port = Integer.parseInt(hostPort.split(":")[1]); role = items[2]; for (InstanceInfo instance : instanceList) { if (redisCenter.forget(appId, instance.getIp(), instance.getPort(), nodeId)) { count++; } } if (count == instanceList.size()) { //所有节点都forget了该nodeId total++; instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.FORGET_STATUS.getStatus()); logger.warn("instance {}:{} id {} role {} was forgot by all online instances", host, port, nodeId, role); } } } } } clusterNodes = redisCenter.getClusterNodes(appId, firstRun.getIp(), firstRun.getPort()); //拿到cluster nodes logger.warn("app {} clear total {} fail nodes. current cluster nodes\n{}", appId, total, clusterNodes); return true; } } catch (Exception e) { logger.error("app {} clear fail nodes error!", appId, e); } return false; } private String getNodeIdFromClusterNodes(String clusterNodes, String host, int port) { String nodeId = null; String hostPort = host + ":" + port; if (StringUtils.isNotBlank(clusterNodes)) { String[] lines = clusterNodes.split(LINE_SEP); if (lines != null && lines.length > 0) { for (String line : lines) { if (line.contains(hostPort)) { String[] items = line.split(" "); if (items != null && items.length > 0) { nodeId = items[0]; break; } } } } } return nodeId; } @Override public String showInstanceRecentLog(int instanceId, int maxLineNum) { Assert.isTrue(instanceId > 0L); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); Assert.isTrue(instanceInfo != null); try { return machineCenter.showInstanceRecentLog(instanceInfo, maxLineNum); } catch (Exception e) { logger.error(e.getMessage(), e); return ""; } } @Override public boolean modifyInstanceConfig(long appId, Long appAuditId, String host, int port, String instanceConfigKey, String instanceConfigValue) { // Assert.isTrue(appAuditId != null && appAuditId > 0L); Assert.isTrue(StringUtils.isNotBlank(host)); Assert.isTrue(port > 0); Assert.isTrue(StringUtils.isNotBlank(instanceConfigKey)); // Assert.isTrue(StringUtils.isNotBlank(instanceConfigValue)); boolean isModify = redisDeployCenter.modifyInstanceConfig(appId, host, port, instanceConfigKey, instanceConfigValue); if (isModify && appAuditId != null) { // 改变审核状态 appAuditDao.updateAppAudit(appAuditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return isModify; } public MachineSyncEnum podChangeStatus(String ip) { // 获取pod变更历史 MachineSyncEnum syncEnum = null; List relationList = machineRelationDao.getOnlinePodList(ip, PodStatusEnum.ONLINE.getValue()); if (CollectionUtils.isEmpty(relationList) || relationList.size() == 1) { return MachineSyncEnum.NO_CHANGE; } else { // 1.当前pod的变更信息 MachineRelation current_podinfo = relationList.get(0); // 2.上一次pod的变更信息 MachineRelation pre_podinfo = relationList.get(1); // 3.判定宿主机是否变更 String sourceIp = pre_podinfo.getRealIp();//源宿主机 String targetIp = current_podinfo.getRealIp();//目标宿主机 if (!sourceIp.equals(targetIp)) { int relationId = pre_podinfo.getId(); String key = String.format("%s-%s", sourceIp, targetIp); try { // 3.1 保证只有同一个宿主机/目标宿主机执行同步任务 (多个pod ip对应一个宿主机) boolean setlock = assistRedisService.setNx(key, "sync"); if (setlock) { long taskId = taskService.addMachineSyncTask(sourceIp, targetIp, ip, String.format("sourceMachine:%s tagetMachine:%s ", sourceIp, targetIp), 0); if (taskId > 0) { logger.info("add machine sync task tashid:{} ", taskId); machineDeployCenter.updateMachineRelation(relationId, taskId, MachineTaskEnum.SYNCING.getValue()); // 3.2 探测 taskId 执行情况 10s轮训一次 long start = System.currentTimeMillis(); while (true) { TaskQueue taskQueue = taskService.getTaskQueueById(taskId); if (taskQueue.getStatus() == TaskQueueEnum.TaskStatusEnum.SUCCESS.getStatus()) { // a).同步任务执行完成退出 syncEnum = MachineSyncEnum.SYNC_SUCCESS; break; } if (taskQueue.getStatus() == TaskQueueEnum.TaskStatusEnum.ABORT.getStatus()) { // b).机器同步数据异常 发送邮件通知管理员 syncEnum = MachineSyncEnum.SYNC_ABORT; break; } logger.info("machine sync taskid:{} status:{} waitting .... sleep 10s ", taskId, taskQueue.getStatus()); TimeUnit.SECONDS.sleep(10); } String emailTitle = String.format("Pod重启机器同步任务报警"); String emailContent = String.format("Pod ip:%s 发生重启, 宿主机发生变更[%s]->[%s],机器同步任务id:(%s) 状态:(%s), 数据同步时间开销:(%s s)", ip, sourceIp, targetIp, taskId, syncEnum.getDesc(), (System.currentTimeMillis() - start) / 1000); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.POD_RESTART_SYNC_TASK, emailTitle, emailContent, ip); emailComponent.sendMailToAdmin(emailTitle, emailContent); } } else { return MachineSyncEnum.SYNC_EXECUTING; } } catch (Exception e) { logger.error("machine sync get lock error :{}", e.getMessage(), e); return MachineSyncEnum.SYNC_ERROR; } finally { assistRedisService.del(key); } } else { syncEnum = MachineSyncEnum.NO_CHANGE; String emailTitle = String.format("Pod重启机器同步任务报警"); String emailContent = String.format("Pod ip:%s 发生重启, 宿主机未变更[%s]->[%s] 状态:(%s)", ip, sourceIp, targetIp, syncEnum.getDesc()); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.POD_RESTART_SYNC_TASK, emailTitle, emailContent, ip); emailComponent.sendMailToAdmin(emailTitle, emailContent); } return syncEnum; } } @Override public List checkAndStartExceptionInstance(String ip, Boolean isAlert) { // 1.获取容器心跳停止/运行中的实例列表 List instanceInfos = instanceDao.checkHeartStopInstance(ip); List recoverInstInfo = new ArrayList<>(); // 2.滚动检测实例列表 if (!CollectionUtils.isEmpty(instanceInfos)) { for (InstanceInfo instance : instanceInfos) { long appId = instance.getAppId(); int instanceId = instance.getId(); String host = instance.getIp(); int port = instance.getPort(); int type = instance.getType(); logger.info("checkAndStartExceptionInstance scroll check instance {}:{} ", host, port); //2.1 检测实例是否启动 if (redisCenter.isRun(appId, ip, port)) { continue; } // 2.2 异常实例恢复 // 2.3 检测异常实例启动成功 & 加载完成数据 & 启动下一个实例 Jedis jedis = null; int retry = 1;//重试次数 try { startExistInstance(appId, instanceId); TimeUnit.SECONDS.sleep(5);//等待实例启动 if (TypeUtil.isRedisSentinel(type)) { jedis = redisCenter.getJedis(host, port); } else { jedis = redisCenter.getAdminJedis(appId, host, port); } while (true) { // 等待节点加载数据 & PONG String ping = ""; try { ping = jedis.ping(); } catch (JedisDataException e) { String message = e.getMessage(); logger.warn(e.getMessage()); if (StringUtils.isNotBlank(message) && message.startsWith("LOADING")) { logger.warn("scroll restart {}:{} waiting loading data ,sleep 2s", host, port); TimeUnit.SECONDS.sleep(2); } } catch (JedisConnectionException e){ logger.error("scroll restart {}:{} ping connect exception :{} ", host, port, e.getMessage(), e); break; //启动异常兼容 } catch (Exception e) { logger.error("scroll restart {}:{} ping exception sleep 200ms :{} ", host, port, e.getMessage(), e); TimeUnit.MILLISECONDS.sleep(200); } if (ping.equalsIgnoreCase("PONG") || retry++ >= 15) { InstanceAlertValueResult instanceAlertValueResult = new InstanceAlertValueResult(); instanceAlertValueResult.setInstanceInfo(instance); instanceAlertValueResult.setOtherInfo(DateUtil.formatYYYYMMddHHMMSS(new Date()));//实例恢复时间 recoverInstInfo.add(instanceAlertValueResult); break; } } } catch (Exception e) { logger.error("checkAndStartExceptionInstance {}:{} {} ", host, port, e.getMessage(), e); } finally { if (jedis != null) { try { jedis.close(); } catch (Exception e) { logger.error("jedis close exception {}:{} {} ", host, port, e.getMessage(), e); } } } } if (isAlert) { // 邮件通知:实例信息 恢复时间 String emailTitle = String.format("Pod重启探测Redis实例报警"); Map context = new HashMap<>(); context.put("instanceAlertValueResultList", recoverInstInfo); String emailContent = FreemakerUtils.createText("instanceRecover.ftl", configuration, context); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.POD_RESTART_INSTANCE_RECOVER, emailTitle, null, recoverInstInfo); emailComponent.sendMailToAdmin(emailTitle, emailContent.toString()); } } else { logger.info("checkAndStartExceptionInstance ip:{} has instances is empty ", ip); } return recoverInstInfo; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/stats/instance/impl/InstanceStatsCenterImpl.java ================================================ package com.sohu.cache.stats.instance.impl; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Table; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.RedisConstant; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.InstanceStatsDao; import com.sohu.cache.dao.StandardStatsDao; import com.sohu.cache.entity.*; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import java.util.*; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * Created by yijunzhang on 14-9-17. */ @Service("instanceStatsCenter") public class InstanceStatsCenterImpl implements InstanceStatsCenter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final ForkJoinPool forkJoinPool = new ForkJoinPool(20); @Autowired private InstanceDao instanceDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired private StandardStatsDao standardStatsDao; @Autowired @Lazy private RedisCenter redisCenter; @Override public InstanceInfo getInstanceInfo(long instanceId) { return instanceDao.getInstanceInfoById(instanceId); } @Override public InstanceStats getInstanceStats(long instanceId) { InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByInsId(instanceId); if (instanceStats == null) { logger.error("instanceStats id={} is null", instanceId); return null; } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); int type = instanceInfo.getType(); boolean isRun = redisCenter.isRun(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); instanceStats.setRun(isRun); if (isRun) { Map infoMap = getInfoMap(instanceInfo.getAppId(), type, instanceInfo.getIp(), instanceInfo.getPort()); instanceStats.setInfoMap(infoMap); if (infoMap == null || infoMap.isEmpty()) { instanceStats.setRun(false); } } return instanceStats; } private Map getInfoMap(long appId, int type, String ip, int port) { Map> infoMap = redisCenter.getInfoStats(appId, ip, port); Map resultMap = new LinkedHashMap(); if (infoMap != null) { for (Map.Entry> entry : infoMap.entrySet()) { resultMap.put(((RedisConstant) entry.getKey()).getValue(), entry.getValue()); } } return resultMap; } @Override public List getCommandStatsList(Long instanceId, long beginTime, long endTime, String commandName) { if (instanceId == null) { return Collections.emptyList(); } InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); List resultList = new ArrayList(); String ip = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); List> objectList = this.queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS); ; if (objectList != null) { for (Map map : objectList) { InstanceCommandStats stats = parseCommand(instanceId, commandName, map, true, type); if (stats != null) { resultList.add(stats); } } } return resultList; } @Override public Map>> getStandardStatsList(Long appId, long beginTime, long endTime, List commands) { if (appId == null) { return Collections.emptyMap(); } List list = instanceDao.getInstListByAppId(appId); if (list == null || list.isEmpty()) { return Collections.emptyMap(); } Map>> resultMap = new LinkedHashMap>>(); for (InstanceInfo instance : list) { if (instance.isOffline()) { continue; } int instanceId = instance.getId(); String ip = instance.getIp(); int port = instance.getPort(); int type = instance.getType(); // BooleanEnum isMaster = redisCenter.isMaster(appId, ip, port); // if (isMaster != BooleanEnum.TRUE) { // continue; // } List> objectList = this .queryDiffMapList(beginTime, endTime, ip, port, ConstUtils.REDIS); if (objectList != null) { Map> commandMap = new LinkedHashMap>(); for (String commandName : commands) { List resultList = new ArrayList(objectList.size()); for (Map map : objectList) { InstanceCommandStats stats = parseCommand(instanceId, commandName, map, false, type); if (stats != null) { resultList.add(stats); } } commandMap.put(commandName, resultList); } resultMap.put(instanceId, commandMap); } } return resultMap; } @Override public Table>> getInstanceMinuteStatsList(Long appId, long beginTime, long endTime, List commands) { if (appId == null) { return HashBasedTable.create(); } List list = instanceDao.getInstListByAppId(appId); if (list == null || list.isEmpty()) { return HashBasedTable.create(); } List onlineMasterList = list.stream() .filter(x -> !x.isOffline()) .filter(x -> BooleanEnum.TRUE == redisCenter.isMaster(appId, x.getIp(), x.getPort())) .collect(Collectors.toList()); long start = System.currentTimeMillis(); List taskList = onlineMasterList.stream() .map(x -> forkJoinPool.submit(new QueryDiffMapListTask(x, beginTime, endTime, commands, ConstUtils.REDIS))) .collect(Collectors.toList()); Table>> resultTable = HashBasedTable.create(); for (ForkJoinTask>>> task : taskList) { try { Table>> instanceTable = task.get(3000, TimeUnit.MILLISECONDS); resultTable.putAll(instanceTable); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("get total {} online master instances diffMapList cost sum {} ms", onlineMasterList.size(), (System.currentTimeMillis() - start)); return resultTable; } private InstanceCommandStats parseCommand(long instanceId, String command, Map commandMap, boolean isCommand, int type) { Long collectTime = MapUtils.getLong(commandMap, ConstUtils.COLLECT_TIME, null); if (collectTime == null) { return null; } Long count; if (isCommand) { count = MapUtils.getLong(commandMap, "cmdstat_" + command.toLowerCase(), null); } else { count = MapUtils.getLong(commandMap, command.toLowerCase(), null); } if (count == null) { return null; } InstanceCommandStats stats = new InstanceCommandStats(); stats.setCommandCount(count); stats.setCommandName(command); stats.setCollectTime(collectTime); stats.setCreateTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setModifyTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setInstanceId(instanceId); return stats; } private InstanceMinuteStats parseMinuteStats(long instanceId, String command, Map commandMap, boolean isCommand, int type) { Long collectTime = MapUtils.getLong(commandMap, ConstUtils.COLLECT_TIME, null); if (collectTime == null) { return null; } Double count; if (isCommand) { count = MapUtils.getDouble(commandMap, "cmdstat_" + command.toLowerCase(), null); } else { count = MapUtils.getDouble(commandMap, command.toLowerCase(), null); } if (count == null) { return null; } InstanceMinuteStats stats = new InstanceMinuteStats(); stats.setMemFragmentationRatio(count); stats.setCommandName(command); stats.setCollectTime(collectTime); stats.setCreateTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setModifyTime(DateUtil.getDateByFormat(String.valueOf(collectTime), "yyyyMMddHHmm")); stats.setInstanceId(instanceId); return stats; } @Override public String executeCommand(String host, int port, String command) { if (StringUtils.isBlank(host) || port == 0) { return "host or port is null"; } InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port); if (instanceInfo == null) { return "instance not exist"; } if (TypeUtil.isRedisType(instanceInfo.getType())) { return redisCenter.executeCommand(instanceInfo.getAppId(), host, port, command); } return "not support type"; } @Override public String executeCommand(Long instanceId, String command) { InstanceInfo instanceInfo = getInstanceInfo(instanceId); return executeCommand(instanceInfo.getIp(), instanceInfo.getPort(), command); } @Override public List getInstanceStats() { return instanceStatsDao.getInstanceStats(); } @Override public List getInstanceStats(String ip) { List instanceStatsList = instanceStatsDao.getInstanceStatsByIp(ip); return instanceStatsList; } @Override public boolean saveStandardStats(Map infoMap, Map clusterInfoMap, String ip, int port, String dbType) { Assert.isTrue(infoMap != null && infoMap.size() > 0); Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(infoMap.containsKey(ConstUtils.COLLECT_TIME), ConstUtils.COLLECT_TIME + " not in infoMap"); long collectTime = MapUtils.getLong(infoMap, ConstUtils.COLLECT_TIME); StandardStats ss = new StandardStats(); ss.setCollectTime(collectTime); ss.setIp(ip); ss.setPort(port); ss.setDbType(dbType); if (infoMap.containsKey(RedisConstant.DIFF.getValue())) { Map diffMap = (Map) infoMap.get(RedisConstant.DIFF.getValue()); ss.setDiffMap(diffMap); infoMap.remove(RedisConstant.DIFF.getValue()); } else { ss.setDiffMap(new HashMap(0)); } ss.setInfoMap(infoMap); ss.setClusterInfoMap(clusterInfoMap); int mergeStandardCount = standardStatsDao.mergeStandardStats(ss); int mergeInstanceCount = standardStatsDao.mergeInstanceMinuteStats(ss); return mergeStandardCount > 0 && mergeInstanceCount > 0; } @Override public Map queryStandardInfoMap(long collectTime, String ip, int port, String dbType) { Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(collectTime > 0); StandardStats ss = standardStatsDao.getStandardStats(collectTime, ip, port, dbType); if (ss != null) { Map infoMap = ss.getInfoMap(); Map diffMap = ss.getDiffMap(); infoMap.put(RedisConstant.DIFF.getValue(), diffMap); return infoMap; } else { return Collections.emptyMap(); } } @Override public List> queryDiffMapList(long beginTime, long endTime, String ip, int port, String dbType) { Assert.isTrue(StringUtils.isNotBlank(ip)); Assert.isTrue(port > 0); Assert.isTrue(beginTime > 0); Assert.isTrue(endTime > 0); List list = standardStatsDao.getDiffJsonList(beginTime, endTime, ip, port, dbType); if (list == null || list.isEmpty()) { return new ArrayList>(0); } List> resultList = new ArrayList>(list.size()); for (StandardStats ss : list) { Map diffMap = ss.getDiffMap(); diffMap.put(ConstUtils.COLLECT_TIME, ss.getCollectTime()); resultList.add(diffMap); } return resultList; } class QueryDiffMapListTask extends KeyCallable>>> { private InstanceInfo instance; private long beginTime; private long endTime; private List commands; private String dbType; public QueryDiffMapListTask(InstanceInfo instance, long beginTime, long endTime, List commands, String dbType) { super("QueryDiffMapListTask-" + instance.getIp() + ":" + instance.getPort()); this.instance = instance; this.beginTime = beginTime; this.endTime = endTime; this.commands = commands; this.dbType = dbType; } @Override public Table>> execute() { int instanceId = instance.getId(); String ip = instance.getIp(); int port = instance.getPort(); int type = instance.getType(); List> objectList = queryDiffMapList(beginTime, endTime, ip, port, dbType); Table>> table = HashBasedTable.create(); if (objectList != null) { Map> commandMap = new LinkedHashMap<>(); for (String commandName : commands) { List resultList = new ArrayList<>(objectList.size()); for (Map map : objectList) { InstanceMinuteStats stats = parseMinuteStats(instanceId, commandName, map, false, type); if (stats != null) { resultList.add(stats); } } commandMap.put(commandName, resultList); } table.put(instanceId, instance.getHostPort(), commandMap); } return table; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/swagger/Swagger2.java ================================================ package com.sohu.cache.swagger; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @ConditionalOnProperty(name = "springfox.documentation.enabled", havingValue = "true") @Configuration @EnableSwagger2 public class Swagger2 { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.sohu.cache.web.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("CacheCloud项目 RESTful APIs") .description("CacheCloud项目后台api接口文档") .version("3.0") .build(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/BaseTask.java ================================================ package com.sohu.cache.task; import com.google.common.collect.Lists; import com.sohu.cache.async.AsyncService; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.task.constant.InstanceInfoEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.NutCrackerNode; import com.sohu.cache.task.entity.RedisSentinelNode; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.task.util.AppWechatUtil; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.InstancePortService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.service.ToolService; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.util.SimpleFileUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.Marker; import org.slf4j.MarkerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; /** * @author fulei */ public abstract class BaseTask { protected Logger logger = LoggerFactory.getLogger(this.getClass()); public final static String MARKER_NAME = "task_logger"; public final static Marker marker = MarkerFactory.getMarker(MARKER_NAME); @Value("${spring.profiles.active}") protected String appEnvName; /** * 任务参数 */ protected Map paramMap; @Autowired protected InstanceBigKeyDao instanceBigKeyDao; @Autowired protected InstanceStatsDao instanceStatsDao; @Autowired protected AppEmailUtil appEmailUtil; @Autowired protected AppWechatUtil appWechatUtil; @Autowired protected MachineCenter machineCenter; @Autowired protected RedisConfigTemplateService redisConfigTemplateService; @Autowired protected AppService appService; @Autowired protected AppStatsCenter appStatsCenter; @Autowired protected SSHService sshService; @Autowired protected AppDao appDao; @Autowired protected RedisCenter redisCenter; @Autowired protected MachineDao machineDao; @Autowired protected InstanceDao instanceDao; @Autowired protected AppAuditDao appAuditDao; @Autowired protected TaskService taskService; @Autowired protected RedisDeployCenter redisDeployCenter; @Autowired protected MachineRoomDao machineRoomDao; @Autowired protected MachineStatsDao machineStatsDao; @Autowired protected MachineRelationDao machineRelationDao; @Autowired protected AssistRedisService assistRedisService; @Autowired protected InstancePortService instancePortService; @Autowired protected Environment environment; @Autowired protected InstanceDeployCenter instanceDeployCenter; @Autowired protected DiagnosticTaskRecordDao diagnosticTaskRecordDao; @Autowired protected ResourceService resourceService; @Autowired protected ResourceDao resourceDao; @Autowired protected ToolService toolService; @Autowired protected AppScrollRestartService appScrollRestartService; @Autowired protected AsyncService asyncService; /** * 任务id */ protected long taskId; /** * redis common启动模板文件 */ private final static String REDIS_COMMON_TEMPLATE_FILE = "scripts/redis_common_control.txt"; private final static String REDIS_COMMON_TEMPLATE_NO_CPUIDX_FILE = "scripts/redis_common_control_no_cpuidx.txt"; /** * nutcracker启动模板文件 */ private final static String NUT_CRACKER_TEMPLATE_FILE = "scripts/nutcracker_control.txt"; private final static String NUT_CRACKER_TEMPLATE_NO_CPUIDX_FILE = "scripts/nutcracker_control_no_cpuidx.txt"; /** * redis port启动模板文件 */ private final static String REDIS_PORT_TEMPLATE_FILE = "scripts/redis-port.txt"; /** * redis migrate启动模板文件 */ private final static String REDIS_MIGRATE_TOOL_TEMPLATE_FILE = "scripts/redis-migrate-tool.txt"; /** * pika启动模板文件 */ private final static String PIKA_TEMPLATE_FILE = "scripts/pika.txt"; public abstract List getTaskSteps(); public TaskFlowStatusEnum init() { taskId = MapUtils.getLongValue(paramMap, TaskConstants.TASK_ID_KEY); return TaskFlowStatusEnum.SUCCESS; } public Map getParamMap() { return paramMap; } public void setParamMap(Map paramMap) { this.paramMap = paramMap; } /** * 准备实例相关目录 * * @param appId * @param host * @param port * @param instanceTypeEnum * @return */ protected TaskFlowStatusEnum prepareRelateDir(long appId, String host, int port, InstanceInfoEnum.InstanceTypeEnum instanceTypeEnum) { //准备实例基准目录 todo return TaskFlowStatusEnum.SUCCESS; } /** * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ private List generateRedisPortServiceShell(int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { Map replaceMap = new HashMap(); replaceMap.put("${cpuidx}", String.valueOf(cpuidx)); replaceMap.put("${startcmd}", startCmd); replaceMap.put("${runcmd}", runCmd); replaceMap.put("${PID_FILE}", RedisProtocol.getRedisPortPidFilePath()); List resultList = generateRealShell(REDIS_PORT_TEMPLATE_FILE, replaceMap); if (CollectionUtils.isEmpty(resultList)) { logger.error(marker, "{} {} {} service shell is empty!", cpuidx, startCmd, runCmd); } return resultList; } /** * 生成实际shell * * @param replaceMap * @return */ private List generateRealShell(String templateFile, Map replaceMap) { List resultList = new ArrayList(); List lines = SimpleFileUtil.getListFromFile(templateFile, "utf-8"); for (String line : lines) { for (Entry entry : replaceMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (line.contains(key)) { line = line.replace(key, value); } } resultList.add(line); } return resultList; } /** * @param host * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ private List generateRedisCommonServiceShell(String host, int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { Map replaceMap = new HashMap(); replaceMap.put("${cpuidx}", String.valueOf(cpuidx)); replaceMap.put("${startcmd}", startCmd); replaceMap.put("${runcmd}", runCmd); MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo == null) { logger.error(marker, "machine {} is empty", host); return Collections.emptyList(); } String templateFile = machineInfo.isYunMachine() ? REDIS_COMMON_TEMPLATE_NO_CPUIDX_FILE : REDIS_COMMON_TEMPLATE_FILE; List resultList = generateRealShell(templateFile, replaceMap); if (CollectionUtils.isEmpty(resultList)) { logger.error(marker, "{} {} {} service shell is empty!", cpuidx, startCmd, runCmd); } return resultList; } /** * @param host * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ private List generateNutCrackerServiceShell(String host, int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { Map replaceMap = new HashMap(); replaceMap.put("${cpuidx}", String.valueOf(cpuidx)); replaceMap.put("${startcmd}", startCmd); replaceMap.put("${runcmd}", runCmd); MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo == null) { logger.error(marker, "machine {} is empty", host); return Collections.emptyList(); } String templateFile = machineInfo.isYunMachine() ? NUT_CRACKER_TEMPLATE_NO_CPUIDX_FILE : NUT_CRACKER_TEMPLATE_FILE; List resultList = generateRealShell(templateFile, replaceMap); if (CollectionUtils.isEmpty(resultList)) { logger.error(marker, "{} {} {} service shell is empty!", cpuidx, startCmd, runCmd); } return resultList; } /** * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ private List generateRedisMigrateServiceShell(int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { Map replaceMap = new HashMap(); replaceMap.put("${cpuidx}", String.valueOf(cpuidx)); replaceMap.put("${startcmd}", startCmd); replaceMap.put("${runcmd}", runCmd); List resultList = generateRealShell(REDIS_MIGRATE_TOOL_TEMPLATE_FILE, replaceMap); if (CollectionUtils.isEmpty(resultList)) { logger.error(marker, "{} {} {} service shell is empty!", cpuidx, startCmd, runCmd); } return resultList; } /** * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ private List generatePikaServiceShell(int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { Map replaceMap = new HashMap(); replaceMap.put("${cpuidx}", String.valueOf(cpuidx)); replaceMap.put("${startcmd}", startCmd); replaceMap.put("${runcmd}", runCmd); List resultList = generateRealShell(PIKA_TEMPLATE_FILE, replaceMap); if (CollectionUtils.isEmpty(resultList)) { logger.error(marker, "{} {} {} service shell is empty!", cpuidx, startCmd, runCmd); } return resultList; } /** * 生成并推service * * @param appId * @param host * @param port * @param instanceRemoteBasePath * @param instanceLocalTmpPath * @param cpuidx * @param startCmd * @param runCmd * @param serviceShellFileName * @return */ protected TaskFlowStatusEnum pushService(long appId, InstanceTypeEnum instanceTypeEnum, String host, int port, String instanceRemoteBasePath, String instanceLocalTmpPath, int cpuidx, String startCmd, String runCmd, String serviceShellFileName) { //生成和推送脚本 List serviceShell; if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_PORT)) { serviceShell = generateRedisPortServiceShell(cpuidx, startCmd, runCmd, serviceShellFileName); } else if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_MIGRATE_TOOL)) { serviceShell = generateRedisMigrateServiceShell(cpuidx, startCmd, runCmd, serviceShellFileName); } else if (instanceTypeEnum.equals(InstanceTypeEnum.NUTCRACKER)) { serviceShell = generateNutCrackerServiceShell(host, cpuidx, startCmd, runCmd, serviceShellFileName); } else if (instanceTypeEnum.equals(InstanceTypeEnum.PIKA)) { serviceShell = generatePikaServiceShell(cpuidx, startCmd, runCmd, serviceShellFileName); } else { serviceShell = generateRedisCommonServiceShell(host, cpuidx, startCmd, runCmd, serviceShellFileName); } String remoteFile = machineCenter.createRemoteFile(host, serviceShellFileName, serviceShell); if (StringUtils.isBlank(remoteFile)) { logger.error(marker, "{} {}:{} {} push fail", appId, host, port, remoteFile); return TaskFlowStatusEnum.ABORT; } //修改执行权限 //todo //ChmodEnum chmodEnum = ChmodEnum.EXECUTE; //String remoteFilePath = instanceRemoteBasePath + "/" + serviceShellFileName; //boolean isSuccess = machineCenter.chmod(host, remoteFilePath, chmodEnum); // if (!isSuccess) { // logger.error(marker, "{} {}:{} {} chmod +x fail", appId, host, port, remoteFilePath); // return TaskFlowStatusEnum.ABORT; // } return TaskFlowStatusEnum.SUCCESS; } /** * 准备相关bin * * @param appId * @param host * @param port * @param instanceTypeEnum * @param version * @return */ protected TaskFlowStatusEnum prepareRelateBin(long appId, String host, int port, InstanceTypeEnum instanceTypeEnum, String version) { AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { logger.error(marker, "appId {} get appDesc is empty", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 准备相关bin * * @param appId * @param host * @param port * @return */ protected TaskFlowStatusEnum preparePikaBin(long appId, String host, int port, InstanceTypeEnum instanceTypeEnum) { // todo return TaskFlowStatusEnum.SUCCESS; } /** * 实例进程是否存在 * * @param appId * @param host * @param port * @param instanceTypeEnum * @return */ protected TaskFlowStatusEnum checkInstanceIsExist(long appId, String host, int port, InstanceTypeEnum instanceTypeEnum) { //1. 检查目录是否存在 // String remoteBasePath = machineCenter.getInstanceRemoteBasePath(appId, port, instanceTypeEnum); // if (StringUtils.isBlank(remoteBasePath)) { // logger.error(marker, "appId {} host {} port {} remoteBasePath is empty", appId, host, port); // return TaskFlowStatusEnum.ABORT; // } // boolean isExist = machineCenter.checkExistDir(host, remoteBasePath); // if (isExist) { // logger.error(marker, "{} {} already exists", host, remoteBasePath); // return TaskFlowStatusEnum.ABORT; // } //2. 检查进程是否存在 if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_PORT)) { if (redisCenter.isRun(host, port)) { logger.error(marker, "{} {}:{} is already run", instanceTypeEnum.getInfo(), host, port); return TaskFlowStatusEnum.ABORT; } } else if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_SERVER) || instanceTypeEnum.equals(InstanceTypeEnum.REDIS_CLUSTER) || instanceTypeEnum.equals(InstanceTypeEnum.REDIS_SENTINEL) || instanceTypeEnum.equals(InstanceTypeEnum.PIKA) || instanceTypeEnum.equals(InstanceTypeEnum.NUTCRACKER) || instanceTypeEnum.equals(InstanceTypeEnum.CODIS_SERVER) || instanceTypeEnum.equals(InstanceTypeEnum.CODIS_PROXY)) { if (redisCenter.isRun(host, port)) { logger.error(marker, "{} {}:{} is already run", instanceTypeEnum.getInfo(), host, port); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 实例进程是否不存在(不和上面写一起了,虽然冗余了) * * @param appId * @param host * @param port * @param instanceTypeEnum * @return */ protected TaskFlowStatusEnum checkInstanceIsNotExist(long appId, String host, int port, InstanceTypeEnum instanceTypeEnum) { //todo return TaskFlowStatusEnum.SUCCESS; } /** * 保存实例信息 * * @param appId * @param host * @param port * @param maxMemory * @param instanceTypeEnum * @param instanceStatusEnum * @param cmd * @return */ protected Integer saveInstance(long appId, String host, int port, int maxMemory, InstanceTypeEnum instanceTypeEnum, InstanceStatusEnum instanceStatusEnum, String cmd) { InstanceInfo instanceInfo; try { instanceInfo = new InstanceInfo(); instanceInfo.setAppId(appId); MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo == null) { logger.error(marker, "host {} machineInfo is empty", host); return null; } instanceInfo.setHostId(machineInfo.getId()); instanceInfo.setMem(maxMemory); instanceInfo.setStatus(InstanceStatusEnum.NEW_STATUS.getStatus()); instanceInfo.setPort(port); instanceInfo.setType(instanceTypeEnum.getType()); instanceInfo.setCmd(cmd); instanceInfo.setIp(host); instanceDao.saveInstance(instanceInfo); logger.info(marker, "{} {}:{} save success", instanceTypeEnum.getInfo(), host, port); return instanceInfo.getId(); } catch (Exception e) { logger.error(marker, "{} {}:{} save error" + e.getMessage(), instanceTypeEnum.getInfo(), host, port, e); return null; } } /** * low b 版本 * * @param currentTaskId * @param timeoutSeconds 超时时间 * @return */ protected TaskFlowStatusEnum waitTaskFinish(long currentTaskId, int timeoutSeconds) { // 耗时 int totalSeconds = 0; while (true) { // 简单的计时器 long startTime = System.currentTimeMillis(); TaskQueue taskQueue = taskService.getTaskQueueById(currentTaskId); logger.warn("task {} totalSeconds is {}, timeout is {}, status:{}", currentTaskId, totalSeconds, timeoutSeconds, taskQueue.getStatusDesc()); if (taskQueue.isSuccess()) { return TaskFlowStatusEnum.SUCCESS; } else if (taskQueue.isAbort()) { return TaskFlowStatusEnum.ABORT; } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { logger.error(marker, e.getMessage(), e); } // 简单的计时器(秒) long costTime = System.currentTimeMillis() - startTime; totalSeconds += (costTime / 1000); if (totalSeconds > timeoutSeconds) { return TaskFlowStatusEnum.ABORT; } } } protected void sleepSeconds(int seconds) { try { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { logger.error(marker, e.getMessage(), e); } } /** * 获取所有master节点 * * @return */ protected List getAppMasterRedisServerNodes(long appId) { AppDesc appDesc = appDao.getAppDescById(appId); String appFullName = appDesc.getName(); if (StringUtils.isBlank(appFullName)) { logger.error(marker, "appId {} fullName is empty", appId); return Collections.emptyList(); } List masterRedisServerInfoList = appService.getAppMasterInstanceInfoList(appId); List masterRedisServerNodes = new ArrayList(); for (InstanceInfo instanceInfo : masterRedisServerInfoList) { RedisServerNode masterRedisServerNode = new RedisServerNode(); masterRedisServerNode.setIp(instanceInfo.getIp()); masterRedisServerNode.setPort(instanceInfo.getPort()); String masterName = generateMasterName(appDesc.getName(), instanceInfo.getPort()); masterRedisServerNode.setMasterName(masterName); masterRedisServerNodes.add(masterRedisServerNode); } return masterRedisServerNodes; } /** * 清理falcon * * @param instanceTypeEnum * @return */ protected TaskFlowStatusEnum clearFalconConfig(String host, InstanceTypeEnum instanceTypeEnum) { String config = ""; if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_SERVER)) { config = "/tmp/redisPort.txt"; } else if (instanceTypeEnum.equals(InstanceTypeEnum.NUTCRACKER)) { config = "/tmp/nutcrackerPort.txt"; } else if (instanceTypeEnum.equals(InstanceTypeEnum.REDIS_SENTINEL)) { config = "/tmp/redis_sentinel_port.txt"; } else if (instanceTypeEnum.equals(InstanceTypeEnum.PIKA)) { config = "/tmp/pika_port.txt"; } else if (instanceTypeEnum.equals(InstanceTypeEnum.MEMCACHE)) { config = "/tmp/memcache_port.txt"; } if (StringUtils.isNotBlank(config)) { try { String command = "echo '' > " + config; logger.info(marker, "{} execute command {}", host, command); machineCenter.executeShell(host, command); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } } else { logger.info(marker, "instanceTypeEnum {} falcon config is empty", instanceTypeEnum.getInfo()); } return TaskFlowStatusEnum.SUCCESS; } /** * 机器统计更新判断 * * @param machineStats * @return */ protected boolean checkMachineStatIsUpdate(MachineStats machineStats) { //todo return true; //Date updateTime = machineStats.getUpdateTime(); //return updateTime.getTime() > DateUtils.addHours(new Date(), -5).getTime(); } protected TaskFlowStatusEnum checkResourceAllow(List redisServerMachineList, long memoryNeed){ for (String redisServerIp : redisServerMachineList) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(redisServerIp); if (machineStats == null) { logger.error(marker, "{} redis server machineStats is null", redisServerIp); return TaskFlowStatusEnum.ABORT; } MachineInfo machineInfo = machineDao.getMachineInfoByIp(redisServerIp); if (machineInfo == null) { logger.error(marker, "redis server machine info is null"); return TaskFlowStatusEnum.ABORT; } // 机器是否分配 isAllocate if (machineInfo.getIsAllocating() == 1) { logger.error(marker, "redis server machine info {} {} allocating is 1", machineInfo.getIp(), redisServerIp); return TaskFlowStatusEnum.ABORT; } if (!checkMachineStatIsUpdate(machineStats)) { logger.error(marker, "redis server machine stats {} update_time is {}, may be not updated recently", machineInfo.getIp(), machineStats.getUpdateTimeFormat()); return TaskFlowStatusEnum.ABORT; } //兆 long memoryFree = NumberUtils.toLong(machineStats.getMemoryFree()) / 1024 / 1024; if (memoryNeed > memoryFree * 0.85) { logger.error(marker, "{} need {} MB, but memoryFree is {} MB", redisServerIp, memoryNeed, memoryFree); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 计算quorum * * @return */ protected int getQuorum(int sentinelSize) { int quorum; if (sentinelSize % 2 == 0) { quorum = sentinelSize / 2; } else { quorum = sentinelSize / 2 + 1; } return Math.max(quorum, 1); } /** * 执行一个ls命令,确认ssh以及不是只读盘 * * @return */ protected boolean checkMachineIsConnect(String ip) { try { SSHTemplate.Result result = sshService.executeWithResult(ip, "ls / | wc -l"); if (result.isSuccess()) { return true; } } catch (Exception e) { logger.error(marker, e.getMessage()); e.printStackTrace(); } return false; } protected TaskFlowStatusEnum checkMachineConnect(List ipList, String errorTip) { for (String redisServerIp : ipList) { boolean isConnected = checkMachineIsConnect(redisServerIp); if (!isConnected) { logger.error(marker, errorTip, redisServerIp); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 获取复制master需要等待的秒数 * * @param masterHost * @param masterPort * @return */ protected int getSlaveOfSleepSeconds(String masterHost, int masterPort) { InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByHost(masterHost, masterPort); long usedMemoryMB = instanceStats.getUsedMemory() / 1024 / 1024; //40MB一秒,一分钟2GB int seconds = (int) (usedMemoryMB / 40 + 5); logger.info(BaseTask.marker, "{}:{} usedMemory is {}MB need sleep {} seconds", masterHost, masterPort, usedMemoryMB, seconds); return seconds; } protected List transformNutCrackerFromInstance(List instanceInfoList) { List nutCrackerNodes = new ArrayList(); for (InstanceInfo instanceInfo : instanceInfoList) { NutCrackerNode nutCrackerNode = new NutCrackerNode(instanceInfo.getIp(), instanceInfo.getPort()); nutCrackerNodes.add(nutCrackerNode); } return nutCrackerNodes; } protected List transformRedisSentinelFromInstance(List instanceInfoList) { List redisSentinelNodes = new ArrayList(); for (InstanceInfo instanceInfo : instanceInfoList) { RedisSentinelNode redisSentinelNode = new RedisSentinelNode(instanceInfo.getIp(), instanceInfo.getPort()); redisSentinelNodes.add(redisSentinelNode); } return redisSentinelNodes; } /** * 生成masterName * * @param appFullName * @param port * @return */ public static String generateMasterName(String appFullName, int port) { return appFullName + "-" + port; } /** * @param redisServerNodes * @param appId * @return */ protected List buildRedisServerNodes(List redisServerNodes, long appId) { List list = Lists.newArrayList(); if (CollectionUtils.isEmpty(redisServerNodes)) { List instanceInfoList = appService.getAppMasterInstanceInfoList(appId); redisServerNodes = transformRedisServerFromInstance(instanceInfoList); list.addAll(redisServerNodes); } else { for (RedisServerNode redisServerNode : redisServerNodes) { list.add(new RedisServerNode(redisServerNode.getIp(), redisServerNode.getPort())); } } return list; } private List transformRedisServerFromInstance(List instanceInfoList) { List redisServerNodes = new ArrayList<>(); for (int i = 0; i < instanceInfoList.size(); i++) { InstanceInfo instanceInfo = instanceInfoList.get(i); RedisServerNode redisServerNode = new RedisServerNode(); redisServerNode.setIp(instanceInfo.getIp()); redisServerNode.setPort(instanceInfo.getPort()); redisServerNodes.add(redisServerNode); } return redisServerNodes; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/TaskService.java ================================================ package com.sohu.cache.task; import com.sohu.cache.constant.OperateResult; import com.sohu.cache.entity.AppUser; import com.sohu.cache.task.constant.PikaNode; import com.sohu.cache.task.constant.TaskQueueEnum.TaskStatusEnum; import com.sohu.cache.task.entity.*; import java.util.List; import java.util.Map; /** * 任务相关 */ public interface TaskService { /** * 执行任务 * * @param taskId * @return */ TaskStatusEnum executeTask(long taskId); /** * @param taskId * @return */ List getTaskStepFlowList(long taskId); /** * @param taskId * @return */ TaskQueue getTaskQueueById(long taskId); /** * 任务流描述信息 * * @param className * @return */ List getTaskStepMetaList(String className); /** * 获取当前任务流 * * @param taskId * @return */ TaskStepFlow getCurrentTaskStepFlow(long taskId); /** * 添加pika实例安装任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addPikaInstallTask(long appId, String host, int port, long parentTaskId); /** * 添加redis server实例安装任务 * * @param appId * @param host * @param port * @param maxMemory * @param version * @param parentTaskId */ long addRedisServerInstallTask(long appId, String host, int port, int maxMemory, String version, Boolean isCluster, long parentTaskId); /** * 添加redis server实例stop任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addRedisServerStopTask(long appId, String host, int port, long parentTaskId); /** * 添加memcache实例stop任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addMemcacheStopTask(long appId, String host, int port, long parentTaskId); /** * 添加memcache集群下线 * * @param appId * @param auditId * @param parentTaskId */ long addMemcacheClusterOfflineTask(long appId, long auditId, long parentTaskId); /** * 添加pika实例stop任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addPikaStopTask(long appId, String host, int port, long parentTaskId); /** * 添加redis server实例start任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addRedisServerStartTask(long appId, String host, int port, long parentTaskId); /** * 添加redis sentinel实例安装任务 * * @param appId * @param host * @param port * @param masterRedisServerNodes * @param quorum * @param dbVersion * @param parentTaskId * @return */ long addRedisSentinelInstallTask(long appId, String host, int port, List masterRedisServerNodes, int quorum, String dbVersion, long parentTaskId); /** * 添加redis sentinel实例stop任务 * * @param appId * @param host * @param port * @param parentTaskId * @return */ long addRedisSentinelStopTask(long appId, String host, int port, long parentTaskId); /** * 添加redis port实例安装任务 * * @param appId * @param redisPortHost * @param redisPortHttpPort * @param sourceHost * @param sourcePort * @param targetHost * @param targetPort * @param parentTaskId * @return */ // long addRedisPortInstallTask(long appId, String redisPortHost, int redisPortHttpPort, String sourceHost, // int sourcePort, String targetHost, int targetPort, long parentTaskId); /** * 添加redis migrate tool任务 * * @param migrateToolHost * @param migrateToolPort * @param sourceAppId * @param targetAppId * @param sourceRedisServerNodes * @param parentTaskId * @return */ long addRedisMigrateToolInstallTask(String migrateToolHost, int migrateToolPort, long sourceAppId, long targetAppId, List sourceRedisServerNodes, long parentTaskId); /** * 添加nutcracker实例 * * @param appId * @param host * @param port * @param masterRedisServerNodes * @param parentTaskId */ long addNutCrackerInstallTask(long appId, String host, int port, List masterRedisServerNodes, long parentTaskId); /** * 添加codis proxy实例 * * @param appId * @param host * @param port * @param parentTaskId */ long addCodisProxyInstallTask(long appId, String host, int port, long parentTaskId); /** * 添加codis dashboard实例 * * @param appId * @param host * @param port * @param parentTaskId */ long addCodisDashboardTask(long appId, String host, int port, long parentTaskId); /** * 添加nutcracker实例stop任务 * * @param appId * @param host * @param port * @param parentTaskId */ long addNutCrackerStopTask(long appId, String host, int port, long parentTaskId); /** * 添加清理redisserver数据任务 * * @param appId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerFlushDataTask(long appId, String host, int port, long parentTaskId); /** * 应用刷新配置 * * @param appId * @param appIsNew * @param parentTaskId * @return */ long addAppConfigFlushZkTask(long appId, Boolean appIsNew, long parentTaskId); /** * 添加twemproxy应用 * * @param appId * @param auditId * @param maxMemory * @param redisServerMachineList * @param redisSentinelMachineList * @param nutCrackerMachineList * @param masterPerMachine * @param sentinelPerMachine * @param nutCrackerPerMachine * @param isNeedFlushZkConfig 是否要刷新zk配置 * @param version * @param parentTaskId * @return */ long addTwemproxyAppTask(long appId, long auditId, int maxMemory, List redisServerMachineList, List redisSentinelMachineList, List nutCrackerMachineList, int masterPerMachine, int sentinelPerMachine, int nutCrackerPerMachine, Boolean isNeedFlushZkConfig, String version, long parentTaskId); /** * redis standalone * * @param appId 应用id * @param appAuditId 审核id * @param maxMemory 实例内存 * @param redisServerMachineList 部署节点 * @param masterPerMachine 部署实例数 * @param dbVersion redis版本 * @param parentTaskId 父任务id * @return */ long addRedisStandaloneAppTask(long appId, long appAuditId, int maxMemory, List redisServerMachineList, int masterPerMachine, String dbVersion, long parentTaskId); /** * redis cluster集群 * * @param appId 应用id * @param appAuditId 审核id * @param maxMemory 实例内存 * @param appDeployInfoList 部署节点信息(masterIp:memory:slaveIp) * @param redisServerMachineList 部署节点 * @param masterPerMachine 部署实例数 * @param dbVersion redis版本 * @param parentTaskId 父任务id * @return */ long addRedisClusterAppTask(long appId, long appAuditId, int maxMemory, List appDeployInfoList, List redisServerMachineList, int masterPerMachine, String dbVersion, long parentTaskId); /** * redis sentinel集群 * * @param appId * @param appAuditId * @param maxMemory * @param redisServerMachineList * @param redisSentinelMachineList * @param masterPerMachine * @param sentinelPerMachine * @param dbVersion * @param parentTaskId * @return */ long addRedisSentinelAppTask(long appId, long appAuditId, int maxMemory, List redisServerMachineList, List redisSentinelMachineList, int masterPerMachine, int sentinelPerMachine, String dbVersion, long parentTaskId); /** * 添加twemproxy pika * * @param appId * @param auditId * @param maxMemory * @param pikaMachineList * @param redisSentinelMachineList * @param nutCrackerMachineList * @param masterPerMachine * @param sentinelPerMachine * @param nutCrackerPerMachine * @param isNeedFlushZkConfig 是否要刷新zk配置 * @param parentTaskId * @return */ long addTwemproxyPikaTask(long appId, long auditId, int maxMemory, List pikaMachineList, List redisSentinelMachineList, List nutCrackerMachineList, int masterPerMachine, int sentinelPerMachine, int nutCrackerPerMachine, Boolean isNeedFlushZkConfig, long parentTaskId); /** * pika sentinel * * @param appId * @param appAuditId * @param maxMemory * @param pikaMachineList * @param redisSentinelMachineList * @param masterPerMachine * @param sentinelPerMachine * @param parentTaskId * @return */ long addPikaSentinelAppTask(long appId, long appAuditId, int maxMemory, List pikaMachineList, List redisSentinelMachineList, int masterPerMachine, int sentinelPerMachine, long parentTaskId); /** * twemproxy redis下线 * * @param appId * @param auditId * @param parentTaskId * @return */ long addTwemproxyOfflineTask(long appId, long auditId, long parentTaskId); /** * redis sentinel app下线 * * @param appId * @param auditId * @param parentTaskId * @return */ long addRedisSentinelAppOfflineTask(long appId, long auditId, long parentTaskId); /** * pika sentinel app下线 * * @param appId * @param auditId * @param parentTaskId * @return */ long addPikaSentinelAppOfflineTask(long appId, long auditId, long parentTaskId); /** * twemproxy pika下线 * * @param appId * @param auditId * @param parentTaskId * @return */ long addTwemproxyPikaOfflineTask(long appId, long auditId, long parentTaskId); /** * twemproxy -> twemproxy * * @param sourceAppId * @param targetAppId * @param appAuditId * @param isScaleOut * @param parentTaskId * @return */ long addTwemproxyToTwemproxyTask(long sourceAppId, long targetAppId, long appAuditId, boolean isScaleOut, long parentTaskId); /** * twemproxy -> twemproxy(v2) * * @param sourceAppId * @param targetAppId * @param appAuditId * @param isScaleOut * @param onlyMigrate * @param parentTaskId * @return */ long addTwemproxyToTwemproxyTaskV2(long sourceAppId, long targetAppId, long appAuditId, boolean isScaleOut, boolean onlyMigrate, long parentTaskId); /** * 备库重搭 * * @param appId * @param masterHost * @param masterPort * @param slaveMachineHost * @param parentTaskId * @return */ long addSlaveRedisServerRebuildTask(long appId, String masterHost, int masterPort, String slaveMachineHost, long parentTaskId); /** * pika备库重搭 * * @param appId * @param masterHost * @param masterPort * @param slaveMachineHost * @param parentTaskId * @return */ long addSlavePikaRebuildTask(long appId, String masterHost, int masterPort, String slaveMachineHost, long parentTaskId); /** * sentinel failover * * @param appId * @param masterHost * @param masterPort * @param parentTaskId * @return */ long addSlaveRedisSentinelFailoverTask(long appId, String masterHost, int masterPort, long parentTaskId); /** * 实例idle key分析任务 * * @param appId * @param auditId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerIdleKeyAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId); /** * 实例idle key分析任务 * * @param appId * @param auditId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerKeyTypeAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId); /** * 实例key ttl分析任务 * * @param appId * @param auditId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerKeyTtlAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId); /** * 实例key value size分析任务 * * @param appId * @param auditId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerKeyValueAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId); /** * 实例big key分析任务 * * @param appId * @param auditId * @param host * @param port * @param parentTaskId * @return */ long addRedisServerBigKeyAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId); /** * twemproxy key分析任务 * * @param appId * @param auditId * @param parentTaskId * @return */ long addAppKeyAnalysisTask(long appId, long auditId, long parentTaskId); /** * twemproxy flushall任务 * * @param appId * @param auditId * @param parentTaskId * @return */ long addTwemproxyFlushAllDataTask(long appId, long auditId, long parentTaskId); /** * twemproxy pika flushall任务 * * @param appId * @param auditId * @param parentTaskId * @return */ long addTwemproxyPikaFlushAllDataTask(long appId, long auditId, long parentTaskId); /** * @param host * @param port * @param sourceAppId * @param targetAppId * @param parentTaskId * @return */ long addRemoveRedisMigrateToolTask(String host, int port, long sourceAppId, long targetAppId, long parentTaskId); /** * 添加nut cracker扩容任务 * * @param appId * @param nutCrackerMachineList * @param nutCrackerPerMachine * @param parentTaskId * @return */ long addNutCrackerScaleOutTask(long appId, List nutCrackerMachineList, int nutCrackerPerMachine, long parentTaskId); /** * 添加nut cracker批量下线任务 * * @param appId * @param nutCrackerNodes * @param parentTaskId * @return */ long addNutCrackerListOfflineTask(long appId, List nutCrackerNodes, long parentTaskId); /** * 添加redis sentinel批量下线任务 * * @param appId * @param redisSentinelNodes * @param parentTaskId * @return */ long addRedisSentinelListOfflineTask(long appId, List redisSentinelNodes, long parentTaskId); /** * 添加redis slave server批量下线任务 * * @param appId * @param redisServerNodes * @param parentTaskId * @return */ long addRedisSlaveServerOfflineTask(long appId, List redisServerNodes, long parentTaskId); /** * 添加pika slave批量下线任务 * * @param appId * @param pikaNodes * @param parentTaskId * @return */ long addPikaSlaveOfflineTask(long appId, List pikaNodes, long parentTaskId); /** * 添加redis sentinel添加任务 * * @param appId * @param redisSentinelMachineList * @param dbVersion * @param parentTaskId * @return */ long addRedisSentinelAddTask(long appId, List redisSentinelMachineList, String dbVersion, long parentTaskId); /** * 为故障机器添加批量failover * * @param appId * @param host * @param parentTaskId * @return */ long addTwemproxyFaultMachineFailoverTask(long appId, String host, long parentTaskId); /** * 为应用故障机器做备库重搭 * * @param appId * @param host * @param parentTaskId * @return */ long addMachineSlaveRebuildTask(long appId, String host, long parentTaskId); long addAppTopologyExamTask(boolean auto, int examType, long appId, long parentTaskId); long addMachineExamTask(List ipList, Integer useType, long parentTaskId); long addOffLineAppTask(long appId, Long auditId, long parentTaskId, AppUser userInfo); /** * scan key * * @param appId * @param auditId * @param pattern * @param size * @param parentTaskId * @return */ long addAppScanKeyTask(long appId, long auditId, String nodes, String pattern, int size, long parentTaskId); long addInstanceScanKeyTask(long appId, long auditId, String host, int port, String pattern, int size, long parentTaskId); long addInstanceScanCleanKeyTask(long appId, long auditId, String host, int port, Map params, long parentTaskId); /** * delete key * * @param appId * @param nodes * @param pattern * @param auditId * @param parentTaskId * @return */ long addAppDelKeyTask(long appId, String nodes, String pattern, long auditId, long parentTaskId); long addInstanceDelKeyTask(long appId, String host, int port, String pattern, long auditId, long parentTaskId); /** * bigkey * * @param appId * @param nodes * @param fromBytes * @param toBytes * @param auditId * @param parentTaskId * @return */ long addAppBigKeyTask(long appId, String nodes, long fromBytes, long toBytes, int size, long auditId, long parentTaskId); long addInstanceBigKeyTask(long appId, String host, int port, long fromBytes, long toBytes, int size, long auditId, long parentTaskId); /** * idle key * * @param appId * @param nodes * @param idleTime * @param auditId * @param parentTaskId * @return */ long addAppIdleKeyTask(long appId, String nodes, long idleTime, int size, long auditId, long parentTaskId); long addInstanceIdleKeyTask(long appId, String host, int port, long idleTime, int size, long auditId, long parentTaskId); /** * hot key * * @param appId * @param nodes * @param command * @param auditId * @param parentTaskId * @return */ long addAppHotKeyTask(long appId, String nodes, String command, long auditId, long parentTaskId); long addInstanceHotKeyTask(long appId, String host, int port, String command, long auditId, long parentTaskId); /** * slotAnalysis * * @param appId * @param nodes * @param auditId * @param parentTaskId * @return */ long addAppSlotAnalysisTask(long appId, String nodes, long auditId, long parentTaskId); long addInstanceSlotAnalysisTask(long appId, String host, int port, long auditId, long parentTaskId); /** * scan key * @param appId * @param auditId * @param parentTaskId * @return */ long addAppScanCleanTask(long appId, Map params, long auditId, long parentTaskId); /** * 更新childTaskId * * @param taskStepFlowId * @param masterChildTaskId */ void updateTaskStepFlowChildTaskId(long taskStepFlowId, long masterChildTaskId); /** * 任务状态 * * @param taskStatusEnum */ List getTaskQueueList(TaskStatusEnum taskStatusEnum); /** * 更新任务状态 * * @param taskId * @param taskStatusEnum */ void updateTaskQueueStatus(long taskId, TaskStatusEnum taskStatusEnum); /** * @param taskSearch * @return */ int getTaskQueueCount(TaskSearch taskSearch); /** * @param taskSearch * @return */ List getTaskQueueList(TaskSearch taskSearch); /** * @param searchTaskId * @return */ List getTaskQueueTreeByTaskId(long searchTaskId); /** * 修改任务参数 * * @param taskId * @param param */ OperateResult updateParam(long taskId, String param); /** * 执行新任务 */ void executeNewTask(); /** * @param taskFlowId * @param status * @return */ OperateResult updateTaskFlowStatus(long taskFlowId, int status); /** * @param appId * @param className * @return */ List getByAppAndClass(long appId, String className); /** * 添加机器同步数据任务task */ long addMachineSyncTask(String sourceIp, String targetIp, String containerIp, String important_Info, long parentTaskId); long addResourceCompileTask(Integer resourceId, Integer repositoryId, String containerIp, AppUser userInfo); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/IdleTimeDistriEnum.java ================================================ package com.sohu.cache.task.constant; import com.sohu.cache.util.NumberUtil; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * ilde time时间范围 * * @author fulei */ public enum IdleTimeDistriEnum { BETWEEN_MIN_TO_0_HOURS("-2147483648_0", "非法", 1), BETWEEN_0_TO_1_HOURS("0_1", "0-1小时", 2), BETWEEN_1_TO_2_HOURS("1_2", "1-2小时", 3), BETWEEN_2_TO_5_HOURS("2_5", "2-5小时", 4), BETWEEN_5_TO_10_HOURS("5_10", "5-10小时", 5), BETWEEN_10_TO_24_HOURS("10_24", "10-24小时", 6), BETWEEN_24_TO_120_HOURS("24_120", "1-5天", 7), BETWEEN_120_TO_240_HOURS("120_240", "5-10天", 8), BETWEEN_240_TO_720_HOURS("240_720", "10-30天", 9), BETWEEN_720_TO_MAX_HOURS("720_2147483647", "30天以上", 10); public static final Map MAP; static { Map tmpMap = new HashMap<>(); for (IdleTimeDistriEnum enumObject : IdleTimeDistriEnum.values()) { tmpMap.put(enumObject.getValue(), enumObject); } MAP = Collections.unmodifiableMap(tmpMap); } private String value; private String info; private int type; private IdleTimeDistriEnum(String value, String info, int type) { this.value = value; this.info = info; this.type = type; } public static IdleTimeDistriEnum getByValue(String targetValue) { return MAP.get(targetValue); } /** * 查看Idle在哪个区间 * * @param costTime * @return */ public static IdleTimeDistriEnum getRightIdleDistri(long costTime) { IdleTimeDistriEnum[] enumArr = IdleTimeDistriEnum.values(); for (IdleTimeDistriEnum enumObject : enumArr) { if (isInSize(enumObject, costTime)) { return enumObject; } } return null; } /** * 确定length在指定区间 * * @param enumObject * @param costTime * @return */ private static boolean isInSize(IdleTimeDistriEnum enumObject, long costTime) { String value = enumObject.getValue(); int index = value.indexOf("_"); int start = NumberUtil.toInt(value.substring(0, index)); int end = NumberUtil.toInt(value.substring(index + 1)); if (costTime >= start && costTime < end) { return true; } return false; } public String getValue() { return value; } public String getInfo() { return info; } public int getType() { return type; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/InstanceInfoEnum.java ================================================ package com.sohu.cache.task.constant; import java.util.HashMap; import java.util.Map; /** * @author fulei */ public class InstanceInfoEnum { /** * 实例状态 * * @author fulei * @date 2018年6月22日 * @time 下午1:53:07 */ public enum InstanceStatusEnum { NEW_STATUS(-1, "元数据,没有真实实例"), ERROR_STATUS(0, "心跳停止"), GOOD_STATUS(1, "运行中"), OFFLINE_STATUS(2, "已下线"), PAUSE_STATUS(3, "暂停"); private int status; private String info; private static Map MAP = new HashMap(); static { for (InstanceStatusEnum instanceStatusEnum : InstanceStatusEnum.values()) { MAP.put(instanceStatusEnum.getStatus(), instanceStatusEnum); } } public static InstanceStatusEnum getByStatus(int status) { return MAP.get(status); } private InstanceStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } /** * redis-port状态 */ public enum RedisPortStatusEnum { NEW_STATUS(0, "新节点"), GOOD_STATUS(1, "运行中"), SYNC_FINISH_STATUS(2, "同步完成"), PAUSE_STATUS(3, "暂停"), OFFLINE(4, "下线"), ERROR(5, "异常"), ; private int status; private String info; private static Map MAP = new HashMap(); static { for (RedisPortStatusEnum redisPortStatusEnum : RedisPortStatusEnum.values()) { MAP.put(redisPortStatusEnum.getStatus(), redisPortStatusEnum); } } public static RedisPortStatusEnum getByStatus(int status) { return MAP.get(status); } RedisPortStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } /** * redis-port状态 * * @author fulei * @date 2018年6月22日 * @time 下午1:53:07 */ public enum RedisMigrateToolStatusEnum { NEW_STATUS(0, "新节点"), GOOD_STATUS(1, "运行中"), SYNC_FINISH_STATUS(2, "同步完成"), PAUSE_STATUS(3, "暂停"), OFFLINE(4, "下线"), ERROR(5, "异常"), ; private int status; private String info; private static Map MAP = new HashMap(); static { for (RedisMigrateToolStatusEnum redisMigrateToolStatusEnum : RedisMigrateToolStatusEnum.values()) { MAP.put(redisMigrateToolStatusEnum.getStatus(), redisMigrateToolStatusEnum); } } public static RedisMigrateToolStatusEnum getByStatus(int status) { return MAP.get(status); } RedisMigrateToolStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } /** * 实例类型 * */ public enum InstanceTypeEnum { NUTCRACKER(1, "nutcracker", "nutcracker", "nutcracker"), REDIS_CLUSTER(2, "redis-cluster", "redis-cluster", "redis"), CODIS_PROXY(3, "codis-proxy", "codis-proxy", "codis"), PIKA(4, "pika", "pika", "pika"), REDIS_SENTINEL(5, "sentinel", "sentinel", "redis"), REDIS_SERVER(6, "redis", "redis-server", "redis"), MEMCACHE(7, "memcache", "memcache", "memcache"), REDIS_MIGRATE_TOOL(8, "redis-migrate-tool", "redis-migrate-tool", "redis-migrate-tool"), CODIS_SERVER(9, "codis-server", "codis-server", "codis"), CODIS_DASHBOARD(10, "codis-dashboard", "codis-dashboard", "codis"), REDIS_PORT(11, "redis-port", "redis-port", "redis-port"), ; private int type; /** * 目录用,不要改 */ private String name; private String info; private String localDir; private static Map MAP = new HashMap(); static { for (InstanceTypeEnum instanceTypeEnum : InstanceTypeEnum.values()) { MAP.put(instanceTypeEnum.getType(), instanceTypeEnum); } } public static InstanceTypeEnum getByType(int type) { return MAP.get(type); } private InstanceTypeEnum(int type, String name, String info, String localDir) { this.type = type; this.name = name; this.info = info; this.localDir = localDir; } public int getType() { return type; } public String getName() { return name; } public String getInfo() { return info; } public String getLocalDir() { return localDir; } } /** * 是否报警 */ public static enum InstanceWarnEnum { YES(1), NO(0); private int value; private InstanceWarnEnum(int value) { this.value = value; } public int getValue() { return value; } } /** * 是否是临时实例 */ public static enum InstanceTempEumn { YES(1), NO(0); private int value; private InstanceTempEumn(int value) { this.value = value; } public int getValue() { return value; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/InstanceRoleEnum.java ================================================ package com.sohu.cache.task.constant; import java.util.HashMap; import java.util.Map; /** * @author fulei * @date 2018年6月27日 */ public enum InstanceRoleEnum { MASTER(1, "master"), SLAVE(2, "slave"), SENTINEL(3,"sentinel"); private static Map MAP = new HashMap(); static { for (InstanceRoleEnum instanceRoleEnum : InstanceRoleEnum.values()) { MAP.put(instanceRoleEnum.getRole(), instanceRoleEnum); } } public static InstanceRoleEnum getInstanceRoleEnum(int role) { return MAP.get(role); } private int role; private String info; private InstanceRoleEnum(int role, String info) { this.role = role; this.info = info; } public int getRole() { return role; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/MachineExamContants.java ================================================ package com.sohu.cache.task.constant; /** * Created by rucao on 2019/1/23 */ public class MachineExamContants { public final static double BASE_RATIO=1.0; public final static double defult_memUseThreshold=0.80; public final static double middle_memUseThreshold=0.75; public final static double small_memUseThreshold=0.70; public final static String MACHINE_IP="machineIp"; public final static String MEM="mem"; public final static String CPU="cpu"; public final static String USED_MEM="used_mem"; public final static String APPLY_MEM="apply_mem"; public final static String USED_CPU="used_cpu"; public final static String USED_MEM_RATIO="used_mem_ratio"; public final static String APPLY_MEM_RATIO="apply_mem_ratio"; public final static String USED_CPU_RATIO="used_cpu_ratio"; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/MachineSyncEnum.java ================================================ package com.sohu.cache.task.constant; /** * Created by chenshi on 2020/5/18. */ public enum MachineSyncEnum { NO_CHANGE(0, "不执行同步任务"), SYNC_EXECUTING(4, "同步任务执行中..."), SYNC_SUCCESS(1, "同步任务成功"), SYNC_ABORT(2, "同步任务中断"), SYNC_ERROR(3, "同步任务异常"); private int value; private String desc; public int getValue() { return value; } public String getDesc() { return desc; } MachineSyncEnum(int value, String desc) { this.value = value; this.desc = desc; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/PikaNode.java ================================================ package com.sohu.cache.task.constant; import lombok.Data; /** * @author fulei * @date 2018年6月26日 */ @Data public class PikaNode { private long taskId; private String ip; private int port; private int role; private String masterHost; private int masterPort; private String masterName; public PikaNode() { } public PikaNode(String ip, int port) { this.ip = ip; this.port = port; } public PikaNode(String ip, int port, String masterName) { this.ip = ip; this.port = port; this.masterName = masterName; } public PikaNode(String ip, int port, int role, String masterHost, int masterPort) { this.ip = ip; this.port = port; this.role = role; this.masterHost = masterHost; this.masterPort = masterPort; } public String genHostAndPort() { return masterHost + ":" + masterPort; } public String getUniqKey() { return ip + "-" + port + "-" + masterName; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/PushEnum.java ================================================ package com.sohu.cache.task.constant; /** * Created by chenshi on 2020/7/7. */ public enum PushEnum { NO(0, "未推送"), YES(1, "已推送"), NO_WITH_MODIFY(2, "未推送,有新修改"), YES_WITH_MODIFY(3, "已推送,有新修改"), COMPILEING(4,"编译中"); private int value; private String desc; public int getValue() { return value; } public String getDesc() { return desc; } PushEnum(int value, String desc) { this.value = value; this.desc = desc; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/RedisDataStructureTypeEnum.java ================================================ package com.sohu.cache.task.constant; public enum RedisDataStructureTypeEnum { string("string"), hash("hash"), list("list"), set("set"), zset("zset"); private String value; private RedisDataStructureTypeEnum(String value) { this.value = value; } public String getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/ResourceEnum.java ================================================ package com.sohu.cache.task.constant; /** * Created by chenshi on 2020/7/6. */ public enum ResourceEnum { ALL(0, "所有资源"), Repository(1, "仓库管理"), SCRIPT(2, "脚本管路"), REDIS(3, "Redis资源管理"), SSHKEY(4, "sshkey管理"), DOCKERFILE(5, "镜像管理"), DIR(6, "目录管理"), TOOL(7, "迁移工具管理"); private int value; private String desc; public int getValue() { return value; } public String getDesc() { return desc; } ResourceEnum(int value, String desc) { this.value = value; this.desc = desc; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/ScanCleanConstants.java ================================================ package com.sohu.cache.task.constant; /** * 键匹配相关常量 * * @author zengyizhao */ public class ScanCleanConstants { /** * 操作类型,仅分析,分析清理,分析重置ttl */ public final static String OPERATE_TYPE = "operateType"; /** * 指定节点 */ public final static String POINTED_NODES = "nodes"; /** * 匹配串 */ public final static String PATTERN = "pattern"; /** * ttl 超时 */ public final static String TTL_LESS = "ttlLess"; public final static String TTL_MORE = "ttlMore"; /** * 重置ttl超时设置 */ public final static String TTL_RESET_LESS = "ttlResetLess"; public final static String TTL_RESET_MORE = "ttlResetMore"; /** * 每次scan数量 */ public final static String PER_COUNT = "perCount"; /** * 单个实例最大处理数量 */ public final static String MAX_HANDLE_COUNT = "maxHandleCount"; public final static String OPERATE_ANALYSE = "0"; public final static String OPERATE_CLEAN = "1"; public final static String OPERATE_TTL_RESET = "2"; public final static Integer COMPARE_TYPE_LESS_THAN = 0; public final static Integer COMPARE_TYPE_MORE_THAN = 1; public final static String NODE_TYPE_SLAVE = "allSlave"; public final static String NODE_TYPE_MASTER = "allMaster"; public final static int REDIS_SCAN_CLEAN_TIMEOUT = 7200; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/TaskConstants.java ================================================ package com.sohu.cache.task.constant; import com.sohu.cache.task.tasks.MachineSyncTask; import com.sohu.cache.task.tasks.RedisClusterAppDeployTask; import com.sohu.cache.task.tasks.RedisSentinelAppDeployTask; import com.sohu.cache.task.tasks.RedisStandaloneAppDeployTask; import com.sohu.cache.task.tasks.daily.MachineExamTask; import com.sohu.cache.task.tasks.daily.TopologyExamTask; import com.sohu.cache.task.tasks.install.RedisSentinelInstallTask; import com.sohu.cache.task.tasks.install.RedisServerInstallTask; import com.sohu.cache.task.tasks.resource.PackCompileTask; /** * 任务相关常量 * * @author fulei */ public class TaskConstants { /** * init方法 */ public final static String INIT_METHOD_KEY = "init"; /** * 任务id */ public final static String TASK_ID_KEY = "taskId"; /** * 任务流id */ public final static String TASK_STEP_FLOW_ID = "taskStepFlowId"; /** * 各种类型实例列表 */ //单个实例 public final static String REDIS_SERVER_NODE_KEY = "redisServerNode"; public final static String REDIS_SERVER_NODES_KEY = "redisServerNodes"; public final static String REDIS_SENTINEL_NODES_KEY = "redisSentinelNodes"; public final static String NUT_CRACKER_NODES_KEY = "nutCrackerNodes"; public final static String REDIS_PORT_NODES_KEY = "redisPortNodes"; public final static String REDIS_MIGRATE_TOOL_NODES_KEY = "redisMigrateToolNodes"; public final static String PIKA_NODES_KEY = "pikaNodes"; public final static String PIKA_NODE_KEY = "pikaNode"; public final static String MEMCACHE_NODES_KEY = "memcacheNodes"; /** * for codis */ public final static String CODIS_SERVER_NODES_KEY = "codisServerNodes"; public final static String CODIS_PROXY_NODES_KEY = "codisProxyNodes"; public final static String CODIS_DASHBOARD_NODES_KEY = "codisDashboardNodes"; /** * 主节点列表 */ public final static String MASTER_REDIS_SERVER_NODES = "masterRedisServerNodes"; /** * 实例信息 */ public final static String APPID_KEY = "appId"; public final static String AUDIT_ID_KEY = "auditId"; public final static String HOST_KEY = "host"; public final static String PORT_KEY = "port"; public final static String VERSION_KEY = "db_version"; public final static String IS_CLUSTER_KEY = "is_cluster"; public final static String MASTER_HOST_KEY = "master_host"; public final static String MASTER_PORT_KEY = "master_port"; public final static String SLAVE_MACHINE_KEY = "slave_machine"; public final static String SLAVE_MACHINE_LIST_KEY = "slave_machine_list"; public final static String MACHINE_IP_LIST_KEY = "machineIpList"; public final static String USE_TYPE_KEY = "useType"; public final static String EXAM_TYPE_KEY = "examType"; public final static String USER_INFO_KEY = "user_info_key"; /** * redis-port相关 */ public final static String HTTP_PORT_KEY = "http_port"; public final static String SOURCE_HOST_KEY = "source_host"; public final static String SOURCE_PORT_KEY = "source_port"; public final static String SOURCE_PASSWORD_KEY = "source_password"; public final static String TARGET_HOST_KEY = "target_host"; public final static String TARGET_PORT_KEY = "target_port"; public final static String TARGET_PASSWORD_KEY = "target_password"; /** * 机器相关 */ public final static String CONTAINER_IP = "container_ip"; /** * 资源信息 */ public final static String RESOURCE_ID = "resource_id"; public final static String REPOSITORY_ID = "repository_id"; /** * flush config */ public final static String APP_IS_NEW_KEY = "appIsNew"; /** * twemproxy */ public final static String APP_DEPLOY_INFO_LIST_KEY = "appDeployInfoList"; public final static String REDIS_SERVER_MACHINE_LIST_KEY = "redisServerMachineList"; public final static String REDIS_SENTINEL_MACHINE_LIST_KEY = "redisSentinelMachineList"; public final static String NUT_CRACKER_MACHINE_LIST_KEY = "nutCrackerMachineList"; public final static String MASTER_PER_MACHINE_KEY = "masterPerMachine"; public final static String SENTINEL_PER_MACHINE_KEY = "sentinelPerMachine"; public final static String NUT_CRACKER_PER_MACHINE_KEY = "nutCrackerPerMachine"; /** * pika */ public final static String PIKA_MACHINE_LIST_KEY = "pikaMachineList"; /** * for codis */ public final static String CODIS_SERVER_MACHINE_LIST_KEY = "codisServerMachineList"; public final static String CODIS_PRORY_MACHINE_LIST_KEY = "codisProxyMachineList"; public final static String CODIS_DASHBOARD_MACHINE_LIST_KEY = "codisDashboardMachineList"; public final static String CODIS_PROXY_PER_MACHINE_KEY = "codisProxyPerMachine"; /** * redis sentinel quorum */ public final static String REDIS_SENTINEL_QUORUM_KEY = "quorum"; /** * redis server maxmemory */ public final static String REDIS_SERVER_MAX_MEMORY_KEY = "maxMemory"; /** * flush zk config taskId */ public final static String FLUSH_ZK_CONFIG_TASKID_KEY = "flushZkConfigTaskId"; /** * offline slave taskId */ public final static String OFFLINE_SLAVE_TASKID_KEY = "offlineSlaveTaskId"; /** * 是否需要刷新zk */ public static final String IS_NEED_FLUSH_ZK_CONFIG_KEY = "isNeedFlushZkConfig"; /** * stopRmtTaskId */ public final static String STOP_RMT_TASKID_KEY = "stopRmtTaskId"; /** * offlineSourceAppTaskId */ public final static String OFFLINE_SOURCE_APP_TASKID_KEY = "offlineSourceAppTaskId"; /** * 扩容 */ public final static String IS_SCALE_OUT_KEY = "isScaleOut";//是否是扩容 public final static String IS_ONLY_MIGRATE_KEY = "isOnlyMigrate";//是否仅是迁移 public final static String SOURCE_APP_ID_KEY = "sourceAppId"; public final static String TARGET_APP_ID_KEY = "targetAppId"; /** * redis server安装超时时间 */ public final static int REDIS_SERVER_INSTALL_TIMEOUT = 600; /** * pika安装超时时间 */ public final static int PIKA_INSTALL_TIMEOUT = 600; /** * codis server安装超时时间 */ public final static int CODIS_SERVER_INSTALL_TIMEOUT = 300; /** * redis server下线超时时间 */ public final static int REDIS_SERVER_OFFLINE_TIMEOUT = 300; /** * memcache下线超时时间 */ public final static int MEMCACHE_OFFLINE_TIMEOUT = 300; /** * pika下线超时时间 */ public final static int PIKA_OFFLINE_TIMEOUT = 300; /** * redis sentinel安装超时时间 */ public final static int REDIS_SENTINEL_INSTALL_TIMEOUT = 600; /** * redis sentinel下线超时时间 */ public final static int REDIS_SENTINEL_OFFLINE_TIMEOUT = 300; /** * nutcracker安装超时时间 */ public final static int NUT_CRACKER_INSTALL_TIMEOUT = 600; /** * codis proxy安装超时时间 */ public final static int CODIS_PROXY_INSTALL_TIMEOUT = 300; /** * codis dashboard安装超时时间 */ public final static int CODIS_DASHBOARD_INSTALL_TIMEOUT = 300; /** * nutcracker下线装超时时间 */ public final static int NUT_CRACKER_OFFLINE_TIMEOUT = 300; /** * redis port安装超时时间 */ public final static int REDIS_PORT_INSTALL_TIMEOUT = 300; /** * 刷zk配置超时 */ public final static int FLUSH_ZK_CONFIG_TIMEOUT = 300; /** * 下线slave超时 */ public final static int OFFLINE_SLAVE_TIMEOUT = 600; /** * rmt remove超时 */ public final static int RMT_REMOVE_TIMEOUT = 300; /** * rmt start超时 */ public final static int RMT_INSTALL_TIMEOUT = 300; /** * 应用下线超时 */ public final static int APP_OFFLINE_TIMEOUT = 600; /** * rmt同步超时时间 */ public final static int RMT_SYNC_TIMEOUT = 3600 * 4; /** * 等待proxy重启完成时间 */ public final static int NUTCRACKER_ALL_RESTART_TIMEOUT = 600; /** * redis server idle key分析超时时间 */ public final static int REDIS_SERVER_IDLE_KEY_ANALYSIS_TIMEOUT = 3600; /** * redis server key type分析超时时间 */ public final static int REDIS_SERVER_KEY_TYPE_ANALYSIS_TIMEOUT = 3600; /** * redis server key ttl分析超时时间 */ public final static int REDIS_SERVER_KEY_TTL_ANALYSIS_TIMEOUT = 3600; /** * redis server key value size分析超时时间 */ public final static int REDIS_SERVER_KEY_VALUE_SIZE_ANALYSIS_TIMEOUT = 10800; /** * redis server big key分析超时时间 */ public final static int REDIS_SERVER_BIG_KEY_ANALYSIS_TIMEOUT = 3600; /** * single rmt max used memory */ public final static int SINGLE_RMT_USED_MEMORY_GB = 400; /** * max rmt count */ public final static int MAX_RMT_COUNT = 3; /** * redis server big key分析超时时间 */ public final static int REDIS_SERVER_DIAGNOSTIC_TIMEOUT = 3600; // /** // * pika实例安装class name // */ // public final static String PIKA_INSTANCE_INSTALL_CLASS = PikaInstanceInstallTask.class.getSimpleName(); // // /** // * twemproxy pika实例安装class name // */ // public final static String TWEMPROXY_PIKA_OFFLINE_CLASS = TwemproxyPikaOfflineTask.class.getSimpleName(); // // /** * redis server实例安装class name */ public final static String REDIS_SERVER_INSTANCE_INSTALL_CLASS = RedisServerInstallTask.class.getSimpleName(); /** * redis sentinel实例安装class name */ public final static String REDIS_SENTINEL_INSTANCE_INSTALL_CLASS = RedisSentinelInstallTask.class.getSimpleName(); // /** // * redis port实例安装class name // */ // public final static String REDIS_PORT_INSTANCE_INSTALL_CLASS = RedisPortInstallTask.class.getSimpleName(); // // /** // * redis migrate tool实例安装class name // */ // public final static String REDIS_MIGRATE_TOOL_INSTANCE_INSTALL_CLASS = RedisMigrateToolInstallTask.class.getSimpleName(); // // /** // * nutcracker实例安装class name // */ // public final static String NUT_CRACKER_INSTANCE_INSTALL_CLASS = NutCrackerInstallTask.class.getSimpleName(); // /** * redis sentinel应用安装class name */ public final static String REDIS_SENTINEL_APP_DEPLOY_CLASS = RedisSentinelAppDeployTask.class.getSimpleName(); /** * redis cluster应用安装class name */ public final static String REDIS_CLUSTER_APP_DEPLOY_CLASS = RedisClusterAppDeployTask.class.getSimpleName(); /** * redis standalone应用安装class name */ public final static String REDIS_STANDALONE_APP_DEPLOY_CLASS = RedisStandaloneAppDeployTask.class.getSimpleName(); // // /** // * redis sentinel应用安装class name // */ // public final static String PIKA_SENTINEL_APP_INSTALL_CLASS = PikaSentinelInstallTask.class.getSimpleName(); // // /** // * twemproxy应用安装class name // */ // public final static String TWEM_PROXY_APP_INSTALL_CLASS = TwemproxyAppInstallTask.class.getSimpleName(); // // /** // * twemproxy pika应用安装class name // */ // public final static String TWEM_PROXY_PIKA_INSTALL_CLASS = TwemproxyPikaInstallTask.class.getSimpleName(); // // /** // * nutcracker扩容 // */ // public final static String NUT_CRACKER_SCALE_OUT_CLASS = NutCrackerScaleOutTask.class.getSimpleName(); // // /** // * nutcracker下线 // */ // public final static String NUT_CRACKER_LIST_OFFLINE_CLASS = NutCrackerListOfflineTask.class.getSimpleName(); // // /** // * sentinel下线 // */ // public final static String REDIS_SENTINEL_LIST_OFFLINE_CLASS = AppRedisSentinelOfflineTask.class.getSimpleName(); // // /** // * redis slave server下线 // */ // public final static String REDIS_SLAVE_SERVER_OFFLINE_CLASS = RedisSlaveServerOfflineTask.class.getSimpleName(); // // /** // * pika slave下线 // */ // public final static String PIKA_SLAVE_OFFLINE_CLASS = PikaSlaveOfflineTask.class.getSimpleName(); // // /** // * 添加redis sentinel // */ // public final static String REDIS_SENTINEL_ADD_CLASS = RedisSentinelAddTask.class.getSimpleName(); // // /** // * 应用刷新配置 // */ // public final static String APP_CONFIG_FLUSH_ZK_CLASS = AppConfigFlushZkTask.class.getSimpleName(); // // /** // * twemproxy -> twemproxy // */ // public final static String TWEMPROXY_TO_TWEMPROXY_CLASS = TwemproxyToTwemproxyTask.class.getSimpleName(); // // /** // * twemproxy -> twemproxy(v2) // */ // public final static String TWEMPROXY_TO_TWEMPROXY_V2_CLASS = TwemproxyToTwemproxyTaskV2.class.getSimpleName(); // // /** // * 删除redis migrate tool // */ // public final static String REDIS_MIGRATE_TOOL_REMOVE_CLASS = RedisMigrateToolRemoveTask.class.getSimpleName(); // // // /** // * flush redis server data // */ // public final static String REDIS_SERVER_FLUSH_CLASS = RedisServerFlushDataTask.class.getSimpleName(); // // /** // * analysis redis server idle key // */ // public final static String REDIS_SERVER_IDLE_KEY_ANALYSIS_CLASS = RedisServerIdleKeyAnalysisTask.class.getSimpleName(); // // /** // * analysis redis server key type // */ // public final static String REDIS_SERVER_KEY_TYPE_ANALYSIS_CLASS = RedisServerKeyTypeAnalysisTask.class.getSimpleName(); // // /** // * analysis redis server key ttl // */ // public final static String REDIS_SERVER_KEY_TTL_ANALYSIS_CLASS = RedisServerKeyTtlAnalysisTask.class.getSimpleName(); // // /** // * analysis redis server key value size // */ // public final static String REDIS_SERVER_KEY_VALUE_SIZE_ANALYSIS_CLASS = RedisServerKeyValueAnalysisTask.class.getSimpleName(); // // // // /** // * analysis twemproxy key // */ // public final static String TWEMPROXY_KEY_ANALYSIS_CLASS = TwemproxyKeyAnalysisTask.class.getSimpleName(); // // /** // * twemproxy flushall data // */ // public final static String TWEMPROXY_FLUSHALL_DATA_CLASS = TwemproxyFlushDataTask.class.getSimpleName(); // // /** // * twemproxy pika flushall data // */ // public final static String TWEMPROXY_PIKA_FLUSHALL_DATA_CLASS = TwemproxyPikaFlushDataTask.class.getSimpleName(); // // /** // * stop redis server // */ // public final static String REDIS_SERVER_STOP_CLASS = RedisServerStopTask.class.getSimpleName(); // // /** // * stop memcache // */ // public final static String MEMCACHE_STOP_CLASS = MemcacheStopTask.class.getSimpleName(); // // /** // * offline memcache // */ // public final static String MEMCACHE_CLUSTER_OFFLINE_CLASS = MemcacheClusterOfflineTask.class.getSimpleName(); // // /** // * stop redis server // */ // public final static String REDIS_SERVER_START_CLASS = RedisServerStartTask.class.getSimpleName(); // // /** // * stop pika // */ // public final static String PIKA_STOP_CLASS = PikaStopTask.class.getSimpleName(); // // /** // * stop redis sentinel // */ // public final static String REDIS_SENTINEL_STOP_CLASS = RedisSentinelStopTask.class.getSimpleName(); // // /** // * stop nutcracker // */ // public final static String NUT_CRACKER_STOP_CLASS = NutCrackerStopTask.class.getSimpleName(); // // /** // * 下线twemproxy // */ // public final static String TWEMPROXY_OFFLINE_CLASS = TwemproxyOfflineTask.class.getSimpleName(); // // /** // * 下线redis sentinel app // */ // public final static String REDIS_SENTINEL_APP_OFFLINE_CLASS = RedisSentinelAppOfflineTask.class.getSimpleName(); // // /** // * 下线pika sentinel app // */ // public final static String PIKA_SENTINEL_APP_OFFLINE_CLASS = PikaSentinelAppOfflineTask.class.getSimpleName(); // // /** // * 备库重搭redis // */ // public final static String REDIS_SLAVE_SERVER_REBUILD_CLASS = RedisSlaveServerRebuildTask.class.getSimpleName(); // // /** // * 备库重搭pika // */ // public final static String PIKA_SLAVE_REBUILD_CLASS = PikaSlaveRebuildTask.class.getSimpleName(); // // /** // * sentinel failover // */ // public final static String REDIS_SENTINEL_FAILOVER_CLASS = RedisSentinelFailoverTask.class.getSimpleName(); // // /** // * machine slave rebuild // */ // public final static String MACHINE_SLAVE_REBUILD_CLASS = MachineSlaveRebuildTask.class.getSimpleName(); // // /** // * twemproxy fault machine failover // */ // public final static String TWEMPROXY_FAULT_MACHINE_FAILOVER_CLASS = TwemproxyFaultMachineFailoverTask.class.getSimpleName(); // // // /** // * codis server实例安装class name // */ // public final static String CODIS_SERVER_INSTANCE_INSTALL_CLASS = CodisServerInstallTask.class.getSimpleName(); // // /** // * codis proxy实例安装class name // */ // public final static String CODIS_PROXY_INSTANCE_INSTALL_CLASS = CodisProxyInstallTask.class.getSimpleName(); // // // /** // * codis dashboard实例安装class name // */ // public final static String CODIS_DASHBOARD_INSTANCE_INSTALL_CLASS = CodisDashboardInstallTask.class.getSimpleName(); /** * 应用拓扑故障检查class name */ public final static String TOPOLOGY_EXAM_CLASS = TopologyExamTask.class.getSimpleName(); /** * 机器使用情况检查 class name */ public final static String MACHINE_EXAM_CLASS = MachineExamTask.class.getSimpleName(); /** * 机器同步数据任务 className */ public final static String MACHINE_SYNC_CLASS = MachineSyncTask.class.getSimpleName(); public final static String PACK_COMPILE_TASK = PackCompileTask.class.getSimpleName(); /** * 最大内存限制(MB) */ public final static int MAX_MEMORY_LIMIT = 1024 * 10; /** * 一次分配每个机器最大rediserver实例数 */ public final static int MAX_MASTER_PER_MACHINE = 50; /** * 一份分配每个机器最大nutcracker数 */ public final static int MAX_NUT_CRACK_PER_MACHINE = 50; /** * 一份分配每个机器最大codis proxy数 */ public final static int MAX_CODIS_PROXY_PER_MACHINE = 15; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/TaskQueueEnum.java ================================================ package com.sohu.cache.task.constant; import java.util.HashMap; import java.util.Map; /** * 任务队列状态枚举 */ public class TaskQueueEnum { public enum TaskStatusEnum { NEW(0, "新任务"), RUNNING(1, "运行中"), ABORT(2, "中断"), //FAIL(3, "失败"), SUCCESS(4, "成功"), READY(5, "准备执行"), TERMINATE(6, "终止"); private static Map MAP = new HashMap(); static { for (TaskStatusEnum taskStatusEnum : TaskStatusEnum.values()) { MAP.put(taskStatusEnum.getStatus(), taskStatusEnum); } } public static TaskStatusEnum getTaskStatusEnum(int status) { return MAP.get(status); } private int status; private String info; private TaskStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } /** * 错误代码 */ public enum TaskErrorCodeEnum { RIGHT(0, "正确"); private int code; private String info; TaskErrorCodeEnum(int code, String info) { this.code = code; this.info = info; } public int getCode() { return code; } public String getInfo() { return info; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/TaskStepFlowEnum.java ================================================ package com.sohu.cache.task.constant; import com.google.common.collect.Maps; import java.util.Map; /** * 任务步骤流程 * @author fulei */ public class TaskStepFlowEnum { /** * 任务流状态 */ public enum TaskFlowStatusEnum { READY(0, "准备"), RUNNING(1, "运行中"), ABORT(2, "中断"), // FAIL(3, "失败"), SUCCESS(4, "成功"), SKIP(5, "跳过"); private static Map MAP = Maps.newHashMap(); static { for (TaskFlowStatusEnum taskFlowStatusEnum : TaskFlowStatusEnum.values()) { MAP.put(taskFlowStatusEnum.getStatus(), taskFlowStatusEnum); } } public static TaskFlowStatusEnum getTaskFlowStatusEnum(int status) { return MAP.get(status); } private int status; private String info; TaskFlowStatusEnum(int status, String info) { this.status = status; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/TopoloyExamContants.java ================================================ package com.sohu.cache.task.constant; /** * Created by rucao on 2019/1/22 */ public class TopoloyExamContants { public final static String APPID="appId"; public final static String TYPE="type"; public final static String STATUS="status"; public final static String DESC="desc"; public final static String REDIS_STANDALONE="redis-standalone"; public final static String REDIS_CLUSTER="redis-cluster"; public final static String REDIS_SENTINEL="redis-sentinel"; public final static String INSTANCE_FORMAT="{0}:{1}:{2} 宿主机:{3}
"; public final static String CLUSTER_INSTANCE_FORMAT="{0}:{1}:{2} 宿主机:{3}
"; public final static String NETSEGMENT_FORMAT="存在至少两个网段,网段1:{0},网段2:{1}"; public final static String MASTER_SLAVE_DESC="主从节点分布同一台物理机"; public final static String SLAVE_NOT_EXIST="主节点没有从节点"; public final static String NODESNUM_DESC="集群节点分布在少于3台物理机"; public final static String CLUSTER_FAILOVER_DESC="集群中一台物理机宕机不满足故障转移条件"; public final static String NETSEGMENT_DESC="集群节点不在同网段"; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/TtlTimeDistriEnum.java ================================================ package com.sohu.cache.task.constant; import com.sohu.cache.util.NumberUtil; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * ilde time时间范围 * * @author fulei */ public enum TtlTimeDistriEnum { BETWEEN_PERSIST_HOURS("-1_-1", "不过期", 1), BETWEEN_0_TO_1_HOURS("0_1", "0-1小时", 2), BETWEEN_1_TO_2_HOURS("1_2", "1-2小时", 3), BETWEEN_2_TO_5_HOURS("2_5", "2-5小时", 4), BETWEEN_5_TO_10_HOURS("5_10", "5-10小时", 5), BETWEEN_10_TO_24_HOURS("10_24", "10-24小时", 6), BETWEEN_24_TO_120_HOURS("24_120", "1-5天", 7), BETWEEN_120_TO_240_HOURS("120_240", "5-10天", 8), BETWEEN_240_TO_720_HOURS("240_720", "10-30天", 9), BETWEEN_720_TO_MAX_HOURS("720_2147483647", "30天以上", 10), ; public final static Map MAP; static { Map tmpMap = new HashMap<>(); for (TtlTimeDistriEnum enumObject : TtlTimeDistriEnum.values()) { tmpMap.put(enumObject.getValue(), enumObject); } MAP = Collections.unmodifiableMap(tmpMap); } private String value; private String info; private int type; private TtlTimeDistriEnum(String value, String info, int type) { this.value = value; this.info = info; this.type = type; } public static TtlTimeDistriEnum getByValue(String targetValue) { return MAP.get(targetValue); } /** * 计算ttl所属于的区间 * * @return */ public static TtlTimeDistriEnum getRightTtlDistri(long ttl) { TtlTimeDistriEnum[] enumArr = TtlTimeDistriEnum.values(); for (TtlTimeDistriEnum enumObject : enumArr) { if (isInSize(enumObject, ttl)) { return enumObject; } } return null; } /** * @param enumObject * @param costTime * @return */ private static boolean isInSize(TtlTimeDistriEnum enumObject, long costTime) { String value = enumObject.getValue(); int index = value.indexOf("_"); int start = NumberUtil.toInt(value.substring(0, index)); int end = NumberUtil.toInt(value.substring(index + 1)); if (costTime >= start && costTime < end) { return true; } return false; } public static void main(String[] args) { System.out.println(getRightTtlDistri(-2)); } public String getValue() { return value; } public String getInfo() { return info; } public int getType() { return type; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/constant/ValueSizeDistriEnum.java ================================================ package com.sohu.cache.task.constant; import com.sohu.cache.util.NumberUtil; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 值分布memory usage 结果 * * @author fulei */ public enum ValueSizeDistriEnum { // 单位字节 BETWEEN_MIN_TO_0_BYTE("-2147483648_0", "非法", 0), BETWEEN_0_TO_50_BYTE("0_50", "0-0.05k", 1), BETWEEN_50_TO_100_BYTE("50_100", "0.05k-0.1k", 2), BETWEEN_100_TO_200_BYTE("100_200", "0.1k-0.2k", 3), BETWEEN_200_TO_500_BYTE("200_500", "0.2k-0.5k", 4), BETWEEN_500_TO_1024_BYTE("500_1024", "0.5k-1k", 5), BETWEEN_1024_TO_2048_BYTE("1024_2048", "1-2k", 6), BETWEEN_2048_TO_5120_BYTE("2048_5120", "2-5k", 7), BETWEEN_5120_TO_10240_BYTE("5120_10240", "5-10k", 8), BETWEEN_10240_TO_20480_BYTE("10240_20480", "10-20k", 9), BETWEEN_20480_TO_51200_BYTE("20480_51200", "20-50k", 10), BETWEEN_51200_TO_102400_BYTE("51200_102400", "50-100k", 11), BETWEEN_102400_TO_204800_BYTE("102400_204800", "100-200k", 12), BETWEEN_204800_TO_512000_BYTE("204800_512000", "200-500k", 13), BETWEEN_512000_TO_1024000_BYTE("512000_1024000", "500k-1MB", 14), BETWEEN_1024000_TO_2048000_BYTE("1024000_2048000", "1MB-2MB", 15), BETWEEN_2048000_TO_5120000_BYTE("2048000_5120000", "2MB-5MB", 16), BETWEEN_5120000_TO_MAX_BYTE("5120000_2147483647", "5MB以上", 17), ; public final static Map VALUE_MAP; public final static Map TYPE_MAP; static { Map tmpMap = new HashMap<>(); for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) { tmpMap.put(enumObject.getValue(), enumObject); } VALUE_MAP = Collections.unmodifiableMap(tmpMap); } static { Map tmpMap = new HashMap<>(); for (ValueSizeDistriEnum enumObject : ValueSizeDistriEnum.values()) { tmpMap.put(enumObject.getType(), enumObject); } TYPE_MAP = Collections.unmodifiableMap(tmpMap); } private String value; private String info; private int type; private ValueSizeDistriEnum(String value, String info, int type) { this.value = value; this.info = info; this.type = type; } public static ValueSizeDistriEnum getByValue(String targetValue) { return VALUE_MAP.get(targetValue); } public static ValueSizeDistriEnum getByType(int targetType) { return TYPE_MAP.get(targetType); } /** * 查看区间 */ public static ValueSizeDistriEnum getRightSizeBetween(long size) { ValueSizeDistriEnum[] enumArr = ValueSizeDistriEnum.values(); for (ValueSizeDistriEnum enumObject : enumArr) { if (isInSize(enumObject, size)) { return enumObject; } } return null; } /** * 确定length在指定区间 * * @param enumObject * @param size * @return */ private static boolean isInSize(ValueSizeDistriEnum enumObject, long size) { String value = enumObject.getValue(); int index = value.indexOf("_"); long start = NumberUtil.toLong(value.substring(0, index)); long end = NumberUtil.toLong(value.substring(index + 1)); if (size >= start && size < end) { return true; } return false; } public int getType() { return type; } public String getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/InstanceBigKey.java ================================================ package com.sohu.cache.task.entity; import com.sohu.cache.task.constant.RedisDataStructureTypeEnum; import lombok.Data; import lombok.EqualsAndHashCode; import java.text.DecimalFormat; import java.util.Date; @Data @EqualsAndHashCode public class InstanceBigKey { private long id; /** * 实例id */ private long instanceId; /** * app id */ private long appId; /** * 工单id */ private long auditId; /** * ip地址 */ private String ip; /** * port */ private int port; /** * 1主2从 */ private int role; /** * bigkey */ private String bigKey; /** * 类型 */ private String type; /** * 长度 */ private long length; /** * 创建时间 */ private Date createTime; public String getLengthFormat() { if (RedisDataStructureTypeEnum.string.getValue().equals(type)) { return new DecimalFormat("#,###").format(length); } else { return length + "个元素"; } } /*public long getId() { return id; } public void setId(long id) { this.id = id; } public long getInstanceId() { return instanceId; } public void setInstanceId(long instanceId) { this.instanceId = instanceId; } public long getAppId() { return appId; } public void setAppId(long appId) { this.appId = appId; } public long getAuditId() { return auditId; } public void setAuditId(long auditId) { this.auditId = auditId; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getRole() { return role; } public void setRole(int role) { this.role = role; } public String getBigKey() { return bigKey; } public void setBigKey(String bigKey) { this.bigKey = bigKey; } public String getType() { return type; } public void setType(String type) { this.type = type; } public long getLength() { return length; } public void setLength(long length) { this.length = length; }*/ public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/NutCrackerNode.java ================================================ package com.sohu.cache.task.entity; import lombok.Data; /** * @author fulei */ @Data public class NutCrackerNode { private long taskId; private String ip; private int port; public NutCrackerNode() { } public NutCrackerNode(String ip, int port) { this.ip = ip; this.port = port; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/RedisSentinelNode.java ================================================ package com.sohu.cache.task.entity; import lombok.Data; /** * @author fulei * @date 2018年6月26日 */ @Data public class RedisSentinelNode { private long taskId; private String ip; private int port; public RedisSentinelNode() { } public RedisSentinelNode(String ip, int port) { this.ip = ip; this.port = port; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/RedisServerNode.java ================================================ package com.sohu.cache.task.entity; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.task.constant.PikaNode; import lombok.Data; /** * @author fulei * @date 2018年6月26日 * @time 下午5:52:49 */ @Data public class RedisServerNode { private long taskId; private String ip; private int port; private int role; private int maxmemory; private String masterHost; private int masterPort; private String masterName; public RedisServerNode() { } public RedisServerNode(String ip, int port) { this.ip = ip; this.port = port; } public RedisServerNode(String ip, int port, String masterName) { this.ip = ip; this.port = port; this.masterName = masterName; } public RedisServerNode(String ip, int port, int maxmemory) { this.ip = ip; this.port = port; this.maxmemory = maxmemory; } public RedisServerNode(String ip, int port, int role, int maxmemory, String masterHost, int masterPort) { this.ip = ip; this.port = port; this.role = role; this.maxmemory = maxmemory; this.masterHost = masterHost; this.masterPort = masterPort; } public String genHostAndPort() { return masterHost + ":" + masterPort; } public boolean isMaster() { return role == InstanceRoleEnum.MASTER.getRole(); } public boolean isSlave() { return role == InstanceRoleEnum.SLAVE.getRole(); } @Override public String toString() { return "RedisServerNode [taskId=" + taskId + ", ip=" + ip + ", port=" + port + ", role=" + role + ", maxmemory=" + maxmemory + ", masterHost=" + masterHost + ", masterPort=" + masterPort + ", masterName=" + masterName + "]"; } public String getUniqKey() { return ip + "-" + port + "-" + masterName; } public static RedisServerNode transferFromPika(PikaNode pikaNode) { RedisServerNode redisServerNode = new RedisServerNode(); redisServerNode.setIp(pikaNode.getIp()); redisServerNode.setMasterHost(pikaNode.getMasterHost()); redisServerNode.setMasterName(pikaNode.getMasterName()); redisServerNode.setMasterPort(pikaNode.getMasterPort()); redisServerNode.setPort(pikaNode.getPort()); redisServerNode.setRole(pikaNode.getRole()); redisServerNode.setTaskId(pikaNode.getTaskId()); return redisServerNode; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/TaskQueue.java ================================================ package com.sohu.cache.task.entity; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.sohu.cache.task.constant.TaskQueueEnum.TaskStatusEnum; import lombok.Data; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import java.text.DecimalFormat; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; /** * 任务队列 */ @Data public class TaskQueue { /** * 自增id */ private long id; /** * 进行任务的ip:port */ private String executeIpPort; /** * 应用id */ private long appId; /** * 类名 */ private String className; /** * 全局参数:json格式,内容会变 */ private String param; /** * 初始化参数:json格式,内容不变 */ private String initParam; /** * 状态,详见com.sohu.cache.task.constant.TaskQueueEnum.TaskStatusEnum */ private int status; /** * 父任务id */ private long parentTaskId; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; /** * 开始时间 */ private Date startTime; /** * 结束时间 */ private Date endTime; /** * 优先级 */ private int priority = 50; /** * 错误代码,详见 TaskQueueEnum.TaskErrorCodeEnum */ private int errorCode; /** * 错误消息 */ private String errorMsg = ""; /** * 备注 */ private String taskNote = ""; /** * 重要信息 */ private String importantInfo = ""; /** * 任务流 */ private List taskStepFlowList; public Map getParamMap() { if (StringUtils.isEmpty(param)) { return Collections.emptyMap(); } return JSONObject.parseObject(param); } public String getPrettyParam() { if (StringUtils.isEmpty(param)) { return null; } JSONObject jsonObject = JSONObject.parseObject(param); return JSONObject.toJSONString(jsonObject, SerializerFeature.PrettyFormat); } public String getStatusDesc() { TaskStatusEnum taskStatusEnum = TaskStatusEnum.getTaskStatusEnum(status); if (taskStatusEnum != null) { return taskStatusEnum.getInfo(); } return ""; } public String getProgress() { if (CollectionUtils.isEmpty(taskStepFlowList)) { return ""; } int success = 0; int total = taskStepFlowList.size(); for (TaskStepFlow taskStepFlow : taskStepFlowList) { if (taskStepFlow.isSkip() || taskStepFlow.isSuccess()) { success++; } } double percent = success * 100.0 / total * 1.0; return new DecimalFormat("#.00").format(percent) + "%"; } public String getCostSeconds() { if (status != TaskStatusEnum.SUCCESS.getStatus()) { return ""; } if (endTime != null && startTime != null) { long ms = (endTime.getTime() - startTime.getTime()) / 1000; return String.valueOf(ms); } return ""; } public boolean isSuccess() { return TaskStatusEnum.SUCCESS.getStatus() == status; } public boolean isRunning() { return TaskStatusEnum.RUNNING.getStatus() == status; } public boolean isAbort() { return TaskStatusEnum.ABORT.getStatus() == status; } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getStartTime() { return (Date) startTime.clone(); } public void setStartTime(Date startTime) { this.startTime = (Date) startTime.clone(); } public Date getEndTime() { return (Date) endTime.clone(); } public void setEndTime(Date endTime) { this.endTime = (Date) endTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/TaskSearch.java ================================================ package com.sohu.cache.task.entity; import com.sohu.cache.web.util.Page; import lombok.Data; /** * @author fulei * @date 2018年7月11日 */ @Data public class TaskSearch { /** * appId */ private Long appId; /** * 类名 */ private String className; /** * 状态 */ private int status = -1; /** * 分页 */ private Page page; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/TaskStepFlow.java ================================================ package com.sohu.cache.task.entity; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import lombok.Data; import java.util.Date; /** * 任务步骤流 */ @Data public class TaskStepFlow { /** * 自增id */ private long id; /** * 任务id */ private long taskId; /** * 子任务id */ private long childTaskId; /** * 类名 */ private String className; /** * 步骤名 */ private String stepName; /** * 序号 */ private int orderNo; /** * 状态, 参考:TaskFlowStatusEnum */ private int status; /** * 日志 */ private String log = ""; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; /** * 开始时间 */ private Date startTime; /** * 结束时间 */ private Date endTime; /** * 执行ip:port */ private String executeIpPort; /** * 任务流描述 */ private TaskStepMeta taskStepMeta; public boolean isSuccess() { return status == TaskFlowStatusEnum.SUCCESS.getStatus(); } public boolean isSkip() { return status == TaskFlowStatusEnum.SKIP.getStatus(); } public String getExecuteIpPort() { return executeIpPort; } public void setExecuteIpPort(String executeIpPort) { this.executeIpPort = executeIpPort; } public TaskStepMeta getTaskStepMeta() { return taskStepMeta; } public void setTaskStepMeta(TaskStepMeta taskStepMeta) { this.taskStepMeta = taskStepMeta; } public String getStatusDesc() { TaskFlowStatusEnum taskFlowStatusEnum = TaskFlowStatusEnum.getTaskFlowStatusEnum(status); if (taskFlowStatusEnum != null) { return taskFlowStatusEnum.getInfo(); } return ""; } public String getCostSeconds() { if (status != TaskFlowStatusEnum.SUCCESS.getStatus()) { return ""; } if (endTime != null && startTime != null) { long ms = (endTime.getTime() - startTime.getTime()) / 1000; return String.valueOf(ms); } return ""; } public Date getCreateTime() { return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } public Date getStartTime() { return (Date) startTime.clone(); } public void setStartTime(Date startTime) { this.startTime = (Date) startTime.clone(); } public Date getEndTime() { return (Date) endTime.clone(); } public void setEndTime(Date endTime) { this.endTime = (Date) endTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/entity/TaskStepMeta.java ================================================ package com.sohu.cache.task.entity; import lombok.Data; import java.util.Date; /** * 任务步骤元数据 */ @Data public class TaskStepMeta { /** * 自增id */ private long id; /** * 类名 */ private String className; /** * 步骤名 */ private String stepName; /** * 步骤描述 */ private String stepDesc; /** * 运维建议 */ private String opsDevice; /** * 超时时间 */ private int timeout; /** * 顺序 */ private int orderNo; /** * 创建时间 */ private Date createTime; /** * 更新时间 */ private Date updateTime; public Date getCreateTime() { if(createTime == null){ return createTime; } return (Date) createTime.clone(); } public void setCreateTime(Date createTime) { this.createTime = (Date) createTime.clone(); } public Date getUpdateTime() { if(updateTime == null){ return updateTime; } return (Date) updateTime.clone(); } public void setUpdateTime(Date updateTime) { this.updateTime = (Date) updateTime.clone(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/impl/TaskServiceImpl.java ================================================ package com.sohu.cache.task.impl; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.OperateResult; import com.sohu.cache.dao.AppAuditDao; import com.sohu.cache.dao.TaskQueueDao; import com.sohu.cache.dao.TaskStepFlowDao; import com.sohu.cache.dao.TaskStepMetaDao; import com.sohu.cache.entity.AppAudit; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.constant.PikaNode; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskQueueEnum.TaskErrorCodeEnum; import com.sohu.cache.task.constant.TaskQueueEnum.TaskStatusEnum; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.task.entity.*; import com.sohu.cache.task.tasks.AppKeyAnalysisTask; import com.sohu.cache.task.tasks.OffLineAppTask; import com.sohu.cache.task.tasks.analysis.*; import com.sohu.cache.task.tasks.daily.MachineExamTask; import com.sohu.cache.task.tasks.daily.TopologyExamTask; import com.sohu.cache.task.tasks.diagnosticTask.*; import com.sohu.cache.task.util.AppWechatUtil; import com.sohu.cache.task.util.SpringContextUtil; import com.sohu.cache.util.RedisConstUtils; import com.sohu.cache.web.enums.ExamToolEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.IpUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; /** * @author fulei */ @Service public class TaskServiceImpl implements TaskService { private Logger logger = LoggerFactory.getLogger(TaskServiceImpl.class); @Autowired private TaskQueueDao taskQueueDao; @Autowired private TaskStepFlowDao taskStepFlowDao; @Autowired private TaskStepMetaDao taskStepMetaDao; @Autowired private AppAuditDao appAuditDao; @Autowired private SpringContextUtil springContextUtil; @Autowired private AsyncService asyncService; @Autowired private AppService appService; @Autowired private AppWechatUtil appWechatUtil; @Autowired IpUtil ipUtil; private int port; private String host; @PostConstruct public void init() { asyncService.assemblePool(getThreadPoolKey(), AsyncThreadPoolFactory.TASK_EXECUTE_THREAD_POOL); host = ipUtil.getLocalIP(); port = ipUtil.getLocalPort(); } @Override public void executeNewTask() { try { List newTaskQueueList = getTaskQueueList(TaskStatusEnum.NEW); int limit = 20; if (CollectionUtils.isEmpty(newTaskQueueList)) { logger.warn("current newTaskQueueList is empty"); return; } else { logger.warn("current newTaskQueueList size is {}", newTaskQueueList.size()); } for (int i = 0; i < limit && i < newTaskQueueList.size(); i++) { final TaskQueue taskQueue = newTaskQueueList.get(i); updateTaskQueueStatus(taskQueue.getId(), TaskStatusEnum.READY); logger.warn("task {} ready to execute", taskQueue.getId()); String key = getThreadPoolKey() + "_" + taskQueue.getId(); asyncService.submitFuture(getThreadPoolKey(), new KeyCallable(key) { @Override public Boolean execute() { logger.warn("===================={} start task {}==================", Thread.currentThread().getName(), taskQueue.getId()); executeTask(taskQueue.getId()); return true; } }); } } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override public TaskStatusEnum executeTask(long taskId) { TaskStatusEnum taskStatusEnum = null; TaskQueue taskQueue = taskQueueDao.getById(taskId); if (taskQueue == null) { logger.error("taskId {} is null", taskId); taskStatusEnum = TaskStatusEnum.ABORT; taskQueueDao.updateStatus(taskId, taskStatusEnum.getStatus()); return taskStatusEnum; } if (taskQueue.isSuccess()) { logger.error("taskId {} already success", taskId); return TaskStatusEnum.SUCCESS; } //todo // if (taskQueue.isRunning()) { // logger.error("taskId {} is running", taskId); // return TaskStatusEnum.RUNNING; // } //正在执行 taskStatusEnum = TaskStatusEnum.RUNNING; taskQueueDao.updateStatus(taskId, taskStatusEnum.getStatus()); taskQueueDao.updateStartTime(taskId, new Date()); String executeIpPort = host + ":" + port; taskQueueDao.updateExecuteIpPort(taskId, executeIpPort); //实际是beanId String className = taskQueue.getClassName(); //parse参数 Map paramMap = taskQueue.getParamMap(); try { //任务列表 List taskStepFlowList = new ArrayList(); //获取任务 BaseTask task = (BaseTask) springContextUtil.getBeanById(className); paramMap.put(TaskConstants.TASK_ID_KEY, taskQueue.getId()); task.setParamMap(paramMap); //任务步骤 List stepNameList = task.getTaskSteps(); //这块要考虑好重试的问题 @TODO for (int i = 0; i < stepNameList.size(); i++) { String stepName = stepNameList.get(i); TaskStepFlow oldTaskStepFlow = taskStepFlowDao.getByTaskClassStep(taskId, className, stepName); if (oldTaskStepFlow != null) { taskStepFlowList.add(oldTaskStepFlow); } else { TaskStepFlow taskStepFlow = new TaskStepFlow(); taskStepFlow.setClassName(className); taskStepFlow.setStepName(stepName); taskStepFlow.setOrderNo(i + 1); taskStepFlow.setTaskId(taskId); taskStepFlow.setStatus(TaskFlowStatusEnum.READY.getStatus()); Date date = new Date(); taskStepFlow.setStartTime(date); taskStepFlow.setEndTime(date); taskStepFlow.setCreateTime(date); taskStepFlow.setUpdateTime(date); taskStepFlowList.add(taskStepFlow); taskStepFlowDao.save(taskStepFlow); } } // 执行任务 TaskFlowStatusEnum taskFlowStatusEnum = null; for (TaskStepFlow taskStepFlow : taskStepFlowList) { long id = taskStepFlow.getId(); if ((taskStepFlow.isSuccess() || taskStepFlow.isSkip()) && !TaskConstants.INIT_METHOD_KEY .equals(taskStepFlow.getStepName())) { continue; } task.getParamMap().put(TaskConstants.TASK_STEP_FLOW_ID, id); try { // 更新开始时间 taskStepFlowDao.updateStartTime(id, new Date()); taskStepFlowDao.updateStatus(id, TaskFlowStatusEnum.RUNNING.getStatus()); taskStepFlowDao.updateExecuteIpPort(id, host + ":" + port); // 日志 MDC.put(TaskConstants.TASK_STEP_FLOW_ID, String.valueOf(id)); // 执行日志 logger.warn(BaseTask.marker, "task {} {} start", taskId, taskStepFlow.getStepName()); // 执行任务 Method method = task.getClass().getDeclaredMethod(taskStepFlow.getStepName()); taskFlowStatusEnum = (TaskFlowStatusEnum) method.invoke(task); // 执行日志 logger.warn(BaseTask.marker, "task {} {} finish, result is {}", taskId, taskStepFlow.getStepName(), taskFlowStatusEnum.getInfo()); taskStepFlowDao.updateStatus(id, taskFlowStatusEnum.getStatus()); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { appWechatUtil.noticeTaskAbort(taskId, taskStepFlow.getStepName()); break; } taskStepFlowDao.updateEndTime(id, new Date()); // 更新参数 String paramJson = JSONObject.toJSONString(task.getParamMap()); taskQueueDao.updateParam(taskQueue.getId(), paramJson); } catch (Exception e) { taskFlowStatusEnum = TaskFlowStatusEnum.ABORT; appWechatUtil.noticeTaskAbort(taskId, taskStepFlow.getStepName()); taskStepFlowDao.updateStatus(id, taskFlowStatusEnum.getStatus()); taskStepFlowDao.updateLog(id, ExceptionUtils.getFullStackTrace(e)); logger.error(BaseTask.marker, "{} step {} error: " + e.getMessage(), className, taskStepFlow.getStepName(), e); break; } } if (taskFlowStatusEnum != null && taskFlowStatusEnum.equals(TaskFlowStatusEnum.SUCCESS)) { taskQueueDao.updateEndTime(taskId, new Date()); taskStatusEnum = TaskStatusEnum.SUCCESS; } else { taskStatusEnum = TaskStatusEnum.ABORT; } } catch (RuntimeException e) { throw e; } catch (Exception e) { logger.error(e.getMessage(), e); taskStatusEnum = TaskStatusEnum.ABORT; } taskQueueDao.updateStatus(taskId, taskStatusEnum.getStatus()); return taskStatusEnum; } @Override public List getTaskStepFlowList(long taskId) { try { return taskStepFlowDao.getTaskStepFlowList(taskId); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public TaskQueue getTaskQueueById(long taskId) { try { return taskQueueDao.getById(taskId); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public List getTaskStepMetaList(String className) { try { return taskStepMetaDao.getTaskStepMetaList(className); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public TaskStepFlow getCurrentTaskStepFlow(long taskId) { List taskStepFlowList = taskStepFlowDao.getTaskStepFlowList(taskId); if (CollectionUtils.isEmpty(taskStepFlowList)) { return null; } for (TaskStepFlow taskStepFlow : taskStepFlowList) { if (taskStepFlow.isSuccess() || taskStepFlow.isSkip()) { continue; } return taskStepFlow; } // 如果是空,则返回最后一步 return taskStepFlowList.get(taskStepFlowList.size() - 1); } @Override public long addRedisServerInstallTask(long appId, String host, int port, int maxMemory, String version, Boolean isCluster, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.VERSION_KEY, version); paramMap.put(TaskConstants.IS_CLUSTER_KEY, isCluster); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.REDIS_SERVER_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addPikaInstallTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = "pika-" + host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.PIKA_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } /*@Override public long addCodisServerInstallTask(long appId, String host, int port, int maxMemory, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.CODIS_SERVER_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); }*/ @Override public long addRedisSentinelInstallTask(long appId, String host, int port, List masterRedisServerNodes, int quorum, String dbVersion, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put(TaskConstants.REDIS_SENTINEL_QUORUM_KEY, quorum); paramMap.put(TaskConstants.MASTER_REDIS_SERVER_NODES, masterRedisServerNodes); paramMap.put(TaskConstants.VERSION_KEY, dbVersion); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.REDIS_SENTINEL_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } /*@Override public long addRedisPortInstallTask(long appId, String redisPortHost, int redisPortHttpPort, String sourceHost, int sourcePort, String targetHost, int targetPort, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, redisPortHost); paramMap.put(TaskConstants.HTTP_PORT_KEY, redisPortHttpPort); paramMap.put(TaskConstants.SOURCE_HOST_KEY, sourceHost); paramMap.put(TaskConstants.SOURCE_PORT_KEY, sourcePort); paramMap.put(TaskConstants.TARGET_HOST_KEY, targetHost); paramMap.put(TaskConstants.TARGET_PORT_KEY, targetPort); String importantInfo = redisPortHost + ":" + redisPortHttpPort; String param = JSONObject.toJSONString(paramMap); //todo TaskConstants.REDIS_PORT_INSTANCE_INSTALL_CLASS; String className = null; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); }*/ @Override public long addRedisMigrateToolInstallTask(String migrateToolHost, int migrateToolPort, long sourceAppId, long targetAppId, List sourceRedisServerNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.HOST_KEY, migrateToolHost); paramMap.put(TaskConstants.PORT_KEY, migrateToolPort); paramMap.put(TaskConstants.SOURCE_APP_ID_KEY, sourceAppId); paramMap.put(TaskConstants.TARGET_APP_ID_KEY, targetAppId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, sourceRedisServerNodes); String importantInfo = String .format("%s:%s(%s->%s)", migrateToolHost, migrateToolPort, sourceAppId, targetAppId); String param = JSONObject.toJSONString(paramMap); long appId = sourceAppId; String className = null;//todo TaskConstants.REDIS_MIGRATE_TOOL_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addCodisProxyInstallTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.CODIS_PROXY_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addCodisDashboardTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.CODIS_DASHBOARD_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addNutCrackerInstallTask(long appId, String host, int port, List masterRedisServerNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put(TaskConstants.MASTER_REDIS_SERVER_NODES, masterRedisServerNodes); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.NUT_CRACKER_INSTANCE_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyPikaTask(long appId, long auditId, int maxMemory, List pikaMachineList, List redisSentinelMachineList, List nutCrackerMachineList, int masterPerMachine, int sentinelPerMachine, int nutCrackerPerMachine, Boolean isNeedFlushZkConfig, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.PIKA_MACHINE_LIST_KEY, pikaMachineList); paramMap.put(TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY, redisSentinelMachineList); paramMap.put(TaskConstants.NUT_CRACKER_MACHINE_LIST_KEY, nutCrackerMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.SENTINEL_PER_MACHINE_KEY, sentinelPerMachine); paramMap.put(TaskConstants.NUT_CRACKER_PER_MACHINE_KEY, nutCrackerPerMachine); paramMap.put(TaskConstants.IS_NEED_FLUSH_ZK_CONFIG_KEY, isNeedFlushZkConfig); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-pika";//appDesc.getFullName() + "-pika" String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.TWEM_PROXY_PIKA_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyAppTask(long appId, long auditId, int maxMemory, List redisServerMachineList, List redisSentinelMachineList, List nutCrackerMachineList, int masterPerMachine, int sentinelPerMachine, int nutCrackerPerMachine, Boolean isNeedFlushZkConfig, String version, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY, redisServerMachineList); paramMap.put(TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY, redisSentinelMachineList); paramMap.put(TaskConstants.NUT_CRACKER_MACHINE_LIST_KEY, nutCrackerMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.SENTINEL_PER_MACHINE_KEY, sentinelPerMachine); paramMap.put(TaskConstants.NUT_CRACKER_PER_MACHINE_KEY, nutCrackerPerMachine); paramMap.put(TaskConstants.IS_NEED_FLUSH_ZK_CONFIG_KEY, isNeedFlushZkConfig); paramMap.put(TaskConstants.VERSION_KEY, version); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.TWEM_PROXY_APP_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisStandaloneAppTask(long appId, long appAuditId, int maxMemory, List redisServerMachineList, int masterPerMachine, String dbVersion, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY, redisServerMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.VERSION_KEY, dbVersion); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-redis-standalone"; String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.REDIS_STANDALONE_APP_DEPLOY_CLASS; long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(appAuditId, taskId); return taskId; } @Override public long addRedisClusterAppTask(long appId, long appAuditId, int maxMemory, List appDeployInfoList, List redisServerMachineList, int masterPerMachine, String dbVersion, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.APP_DEPLOY_INFO_LIST_KEY,appDeployInfoList); paramMap.put(TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY, redisServerMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.VERSION_KEY, dbVersion.replaceAll(RedisConstUtils.REDIS_VERSION_PREFIX,"")); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-redis-cluster"; String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.REDIS_CLUSTER_APP_DEPLOY_CLASS; long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(appAuditId, taskId); return taskId; } @Override public long addRedisSentinelAppTask(long appId, long appAuditId, int maxMemory, List redisServerMachineList, List redisSentinelMachineList, int masterPerMachine, int sentinelPerMachine, String dbVersion, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY, redisServerMachineList); paramMap.put(TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY, redisSentinelMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.SENTINEL_PER_MACHINE_KEY, sentinelPerMachine); paramMap.put(TaskConstants.VERSION_KEY, dbVersion); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.REDIS_SENTINEL_APP_DEPLOY_CLASS; long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(appAuditId, taskId); return taskId; } @Override public long addPikaSentinelAppTask(long appId, long appAuditId, int maxMemory, List pikaMachineList, List redisSentinelMachineList, int masterPerMachine, int sentinelPerMachine, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); paramMap.put(TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY, maxMemory); paramMap.put(TaskConstants.PIKA_MACHINE_LIST_KEY, pikaMachineList); paramMap.put(TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY, redisSentinelMachineList); paramMap.put(TaskConstants.MASTER_PER_MACHINE_KEY, masterPerMachine); paramMap.put(TaskConstants.SENTINEL_PER_MACHINE_KEY, sentinelPerMachine); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-pika-sentinel"; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.PIKA_SENTINEL_APP_INSTALL_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addNutCrackerScaleOutTask(long appId, List nutCrackerMachineList, int nutCrackerPerMachine, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.NUT_CRACKER_MACHINE_LIST_KEY, nutCrackerMachineList); paramMap.put(TaskConstants.NUT_CRACKER_PER_MACHINE_KEY, nutCrackerPerMachine); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.NUT_CRACKER_SCALE_OUT_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addNutCrackerListOfflineTask(long appId, List nutCrackerNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.NUT_CRACKER_NODES_KEY, nutCrackerNodes); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.NUT_CRACKER_LIST_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisSentinelListOfflineTask(long appId, List redisSentinelNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.REDIS_SENTINEL_NODES_KEY, redisSentinelNodes); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.REDIS_SENTINEL_LIST_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisSlaveServerOfflineTask(long appId, List redisServerNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.REDIS_SLAVE_SERVER_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addPikaSlaveOfflineTask(long appId, List pikaNodes, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.PIKA_NODES_KEY, pikaNodes); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.PIKA_SLAVE_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisSentinelAddTask(long appId, List redisSentinelMachineList, String dbVersion, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY, redisSentinelMachineList); paramMap.put(TaskConstants.VERSION_KEY, dbVersion); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.PIKA_SLAVE_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyOfflineTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.TWEMPROXY_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisSentinelAppOfflineTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.REDIS_SENTINEL_APP_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addPikaSentinelAppOfflineTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.PIKA_SENTINEL_APP_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addMemcacheClusterOfflineTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.MEMCACHE_CLUSTER_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyPikaOfflineTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-pika"; String className = null;//todo TaskConstants.TWEMPROXY_PIKA_OFFLINE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppConfigFlushZkTask(long appId, Boolean appIsNew, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.APP_IS_NEW_KEY, appIsNew); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = null;//todo TaskConstants.APP_CONFIG_FLUSH_ZK_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyToTwemproxyTask(long sourceAppId, long targetAppId, long appAuditId, boolean isScaleOut, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.SOURCE_APP_ID_KEY, sourceAppId); paramMap.put(TaskConstants.TARGET_APP_ID_KEY, targetAppId); paramMap.put(TaskConstants.IS_SCALE_OUT_KEY, isScaleOut); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); String importantInfo = String.format("%s->%s", sourceAppId, targetAppId); String param = JSONObject.toJSONString(paramMap); long appId = sourceAppId; String className = null;//todo TaskConstants.TWEMPROXY_TO_TWEMPROXY_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyToTwemproxyTaskV2(long sourceAppId, long targetAppId, long appAuditId, boolean isScaleOut, boolean isOnlyMigrate, long parentTaskId) { AppDesc appDesc = appService.getByAppId(sourceAppId); Map paramMap = new HashMap(); paramMap.put(TaskConstants.SOURCE_APP_ID_KEY, sourceAppId); paramMap.put(TaskConstants.TARGET_APP_ID_KEY, targetAppId); paramMap.put(TaskConstants.IS_SCALE_OUT_KEY, isScaleOut); paramMap.put(TaskConstants.IS_ONLY_MIGRATE_KEY, isOnlyMigrate); paramMap.put(TaskConstants.AUDIT_ID_KEY, appAuditId); String param = JSONObject.toJSONString(paramMap); String importantInfo = String.format("%s->%s(%s)", sourceAppId, targetAppId, appDesc.getName()); long appId = sourceAppId; String className = null;//todo TaskConstants.TWEMPROXY_TO_TWEMPROXY_V2_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRemoveRedisMigrateToolTask(String host, int port, long sourceAppId, long targetAppId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put(TaskConstants.SOURCE_APP_ID_KEY, sourceAppId); paramMap.put(TaskConstants.TARGET_APP_ID_KEY, targetAppId); String importantInfo = String.format("%s:%s(%s->%s)", host, port, sourceAppId, targetAppId); String param = JSONObject.toJSONString(paramMap); long appId = sourceAppId; String className = null;//todo TaskConstants.REDIS_MIGRATE_TOOL_REMOVE_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerStopTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SERVER_STOP_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addMemcacheStopTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.MEMCACHE_STOP_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerStartTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SERVER_START_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerFlushDataTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SERVER_FLUSH_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerIdleKeyAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = RedisServerIdleKeyAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerBigKeyAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = RedisServerBigKeyAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerKeyTypeAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = RedisServerKeyTypeAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerKeyTtlAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = RedisServerKeyTtlAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisServerKeyValueAnalysisTask(long appId, long auditId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = RedisServerKeyValueAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override @Transactional public long addAppKeyAnalysisTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppKeyAnalysisTask.class.getSimpleName(); AppAudit appAudit = appAuditDao.getAppAudit(auditId); String nodeInfos = StringUtils.isNotBlank(appAudit.getParam1()) ? appAudit.getParam1() : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); // if (StringUtils.isNotBlank(nodeInfo)) { // paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfo))); // logger.info("node-analysis-task: {}", nodeInfo); // } appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } private static List parseNodeInfo(String nodeInfo) { List list = Lists.newArrayList(); String[] nodeList = nodeInfo.split(","); for (String node : nodeList) { RedisServerNode redisNode = new RedisServerNode(); String[] array = node.replace("{", "").replace("}", "").split(":"); if (array.length != 2) { throw new RuntimeException(nodeInfo + " format error"); } redisNode.setIp(array[0]); redisNode.setPort(NumberUtils.toInt(array[1])); list.add(redisNode); } return list; } @Override public long addTwemproxyFlushAllDataTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.TWEMPROXY_KEY_ANALYSIS_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyPikaFlushAllDataTask(long appId, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName() + "-pika"; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.TWEMPROXY_PIKA_FLUSHALL_DATA_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addRedisSentinelStopTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SENTINEL_STOP_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addNutCrackerStopTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.NUT_CRACKER_STOP_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addPikaStopTask(long appId, String host, int port, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.PIKA_STOP_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addSlaveRedisServerRebuildTask(long appId, String masterHost, int masterPort, String slaveMachineHost, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.MASTER_HOST_KEY, masterHost); paramMap.put(TaskConstants.MASTER_PORT_KEY, masterPort); paramMap.put(TaskConstants.SLAVE_MACHINE_KEY, slaveMachineHost); String importantInfo = slaveMachineHost; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SLAVE_SERVER_REBUILD_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addSlavePikaRebuildTask(long appId, String masterHost, int masterPort, String slaveMachineHost, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.MASTER_HOST_KEY, masterHost); paramMap.put(TaskConstants.MASTER_PORT_KEY, masterPort); paramMap.put(TaskConstants.SLAVE_MACHINE_KEY, slaveMachineHost); String importantInfo = slaveMachineHost; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.PIKA_SLAVE_REBUILD_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addSlaveRedisSentinelFailoverTask(long appId, String masterHost, int masterPort, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.MASTER_HOST_KEY, masterHost); paramMap.put(TaskConstants.MASTER_PORT_KEY, masterPort); String importantInfo = masterHost + ":" + masterPort; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.REDIS_SENTINEL_FAILOVER_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addTwemproxyFaultMachineFailoverTask(long appId, String host, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); String importantInfo = host; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.TWEMPROXY_FAULT_MACHINE_FAILOVER_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addMachineSlaveRebuildTask(long appId, String host, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.HOST_KEY, host); String importantInfo = host; String param = JSONObject.toJSONString(paramMap); String className = null;//todo TaskConstants.MACHINE_SLAVE_REBUILD_CLASS; return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppTopologyExamTask(boolean auto, int examType, long appId, long parentTaskId) { Map paramMap = Maps.newHashMap(); paramMap.put(TaskConstants.EXAM_TYPE_KEY, examType); paramMap.put("auto", auto); if (examType == ExamToolEnum.EXAM_APPID.getValue()) { paramMap.put(TaskConstants.APPID_KEY, appId); } String importantInfo = "topology exam, examType:" + String.valueOf(examType); String className = TopologyExamTask.class.getSimpleName(); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(-1, className, param, importantInfo, parentTaskId); return taskId; } @Override public long addMachineExamTask(List ipList, Integer useType, long parentTaskId) { Map paramMap = Maps.newHashMap(); paramMap.put(TaskConstants.MACHINE_IP_LIST_KEY, ipList); paramMap.put(TaskConstants.USE_TYPE_KEY, useType); String importantInfo = "machine cpu/mem exam"; String className = MachineExamTask.class.getSimpleName(); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(-1, className, param, importantInfo, parentTaskId); return taskId; } @Override public long addOffLineAppTask(long appId, Long auditId, long parentTaskId, AppUser userInfo) { Map paramMap = Maps.newHashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId == null ? -1 : auditId); paramMap.put(TaskConstants.USER_INFO_KEY, userInfo); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = OffLineAppTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppScanKeyTask(long appId, long auditId, String nodes, String pattern, int size, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put("pattern", pattern); paramMap.put("size", size); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppScanKeyTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceScanKeyTask(long appId, long auditId, String host, int port, String pattern, int size, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("pattern", pattern); paramMap.put("size", size); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceScanKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addInstanceScanCleanKeyTask(long appId, long auditId, String host, int port, Map params, long parentTaskId) { Map paramMap = new HashMap(); paramMap.putAll(params); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceScanCleanKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppDelKeyTask(long appId, String nodes, String pattern, long auditId, long parentTaskId) { Map paramMap = new HashMap<>(); paramMap.put(TaskConstants.APPID_KEY, appId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("pattern", pattern); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppDelKeyTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceDelKeyTask(long appId, String host, int port, String pattern, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("pattern", pattern); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceDelKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppBigKeyTask(long appId, String nodes, long fromBytes, long toBytes, int size, long auditId, long parentTaskId) { Map paramMap = new HashMap<>(); paramMap.put(TaskConstants.APPID_KEY, appId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("fromBytes", fromBytes); paramMap.put("toBytes", toBytes); paramMap.put("size", size); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppBigKeyTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceBigKeyTask(long appId, String host, int port, long fromBytes, long toBytes, int size, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("fromBytes", fromBytes); paramMap.put("toBytes", toBytes); paramMap.put("size", size); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceBigKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppIdleKeyTask(long appId, String nodes, long idleTime, int size, long auditId, long parentTaskId) { Map paramMap = new HashMap<>(); paramMap.put(TaskConstants.APPID_KEY, appId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put("idleTime", idleTime); paramMap.put("size", size); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppIdleKeyTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceIdleKeyTask(long appId, String host, int port, long idleTime, int size, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put("idleTime", idleTime); paramMap.put("size", size); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceIdleKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppHotKeyTask(long appId, String nodes, String command, long auditId, long parentTaskId) { Map paramMap = new HashMap<>(); paramMap.put(TaskConstants.APPID_KEY, appId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put("command", command); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppHotKeyTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceHotKeyTask(long appId, String host, int port, String command, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); paramMap.put("command", command); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceHotKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppSlotAnalysisTask(long appId, String nodes, long auditId, long parentTaskId) { Map paramMap = new HashMap<>(); paramMap.put(TaskConstants.APPID_KEY, appId); String nodeInfos = StringUtils.isNotBlank(nodes) ? nodes : appService.getAppMasterInstanceInfoList(appId).stream().map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.joining(",")); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, JSONObject.toJSONString(parseNodeInfo(nodeInfos))); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppSlotAnalysisTask.class.getSimpleName(); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); String param = JSONObject.toJSONString(paramMap); long taskId = generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); appAuditDao.updateTaskId(auditId, taskId); return taskId; } @Override public long addInstanceSlotAnalysisTask(long appId, String host, int port, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("parentTaskId", parentTaskId); paramMap.put(TaskConstants.HOST_KEY, host); paramMap.put(TaskConstants.PORT_KEY, port); String importantInfo = host + ":" + port; String param = JSONObject.toJSONString(paramMap); String className = InstanceSlotAnalysisTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } @Override public long addAppScanCleanTask(long appId, Map params, long auditId, long parentTaskId) { Map paramMap = new HashMap(); paramMap.putAll(params); paramMap.put(TaskConstants.APPID_KEY, appId); paramMap.put(TaskConstants.AUDIT_ID_KEY, auditId); paramMap.put("parentTaskId", parentTaskId); String param = JSONObject.toJSONString(paramMap); AppDesc appDesc = appService.getByAppId(appId); String importantInfo = appDesc.getName(); String className = AppScanCleanKeyTask.class.getSimpleName(); return generateAndSaveTaskQueue(appId, className, param, importantInfo, parentTaskId); } /** * 生成并保存taskqueue * * @param appId * @param className * @param param * @param parentTaskId * @return */ private long generateAndSaveTaskQueue(long appId, String className, String param, String importantInfo, long parentTaskId) { TaskQueue taskQueue = generateTaskQueue(appId, className, param, importantInfo, parentTaskId); try { taskQueueDao.save(taskQueue); return taskQueue.getId(); } catch (Exception e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } } @Override public void updateTaskStepFlowChildTaskId(long taskStepFlowId, long childTaskId) { try { taskStepFlowDao.updateChildTaskId(taskStepFlowId, childTaskId); } catch (Exception e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } } @Override public List getTaskQueueList(TaskStatusEnum taskStatusEnum) { try { return taskQueueDao.getTaskQueueListByStatus(taskStatusEnum.getStatus()); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public void updateTaskQueueStatus(long taskId, TaskStatusEnum taskStatusEnum) { try { taskQueueDao.updateStatus(taskId, taskStatusEnum.getStatus()); } catch (Exception e) { logger.error(e.getMessage(), e); } } @Override public int getTaskQueueCount(TaskSearch taskSearch) { try { return taskQueueDao.getTaskQueueCount(taskSearch); } catch (Exception e) { logger.error(e.getMessage(), e); return 0; } } @Override public List getTaskQueueList(TaskSearch taskSearch) { try { return taskQueueDao.getTaskQueueList(taskSearch); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public List getTaskQueueTreeByTaskId(long searchTaskId) { List taskQueueList = new ArrayList(); fillTaskQueueList(taskQueueList, searchTaskId); return taskQueueList; } /** * 递归获取任务 * * @param taskQueueList * @param taskId */ private void fillTaskQueueList(List taskQueueList, long taskId) { TaskQueue parentTaskQueue = taskQueueDao.getById(taskId); if (parentTaskQueue != null) { taskQueueList.add(parentTaskQueue); } else { return; } List childTaskQueueList = taskQueueDao.getChildTaskQueueList(taskId); if (CollectionUtils.isEmpty(childTaskQueueList)) { return; } else { for (TaskQueue taskQueue : childTaskQueueList) { fillTaskQueueList(taskQueueList, taskQueue.getId()); } } } @Override public OperateResult updateParam(long taskId, String param) { try { taskQueueDao.updateParam(taskId, param); return OperateResult.success(); } catch (Exception e) { logger.error(e.getMessage(), e); return OperateResult.fail(e.getMessage()); } } /** * 生成新的任务 * * @param appId * @param className * @param param * @param importantInfo * @param parentTaskId * @return */ private TaskQueue generateTaskQueue(long appId, String className, String param, String importantInfo, long parentTaskId) { TaskQueue taskQueue = new TaskQueue(); taskQueue.setAppId(appId); taskQueue.setClassName(className); taskQueue.setParam(param); taskQueue.setInitParam(param); taskQueue.setStatus(TaskStatusEnum.NEW.getStatus()); taskQueue.setParentTaskId(parentTaskId); Date now = new Date(); taskQueue.setStartTime(now); taskQueue.setEndTime(now); taskQueue.setCreateTime(now); taskQueue.setUpdateTime(now); taskQueue.setErrorCode(TaskErrorCodeEnum.RIGHT.getCode()); taskQueue.setTaskNote(""); taskQueue.setErrorMsg(""); taskQueue.setImportantInfo(importantInfo); return taskQueue; } @Override public OperateResult updateTaskFlowStatus(long taskFlowId, int status) { try { taskStepFlowDao.updateStatus(taskFlowId, status); return OperateResult.success(); } catch (Exception e) { logger.error(e.getMessage(), e); return OperateResult.fail(e.getMessage()); } } private String getThreadPoolKey() { return AsyncThreadPoolFactory.TASK_EXECUTE_POOL; } @Override public List getByAppAndClass(long appId, String className) { try { return taskQueueDao.getByAppAndClass(appId, className); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public long addMachineSyncTask(String sourceIp, String targetIp, String containerIp, String important_info, long parentTaskId) { Map paramMap = new HashMap(); paramMap.put(TaskConstants.SOURCE_HOST_KEY, sourceIp); paramMap.put(TaskConstants.TARGET_HOST_KEY, targetIp); paramMap.put(TaskConstants.CONTAINER_IP, containerIp); String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.MACHINE_SYNC_CLASS; return generateAndSaveTaskQueue(-1, className, param, important_info, parentTaskId); } public long addResourceCompileTask(Integer resourceId, Integer repositoryId, String containerIp, AppUser userInfo){ Map paramMap = new HashMap(); paramMap.put(TaskConstants.RESOURCE_ID, resourceId); paramMap.put(TaskConstants.REPOSITORY_ID, repositoryId); paramMap.put(TaskConstants.CONTAINER_IP, containerIp); paramMap.put(TaskConstants.USER_INFO_KEY, userInfo.getName()); String param = JSONObject.toJSONString(paramMap); String className = TaskConstants.PACK_COMPILE_TASK; return generateAndSaveTaskQueue(-1, className, param, "", -1); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/AppKeyAnalysisTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSONArray; import com.google.common.collect.Lists; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Tuple; import java.util.*; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @author fulei */ @Component("AppKeyAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class AppKeyAnalysisTask extends BaseTask { private long appId; private long auditId; private List redisServerNodes; private final static int MAX_ANALYSIS_COUNT = 1; private final static long TYPE_SLEEP_BASE = 20000000; private final static long TTL_SLEEP_BASE = 20000000; private final static long IDLE_SLEEP_BASE = 20000000; private final static long BIGKEY_SLEEP_BASE = 20000000; private final static long VALUE_SIZE_SLEEP_BASE = 20000000; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2. redis server key type分析 taskStepList.add("createRedisServerKeyTypeTask"); taskStepList.add("waitRedisServerKeyTypeFinish"); taskStepList.add("showKeyTypeResult"); // 3. redis server big key分析 taskStepList.add("createRedisServerBigKeyTask"); taskStepList.add("waitRedisServerBigKeyFinish"); // 4. redis server key ttl分析 taskStepList.add("createRedisServerKeyTtlTask"); taskStepList.add("waitRedisServerKeyTtlFinish"); taskStepList.add("showKeyTtlResult"); // 5. redis server idle key分析 taskStepList.add("createRedisServerIdleKeyTask"); taskStepList.add("waitRedisServerIdleKeyFinish"); taskStepList.add("showIdleKeyResult"); // 6. redis server key value分析 taskStepList.add("createRedisServerKeyValueSizeTask"); taskStepList.add("waitRedisServerKeyValueSizeFinish"); taskStepList.add("showKeyValueSizeResult"); // 7. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } //@TODO 其他比如考虑qps之类 return TaskFlowStatusEnum.SUCCESS; } /** * 6.1.创建分析闲置key子任务(master) */ public TaskFlowStatusEnum createRedisServerIdleKeyTask() { redisServerNodes = buildRedisServerNodes(); // 每个server的dbsize Map redisServerDbSizeMap = new HashMap(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); if (dbSize < 0) { return TaskFlowStatusEnum.ABORT; } redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //可能已经执行过 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * IDLE_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addRedisServerIdleKeyAnalysisTask(appId, auditId, host, port, taskId); redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "appId {} {}:{} redis server idle key analysis task create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(300); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis server idle key analysis create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 6.2.等待分析闲置key子任务(master) */ public TaskFlowStatusEnum waitRedisServerIdleKeyFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_IDLE_KEY_ANALYSIS_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} redis server idle key analysis task execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} redis server idle key analysis task execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 6.3.展示闲置key分析结果 */ public TaskFlowStatusEnum showIdleKeyResult() { String idleKeyResultKey = ConstUtils.getRedisServerIdleKey(appId, auditId); Set tuples = assistRedisService.zrangeWithScores(idleKeyResultKey, 0, -1); for (Tuple tuple : tuples) { String member = tuple.getElement(); double score = tuple.getScore(); logger.info(marker, "{} {} idle distri {} {}", idleKeyResultKey, appId, member, score); assistRedisService.zadd(idleKeyResultKey, (long) score, member); } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建分析key类型子任务 */ public TaskFlowStatusEnum createRedisServerKeyTypeTask() { redisServerNodes = buildRedisServerNodes(); Map redisServerDbSizeMap = new HashMap(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //可能已经执行过 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * TYPE_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addRedisServerKeyTypeAnalysisTask(appId, auditId, host, port, taskId); redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "appId {} {}:{} redis server key type analysis task create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(120); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis server key type analysis create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待key类分析结束 */ public TaskFlowStatusEnum waitRedisServerKeyTypeFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_KEY_TYPE_ANALYSIS_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} redis server key type analysis task execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} redis server key type analysis task execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.3.展示key类分析结束 */ public TaskFlowStatusEnum showKeyTypeResult() { String keyTypeResultKey = ConstUtils.getRedisServerTypeKey(appId, auditId); Set tuples = assistRedisService.zrangeWithScores(keyTypeResultKey, 0, -1); for (Tuple tuple : tuples) { String member = tuple.getElement(); double score = tuple.getScore(); logger.info(marker, "{} {} type distri {} {}", keyTypeResultKey, appId, member, score); assistRedisService.zadd(keyTypeResultKey, (long) score, member); } return TaskFlowStatusEnum.SUCCESS; } /** * 5.1.创建分析key ttl子任务 */ public TaskFlowStatusEnum createRedisServerKeyTtlTask() { redisServerNodes = buildRedisServerNodes(); Map redisServerDbSizeMap = new HashMap(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //可能已经执行过 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * TTL_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addRedisServerKeyTtlAnalysisTask(appId, auditId, host, port, taskId); redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "appId {} {}:{} redis server key ttl analysis task create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(120); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis server key ttl analysis create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 5.2.等待key ttl分析结束 */ public TaskFlowStatusEnum waitRedisServerKeyTtlFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_KEY_TTL_ANALYSIS_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} redis server key ttl analysis task execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} redis server key ttl analysis task execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 5.3.展示key ttl分析结束 */ public TaskFlowStatusEnum showKeyTtlResult() { String keyTtlResultKey = ConstUtils.getRedisServerTtlKey(appId, auditId); Set tuples = assistRedisService.zrangeWithScores(keyTtlResultKey, 0, -1); for (Tuple tuple : tuples) { String member = tuple.getElement(); double score = tuple.getScore(); logger.info(marker, "{} {} ttl distri {} {}", keyTtlResultKey, appId, member, score); assistRedisService.zadd(keyTtlResultKey, (long) score, member); } return TaskFlowStatusEnum.SUCCESS; } /** * 3.1.创建分析big key子任务 */ public TaskFlowStatusEnum createRedisServerBigKeyTask() { redisServerNodes = buildRedisServerNodes(); // 每个server的dbsize Map redisServerDbSizeMap = new HashMap(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //可能已经执行过 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * BIGKEY_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addRedisServerBigKeyAnalysisTask(appId, auditId, host, port, taskId); redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "appId {} {}:{} redis server big key analysis task create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(120); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis server big key analysis create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.2.等待bigkey子任务完成 * * @return */ public TaskFlowStatusEnum waitRedisServerBigKeyFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_BIG_KEY_ANALYSIS_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} redis server big key analysis task execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} redis server big key analysis task execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 6.1.创建分析key value size子任务 */ public TaskFlowStatusEnum createRedisServerKeyValueSizeTask() { redisServerNodes = buildRedisServerNodes(); Map redisServerDbSizeMap = new HashMap(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //可能已经执行过 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * VALUE_SIZE_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addRedisServerKeyValueAnalysisTask(appId, auditId, host, port, taskId); redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "appId {} {}:{} redis server key value size analysis task create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(120); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis server value size analysis create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 6.2.等待key value size分析结束 */ public TaskFlowStatusEnum waitRedisServerKeyValueSizeFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_KEY_VALUE_SIZE_ANALYSIS_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} redis server key value size analysis task execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} redis server key value size analysis task execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 6.3.展示key value size分析结束 */ public TaskFlowStatusEnum showKeyValueSizeResult() { String keyValueSizeResultKey = ConstUtils.getRedisServerValueSizeKey(appId, auditId); Set tuples = assistRedisService.zrangeWithScores(keyValueSizeResultKey, 0, -1); for (Tuple tuple : tuples) { String member = tuple.getElement(); double score = tuple.getScore(); logger.info(marker, "{} {} value size distri {} {}", keyValueSizeResultKey, appId, member, score); assistRedisService.zadd(keyValueSizeResultKey, (long) score, member); } return TaskFlowStatusEnum.SUCCESS; } /** * 7.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("集群(%s-%s)的键值分析完成", appDesc.getAppId(), appDesc.getName())); //appWechatUtil.noticeAuditFinish(auditId, content.toString()); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } private List transformRedisServerFromInstance(List instanceInfoList, int nodeCount) { List redisServerNodes = new ArrayList(); for (int i = 0; i < instanceInfoList.size() && i < nodeCount; i++) { InstanceInfo instanceInfo = instanceInfoList.get(i); RedisServerNode redisServerNode = new RedisServerNode(); redisServerNode.setIp(instanceInfo.getIp()); redisServerNode.setPort(instanceInfo.getPort()); redisServerNodes.add(redisServerNode); } return redisServerNodes; } private List buildRedisServerNodes() { List list = Lists.newArrayList(); if (CollectionUtils.isEmpty(redisServerNodes)) { List instanceInfoList = appService.getAppMasterInstanceInfoList(appId); redisServerNodes = transformRedisServerFromInstance(instanceInfoList, MAX_ANALYSIS_COUNT); list.addAll(redisServerNodes); } else { for (RedisServerNode redisServerNode : redisServerNodes) { list.add(new RedisServerNode(redisServerNode.getIp(), redisServerNode.getPort())); } } return list; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/MachineSyncTask.java ================================================ package com.sohu.cache.task.tasks; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineRelation; import com.sohu.cache.exception.SSHException; import com.sohu.cache.ssh.SSHTemplate.Result; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.MachineTaskEnum; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * Created by chenshi on 2019/5/24. */ @Component("MachineSyncTask") @Scope(SCOPE_PROTOTYPE) public class MachineSyncTask extends BaseTask { /** * 源宿主机ip */ private String sourceIp; /** * 目标宿主机ip */ private String targetIp; /** * 容器ip */ private String containerIp; /** * k8s 持久化/配置/日志 目录 */ private static String baseConfDir = "/data/redis/conf/"; private static String baseDataDir = "/data/redis/data/"; private static String baseLogDir = "/data/redis/logs/"; private static String backupDir = "/data/redis/bak/"; /** * 同步/校验数据 超时时间 */ private static int SYNC_DATA_TIMEOUT = 30 * 60 * 1000; private static int MD5_CHECK_TIMEOUT = 2 * 60 * 1000; private static int BACKUP_DATA_TIMEOUT = 5 * 60 * 1000; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查源主机同步环境 taskStepList.add("checkSourceMachineEnv"); //3. 检查目标主机连通性及目录检查 taskStepList.add("checkTargetMachineEnv"); //4. scp同步数据 source->target host machine taskStepList.add("startSyncData"); //5. 校验目的文件是否一致 taskStepList.add("checkDirMd5"); //6. 备份历史数据 taskStepList.add("backupSourceData"); //7. 同步完成 taskStepList.add("syncOver"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); // 1.源宿主机 sourceIp = MapUtils.getString(paramMap, TaskConstants.SOURCE_HOST_KEY); if (StringUtils.isEmpty(sourceIp)) { logger.error(marker, "task {} source machine ip {} is empty", taskId, sourceIp); return TaskFlowStatusEnum.ABORT; } // 2.目标宿主机 targetIp = MapUtils.getString(paramMap, TaskConstants.TARGET_HOST_KEY); if (StringUtils.isEmpty(targetIp)) { logger.error(marker, "task {} target machine ip {} is empty", taskId, targetIp); return TaskFlowStatusEnum.ABORT; } // 3.容器ip containerIp = MapUtils.getString(paramMap, TaskConstants.CONTAINER_IP); if (!StringUtils.isEmpty(containerIp)) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(containerIp); if (machineInfo == null) { logger.error(marker, "task {} container ip {} is not exist", taskId, containerIp); return TaskFlowStatusEnum.ABORT; } } else { logger.error(marker, "task {} container ip {} is empty", taskId, containerIp); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.源主机: * 2.1.机器连通性 * 2.2.sshpass安装 * 2.3.源数据目录是否存在 */ public TaskFlowStatusEnum checkSourceMachineEnv() { // 1.连通性 + sshpass String sshpass_command = "sshpass -V | head -1 "; // 源数据目录 String checkDir_command = "ls -l " + baseConfDir.concat(containerIp) + " | wc -l && ls -l " + baseDataDir.concat(containerIp) + " | wc -l && ls -l " + baseLogDir.concat(containerIp) + " | wc -l"; try { Result checkResult = sshService.executeWithResult(sourceIp, sshpass_command); if (checkResult.isSuccess() && checkResult.getResult().indexOf("sshpass") > -1) { logger.info(marker, "sourceMachine ip :{} check sshpass env result:{}", sourceIp, checkResult.getResult()); } else { logger.error(marker, "sourceMachine ip :{} check sshpass env error message:{}", sourceIp, checkResult.getResult()); return TaskFlowStatusEnum.ABORT; } Result checkDirResult = sshService.executeWithResult(sourceIp, checkDir_command); if (checkDirResult.isSuccess()) { logger.info(marker, "sourceMachine ip :{} check dir env command:{} , result:{}", sourceIp, checkDir_command, checkDirResult.getResult()); if (checkDirResult.getResult() != null && checkDirResult.getResult().indexOf("0 0 0") > -1) { logger.error(marker, "sourceMachine ip :{} check dir not exist result:{}", sourceIp, checkDirResult.getResult()); return TaskFlowStatusEnum.ABORT; } } else { logger.error(marker, "sourceMachine ip :{} check dir env error message:{}", sourceIp, checkDirResult.getResult()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, "sourceMachine ip :{} check env error message:{}", sourceIp, e.getMessage()); e.printStackTrace(); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3.目标主机检查: * 3.1. 机器连通性 * 3.2. cachecloud用户是否存在 * 3.3. 检测容器上是否有redis进程 * 3.4. 同步目录存在且无redis进程 删除数据目录 */ public TaskFlowStatusEnum checkTargetMachineEnv() { String checkUser_command = "cat /etc/passwd | grep cachecloud "; String checkRedis_command = "ps -ef | grep redis | grep -v \"grep redis\" | wc -l "; String delDir_command = "rm -rf " + baseConfDir.concat(containerIp) + " " + baseDataDir.concat(containerIp) + " " + baseLogDir.concat(containerIp); try { // 等待镜像启动 TimeUnit.SECONDS.sleep(30); // 1.检查用户是否存在 Result checkResult = sshService.executeWithResult(targetIp, checkUser_command); if (checkResult.isSuccess() && checkResult.getResult().indexOf("cachecloud") > -1) { logger.info(marker, "targetMachine ip :{} check user:{} , result:{}", targetIp, checkUser_command, checkResult.getResult()); } else { logger.error(marker, "targetMachine ip :{} check user:{} , error message:{}", targetIp, checkUser_command, checkResult.getResult()); return TaskFlowStatusEnum.ABORT; } // 2.检测容器是否还有redis进程 Result checkRedisResult = sshService.executeWithResult(containerIp, checkRedis_command); if (checkRedisResult.isSuccess() && checkRedisResult.getResult().equals("0")) { logger.info(marker, "container ip :{} check redis:{} size:{} is not exist ", containerIp, checkRedis_command, checkRedisResult.getResult()); } else { logger.error(marker, "container ip :{} check redis:{} size:{} , message:{}", containerIp, checkRedis_command, checkRedisResult.getResult()); return TaskFlowStatusEnum.ABORT; } // 3.清除目标主机的目录数据(防止冲突) Result delResult = sshService.executeWithResult(targetIp, delDir_command); if (delResult.isSuccess()) { logger.info(marker, "targetMachine ip :{} , del success command:{} ", targetIp, delDir_command, delResult.getResult()); } else { logger.error(marker, "targetMachine ip :{} , del command:{}, error message:{}", targetIp, delDir_command, delResult.getResult()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, "sourceMachine ip :{} check env error message:{}", sourceIp, e.getMessage(),e); return TaskFlowStatusEnum.ABORT; } catch (InterruptedException e) { return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 4.持久化数据、配置目录同步任务 */ public TaskFlowStatusEnum startSyncData() { /*String sync_command = " sshpass -p " + ConstUtils.PASSWORD + " scp -oStrictHostKeyChecking=no -r " + baseConfDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseConfDir + " && sshpass -p " + ConstUtils.PASSWORD + " scp -oStrictHostKeyChecking=no -r " + baseDataDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseDataDir + " && sshpass -p " + ConstUtils.PASSWORD + " scp -oStrictHostKeyChecking=no -r " + baseLogDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseLogDir; */ String sync_command = " scp -i "+ConstUtils.DEFAULT_PUBLIC_KEY_PEM+" -oStrictHostKeyChecking=no -r " + baseConfDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseConfDir + " && scp -i "+ConstUtils.DEFAULT_PUBLIC_KEY_PEM+" -oStrictHostKeyChecking=no -r " + baseDataDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseDataDir + " && scp -i "+ConstUtils.DEFAULT_PUBLIC_KEY_PEM+" -oStrictHostKeyChecking=no -r " + baseLogDir.concat(containerIp) + " " + ConstUtils.USERNAME + "@" + targetIp + ":" + baseLogDir; logger.info(marker, "source ip :{} ,execute command :{}", sourceIp, sync_command); Result syncResult = null; try { long start = System.currentTimeMillis(); syncResult = sshService.executeWithResult(sourceIp, sync_command, SYNC_DATA_TIMEOUT); if (syncResult.isSuccess() || syncResult.getResult().indexOf("Permission denied") == -1) { logger.info(marker, "sync data result:{} costTime:{} s", syncResult.getResult(), (System.currentTimeMillis() - start) / 1000); } else { logger.error(marker, "sync data error message:{}", syncResult.getResult()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, "sync data error message:{} {}", syncResult,e.getMessage(),e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 5.同步数据目录文件md5校验 */ public TaskFlowStatusEnum checkDirMd5() { // String sourceShell = "find " + baseConfDir.concat(containerIp) + " " + baseDataDir.concat(containerIp) + " " + baseLogDir.concat(containerIp) + " -type f -exec md5sum {} \\; | sort -k 2"; // String targetShell = "find " + baseConfDir.concat(containerIp) + " " + baseDataDir.concat(containerIp) + " " + baseLogDir.concat(containerIp) + " -type f -exec md5sum {} \\; | sort -k 2"; String sourceShell = "find " + baseConfDir.concat(containerIp) + "/*.conf " + baseDataDir.concat(containerIp) + "/*.conf -type f -exec md5sum {} \\; | sort -k 2"; String targetShell = "find " + baseConfDir.concat(containerIp) + "/*.conf " + baseDataDir.concat(containerIp) + "/*.conf -type f -exec md5sum {} \\; | sort -k 2"; //1.源宿主机和目标宿主机 目录文件列表的md5值 Result sourceMd5Result; Result targetMd5Result; try { sourceMd5Result = sshService.executeWithResult(sourceIp, sourceShell, MD5_CHECK_TIMEOUT); if(sourceMd5Result == null){ logger.error(marker, " source ip:{} validate md5 result is null", sourceIp); return TaskFlowStatusEnum.ABORT; } if (sourceMd5Result.isSuccess()) { logger.info(marker, "source ip:{} validate md5 result: ", sourceIp); for (String sourceMd5 : sourceMd5Result.getResult().split("\n")) { logger.info(marker, "source file md5 {} : ", sourceMd5); } } else { logger.error(marker, " source ip:{} validate md5 error:{}", sourceIp, sourceMd5Result.getExcetion()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, " source ip:{} validate md5 error:{}", sourceIp, e.getMessage()); return TaskFlowStatusEnum.ABORT; } try { targetMd5Result = sshService.executeWithResult(targetIp, targetShell, MD5_CHECK_TIMEOUT); if(targetMd5Result == null){ logger.error(marker, " target ip:{} validate md5 result is null", targetIp); return TaskFlowStatusEnum.ABORT; } if (targetMd5Result.isSuccess()) { logger.info(marker, "target ip:{} validate md5 result:{} ", targetIp, targetMd5Result.getResult()); for (String targetMd5 : targetMd5Result.getResult().split("\n")) { logger.info(marker, "target file md5 {} : ", targetMd5); } } else { logger.error(marker, " target ip:{} validate md5 error:{}", targetIp, targetMd5Result.getResult()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, " target ip:{} validate md5 error:{}", sourceIp, e.getMessage()); return TaskFlowStatusEnum.ABORT; } // 2.print md5 compare result if (sourceMd5Result != null && targetMd5Result != null && targetMd5Result.getResult().equals(sourceMd5Result.getResult())) { logger.info(marker, "===== compare source ip:{} & target ip:{} is equal =====", sourceIp, targetIp); } else { logger.error(marker, "===== compare source ip:{} & target ip:{} is diffrent =====", sourceIp, targetIp); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum backupSourceData() { // 1. backup data : /data/redis/bak/${ip}_${time}/... SimpleDateFormat time = new SimpleDateFormat("yyyyMMddHHmm"); String timeFormat = time.format(new Date()); // 2. backup command String backup_command = " mkdir -p " + backupDir.concat(containerIp + "_" + timeFormat) + " && " + " mv " + baseConfDir.concat(containerIp) + " " + backupDir.concat(containerIp + "_" + timeFormat).concat("/conf") + " && " + " mv " + baseDataDir.concat(containerIp) + " " + backupDir.concat(containerIp + "_" + timeFormat).concat("/data") + " && " + " mv " + baseLogDir.concat(containerIp) + " " + backupDir.concat(containerIp + "_" + timeFormat).concat("/logs"); Result backupResult; try { backupResult = sshService.executeWithResult(sourceIp, backup_command, BACKUP_DATA_TIMEOUT); if (backupResult.isSuccess()) { logger.info(marker, "source ip:{} backup date success ,result:{} ", sourceIp, backupResult.getResult()); } else { logger.error(marker, " source ip:{} backup date error:{}", sourceIp, backupResult.getResult()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, " source ip:{} backup date error:{}", sourceIp, e.getMessage()); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 7.更新机器同步状态 */ public TaskFlowStatusEnum syncOver() { // update machine SYNC status try { List relationList = machineRelationDao.getUnSyncRelationList(containerIp, sourceIp); if (!CollectionUtils.isEmpty(relationList)) { for (MachineRelation machineRelation : relationList) { machineRelationDao.updateMachineSyncStatus(machineRelation.getId(), MachineTaskEnum.SYNCED.getValue()); logger.info(marker, "update machine realtion id:{}, ip:{},realIp:{} sync status success !", machineRelation.getId(), sourceIp, containerIp); } } } catch (Exception e) { logger.error(marker, "update machine relation ", sourceIp, targetIp); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 执行一个ls命令,确认ssh以及不是只读盘 * * @return */ protected boolean checkMachineIsConnect(String ip) { try { Result result = sshService.executeWithResult(ip, "ls / | wc -l"); if (result.isSuccess()) { return true; } } catch (Exception e) { logger.error(marker, e.getMessage()); } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/OffLineAppTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.AppEmailUtil; import org.apache.commons.collections.MapUtils; import org.assertj.core.util.Lists; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; import java.util.stream.Collectors; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * Created by rucao on 2019/11/13 */ @Component("OffLineAppTask") @Scope(SCOPE_PROTOTYPE) public class OffLineAppTask extends BaseTask { private long appId; private AppDesc appDesc; private AppUser userInfo; private long auditId; @Autowired private AppService appService; @Autowired private InstanceDao instanceDao; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; @Override public List getTaskSteps() { List taskStepList = Lists.newArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 2. 执行应用下线处理 taskStepList.add("executeOffLineApp"); // 3. 更新应用信息 taskStepList.add("updateAppStatus"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { TaskFlowStatusEnum taskFlowStatusEnum = super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); taskFlowStatusEnum = TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY, -1); if (auditId <= 0) { logger.info(marker, "task {} auditId {} is wrong", taskId, auditId); } appDesc = appService.getByAppId(appId); if (appDesc == null) { logger.error(marker, "task {} appId {} appDesc is not exist", taskId, appId); taskFlowStatusEnum = TaskFlowStatusEnum.ABORT; } Object userObject = MapUtils.getObject(paramMap, TaskConstants.USER_INFO_KEY, null); if (userObject instanceof JSONObject) { JSONObject userJson = (JSONObject) userObject; userInfo = JSONObject.parseObject(JSON.toJSONString(userJson), AppUser.class); } if (userInfo == null) { logger.error(marker, "task {} appId {} userInfo is not exist", taskId, appId); taskFlowStatusEnum = TaskFlowStatusEnum.ABORT; } else { if (!ConstUtils.SUPER_MANAGER.contains(userInfo.getName())) { logger.error("task {} appId {} user {} who hope to offline hasn't privilege", taskId, appId, userInfo.getName()); taskFlowStatusEnum = TaskFlowStatusEnum.ABORT; } } if (taskFlowStatusEnum == TaskFlowStatusEnum.ABORT) { appEmailUtil.noticeOfflineApp(userInfo, appId, false); } return taskFlowStatusEnum; } /** * 2. 执行应用下线操作 * * @return */ public TaskFlowStatusEnum executeOffLineApp() { logger.info("executeOffLineApp"); if (auditId > 0) { appAuditDao.updateAppAuditUser(auditId, 2, userInfo.getId()); } List instanceInfos = instanceDao.getInstListByAppId(appId); int type = appDesc.getType(); List isShutDownList = Lists.newArrayList(); if (instanceInfos != null) { isShutDownList = instanceInfos.parallelStream() .filter(instanceInfo -> !instanceInfo.isOffline()) .map(instanceInfo -> instanceOffline(instanceInfo, type)) .collect(Collectors.toList()); } if (isShutDownList.contains(false)) { appEmailUtil.noticeOfflineApp(userInfo, appId, false); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } private boolean instanceOffline(InstanceInfo instanceInfo, int type) { final String ip = instanceInfo.getIp(); final int port = instanceInfo.getPort(); boolean isShutdown = TypeUtil.isRedisType(type) ? redisCenter.shutdown(appId, ip, port) : true; if(isShutdown){ isShutdown = redisCenter.checkShutdownSuccess(instanceInfo); } if (isShutdown) { instanceInfo.setStatus(InstanceStatusEnum.OFFLINE_STATUS.getStatus()); instanceDao.update(instanceInfo); } else { logger.error("task {} appId {} {}:{} redis not shutdown!", taskId, appId, ip, port); return false; } return true; } /** * 3. 更新应用信息,发送邮件 * * @return */ public TaskFlowStatusEnum updateAppStatus() { logger.info("updateAppStatus"); appDesc.setStatus(AppStatusEnum.STATUS_OFFLINE.getStatus()); if (auditId > 0) { appAuditDao.updateAppAudit(auditId, 1); } int count = appService.update(appDesc); if (count > 0) { appEmailUtil.noticeOfflineApp(userInfo, appId, true); return TaskFlowStatusEnum.SUCCESS; } else { appEmailUtil.noticeOfflineApp(userInfo, appId, false); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/RedisClusterAppDeployTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.RedisConstant; import com.sohu.cache.redis.util.JedisUtil; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.EnvUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import java.util.*; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** *

* Description: 部署redis-cluster任务 *

* * @author chenshi * @version 1.0 * @date 2019/1/9 */ @Component("RedisClusterAppDeployTask") @Scope(SCOPE_PROTOTYPE) public class RedisClusterAppDeployTask extends BaseTask { /** * 应用id */ private long appId; /** * 审核id */ private long auditId; /** * redis server部署实例列表 */ private List appDeployInfoList; /** * redis server机器列表 */ private List redisServerMachineList; /** * 每台机器redis server实例个数 */ private int masterPerMachine; /** * 每个实例的最大内存(MB) */ private int maxMemory; private List redisServerNodes; /** * Redis版本 */ private String version; /** * 集群的节点信息 */ private Map clusterMap = new LinkedHashMap(); @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查资源 taskStepList.add("checkResourceAllow"); //3. 检查机器可用性 taskStepList.add("checkMachineConnect"); //4. 更新机器分配状态 taskStepList.add("updateMachineAllocateTrue"); //5. 获取实例列表 taskStepList.add("generateInstanceNodes"); //6. 保存实例列表 taskStepList.add("saveInstanceNodes"); //7. 创建redis server job taskStepList.add("createRedisServerTask"); //8. 等待redis server job完成 taskStepList.add("waitRedisServerFinish"); /* 9. 设置密码已放到实例配置文件中,启动后自动带有密码, 此步骤是设置app_desc表的密码字段,避免后续访问操作失败 */ taskStepList.add("setPasswd"); //10. 创建redis cluster job taskStepList.add("startRedisCluster"); //11. 等待redis cluster job完成 taskStepList.add("waitRedisClusterFinish"); //12. 更改实例状态 taskStepList.add("updateInstanceStatus"); //13. 开始收集部署 taskStepList.add("deployCollection"); //14. rdb taskStepList.add("checkFullSync"); //14. 审核 taskStepList.add("updateAudit"); //15. 更新机器分配状态 taskStepList.add("updateMachineAllocateFalse"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } //审核id auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); // if (auditId <= 0) { // logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); // return TaskFlowStatusEnum.ABORT; // } //maxMemory maxMemory = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY); if (maxMemory <= 0 || maxMemory > TaskConstants.MAX_MEMORY_LIMIT) { logger.error(marker, "task {} maxMemory {} is wrong", taskId, maxMemory); return TaskFlowStatusEnum.ABORT; } //masterPerMachine masterPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.MASTER_PER_MACHINE_KEY); if (masterPerMachine < 0 || masterPerMachine > TaskConstants.MAX_MASTER_PER_MACHINE) { logger.error(marker, "task {} masterPerMachine {} is wrong", taskId, masterPerMachine); return TaskFlowStatusEnum.ABORT; } //appDeployInfo String appDeployInfoStr = MapUtils.getString(paramMap, TaskConstants.APP_DEPLOY_INFO_LIST_KEY); appDeployInfoList = JSONArray.parseArray(appDeployInfoStr, String.class); if (CollectionUtils.isEmpty(appDeployInfoList)) { logger.error(marker, "task {} appDeployInfoList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis server machine String redisServerMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY); redisServerMachineList = JSONArray.parseArray(redisServerMachineStr, String.class); if (CollectionUtils.isEmpty(redisServerMachineList)) { logger.error(marker, "task {} redisServerMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } // init cluster map if (MapUtils.isEmpty(clusterMap)) { setClusterMap(redisServerNodes); logger.info(marker, "init cluster map :{} successfully", clusterMap); printClusterMap(clusterMap); } } // redis版本 version = MapUtils.getString(paramMap, TaskConstants.VERSION_KEY); return TaskFlowStatusEnum.SUCCESS; } /** * 检查资源是否充足 * * @return */ public TaskFlowStatusEnum checkResourceAllow() { if (EnvUtil.isLocal(environment)) { return TaskFlowStatusEnum.SUCCESS; } long memoryNeed = 0L; if (masterPerMachine == 0) { memoryNeed = maxMemory; } else { memoryNeed = Long.valueOf(masterPerMachine) * maxMemory; } return checkResourceAllow(redisServerMachineList, memoryNeed); } public TaskFlowStatusEnum checkMachineConnect() { // redis server return checkMachineConnect(redisServerMachineList, "cluster: redisServer {} is not connected"); } /** * 生成实例 * * @return */ public TaskFlowStatusEnum generateInstanceNodes() { redisServerNodes = instancePortService.generateRedisServerNodeListWithDeployInfo(appId, appDeployInfoList, masterPerMachine, maxMemory); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty, appId is {}, redisServerMachineList is {}, masterPerMachine is {}, maxMemory is {}", appId, redisServerMachineList, masterPerMachine, maxMemory); return TaskFlowStatusEnum.ABORT; } //设置环境变量 paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); return TaskFlowStatusEnum.SUCCESS; } /** * 保存实例 * * @return */ public TaskFlowStatusEnum saveInstanceNodes() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty"); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { Integer instanceId = saveInstance(appId, redisServerNode.getIp(), redisServerNode.getPort(), maxMemory, InstanceTypeEnum.REDIS_CLUSTER, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 创建任务 * * @return */ public TaskFlowStatusEnum createRedisServerTask() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "{} redisServerNodes is emtpy", taskId); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addRedisServerInstallTask(appId, host, port, redisServerNode.getMaxmemory(), version, true, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} redis server childTaskId is {}", appId, host, port, childTaskId); return TaskFlowStatusEnum.ABORT; } redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "{}:{} redis server task created successfully", host, port); } catch (Exception e) { logger.error(marker, "{}:{} redis server task created failly", host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待任务完成 */ public TaskFlowStatusEnum waitRedisServerFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { long childTaskId = redisServerNode.getTaskId(); String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{}:{} redis server task fail", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{}:{} redis server task finish successfully", host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 创建redis cluster任务 * * @return */ public TaskFlowStatusEnum startRedisCluster() { // 1.param验证 if (MapUtils.isEmpty(clusterMap)) { setClusterMap(redisServerNodes); printClusterMap(clusterMap); } // 2.构建集群 boolean isCluster = redisDeployCenter.startCluster(appId, clusterMap); if (!isCluster) { logger.error(marker, "create redis Cluster error :{}!", clusterMap); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 确认集群redis cluster构建是否成功 * * @return */ public TaskFlowStatusEnum waitRedisClusterFinish() { Boolean clusterOk = false; while (!clusterOk) { boolean isOk = true; for (Map.Entry node : clusterMap.entrySet()) { Jedis jedis = null; try { jedis = node.getKey(); String clusterInfo = jedis.clusterInfo(); if (!clusterInfo.split("\n")[0].contains("ok")) { isOk = false; break; } // 验证实例的集群是否ok if (isOk) { clusterOk = true; } else { logger.error(marker, " app :{} is not cluster , clusterInfo :{}", appId, clusterInfo); return TaskFlowStatusEnum.ABORT; } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (jedis != null) { jedis.close(); } } } } return TaskFlowStatusEnum.SUCCESS; } /** * 更新实例状态 * * @return */ public TaskFlowStatusEnum updateInstanceStatus() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); } return TaskFlowStatusEnum.SUCCESS; } /** * 部署实例收集 * * @return */ public TaskFlowStatusEnum deployCollection() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); boolean isDeploy = redisCenter.sendDeployRedisRelateCollectionMsg(appId, host, port); if (!isDeploy) { logger.error(marker, "{} {}:{} deploy fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} deploy sucessfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 设置密码 * * @return */ public TaskFlowStatusEnum setPasswd() { try { if (appId > 0) { // 设置密码 appService.updateAppPwd(appId, String.valueOf(appId)); // 密码校验逻辑 boolean checkFlag = redisDeployCenter.checkAuths(appId); logger.info(marker, "check app clutser passwd:{}", checkFlag); if (!checkFlag) { logger.error(marker, "check app clutser passwd error, appId:{}!", appId); return TaskFlowStatusEnum.ABORT; } } } catch (Exception e) { logger.error(e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkFullSync(){ Map fullSyncSet = new HashMap<>(); Map slaveOnLoadingSet = new HashMap<>(); // 耗时 int totalSeconds = 0; redisServerNodes.stream().filter(redisServerNode -> StringUtils.isBlank(redisServerNode.getMasterHost()) && redisServerNode.getMasterPort() == 0) .forEach(redisServerNode -> fullSyncSet.put(redisServerNode, false)); redisServerNodes.stream().filter(redisServerNode -> StringUtils.isNotBlank(redisServerNode.getMasterHost()) && redisServerNode.getMasterPort() != 0) .forEach(redisServerNode -> slaveOnLoadingSet.put(redisServerNode, false)); while (true) { // 简单的计时器 long startTime = System.currentTimeMillis(); boolean syncFlag = true; for (Map.Entry entry : fullSyncSet.entrySet()) { if(entry.getValue().equals(false)){ syncFlag = false; Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, entry.getKey().getIp(), entry.getKey().getPort()); String statsInfo = jedis.info(RedisConstant.Stats.getValue()); if(StringUtils.isNotBlank(statsInfo)){ String[] split = statsInfo.split("\r\n"); for (String str : split){ if(StringUtils.isNotBlank(str) && str.contains("sync_full:")){ String[] pair = StringUtils.splitByWholeSeparator(str, ":"); Long aLong = Long.valueOf(pair[1]); if(aLong > 0){ fullSyncSet.put(entry.getKey(), true); break; } } } } }catch (Exception e){ logger.error(marker, "check full sync, appId:{}, error:{}!", appId, e.getMessage()); }finally { if (jedis != null) { jedis.close(); } } }else{ continue; } } if(syncFlag){ break; } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { logger.error(marker, e.getMessage(), e); } // 简单的计时器(秒) long costTime = System.currentTimeMillis() - startTime; totalSeconds += (costTime / 1000); if (totalSeconds > TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT) { return TaskFlowStatusEnum.ABORT; } } try { TimeUnit.SECONDS.sleep(20); } catch (InterruptedException e) { logger.error(marker, "check full sync, appId:{}, error:{}!", appId, e.getMessage()); logger.error(marker, e.getMessage()); } while (true) { // 简单的计时器 long startTime = System.currentTimeMillis(); boolean loadingFlag = true; for (Map.Entry entry : slaveOnLoadingSet.entrySet()) { if (entry.getValue().equals(false)) { loadingFlag = false; Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, entry.getKey().getIp(), entry.getKey().getPort()); String statsInfo = jedis.info(RedisConstant.Replication.getValue()); if (StringUtils.isNotBlank(statsInfo)) { String[] split = statsInfo.split("\r\n"); for (String str : split) { if (StringUtils.isNotBlank(str) && str.contains("master_sync_in_progress:")) { String[] pair = StringUtils.splitByWholeSeparator(str, ":"); Long aLong = Long.valueOf(pair[1]); if (aLong == 0) { slaveOnLoadingSet.put(entry.getKey(), true); break; } } } } } catch (Exception e) { logger.error(marker, "check not on sync progress, appId:{}, error:{}!", appId, e.getMessage()); } finally { if (jedis != null) { jedis.close(); } } } else { continue; } } if(loadingFlag){ break; } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { logger.error(marker, e.getMessage(), e); } // 简单的计时器(秒) long costTime = System.currentTimeMillis() - startTime; totalSeconds += (costTime / 1000); if (totalSeconds > TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT) { return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 通过初审:资源分配 * * @return */ public TaskFlowStatusEnum updateAudit() { try { if (auditId > 0){ appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } public TaskFlowStatusEnum updateMachineAllocateFalse() { return updateMachineAllocateStatus(0); } public TaskFlowStatusEnum updateMachineAllocateTrue() { return updateMachineAllocateStatus(1); } public TaskFlowStatusEnum updateMachineAllocateStatus(int status) { try { Set allMachineSet = new HashSet(); allMachineSet.addAll(redisServerMachineList); for (String ip : allMachineSet) { machineDao.updateMachineAllocate(ip, status); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } /** * 组装 clusterMap * * @param redisServerNodes */ public void setClusterMap(List redisServerNodes) { if (!CollectionUtils.isEmpty(redisServerNodes)) { for (RedisServerNode redisServerNode : redisServerNodes) { String masterHost = redisServerNode.getMasterHost(); int masterPort = redisServerNode.getMasterPort(); if (masterHost == null || masterPort <= 0) { continue; } String slaveHost = redisServerNode.getIp(); int slavePort = redisServerNode.getPort(); if (StringUtils.isNotBlank(slaveHost)) { Jedis masterJedis = redisCenter.getJedis(appId, masterHost, masterPort); Jedis slaveJedis = redisCenter.getJedis(appId, slaveHost, slavePort); clusterMap.put(masterJedis, slaveJedis); } else { clusterMap.put(redisCenter.getJedis(appId, masterHost, masterPort), null); } } } } /** * 输出集群节点关系 */ public void printClusterMap(Map clusterMap) { if (!MapUtils.isEmpty(clusterMap)) { for (Map.Entry msNode : clusterMap.entrySet()) { Jedis masterNode = msNode.getKey(); Jedis slaveNode = msNode.getValue(); String masterInfo = masterNode != null ? JedisUtil.getHostPort(masterNode) : null; String slaveInfo = slaveNode != null ? JedisUtil.getHostPort(slaveNode) : null; logger.info(marker, "master :{} -> slave :{}", masterInfo, slaveInfo); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/RedisSentinelAppDeployTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineStats; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisSentinelNode; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.EnvUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.*; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** *

* Description: Redis Sentinel应用部署任务流 *

* * @author chenshi * @version 1.0 * @date 2019/1/10 */ @Component("RedisSentinelAppDeployTask") @Scope(SCOPE_PROTOTYPE) public class RedisSentinelAppDeployTask extends BaseTask { /** * 应用id */ private long appId; /** * 审核id */ private long auditId; /** * redis server机器列表 */ private List redisServerMachineList; /** * redis sentinel机器列表 */ private List redisSentinelMachineList; /** * 每台机器redis server实例个数 */ private int masterPerMachine; /** * 每台机器sentinel实例个数 */ private int sentinelPerMachine; /** * 每个实例的最大内存(MB) */ private int maxMemory; private List redisServerNodes; private List redisSentinelNodes; private String version; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查资源 taskStepList.add("checkResourceAllow"); //3. 检查机器可用性 taskStepList.add("checkMachineConnect"); //4. 更新机器分配状态 taskStepList.add("updateMachineAllocateTrue"); //5. 获取实例列表 taskStepList.add("generateInstanceNodes"); //6. 保存实例列表 taskStepList.add("saveRedisInstanceNodes"); taskStepList.add("saveSentinelInstanceNodes"); //7. 创建redis server job taskStepList.add("createRedisServerTask"); //8. 等待redis server job完成 taskStepList.add("waitRedisServerFinish"); /* 9. 设置密码已放到实例配置文件中,启动后自动带有密码, 此步骤是设置app_desc表的密码字段,避免后续访问操作失败 */ taskStepList.add("setPasswd"); //10. 更改实例状态 taskStepList.add("updateInstanceStatus"); //11. 主从复制 taskStepList.add("configReplication"); //12. 创建redis sentinel job taskStepList.add("createRedisSentinelTask"); //13. 等待redis sentinel job完成 taskStepList.add("waitRedisSentinelFinish"); //14. 更改实例状态 taskStepList.add("updateSentinelInstanceStatus"); //15. 开始收集部署 taskStepList.add("deployCollection"); //16. 重置sentinel实例状态 taskStepList.add("sentinelReset"); //17. 审核 taskStepList.add("updateAudit"); //18. 更新机器分配状态 taskStepList.add("updateMachineAllocateFalse"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } //审核id auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); // if (auditId <= 0) { // logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); // return TaskFlowStatusEnum.ABORT; // } //maxMemory maxMemory = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY); if (maxMemory <= 0 || maxMemory > TaskConstants.MAX_MEMORY_LIMIT) { logger.error(marker, "task {} maxMemory {} is wrong", taskId, maxMemory); return TaskFlowStatusEnum.ABORT; } //masterPerMachine masterPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.MASTER_PER_MACHINE_KEY); if (masterPerMachine <= 0 || masterPerMachine > TaskConstants.MAX_MASTER_PER_MACHINE) { logger.error(marker, "task {} masterPerMachine {} is wrong", taskId, masterPerMachine); return TaskFlowStatusEnum.ABORT; } //sentinelPerMachine sentinelPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.SENTINEL_PER_MACHINE_KEY); if (sentinelPerMachine <= 0) { logger.error(marker, "task {} sentinelPerMachine {} is wrong", taskId, sentinelPerMachine); return TaskFlowStatusEnum.ABORT; } //redis server machine String redisServerMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY); redisServerMachineList = JSONArray.parseArray(redisServerMachineStr, String.class); if (CollectionUtils.isEmpty(redisServerMachineList)) { logger.error(marker, "task {} redisServerMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } //redis sentinel machine String redisSentinelMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY); redisSentinelMachineList = JSONArray.parseArray(redisSentinelMachineStr, String.class); if (CollectionUtils.isEmpty(redisSentinelMachineList)) { logger.error(marker, "task {} redisSentinelMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis sentinel list String redisSentinelNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SENTINEL_NODES_KEY); if (StringUtils.isNotBlank(redisSentinelNodesStr)) { redisSentinelNodes = JSONArray.parseArray(redisSentinelNodesStr, RedisSentinelNode.class); if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.error(marker, "task {} redisSentinelNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } version = MapUtils.getString(paramMap, TaskConstants.VERSION_KEY); return TaskFlowStatusEnum.SUCCESS; } /** * 检查资源是否充足 * * @return */ public TaskFlowStatusEnum checkResourceAllow() { if (EnvUtil.isLocal(environment)) { return TaskFlowStatusEnum.SUCCESS; } // 容量和代理 long memoryNeed = Long.valueOf(masterPerMachine) * maxMemory; TaskFlowStatusEnum taskFlowStatusEnum = checkResourceAllow(redisServerMachineList, memoryNeed); if(taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)){ return TaskFlowStatusEnum.ABORT; } // sentinel for (String redisSentinelIp : redisSentinelMachineList) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(redisSentinelIp); if (machineStats == null) { logger.error(marker, "{} redis sentinel machineStats is null", redisSentinelIp); return TaskFlowStatusEnum.ABORT; } MachineInfo machineInfo = machineDao.getMachineInfoByIp(redisSentinelIp); if (machineInfo == null || machineInfo.getIsAllocating() == 1) { logger.error(marker, "redis sentinel machine {} allocating is 1", redisSentinelIp); return TaskFlowStatusEnum.ABORT; } if (!checkMachineStatIsUpdate(machineStats)) { logger.error(marker, "redis sentinel machine stats {} update_time is {}, may be not updated recently", machineInfo.getIp(), machineStats.getUpdateTimeFormat()); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkMachineConnect() { // redis server TaskFlowStatusEnum taskFlowStatusEnum = checkMachineConnect(redisServerMachineList, "sentinelredisServer {} is not connected"); if(taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)){ return TaskFlowStatusEnum.ABORT; } // redis sentinel return checkMachineConnect(redisSentinelMachineList, "redisSentinel {} is not connected"); } /** * 生成实例 * * @return */ public TaskFlowStatusEnum generateInstanceNodes() { redisServerNodes = instancePortService.generateRedisServerNodeList(appId, redisServerMachineList, masterPerMachine, maxMemory); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty, appId is {}, redisServerMachineList is {}, masterPerMachine is {}, maxMemory is {}", appId, redisServerMachineList, masterPerMachine, maxMemory); return TaskFlowStatusEnum.ABORT; } //只取一对 redisServerNodes = redisServerNodes.subList(0, 2); redisSentinelNodes = instancePortService.generateRedisSentinelNodeList(appId, redisSentinelMachineList, sentinelPerMachine); if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.warn(marker, "redisSentinelNodes is empty, appId is {}, redisSentinelMachineList is {}, masterPerMachine is {}", appId, redisSentinelMachineList, sentinelPerMachine); return TaskFlowStatusEnum.ABORT; } //设置环境变量 paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); paramMap.put(TaskConstants.REDIS_SENTINEL_NODES_KEY, redisSentinelNodes); return TaskFlowStatusEnum.SUCCESS; } /** * 保存redis实例信息 */ public TaskFlowStatusEnum saveRedisInstanceNodes() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty"); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { Integer instanceId = saveInstance(appId, redisServerNode.getIp(), redisServerNode.getPort(), maxMemory, InstanceTypeEnum.REDIS_SERVER, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 保存sentinel实例信息 */ public TaskFlowStatusEnum saveSentinelInstanceNodes() { if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.warn(marker, "redisSentinelNodes is empty"); return TaskFlowStatusEnum.ABORT; } // 获取sentinel masterName String masterName = ""; List masterRedisServerNodes = getMasterRedisServerNodes(); if (masterRedisServerNodes.size() == 1) { masterName = masterRedisServerNodes.get(0).getMasterName(); logger.info("sentinel masterName :" + masterName); } else { logger.error(marker, "appId {} masterRedisServerNodes {} is empty", appId, masterRedisServerNodes); return TaskFlowStatusEnum.ABORT; } // 保存sentinel实例信息 if (!StringUtils.isEmpty(masterName)) { for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { Integer instanceId = saveInstance(appId, redisSentinelNode.getIp(), redisSentinelNode.getPort(), 0, InstanceTypeEnum.REDIS_SENTINEL, InstanceStatusEnum.NEW_STATUS, masterName); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } } else { logger.error(marker, "appId {} masterName {} is empty", appId, masterName); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 创建任务 * * @return */ public TaskFlowStatusEnum createRedisServerTask() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "{} redisServerNodes is emtpy", taskId); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addRedisServerInstallTask(appId, host, port, redisServerNode.getMaxmemory(), version, false, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} redis server childTaskId is {}", appId, host, port, childTaskId); return TaskFlowStatusEnum.ABORT; } redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "{}:{} redis server task created successfully", host, port); } catch (Exception e) { logger.error(marker, "{}:{} redis server task created failly", host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待任务完成 * * @return * @TODO 超时时间 */ public TaskFlowStatusEnum waitRedisServerFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { long childTaskId = redisServerNode.getTaskId(); String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{}:{} redis server task fail", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{}:{} redis server task finish successfully", host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 建立主从关系 * * @return */ public TaskFlowStatusEnum configReplication() { for (RedisServerNode redisServerNode : redisServerNodes) { String masterHost = redisServerNode.getMasterHost(); int masterPort = redisServerNode.getMasterPort(); if (masterHost == null || masterPort <= 0) { continue; } String slaveHost = redisServerNode.getIp(); int slavePort = redisServerNode.getPort(); //幂等 boolean isSlaveOf = redisDeployCenter.slaveOf(appId, masterHost, masterPort, slaveHost, slavePort); if (!isSlaveOf) { logger.error(marker, "{}:{} slaveof {}:{} fail", slaveHost, slavePort, masterHost, masterPort); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "{}:{} slaveof {}:{} successfully", slaveHost, slavePort, masterHost, masterPort); } return TaskFlowStatusEnum.SUCCESS; } /** * 创建redis sentinel任务 * * @return */ public TaskFlowStatusEnum createRedisSentinelTask() { List masterRedisServerNodes = getMasterRedisServerNodes(); // 计算quorum int quorum = getQuorum(redisSentinelNodes.size()); for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { String sentinelHost = redisSentinelNode.getIp(); int sentinelPort = redisSentinelNode.getPort(); try { long childTaskId = taskService.addRedisSentinelInstallTask(appId, sentinelHost, sentinelPort, masterRedisServerNodes, quorum, version, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} sentinel childTaskId is {}", appId, sentinelHost, sentinelPort, childTaskId); return TaskFlowStatusEnum.ABORT; } redisSentinelNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SENTINEL_NODES_KEY, redisSentinelNodes); logger.info(marker, "{}:{} redis sentinel task created successfully, childTaskId is {}", sentinelHost, sentinelPort, childTaskId); } catch (Exception e) { logger.error(marker, "{}:{} redis sentinel task created failly", sentinelHost, sentinelPort); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待所有redis sentinel启动 * * @return */ public TaskFlowStatusEnum waitRedisSentinelFinish() { for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { long childTaskId = redisSentinelNode.getTaskId(); String host = redisSentinelNode.getIp(); int port = redisSentinelNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SENTINEL_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{} {}:{} redis sentinel task fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} redis sentinel task success", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 获取所有master节点 * * @return */ private List getMasterRedisServerNodes() { AppDesc appDesc = appDao.getAppDescById(appId); String appFullName = appDesc.getName(); if (StringUtils.isBlank(appFullName)) { logger.error(marker, "appId {} fullName is empty", appId); return Collections.emptyList(); } List masterRedisServerNodes = new ArrayList(); for (RedisServerNode redisServerNode : redisServerNodes) { if (!redisServerNode.isMaster()) { continue; } String masterName = generateMasterName(appFullName, redisServerNode.getPort()); redisServerNode.setMasterName(masterName); masterRedisServerNodes.add(redisServerNode); } return masterRedisServerNodes; } /** * 更新实例状态 * * @return */ public TaskFlowStatusEnum updateInstanceStatus() { redisServerNodes.forEach(redisServerNode -> instanceDao.updateStatus(appId, redisServerNode.getIp(), redisServerNode.getPort(), InstanceStatusEnum.GOOD_STATUS.getStatus()) ); return TaskFlowStatusEnum.SUCCESS; } /** * 更新实例状态 * * @return */ public TaskFlowStatusEnum updateSentinelInstanceStatus() { redisSentinelNodes.forEach(redisSentinelNode -> instanceDao.updateStatus(appId, redisSentinelNode.getIp(), redisSentinelNode.getPort(), InstanceStatusEnum.GOOD_STATUS.getStatus()) ); return TaskFlowStatusEnum.SUCCESS; } /** * 部署实例收集 * * @return */ public TaskFlowStatusEnum deployCollection() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); boolean isDeploy = redisCenter.sendDeployRedisRelateCollectionMsg(appId, host, port); if (!isDeploy) { logger.error(marker, "{} {}:{} deploy fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} deploy sucessfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum setPasswd() { try { if (appId > 0) { // 设置密码 appService.updateAppPwd(appId, String.valueOf(appId)); // 密码校验逻辑 boolean checkFlag = redisDeployCenter.checkAuths(appId); logger.info(marker, "check app sentinel passwd:{}", checkFlag); if (!checkFlag) { logger.error(marker, "check app sentinel passwd error, appId:{}!", appId); return TaskFlowStatusEnum.ABORT; } } } catch (Exception e) { logger.error(e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 清理sentinel实例状态 * * @return */ public TaskFlowStatusEnum sentinelReset() { try { redisDeployCenter.sentinelReset(appId); } catch (Exception e) { logger.error(e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 通过初审:资源分配 * * @return */ public TaskFlowStatusEnum updateAudit() { try { if (auditId > 0) { appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } public TaskFlowStatusEnum updateMachineAllocateFalse() { return updateMachineAllocateStatus(0); } public TaskFlowStatusEnum updateMachineAllocateTrue() { return updateMachineAllocateStatus(1); } public TaskFlowStatusEnum updateMachineAllocateStatus(int status) { try { Set allMachineSet = new HashSet(); allMachineSet.addAll(redisServerMachineList); for (String ip : allMachineSet) { machineDao.updateMachineAllocate(ip, status); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/RedisStandaloneAppDeployTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.EnvUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.*; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** *

* Description:RedisStandalone部署任务流 *

* * @author chenshi * @version 1.0 * @date 2019/1/9 */ @Component("RedisStandaloneAppDeployTask") @Scope(SCOPE_PROTOTYPE) public class RedisStandaloneAppDeployTask extends BaseTask { /** * 应用id */ private long appId; /** * 审核id */ private long auditId; /** * redis server机器列表 */ private List redisServerMachineList; /** * 每台机器redis server实例个数 */ private int masterPerMachine; /** * 每个实例的最大内存(MB) */ private int maxMemory; private List redisServerNodes; /** * Redis版本 */ private String version; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查资源 taskStepList.add("checkResourceAllow"); //3. 检查机器可用性 taskStepList.add("checkMachineConnect"); //4. 更新机器分配状态 taskStepList.add("updateMachineAllocateTrue"); //5. 获取实例列表 taskStepList.add("generateInstanceNodes"); //6. 保存实例列表 taskStepList.add("saveInstanceNodes"); //7. 创建redis server job taskStepList.add("createRedisServerTask"); //8. 等待redis server job完成 taskStepList.add("waitRedisServerFinish"); /* 9. 设置密码已放到实例配置文件中,启动后自动带有密码, 此步骤是设置app_desc表的密码字段,避免后续访问操作失败 */ taskStepList.add("setPasswd"); //10. 更改实例状态 taskStepList.add("updateInstanceStatus"); //11. 开始收集部署 taskStepList.add("deployCollection"); //12. 审核 taskStepList.add("updateAudit"); //13. 更新机器分配状态 taskStepList.add("updateMachineAllocateFalse"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } //审核id auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); // if (auditId <= 0) { // logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); // return TaskFlowStatusEnum.ABORT; // } //maxMemory maxMemory = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY); if (maxMemory <= 0 || maxMemory > TaskConstants.MAX_MEMORY_LIMIT) { logger.error(marker, "task {} maxMemory {} is wrong", taskId, maxMemory); return TaskFlowStatusEnum.ABORT; } //masterPerMachine masterPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.MASTER_PER_MACHINE_KEY); if (masterPerMachine <= 0 || masterPerMachine > TaskConstants.MAX_MASTER_PER_MACHINE) { logger.error(marker, "task {} masterPerMachine {} is wrong", taskId, masterPerMachine); return TaskFlowStatusEnum.ABORT; } //redis server machine String redisServerMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY); redisServerMachineList = JSONArray.parseArray(redisServerMachineStr, String.class); if (CollectionUtils.isEmpty(redisServerMachineList)) { logger.error(marker, "task {} redisServerMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "standalone task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } // redis版本 version = MapUtils.getString(paramMap, TaskConstants.VERSION_KEY); return TaskFlowStatusEnum.SUCCESS; } /** * 检查资源是否充足 * * @return */ public TaskFlowStatusEnum checkResourceAllow() { if (EnvUtil.isLocal(environment)) { return TaskFlowStatusEnum.SUCCESS; } // 容量和代理 long memoryNeed = Long.valueOf(masterPerMachine) * maxMemory; return checkResourceAllow(redisServerMachineList, memoryNeed); } public TaskFlowStatusEnum checkMachineConnect() { // redis server return checkMachineConnect(redisServerMachineList, "standalone: redisServer {} is not connected"); } /** * 生成实例 * * @return */ public TaskFlowStatusEnum generateInstanceNodes() { redisServerNodes = instancePortService.generateRedisServerNodeList(appId, redisServerMachineList, masterPerMachine, maxMemory); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty, appId is {}, redisServerMachineList is {}, masterPerMachine is {}, maxMemory is {}", appId, redisServerMachineList, masterPerMachine, maxMemory); return TaskFlowStatusEnum.ABORT; } // 设置master节点 for (RedisServerNode redisServerNode : redisServerNodes) { if (redisServerNode.isMaster()) { redisServerNodes.remove(redisServerNode); } } //设置环境变量 paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); return TaskFlowStatusEnum.SUCCESS; } /** * 保存实例 * * @return */ public TaskFlowStatusEnum saveInstanceNodes() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty"); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { Integer instanceId = saveInstance(appId, redisServerNode.getIp(), redisServerNode.getPort(), maxMemory, InstanceTypeEnum.REDIS_SERVER, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 创建任务 * * @return */ public TaskFlowStatusEnum createRedisServerTask() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "{} redisServerNodes is emtpy", taskId); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addRedisServerInstallTask(appId, host, port, redisServerNode.getMaxmemory(), version, false, taskId); if (childTaskId <= 0) { logger.error(marker, "standalone : {} {} {} redis server childTaskId is {}", appId, host, port, childTaskId); return TaskFlowStatusEnum.ABORT; } redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "{}:{} redis server task created successfully", host, port); } catch (Exception e) { logger.error(marker, "{}:{} redis server task created failly", host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待任务完成 */ public TaskFlowStatusEnum waitRedisServerFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { long childTaskId = redisServerNode.getTaskId(); String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "standalone : {}:{} redis server task fail", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "standalone : {}:{} redis server task finish successfully", host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 更新实例状态 * * @return */ public TaskFlowStatusEnum updateInstanceStatus() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); } return TaskFlowStatusEnum.SUCCESS; } /** * 部署实例收集 * * @return */ public TaskFlowStatusEnum deployCollection() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); boolean isDeploy = redisCenter.sendDeployRedisRelateCollectionMsg(appId, host, port); if (!isDeploy) { logger.error(marker, "{} {}:{} deploy fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} deploy sucessfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 设置密码 * * @return */ public TaskFlowStatusEnum setPasswd() { try { if (appId > 0) { // 设置密码 appService.updateAppPwd(appId, String.valueOf(appId)); // 密码校验逻辑 boolean checkFlag = redisDeployCenter.checkAuths(appId); logger.info(marker, "check app standalone passwd:{}", checkFlag); if (!checkFlag) { logger.error(marker, "check app standalone passwd error, appId:{}!", appId); return TaskFlowStatusEnum.ABORT; } } } catch (Exception e) { logger.error(e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 通过初审:资源分配 * * @return */ public TaskFlowStatusEnum updateAudit() { try { if (auditId > 0) { appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } public TaskFlowStatusEnum updateMachineAllocateFalse() { return updateMachineAllocateStatus(0); } public TaskFlowStatusEnum updateMachineAllocateTrue() { return updateMachineAllocateStatus(1); } public TaskFlowStatusEnum updateMachineAllocateStatus(int status) { try { Set allMachineSet = new HashSet(); allMachineSet.addAll(redisServerMachineList); for (String ip : allMachineSet) { machineDao.updateMachineAllocate(ip, status); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/TwemproxyAppDeployTask.java ================================================ package com.sohu.cache.task.tasks; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.entity.MachineStats; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceStatusEnum; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.NutCrackerNode; import com.sohu.cache.task.entity.RedisSentinelNode; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.EnvUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.*; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * twemproxy安装 * * @author fulei * @date 2018年7月3日 * @time 下午3:42:53 */ @Component("TwemproxyAppDeployTask") @Scope(SCOPE_PROTOTYPE) public class TwemproxyAppDeployTask extends BaseTask { /** * 应用id */ private long appId; /** * 审核id */ private long auditId; /** * redis server机器列表 */ private List redisServerMachineList; /** * nut cracker机器列表 */ private List nutCrackerMachineList; /** * redis sentinel机器列表 */ private List redisSentinelMachineList; /** * 每台机器redis server实例个数 */ private int masterPerMachine; /** * 每台机器nutcracker实例个数 */ private int nutcrackerPerMachine; /** * 每台机器sentinel实例个数 */ private int sentinelPerMachine; /** * 每个实例的最大内存(MB) */ private int maxMemory; private List redisServerNodes; private List redisSentinelNodes; private List nutCrackerNodes; private String version; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查资源,例如内存和代理个数 taskStepList.add("checkResourceAllow"); //3. 检查机器可用性 taskStepList.add("checkMachineConnect"); //4. 更新机器分配状态 taskStepList.add("updateMachineAllocateTrue"); //5. 获取实例列表 taskStepList.add("generateInstanceNodes"); //6. 保存实例列表 taskStepList.add("saveInstanceNodes"); //7. 创建redis server job taskStepList.add("createRedisServerTask"); //8. 等待redis server job完成 taskStepList.add("waitRedisServerFinish"); //9. 主从复制 taskStepList.add("configReplication"); //10. 创建redis sentinel job taskStepList.add("createRedisSentinelTask"); //11. 等待redis sentinel job完成 taskStepList.add("waitRedisSentinelFinish"); //12. 创建nutcracker job taskStepList.add("createNutCrackerTask"); //13. 等待nutcracker job完成 taskStepList.add("waitNutCrackerFinish"); //14. 更改实例状态 taskStepList.add("updateInstanceStatus"); //15. 开始收集部署 taskStepList.add("deployCollection"); //16. 检查proxy是否一致 taskStepList.add("checkNutCrackerConfIsSame"); //17.检查nut cracker 哈希一致性(进程内) taskStepList.add("checkNutCrackerHashIsSame"); //18. 审核 taskStepList.add("updateAudit"); //19. 更新机器分配状态 taskStepList.add("updateMachineAllocateFalse"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } //审核id auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } //maxMemory maxMemory = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY); if (maxMemory <= 0 || maxMemory > TaskConstants.MAX_MEMORY_LIMIT) { logger.error(marker, "task {} maxMemory {} is wrong", taskId, maxMemory); return TaskFlowStatusEnum.ABORT; } //masterPerMachine masterPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.MASTER_PER_MACHINE_KEY); if (masterPerMachine <= 0 || masterPerMachine > TaskConstants.MAX_MASTER_PER_MACHINE) { logger.error(marker, "task {} masterPerMachine {} is wrong", taskId, masterPerMachine); return TaskFlowStatusEnum.ABORT; } //sentinelPerMachine sentinelPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.SENTINEL_PER_MACHINE_KEY); if (sentinelPerMachine <= 0) { logger.error(marker, "task {} sentinelPerMachine {} is wrong", taskId, sentinelPerMachine); return TaskFlowStatusEnum.ABORT; } //nutcrackerPerMachine nutcrackerPerMachine = MapUtils.getIntValue(paramMap, TaskConstants.NUT_CRACKER_PER_MACHINE_KEY); if (nutcrackerPerMachine <= 0 || nutcrackerPerMachine > TaskConstants.MAX_NUT_CRACK_PER_MACHINE) { logger.error(marker, "task {} nutcrackerPerMachine {} is wrong", taskId, nutcrackerPerMachine); return TaskFlowStatusEnum.ABORT; } //redis server machine String redisServerMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_MACHINE_LIST_KEY); redisServerMachineList = JSONArray.parseArray(redisServerMachineStr, String.class); if (CollectionUtils.isEmpty(redisServerMachineList)) { logger.error(marker, "task {} redisServerMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } //redis sentinel machine String redisSentinelMachineStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SENTINEL_MACHINE_LIST_KEY); redisSentinelMachineList = JSONArray.parseArray(redisSentinelMachineStr, String.class); if (CollectionUtils.isEmpty(redisSentinelMachineList)) { logger.error(marker, "task {} redisSentinelMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //redis sentinel list String redisSentinelNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SENTINEL_NODES_KEY); if (StringUtils.isNotBlank(redisSentinelNodesStr)) { redisSentinelNodes = JSONArray.parseArray(redisSentinelNodesStr, RedisSentinelNode.class); if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.error(marker, "task {} redisSentinelNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } //nut cracker machine String nutCrackerMachineStr = MapUtils.getString(paramMap, TaskConstants.NUT_CRACKER_MACHINE_LIST_KEY); nutCrackerMachineList = JSONArray.parseArray(nutCrackerMachineStr, String.class); if (CollectionUtils.isEmpty(nutCrackerMachineList)) { logger.error(marker, "task {} nutCrackerMachineList is empty", taskId); return TaskFlowStatusEnum.ABORT; } //nut cracker list String nutCrackerNodesStr = MapUtils.getString(paramMap, TaskConstants.NUT_CRACKER_NODES_KEY); if (StringUtils.isNotBlank(nutCrackerNodesStr)) { nutCrackerNodes = JSONArray.parseArray(nutCrackerNodesStr, NutCrackerNode.class); if (CollectionUtils.isEmpty(nutCrackerNodes)) { logger.error(marker, "task {} nutCrackerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } } version = MapUtils.getString(paramMap, TaskConstants.VERSION_KEY); return TaskFlowStatusEnum.SUCCESS; } /** * 检查资源是否充足 * * @return */ public TaskFlowStatusEnum checkResourceAllow() { if (EnvUtil.isLocal(environment)) { return TaskFlowStatusEnum.SUCCESS; } // 容量和代理 for (String redisServerIp : redisServerMachineList) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(redisServerIp); if (machineStats == null) { logger.error(marker, "{} redis server machineStats is null", redisServerIp); return TaskFlowStatusEnum.ABORT; } MachineInfo machineInfo = machineDao.getMachineInfoByIp(redisServerIp); if (machineInfo.getIsAllocating() == 1) { logger.error(marker, "redis server machine info {} {} allocating is 1", machineInfo.getIp(), redisServerIp); return TaskFlowStatusEnum.ABORT; } if (!checkMachineStatIsUpdate(machineStats)) { logger.error(marker, "redis server machine stats {} {} update_time is {}, may be not updated recently", machineInfo.getIp(), machineInfo.getIp(), machineStats.getUpdateTimeFormat()); return TaskFlowStatusEnum.ABORT; } //兆 long memoryFree = NumberUtils.toLong(machineStats.getMemoryFree()) / 1024 / 1024; long memoryNeed = Long.valueOf(masterPerMachine) * maxMemory; if (memoryNeed > memoryFree * 0.7) { logger.error(marker, "{} need {} MB, but memoryFree is {} MB", redisServerIp, memoryNeed, memoryFree); return TaskFlowStatusEnum.ABORT; } } // sentinel for (String redisSentinelIp : redisSentinelMachineList) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(redisSentinelIp); if (machineStats == null) { logger.error(marker, "{} redis sentinel machineStats is null", redisSentinelIp); return TaskFlowStatusEnum.ABORT; } MachineInfo machineInfo = machineDao.getMachineInfoByIp(redisSentinelIp); if (machineInfo == null || machineInfo.getIsAllocating() == 1) { logger.error(marker, "redis sentinel machine {} allocating is 1", redisSentinelIp); return TaskFlowStatusEnum.ABORT; } if (!checkMachineStatIsUpdate(machineStats)) { logger.error(marker, "redis sentinel machine stats {} {} update_time is {}, may be not updated recently", machineInfo.getIp(), machineInfo.getIp(), machineStats.getUpdateTimeFormat()); return TaskFlowStatusEnum.ABORT; } } // 代理 for (String nutCrackerIp : nutCrackerMachineList) { MachineStats machineStats = machineStatsDao.getMachineStatsByIp(nutCrackerIp); if (machineStats == null) { logger.error(marker, "{} nutcracker machineStats is null", nutCrackerIp); return TaskFlowStatusEnum.ABORT; } MachineInfo machineInfo = machineDao.getMachineInfoByIp(nutCrackerIp); if (machineInfo == null || machineInfo.getIsAllocating() == 1) { logger.error(marker, "nut cracker machine info {} allocating is 1", nutCrackerIp); return TaskFlowStatusEnum.ABORT; } if (!checkMachineStatIsUpdate(machineStats)) { logger.error(marker, "nut cracker machine stats {} {} update_time is {}, may be not updated recently", machineInfo.getIp(), machineInfo.getIp(), machineStats.getUpdateTimeFormat()); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkMachineConnect() { // redis server for (String redisServerIp : redisServerMachineList) { boolean isConnected = checkMachineIsConnect(redisServerIp); if (!isConnected) { logger.error(marker, "redisServer {} is not connected", redisServerIp); return TaskFlowStatusEnum.ABORT; } } // redis sentinel for (String redisSentinelIp : redisSentinelMachineList) { boolean isConnected = checkMachineIsConnect(redisSentinelIp); if (!isConnected) { logger.error(marker, "redisSentinel {} is not connected", redisSentinelIp); return TaskFlowStatusEnum.ABORT; } } // 代理 for (String nutCrackerIp : nutCrackerMachineList) { boolean isConnected = checkMachineIsConnect(nutCrackerIp); if (!isConnected) { logger.error(marker, "nutCrackerIp {} is not connected", nutCrackerIp); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 生成实例 * * @return */ public TaskFlowStatusEnum generateInstanceNodes() { redisServerNodes = instancePortService.generateRedisServerNodeList(appId, redisServerMachineList, masterPerMachine, maxMemory); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty, appId is {}, redisServerMachineList is {}, masterPerMachine is {}, maxMemory is {}", appId, redisServerMachineList, masterPerMachine, maxMemory); return TaskFlowStatusEnum.ABORT; } redisSentinelNodes = instancePortService.generateRedisSentinelNodeList(appId, redisSentinelMachineList, sentinelPerMachine); if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.warn(marker, "redisSentinelNodes is empty, appId is {}, redisSentinelMachineList is {}, masterPerMachine is {}", appId, redisSentinelMachineList, sentinelPerMachine); return TaskFlowStatusEnum.ABORT; } nutCrackerNodes = instancePortService.generateNutCrackerNodeList(appId, nutCrackerMachineList, nutcrackerPerMachine); if (CollectionUtils.isEmpty(nutCrackerNodes)) { logger.warn(marker, "nutCrackerNodes is empty, appId is {}, nutCrackerMachineList is {}, nutcrackerPerMachine is {}", appId, nutCrackerMachineList, nutcrackerPerMachine); return TaskFlowStatusEnum.ABORT; } //设置环境变量 paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); paramMap.put(TaskConstants.REDIS_SENTINEL_NODES_KEY, redisSentinelNodes); paramMap.put(TaskConstants.NUT_CRACKER_NODES_KEY, nutCrackerNodes); return TaskFlowStatusEnum.SUCCESS; } /** * 保存实例 * * @return */ public TaskFlowStatusEnum saveInstanceNodes() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "redisServerNodes is empty"); return TaskFlowStatusEnum.ABORT; } if (CollectionUtils.isEmpty(redisSentinelNodes)) { logger.warn(marker, "redisSentinelNodes is empty"); return TaskFlowStatusEnum.ABORT; } if (CollectionUtils.isEmpty(nutCrackerNodes)) { logger.warn(marker, "nutCrackerNodes is empty"); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { Integer instanceId = saveInstance(appId, redisServerNode.getIp(), redisServerNode.getPort(), maxMemory, InstanceTypeEnum.REDIS_SERVER, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { Integer instanceId = saveInstance(appId, redisSentinelNode.getIp(), redisSentinelNode.getPort(), 0, InstanceTypeEnum.REDIS_SENTINEL, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } for (NutCrackerNode nutCrackerNode : nutCrackerNodes) { Integer instanceId = saveInstance(appId, nutCrackerNode.getIp(), nutCrackerNode.getPort(), 0, InstanceTypeEnum.NUTCRACKER, InstanceStatusEnum.NEW_STATUS, ""); if (instanceId == null || instanceId.equals(0)) { return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 创建任务 * * @return */ public TaskFlowStatusEnum createRedisServerTask() { if (CollectionUtils.isEmpty(redisServerNodes)) { logger.warn(marker, "{} redisServerNodes is emtpy", taskId); return TaskFlowStatusEnum.ABORT; } for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addRedisServerInstallTask(appId, host, port, redisServerNode.getMaxmemory(), version, false, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} redis server childTaskId is {}", appId, host, port, childTaskId); return TaskFlowStatusEnum.ABORT; } redisServerNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); logger.info(marker, "{}:{} redis server task created successfully", host, port); } catch (Exception e) { logger.error(marker, "{}:{} redis server task created failly", host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待任务完成 * * @return * @TODO 超时时间 */ public TaskFlowStatusEnum waitRedisServerFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { long childTaskId = redisServerNode.getTaskId(); String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{}:{} redis server task fail", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{}:{} redis server task finish successfully", host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 建立主从关系 * * @return */ public TaskFlowStatusEnum configReplication() { for (RedisServerNode redisServerNode : redisServerNodes) { String masterHost = redisServerNode.getMasterHost(); int masterPort = redisServerNode.getMasterPort(); if (masterHost == null || masterPort <= 0) { continue; } String slaveHost = redisServerNode.getIp(); int slavePort = redisServerNode.getPort(); //幂等 boolean isSlaveOf = redisDeployCenter.slaveOf(appId, masterHost, masterPort, slaveHost, slavePort); if (!isSlaveOf) { logger.error(marker, "{}:{} slaveof {}:{} fail", slaveHost, slavePort, masterHost, masterPort); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "{}:{} slaveof {}:{} successfully", slaveHost, slavePort, masterHost, masterPort); } return TaskFlowStatusEnum.SUCCESS; } /** * 创建redis sentinel任务 * * @return */ public TaskFlowStatusEnum createRedisSentinelTask() { List masterRedisServerNodes = getMasterRedisServerNodes(); // 计算quorum int quorum = getQuorum(redisSentinelNodes.size()); for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { String sentinelHost = redisSentinelNode.getIp(); int sentinelPort = redisSentinelNode.getPort(); try { long childTaskId = taskService.addRedisSentinelInstallTask(appId, sentinelHost, sentinelPort, masterRedisServerNodes, quorum, version, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} sentinel childTaskId is {}", appId, sentinelHost, sentinelPort, childTaskId); return TaskFlowStatusEnum.ABORT; } redisSentinelNode.setTaskId(childTaskId); paramMap.put(TaskConstants.REDIS_SENTINEL_NODES_KEY, redisSentinelNodes); logger.info(marker, "{}:{} redis sentinel task created successfully, childTaskId is {}", sentinelHost, sentinelPort, childTaskId); } catch (Exception e) { logger.error(marker, "{}:{} redis sentinel task created failly", sentinelHost, sentinelPort); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待所有redis sentinel启动 * * @return */ public TaskFlowStatusEnum waitRedisSentinelFinish() { for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { long childTaskId = redisSentinelNode.getTaskId(); String host = redisSentinelNode.getIp(); int port = redisSentinelNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SENTINEL_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{} {}:{} redis sentinel task fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} redis sentinel task success", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 获取所有master节点 * * @return */ private List getMasterRedisServerNodes() { AppDesc appDesc = appDao.getAppDescById(appId); String appFullName = appDesc.getName(); if (StringUtils.isBlank(appFullName)) { logger.error(marker, "appId {} fullName is empty", appId); return Collections.emptyList(); } List masterRedisServerNodes = new ArrayList(); for (RedisServerNode redisServerNode : redisServerNodes) { if (!redisServerNode.isMaster()) { continue; } String masterName = generateMasterName(appDesc.getName(), redisServerNode.getPort()); redisServerNode.setMasterName(masterName); masterRedisServerNodes.add(redisServerNode); } return masterRedisServerNodes; } /** * 创建nutcracker任务 * * @return */ public TaskFlowStatusEnum createNutCrackerTask() { List masterRedisServerNodes = getMasterRedisServerNodes(); if (CollectionUtils.isEmpty(masterRedisServerNodes)) { return TaskFlowStatusEnum.ABORT; } //防止集中ssh一个host Collections.shuffle(nutCrackerNodes); for (NutCrackerNode nutCrackerNode : nutCrackerNodes) { //控制并发 String nutCrackerHost = nutCrackerNode.getIp(); int nutCrackerPort = nutCrackerNode.getPort(); try { long childTaskId = taskService.addNutCrackerInstallTask(appId, nutCrackerHost, nutCrackerPort, masterRedisServerNodes, taskId); if (childTaskId <= 0) { logger.error(marker, "{} {} {} nut cracker childTaskId is {}", appId, nutCrackerHost, nutCrackerPort, childTaskId); return TaskFlowStatusEnum.ABORT; } nutCrackerNode.setTaskId(childTaskId); //回写配置 paramMap.put(TaskConstants.NUT_CRACKER_NODES_KEY, nutCrackerNodes); logger.info(marker, "{}:{} nut cracker task created successfully", nutCrackerHost, nutCrackerPort); } catch (Exception e) { logger.error(marker, "{}:{} nut cracker task created failly", nutCrackerHost, nutCrackerPort); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 等待所有nut cracker启动 * * @return */ public TaskFlowStatusEnum waitNutCrackerFinish() { for (NutCrackerNode nutCrackerNode : nutCrackerNodes) { long childTaskId = nutCrackerNode.getTaskId(); String host = nutCrackerNode.getIp(); int port = nutCrackerNode.getPort(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.NUT_CRACKER_INSTALL_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "{}:{} nut cracker task fail", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{}:{} nut cracker task success", host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 更新实例状态 * * @return */ public TaskFlowStatusEnum updateInstanceStatus() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); } for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { String host = redisSentinelNode.getIp(); int port = redisSentinelNode.getPort(); instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); } for (NutCrackerNode nutCrackerNode : nutCrackerNodes) { String host = nutCrackerNode.getIp(); int port = nutCrackerNode.getPort(); instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); } return TaskFlowStatusEnum.SUCCESS; } /** * 部署实例收集 * * @return */ public TaskFlowStatusEnum deployCollection() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); boolean isDeploy = redisCenter.sendDeployRedisRelateCollectionMsg(appId, host, port); if (!isDeploy) { logger.error(marker, "{} {}:{} deploy fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "{} {}:{} deploy sucessfully", appId, host, port); } } // for (RedisSentinelNode redisSentinelNode : redisSentinelNodes) { // String host = redisSentinelNode.getIp(); // int port = redisSentinelNode.getPort(); // instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); // } // for (NutCrackerNode nutCrackerNode : nutCrackerNodes) { // String host = nutCrackerNode.getIp(); // int port = nutCrackerNode.getPort(); // instanceDao.updateStatus(appId, host, port, InstanceStatusEnum.GOOD_STATUS.getStatus()); // } return TaskFlowStatusEnum.SUCCESS; } /** * 通过初审:资源分配 * * @return */ public TaskFlowStatusEnum updateAudit() { try { appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value()); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } /** * 检查proxy配置的一致性 */ public TaskFlowStatusEnum checkNutCrackerConfIsSame() { boolean isSame = redisCenter.checkNutCrackerConfIsSame(appId); if (!isSame) { logger.error(marker, "appId {} nutcracker config is not same, please check!!!", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 6.检查proxy hash的一致性 */ public TaskFlowStatusEnum checkNutCrackerHashIsSame() { List instanceInfoList = redisCenter.checkNutCrackerHashIsSame(appId, true); if (CollectionUtils.isNotEmpty(instanceInfoList)) { for (InstanceInfo instanceInfo : instanceInfoList) { logger.error(marker, "appId {} {}:{} hash is wrong", appId, instanceInfo.getIp(), instanceInfo.getPort()); } return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} proxy hash is same", appId); return TaskFlowStatusEnum.SUCCESS; } } public TaskFlowStatusEnum updateMachineAllocateFalse() { return updateMachineAllocateStatus(0); } public TaskFlowStatusEnum updateMachineAllocateTrue() { return updateMachineAllocateStatus(1); } public TaskFlowStatusEnum updateMachineAllocateStatus(int status) { try { Set allMachineSet = new HashSet(); allMachineSet.addAll(redisServerMachineList); allMachineSet.addAll(nutCrackerMachineList); for (String ip : allMachineSet) { machineDao.updateMachineAllocate(ip, status); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/analysis/RedisServerBigKeyAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.analysis; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.RedisDataStructureTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.InstanceBigKey; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.Pair; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * bigkey分析 * * @author fulei */ @Component("RedisServerBigKeyAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerBigKeyAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; private final static int SCAN_COUNT = 100; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // big key分析 taskStepList.add("bigKeyAnalysis"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3. bigkey分析 * * @return */ public TaskFlowStatusEnum bigKeyAnalysis() { long startTime = System.currentTimeMillis(); InstanceStats instanceStats = instanceStatsDao.getInstanceStatsByHost(host, port); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); jedis.readonly(); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); long count = 0; int totalSplit = 10; int curSplit = 1; while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); // 使用pipeline获取type Pipeline pipeline = jedis.pipelined(); keyList.stream().forEach(key -> pipeline.type(key)); List typeObjectList; try { typeObjectList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue; // ignore } List typeList = typeObjectList; // key type Map Map keyTypeMap = IntStream.range(0, keyList.size()) .filter(i -> !"none".equalsIgnoreCase(String.valueOf(typeList.get(i))) && (typeList.get(i) instanceof String)) .mapToObj(i -> new Pair<>(keyList.get(i), String.valueOf(typeList.get(i)))) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); Pipeline pipeline2 = jedis.pipelined(); // 计算长度pipeline keyTypeMap.entrySet().stream().forEach(entry -> { byte[] key = entry.getKey(); String type = entry.getValue(); if (RedisDataStructureTypeEnum.string.getValue().equals(type)) { pipeline2.strlen(key); } else if (RedisDataStructureTypeEnum.hash.getValue().equals(type)) { pipeline2.hlen(key); } else if (RedisDataStructureTypeEnum.list.getValue().equals(type)) { pipeline2.llen(key); } else if (RedisDataStructureTypeEnum.set.getValue().equals(type)) { pipeline2.scard(key); } else if (RedisDataStructureTypeEnum.zset.getValue().equals(type)) { pipeline2.zcard(key); } }); List lengthList; try { lengthList = pipeline2.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue;// ignore } List instanceBigKeyList = IntStream.range(0, lengthList.size()) .filter(i -> (typeList.get(i) instanceof String) && (lengthList.get(i) instanceof Long)) .mapToObj(i -> { long length = (long) lengthList.get(i); String type = String.valueOf(typeList.get(i)); byte[] key = keyList.get(i); boolean isBigKey = checkIsBigKey(type, length); if (!isBigKey) { return null; } InstanceBigKey instanceBigKey = new InstanceBigKey(); instanceBigKey.setAppId(appId); instanceBigKey.setInstanceId(instanceStats.getInstId()); instanceBigKey.setAuditId(auditId); instanceBigKey.setIp(host); instanceBigKey.setPort(port); instanceBigKey.setRole(instanceStats.getRole()); instanceBigKey.setBigKey(new String(key)); instanceBigKey.setLength(length); instanceBigKey.setType(type); instanceBigKey.setCreateTime(new Date()); return instanceBigKey; }) .filter(instanceBigKey -> instanceBigKey != null) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(instanceBigKeyList)) { instanceBigKeyDao.batchSave(instanceBigKeyList); } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(2); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } logger.info(marker, "{} {}:{} analysis bigkey key successfully, cost time is {} ms, total key is {}", appId, host, port, (System.currentTimeMillis() - startTime), count); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} adminauth error", host, port); logger.error(marker, "bigkey custinsId {} {}:{} bigkey connect error:" + e.getMessage(), appId, host, port, e); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } /** * 按照类型判断是否为bigkey * * @param type * @param length * @return */ private boolean checkIsBigKey(String type, long length) { if (RedisDataStructureTypeEnum.string.getValue().equals(type)) { return length > ConstUtils.STRING_MAX_LENGTH; } else if (RedisDataStructureTypeEnum.hash.getValue().equals(type)) { return length > ConstUtils.HASH_MAX_LENGTH; } else if (RedisDataStructureTypeEnum.list.getValue().equals(type)) { return length > ConstUtils.LIST_MAX_LENGTH; } else if (RedisDataStructureTypeEnum.set.getValue().equals(type)) { return length > ConstUtils.SET_MAX_LENGTH; } else if (RedisDataStructureTypeEnum.zset.getValue().equals(type)) { return length > ConstUtils.ZSET_MAX_LENGTH; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/analysis/RedisServerIdleKeyAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.analysis; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.IdleTimeDistriEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * redis server空闲key分析 * * @author fulei */ @Component("RedisServerIdleKeyAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerIdleKeyAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; /** * 扫描master */ private final static int SCAN_COUNT = 100; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); //检查实例是否运行 taskStepList.add("checkIsRun"); //idle key分析 taskStepList.add("idleKeyAnalysis"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum idleKeyAnalysis() { long startTime = System.currentTimeMillis(); //本地结果集 AtomicLongMap idleTimeCountMap = AtomicLongMap.create(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); jedis.readonly(); //如果 long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); long count = 0; int totalSplit = 10; int curSplit = 1; while (true) { int retryTimes = 10; try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); //pipeline object idle Pipeline pipeline = jedis.pipelined(); keyList.stream().forEach(key -> pipeline.objectIdletime(key)); List idleTimeList; try { idleTimeList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue;// ignore } idleTimeList.stream() .filter(obj -> obj != null && (obj instanceof Long)) .forEach(obj -> { long idleSeconds = (long) obj; long idleHours = idleSeconds / 3600; IdleTimeDistriEnum idleTimeDistriEnum = IdleTimeDistriEnum .getRightIdleDistri(idleHours); if (idleTimeDistriEnum == null) { logger.error(marker, "idleHours {} {} IdleTimeDistriEnum is null", idleHours, idleSeconds); } else { idleTimeCountMap.incrementAndGet(idleTimeDistriEnum); } }); count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(2); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } logger.info(marker, "{} {}:{} analysis idle key successfully, cost time is {} ms, total key is {}", appId, host, port, (System.currentTimeMillis() - startTime), count); String idleKeyResultKey = ConstUtils.getRedisServerIdleKey(appId, auditId); idleTimeCountMap.asMap().entrySet().stream().forEach(entry -> { String member = entry.getKey().getValue(); assistRedisService.zincrby(idleKeyResultKey, entry.getValue(), member); logger.info(marker, "{} {} {}:{} idle distri {} {}", idleKeyResultKey, appId, host, port, entry.getKey(), entry.getValue()); }); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { throw e; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/analysis/RedisServerKeyTtlAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.analysis; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.constant.TtlTimeDistriEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * key过期时间分析 * * @author fulei */ @Component("RedisServerKeyTtlAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerKeyTtlAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; /** * 扫描slave */ private final static int SCAN_COUNT = 100; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // key类型分析 taskStepList.add("keyTtlAnalysis"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum keyTtlAnalysis() { long startTime = System.currentTimeMillis(); //本地结果集 AtomicLongMap ttlTimeCountMap = AtomicLongMap.create(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); jedis.readonly(); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); long count = 0; int totalSplit = 10; int curSplit = 1; while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); Pipeline pipeline = jedis.pipelined(); keyList.stream().forEach(key -> pipeline.ttl(key)); List ttlObjectList; try { ttlObjectList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue;// ignore } ttlObjectList.stream() .filter(obj -> obj != null && (obj instanceof Long)) .forEach(obj -> { long ttlSeconds = (long) obj; TtlTimeDistriEnum ttlTimeDistriEnum; if (ttlSeconds == -1) { ttlTimeDistriEnum = TtlTimeDistriEnum.BETWEEN_PERSIST_HOURS; } else { long ttlHours = ttlSeconds / 3600; ttlTimeDistriEnum = TtlTimeDistriEnum.getRightTtlDistri(ttlHours); } if (ttlTimeDistriEnum == null) { logger.error(marker, "ttlSeconds {} TtlTimeDistriEnum is null", ttlSeconds); } ttlTimeCountMap.incrementAndGet(ttlTimeDistriEnum); }); count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } logger.info(marker, "{} {}:{} analysis key ttl successfully, cost time is {} ms, total key is {}", appId, host, port, (System.currentTimeMillis() - startTime), count); String keyTtlResultKey = ConstUtils.getRedisServerTtlKey(appId, auditId); ttlTimeCountMap.asMap().entrySet().stream().forEach(entry -> { String ttlDistri = entry.getKey().getValue(); assistRedisService.zincrby(keyTtlResultKey, entry.getValue(), ttlDistri); logger.info(marker, "{} {} {}:{} ttl distri {} {}", keyTtlResultKey, appId, host, port, ttlDistri, entry.getValue()); }); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/analysis/RedisServerKeyTypeAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.analysis; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * key类型分析 * * @author fulei */ @Component("RedisServerKeyTypeAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerKeyTypeAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; /** * 扫描slave */ private final static int SCAN_COUNT = 100; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // key类型分析 taskStepList.add("keyTypeAnalysis"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum keyTypeAnalysis() { long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); jedis.readonly(); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); AtomicLongMap typeCountMap = AtomicLongMap.create(); long count = 0; int totalSplit = 10; int curSplit = 1; while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); Pipeline pipeline = jedis.pipelined(); keyList.stream().forEach(key -> pipeline.type(key)); List typeObjectList; try { typeObjectList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue; // ignore } typeObjectList.stream() .filter(type -> !"none".equalsIgnoreCase(String.valueOf(type)) && (type instanceof String)) .forEach(type -> typeCountMap.incrementAndGet(String.valueOf(type))); count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } logger.info(marker, "{} {}:{} analysis key type successfully, cost time is {} ms, total key is {}", appId, host, port, (System.currentTimeMillis() - startTime), count); String keyTypeResultKey = ConstUtils.getRedisServerTypeKey(appId, auditId); typeCountMap.asMap().entrySet().stream().forEach(entry -> { String type = entry.getKey(); assistRedisService.zincrby(keyTypeResultKey, entry.getValue(), type); logger.info(marker, "{} {} {}:{} type distri {} {}", keyTypeResultKey, appId, host, port, type, entry.getValue()); }); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/analysis/RedisServerKeyValueAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.analysis; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.constant.ValueSizeDistriEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.DebugParams; import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisException; import java.nio.charset.Charset; import java.util.*; import java.util.Map.Entry; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * value size分析 memory usage结果 * * @author fulei */ @Component("RedisServerKeyValueAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerKeyValueAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; /** * 扫描slave */ private final static int SCAN_COUNT = 100; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // key类型分析 taskStepList.add("keyValueAnalysis"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum keyValueAnalysis() { long startTime = System.currentTimeMillis(); //本地结果集 Map valueSizeCountMap = new HashMap(); Jedis jedis = null; try { jedis = redisCenter.getJedis(appId, host, port);; jedis.readonly(); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); long count = 0; int totalSplit = 10; int curSplit = 1; while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); for (byte[] key : keyList) { Long memoryUsage = null; try { // key 可能不存在,报 ERR no such key memoryUsage = jedis.memoryUsage(new String(key, Charset.forName("UTF-8"))); } catch (JedisException e) { logger.warn("memoryUsage-error: key={}", new String(key, Charset.forName("UTF-8"))); logger.error("memoryUsage-error: ", e); //ignore } if (memoryUsage == null) { continue; } ValueSizeDistriEnum valueSizeDistriEnum = ValueSizeDistriEnum.getRightSizeBetween(memoryUsage); if (valueSizeDistriEnum == null) { logger.warn("key {} valueBytes {} is wrong", key, memoryUsage); continue; } if (valueSizeCountMap.containsKey(valueSizeDistriEnum)) { valueSizeCountMap.put(valueSizeDistriEnum, valueSizeCountMap.get(valueSizeDistriEnum) + 1); } else { valueSizeCountMap.put(valueSizeDistriEnum, 1L); } } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } logger.info(marker, "{} {}:{} analysis key value size successfully, cost time is {} ms, total key is {}", appId, host, port, (System.currentTimeMillis() - startTime), count); if (MapUtils.isNotEmpty(valueSizeCountMap)) { String keyValueSizeResultKey = ConstUtils.getRedisServerValueSizeKey(appId, auditId); for (Entry entry : valueSizeCountMap.entrySet()) { String valueSizeDistri = entry.getKey().getValue(); assistRedisService.zincrby(keyValueSizeResultKey, entry.getValue(), valueSizeDistri); logger.info(marker, "{} {} {}:{} value size distri {} {}", keyValueSizeResultKey, appId, host, port, valueSizeDistri, entry.getValue()); } } else { logger.error(marker, "{} {}:{} value size distri is empty", appId, host, port); } return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/daily/MachineExamTask.java ================================================ package com.sohu.cache.task.tasks.daily; import com.google.common.collect.Maps; import com.sohu.cache.entity.MachineStats; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.MachineExamContants; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import org.apache.commons.collections.MapUtils; import org.assertj.core.util.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * Created by rucao on 2019/1/17 */ @Component("MachineExamTask") @Scope(SCOPE_PROTOTYPE) public class MachineExamTask extends BaseTask { private List machineIpList; private Integer useType; private List machineStatsList = Lists.newArrayList(); private Map machineInstanceCountMap = Maps.newHashMap(); private List examResult = Lists.newArrayList(); @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 准备任务参数 taskStepList.add("prepareAppParam"); // 2. 执行机器故障检查 taskStepList.add("executeMachineExam"); // 3. 检查结果展示 taskStepList.add("showMachineExamResult"); return taskStepList; } @Override public TaskStepFlowEnum.TaskFlowStatusEnum init() { super.init(); useType = MapUtils.getInteger(paramMap, TaskConstants.USE_TYPE_KEY, null); machineIpList = (List) MapUtils.getObject(paramMap, TaskConstants.MACHINE_IP_LIST_KEY); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } /** * 1. 准备任务参数 * * @return */ public TaskFlowStatusEnum prepareAppParam() { for (String ip : machineIpList) { List list = machineCenter.getMachineStats(ip, useType, null,null, null, -1, null); machineStatsList.addAll(list); } machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); if (machineStatsList.isEmpty() || machineInstanceCountMap.isEmpty()) { return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2. 执行机器故障检查 * * @return */ public TaskFlowStatusEnum executeMachineExam() { for (MachineStats machineStats : machineStatsList) { String ip = machineStats.getIp(); double mem = (double) machineStats.getInfo().getMem();//G double usedMem = machineStats.getMachineMemInfo().getUsedMemRss() / 1024 / 1024 / 1024;//byte double applyMem = (double) machineStats.getMachineMemInfo().getApplyMem() / 1024 / 1024 / 1024;//byte double usedMemRatio = usedMem / mem; double applyMemRatio = applyMem / mem; int cpu = machineStats.getInfo().getCpu(); int usedCpu = machineInstanceCountMap.get(ip); double usedCpuRatio = (double) usedCpu / cpu; if (judgeMemUsed(usedMemRatio, mem) || judgeMemUsed(applyMemRatio, mem) || judgeCpuUsed(usedCpuRatio)) { examResult.add( new HashMap() {{ put(MachineExamContants.MACHINE_IP, ip); put(MachineExamContants.MEM, String.valueOf(mem)); put(MachineExamContants.APPLY_MEM, String.valueOf(applyMem)); put(MachineExamContants.APPLY_MEM_RATIO, String.valueOf(applyMemRatio)); put(MachineExamContants.USED_MEM, String.valueOf(usedMem)); put(MachineExamContants.USED_MEM_RATIO, String.valueOf(usedMemRatio)); put(MachineExamContants.CPU, String.valueOf(cpu)); put(MachineExamContants.USED_CPU, String.valueOf(usedCpu)); put(MachineExamContants.USED_CPU_RATIO, String.valueOf(usedCpuRatio)); }} ); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3. 检查结果展示 * * @return */ public TaskFlowStatusEnum showMachineExamResult() { return TaskFlowStatusEnum.SUCCESS; } private boolean judgeMemUsed(double ratio, double mem) { if (mem > 20 && ratio > MachineExamContants.defult_memUseThreshold) { return true; } else if (mem > 10 && mem <= 20 && ratio > MachineExamContants.middle_memUseThreshold) { return true; } else if (mem <= 10 && ratio > MachineExamContants.small_memUseThreshold) { return true; } return false; } private boolean judgeCpuUsed(double ratio) { if (ratio >= MachineExamContants.BASE_RATIO) { return true; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/daily/TopologyExamTask.java ================================================ package com.sohu.cache.task.tasks.daily; import com.google.common.collect.Maps; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.entity.AppClientStatisticGather; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.stats.app.impl.AppDailyDataCenterImpl; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.constant.TopoloyExamContants; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.ExamToolEnum; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import org.assertj.core.util.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.text.MessageFormat; import java.util.*; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * Created by rucao on 2019/1/17 */ @Component("TopologyExamTask") @Scope(SCOPE_PROTOTYPE) public class TopologyExamTask extends BaseTask { private Logger logger = LoggerFactory.getLogger(TopologyExamTask.class); @Resource private AppDailyDataCenterImpl appDailyDataCenter; private boolean auto; private int examType; private List appDescList = Lists.newArrayList(); private List examResult = Lists.newArrayList(); private Map examInfo = Maps.newHashMap(); private int appType; private long appId; /** * instance list */ private List instances; /** * entry */ private Map> master_slaves; /** * machine realip / 机房信息 */ private Map> machineInstancesMap; private Map instanceInfoMap; private Map machineInfoMap; private int slaveNum; /** * sentinelInst */ private List sentinels; private static final String DOT = "."; @Override public List getTaskSteps() { List taskStepList = Lists.newArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查应用参数 taskStepList.add("prepareAppParam"); // 2. 执行应用拓扑故障检查 taskStepList.add("executeAppTopologyExam"); // 3. 检查结果展示/发送结果邮件 taskStepList.add("showAppTopologyExamResult"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); auto = MapUtils.getBooleanValue(paramMap, "auto"); examType = MapUtils.getIntValue(paramMap, TaskConstants.EXAM_TYPE_KEY); appDescList.clear(); examResult.clear(); return TaskFlowStatusEnum.SUCCESS; } /** * 1.准备应用参数 * * @return */ public TaskFlowStatusEnum prepareAppParam() { logger.info("prepareAppParam"); if (examType == ExamToolEnum.EXAM_NON_TEST.getValue()) { appDescList = appDao.getOnlineAppsNonTest(); } else if (examType == ExamToolEnum.EXAM_ALL.getValue()) { appDescList = appDao.getOnlineApps(); } else if (examType == ExamToolEnum.EXAM_APPID.getValue()) { long appId = MapUtils.getIntValue(paramMap, TaskConstants.APPID_KEY); appDescList.add(appDao.getAppDescById(appId)); } if (CollectionUtils.isEmpty(appDescList)) { logger.error(marker, "task {} appDesc is empty", taskId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2. 执行应用拓扑故障检查 * * @return */ public TaskFlowStatusEnum executeAppTopologyExam() { logger.info("executeAppTopologyExam"); check(appDescList); return TaskFlowStatusEnum.SUCCESS; } public Map check(List appDescList) { examResult.clear(); examInfo.clear(); if (!CollectionUtils.isEmpty(appDescList)) { for (AppDesc appDesc : appDescList) { try { getAppParam(appDesc); switch (appType) { case ConstUtils.CACHE_REDIS_STANDALONE: standaloneExam(); break; case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: clusterExam(); break; case ConstUtils.CACHE_REDIS_SENTINEL: sentinelExam(); break; default: break; } } catch (Exception e) { logger.error("executeAppTopologyExam error. appId:{}", appDesc.getAppId()); logger.error(e.getMessage(), e); } } examInfo.put("appDesc", appDescList.get(0)); examInfo.put("tips", examResult); } return examInfo; } public List checkAppsTopology(Date date) { List result = new ArrayList<>(); if (date == null) { //获取前一天日期 date = new Date(); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_MONTH, -1); date = calendar.getTime(); } Date checkDate = date; List appDescList = appDao.getOnlineApps(); appDescList.forEach(appDesc -> { AppClientStatisticGather gather = new AppClientStatisticGather(); Map info = check(new ArrayList() {{ add(appDesc); }}); gather.setGatherTime(DateUtil.formatYYYY_MM_dd(checkDate)); gather.setAppId(appDesc.getAppId()); if (MapUtils.isNotEmpty(info)) { List tips = (List) info.get("tips"); int topologyExamResult = CollectionUtils.isNotEmpty(tips) && tips.size() > 0 ? 1 : 0; gather.setTopologyExamResult(topologyExamResult); } else { gather.setTopologyExamResult(-1); } result.add(gather); }); return result; } /** * 3. 检查结果显示 * * @return */ public TaskFlowStatusEnum showAppTopologyExamResult() { logger.info("showAppTopologyExamResult"); Date startDate = DateUtils.addDays(new Date(), -1); appDailyDataCenter.noteAppTopologyDaily(startDate, examResult); return TaskFlowStatusEnum.SUCCESS; } /** * getAppParam 获取应用检查参数 */ private boolean getAppParam(AppDesc appDesc) { if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return false; } instances = Lists.newArrayList(); master_slaves = Maps.newHashMap(); sentinels = Lists.newArrayList(); machineInfoMap = Maps.newHashMap(); instanceInfoMap = Maps.newHashMap(); machineInstancesMap = Maps.newHashMap(); slaveNum = 0; appId = appDesc.getAppId(); if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return false; } appType = appDesc.getType(); instances = appService.getAppOnlineInstanceInfo(appId); if (instances.isEmpty()) { logger.error(marker, "appId {} : instance list is null ", appId); return false; } for (InstanceInfo inst : instances) { if (inst.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && inst.getRoleDesc().equals(InstanceRoleEnum.MASTER.getInfo())) { master_slaves.put(inst, Lists.newArrayList()); } else if (inst.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && inst.getRoleDesc().equals(InstanceRoleEnum.SENTINEL.getInfo())) { sentinels.add(inst); } } for (InstanceInfo inst : instances) { if (inst.getStatus() == 1 && inst.getRoleDesc().equals(InstanceRoleEnum.SLAVE.getInfo())) { slaveNum++; for (Map.Entry> entry : master_slaves.entrySet()) { InstanceInfo masterInst = entry.getKey(); if (inst.getMasterInstanceId() == masterInst.getId()) { List slaveInstList = entry.getValue(); slaveInstList.add(inst); master_slaves.put(masterInst, slaveInstList); } } } } // machineInfo for (InstanceInfo inst : instances) { if (inst.getStatus() == 1) { MachineInfo machineInfo = machineCenter.getMachineInfoByIp(inst.getIp()); if (machineInfo != null) { List instanceInfos = new ArrayList<>(); // realip String realIp = StringUtils.isEmpty(machineInfo.getRealIp()) ? machineInfo.getIp() : machineInfo.getRealIp(); if (!CollectionUtils.isEmpty(machineInstancesMap.get(realIp))) { instanceInfos = machineInstancesMap.get(realIp); } instanceInfos.add(inst); machineInstancesMap.put(realIp, instanceInfos); machineInfoMap.put(realIp, machineInfo); instanceInfoMap.put(inst.getIp(), machineInfo); } } } // master-slave validate boolean msFlag = false; for (Map.Entry> ms : master_slaves.entrySet()) { InstanceInfo masterNode = ms.getKey(); if (!CollectionUtils.isEmpty(ms.getValue())) { for (InstanceInfo slaveNode : ms.getValue()) { String masterRealIp = getRealIp(masterNode.getIp()); String slaveRealIp = getRealIp(slaveNode.getIp()); if (!StringUtils.isEmpty(masterRealIp) && !StringUtils.isEmpty(slaveRealIp) && masterRealIp.equals(slaveRealIp)) { msFlag = true; break; } } } if (msFlag) { break; } } examInfo.put("instances", instances); examInfo.put("master_slaves", master_slaves); examInfo.put("sentinels", sentinels); examInfo.put("sameNetSegment", checkSameNetSegment()); examInfo.put("slaveNum", slaveNum); examInfo.put("machineInfoMap", machineInfoMap); examInfo.put("instanceInfoMap", instanceInfoMap); examInfo.put("machineInstancesMap", machineInstancesMap); examInfo.put("msFlag", msFlag); return true; } private boolean checkSameNetSegment(){ boolean sameFlag = true; if (appType == ConstUtils.CACHE_TYPE_REDIS_CLUSTER && CollectionUtils.isNotEmpty(instances)) { Optional masterOptional = instances.stream().filter(instanceInfo -> instanceInfo.getRoleDesc().equals(InstanceRoleEnum.MASTER.getInfo())).findFirst(); if(masterOptional.isPresent()){ String ip = masterOptional.get().getIp(); String[] split = ip.split("\\."); if(split != null && split.length > 2){ String netSegment = split[0] + DOT + split[1]; Optional notMatchInstance = instances.stream().filter(instanceInfo -> InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc()) || InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())).filter(instanceInfo -> !instanceInfo.getIp().startsWith(netSegment)).findFirst(); if(notMatchInstance.isPresent()){ String notMatchIp = notMatchInstance.get().getIp(); String notMatchNetSegment = notMatchIp; if(notMatchIp != null){ String[] split1 = notMatchIp.split("\\."); notMatchNetSegment = split1[0] + DOT + split1[1]; } String diffNetSegment = notMatchNetSegment; sameFlag = false; examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, appType == ConstUtils.CACHE_TYPE_REDIS_CLUSTER ? TopoloyExamContants.REDIS_CLUSTER : TopoloyExamContants.REDIS_SENTINEL); put(TopoloyExamContants.STATUS, TopoloyExamContants.NETSEGMENT_DESC); put(TopoloyExamContants.DESC, MessageFormat.format(TopoloyExamContants.NETSEGMENT_FORMAT, netSegment, diffNetSegment)); }} ); } } } } return sameFlag; } /** * redis-standalone类型应用故障检查 */ private void standaloneExam() { for (Map.Entry> entry : master_slaves.entrySet()) { masterSlaveExam(TopoloyExamContants.REDIS_STANDALONE, entry.getKey(), entry.getValue()); break; } } /** * redis-cluster类型应用故障检查 */ private void clusterExam() { Map> masterMealIpMap = Maps.newHashMap(); for (Map.Entry> entry : master_slaves.entrySet()) { InstanceInfo masterInst = entry.getKey(); //1.master-slave检查 masterSlaveExam(TopoloyExamContants.REDIS_CLUSTER, masterInst, entry.getValue()); //for failover exam String realIp = getRealIp(masterInst.getIp()); List masterInstList = (List) MapUtils.getObject(masterMealIpMap, realIp, Lists.newArrayList()); masterInstList.add(masterInst); masterMealIpMap.put(realIp, masterInstList); } //2.master节点数检查 if (masterMealIpMap.size() < 3) { StringBuilder tmpBuilder = new StringBuilder(); for (Map.Entry> entry : master_slaves.entrySet()) { InstanceInfo masterInst = entry.getKey(); tmpBuilder.append(MessageFormat.format(TopoloyExamContants.INSTANCE_FORMAT, masterInst.getRoleDesc(), masterInst.getIp(), String.valueOf(masterInst.getPort()), getRealIp(masterInst.getIp()))); } final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, TopoloyExamContants.REDIS_CLUSTER); put(TopoloyExamContants.STATUS, TopoloyExamContants.NODESNUM_DESC); put(TopoloyExamContants.DESC, descStr); }} ); } //3.failover检查 failoverExam(masterMealIpMap); } /** * redis-sentinel类型应用故障检查 */ private void sentinelExam() { Set sentinelRealIpSet = new HashSet<>(); for (InstanceInfo sentinelInst : sentinels) { sentinelRealIpSet.add(getRealIp(sentinelInst.getIp())); } //sentinel result if (sentinelRealIpSet.size() < 3) { logger.info(marker, "appId:{}, sentinel节点分布少于3台物理机", appId); StringBuilder tmpBuilder = new StringBuilder(); for (InstanceInfo sentinelInst : sentinels) { tmpBuilder.append(MessageFormat.format(TopoloyExamContants.INSTANCE_FORMAT, sentinelInst.getRoleDesc(), sentinelInst.getIp(), String.valueOf(sentinelInst.getPort()), getRealIp(sentinelInst.getIp()))); } final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, TopoloyExamContants.REDIS_SENTINEL); put(TopoloyExamContants.STATUS, TopoloyExamContants.NODESNUM_DESC); put(TopoloyExamContants.DESC, descStr); }} ); } //master-slave result for (Map.Entry> entry : master_slaves.entrySet()) { masterSlaveExam(TopoloyExamContants.REDIS_SENTINEL, entry.getKey(), entry.getValue()); break; } } private void masterSlaveExam(String appType, InstanceInfo masterInst, List slaveInstList) { String masterIp = masterInst.getIp(); String port = String.valueOf(masterInst.getPort()); String masterRealIp = getRealIp(masterIp); StringBuilder tmpBuilder = new StringBuilder(MessageFormat.format(TopoloyExamContants.CLUSTER_INSTANCE_FORMAT, masterInst.getRoleDesc(), masterIp, port, masterRealIp)); if (slaveNum != 0 && slaveInstList.size() == 0) { //double check BooleanEnum hasSlaves = redisCenter.hasSlaves(appId, masterInst.getIp(), masterInst.getPort()); if (hasSlaves == BooleanEnum.FALSE) { final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, appType); put(TopoloyExamContants.STATUS, TopoloyExamContants.SLAVE_NOT_EXIST); put(TopoloyExamContants.DESC, descStr); }} ); logger.info(marker, "appId:{}, master没有对应的slave", appId); } } boolean flag = false; for (InstanceInfo slaveInst : slaveInstList) { String slaveIp = slaveInst.getIp(); String slaveRealIp = getRealIp(slaveIp); if (masterRealIp.equals(slaveRealIp)) { flag = true; tmpBuilder.append(MessageFormat.format(TopoloyExamContants.INSTANCE_FORMAT, InstanceRoleEnum.SLAVE.getInfo(), slaveIp, String.valueOf(slaveInst.getPort()), slaveRealIp)); } } if (flag) { final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, appType); put(TopoloyExamContants.STATUS, TopoloyExamContants.MASTER_SLAVE_DESC); put(TopoloyExamContants.DESC, descStr); }} ); } } private void failoverExam(Map> masterMealIpMap) { for (Map.Entry> entry : masterMealIpMap.entrySet()) { String masterRealIp = entry.getKey(); StringBuilder tmpBuilder = new StringBuilder(""); for (InstanceInfo masterInst : entry.getValue()) { tmpBuilder.append(MessageFormat.format(TopoloyExamContants.CLUSTER_INSTANCE_FORMAT, masterInst.getRoleDesc(), masterInst.getIp(), String.valueOf(masterInst.getPort()), masterRealIp)); } final String descStr = tmpBuilder.toString(); if (master_slaves.size() - entry.getValue().size() < master_slaves.size() / 2 + 1) { examResult.add( new HashMap() {{ put(TopoloyExamContants.APPID, String.valueOf(appId)); put(TopoloyExamContants.TYPE, TopoloyExamContants.REDIS_CLUSTER); put(TopoloyExamContants.STATUS, TopoloyExamContants.CLUSTER_FAILOVER_DESC); put(TopoloyExamContants.DESC, descStr); }} ); examInfo.put("failoverStatus", false); } } } private String getRealIp(String ip) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); if (machineInfo.getVirtual() == 1 && !StringUtils.isEmpty(machineInfo.getRealIp())) { return machineInfo.getRealIp(); } else { return ip; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppBigKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppBigKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppBigKeyTask extends BaseTask { private long appId; private long auditId; private long fromBytes; private long toBytes; private int size; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2.1 创建delete key taskStepList.add("createAppBigKeyTask"); // 2.2 等到delete key完成 taskStepList.add("waitAppBigKeyTaskFinish"); // 4. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } fromBytes = MapUtils.getLongValue(paramMap, "fromBytes"); if (fromBytes <= 0) { logger.info(marker, "task {} fromBytes is empty", taskId); } size = MapUtils.getIntValue(paramMap, "size"); if (size <= -2) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建delete key子任务 */ public TaskFlowStatusEnum createAppBigKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addInstanceBigKeyTask(appId, host, port, fromBytes, toBytes, size, auditId, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} instanceBigKeyTask create successfully", appId, host, port); } catch (Exception e) { logger.error(marker, "appId {} {}:{} instanceBigKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待delkey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppBigKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceBigKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceBigKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s) appBigKeyTask 完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppDelKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppDelKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppDelKeyTask extends BaseTask { private long appId; private long auditId; private String pattern; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2.1 创建delete key taskStepList.add("createAppDelKeyTask"); // 2.2 等到delete key完成 taskStepList.add("waitAppDelKeyTaskFinish"); // 4. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, "pattern"); if (StringUtils.isBlank(pattern)) { logger.info(marker, "task {} pattern is empty", taskId); } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建delete key子任务 */ public TaskFlowStatusEnum createAppDelKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addInstanceDelKeyTask(appId, host, port, pattern, auditId, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} instanceDelKeyTask create successfully", appId, host, port); } catch (Exception e) { logger.error(marker, "appId {} {}:{} instanceDelKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待delkey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppDelKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceDelKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceDelKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s)的del key完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppHotKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppHotKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppHotKeyTask extends BaseTask { private long appId; private long auditId; private String command; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2.1 创建delete key taskStepList.add("createAppHotKeyTask"); // 2.2 等到delete key完成 taskStepList.add("waitAppHotKeyTaskFinish"); // 4. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } command = MapUtils.getString(paramMap, "command"); if (StringUtils.isBlank(command)) { logger.error(marker, "task {} command {} is wrong", taskId, command); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建hotkey子任务 */ public TaskFlowStatusEnum createAppHotKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addInstanceHotKeyTask(appId, host, port, command, auditId, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} instanceHotKeyTask create successfully", appId, host, port); } catch (Exception e) { logger.error(marker, "appId {} {}:{} instanceHotKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待hotkey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppHotKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceHotKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceHotKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s)的hotkey完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppIdleKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppIdleKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppIdleKeyTask extends BaseTask { private long appId; private long idleTime; private int size; private long auditId; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2.1 创建delete key taskStepList.add("createAppIdleKeyTask"); // 2.2 等到delete key完成 taskStepList.add("waitAppIdleKeyTaskFinish"); // 4. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } idleTime = MapUtils.getIntValue(paramMap, "idleTime"); if (idleTime <= 0) { logger.error(marker, "task {} idleTime {} is wrong", taskId, idleTime); return TaskFlowStatusEnum.ABORT; } size = MapUtils.getIntValue(paramMap, "size"); if (size <= -2) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建delete key子任务 */ public TaskFlowStatusEnum createAppIdleKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addInstanceIdleKeyTask(appId, host, port, idleTime, size, auditId, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} instanceIdleKeyTask create successfully", appId, host, port); } catch (Exception e) { logger.error(marker, "appId {} {}:{} instanceIdleKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待delkey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppIdleKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceIdleKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceIdleKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s) appIdleKeyTask 完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppScanCleanKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.task.constant.ScanCleanConstants; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.*; import java.util.stream.Collectors; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: zengyizhao * @Date: 2022/5/26 */ @Component("AppScanCleanKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppScanCleanKeyTask extends BaseTask { private long appId; private long auditId; private String pattern; private String nodes; private List instanceList; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2. redis server big key分析 taskStepList.add("createAppScanCleanKeyTask"); taskStepList.add("waitAppScanCleanKeyTaskFinish"); // 3. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, "pattern"); if (StringUtils.isBlank(pattern)) { logger.info(marker, "task {} pattern is empty", taskId); } instanceList = appService.getAppOnlineInstanceInfo(appId); //redis server list nodes = MapUtils.getString(paramMap, ScanCleanConstants.POINTED_NODES); Integer operateType = MapUtils.getInteger(paramMap, ScanCleanConstants.OPERATE_TYPE); if(operateType == null){ logger.error(marker, "task {} operateType is illegal", taskId); return TaskFlowStatusEnum.ABORT; } boolean nodesAndJudge = getNodesAndJudge(operateType); if(!nodesAndJudge){ logger.error(marker, "task {} pointed nodes is illegal", taskId); return TaskFlowStatusEnum.ABORT; } if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "task {} user paramMap node: {}", taskId, nodes); return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建scan clean key子任务 */ public TaskFlowStatusEnum createAppScanCleanKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); // 每个server的dbsize Map redisServerDbSizeMap = new HashMap<>(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); long childTaskId = taskService.addInstanceScanCleanKeyTask(appId, auditId, host, port, paramMap, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} dbsize:{} redis scanCleanKeyTask create successfully", appId, host, port, dbSize); } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis scanCleanKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待scanCleankey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppScanCleanKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, ScanCleanConstants.REDIS_SCAN_CLEAN_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceScanKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceScanKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s)的scan clean key完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } private boolean getNodesAndJudge(int operateType){ boolean judgePointedNodeFlag = true; List instanceInfoList = new ArrayList<>(); redisServerNodes = new ArrayList<>(); if(ScanCleanConstants.NODE_TYPE_MASTER.equals(nodes)){ instanceInfoList = instanceList.stream().filter(instanceInfo -> InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())).collect(Collectors.toList()); }else if(ScanCleanConstants.NODE_TYPE_SLAVE.equals(nodes)){ instanceInfoList = instanceList.stream().filter(instanceInfo -> InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())).collect(Collectors.toList()); }else if(nodes != null){ List instanceInfos = new ArrayList<>(); String[] split = nodes.split(","); for (String nodeStr : split){ instanceList.forEach(instanceInfo -> { if(instanceInfo.getHostPort().equals(nodeStr)){ instanceInfos.add(instanceInfo); } }); } instanceInfoList = instanceInfos; } instanceInfoList.forEach(instanceInfo -> redisServerNodes.add(new RedisServerNode(instanceInfo.getIp(), instanceInfo.getPort()))); if(operateType == 1 || operateType == 2){ Optional slaveExist = instanceInfoList.stream().filter(instanceInfo -> InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())).findFirst(); if(slaveExist.isPresent()){ judgePointedNodeFlag = false; } } //仅扫描时,不增加节点角色类型校验 // else if(operateType == 0){ // Optional masterExist = instanceInfoList.stream().filter(instanceInfo -> InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())).findFirst(); // if(masterExist.isPresent()){ // judgePointedNodeFlag = false; // } // } return judgePointedNodeFlag; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppScanKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppScanKeyTask") @Scope(SCOPE_PROTOTYPE) public class AppScanKeyTask extends BaseTask { private long appId; private long auditId; private String pattern; private int size; private List redisServerNodes; private final static long SCANKEY_SLEEP_BASE = 20000000; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2. redis server big key分析 taskStepList.add("createAppScanKeyTask"); taskStepList.add("waitAppScanKeyTaskFinish"); // 3. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, "pattern"); if (StringUtils.isBlank(pattern)) { logger.info(marker, "task {} pattern is empty", taskId); } size = MapUtils.getIntValue(paramMap, "size"); if (size <= 0) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建scan key子任务 */ public TaskFlowStatusEnum createAppScanKeyTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); // 每个server的dbsize Map redisServerDbSizeMap = new HashMap<>(); for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long dbSize = redisCenter.getDbSize(appId, redisServerNode.getIp(), redisServerNode.getPort()); logger.info(marker, "appId {} {}:{} dbSize is {} ", appId, host, port, dbSize); redisServerDbSizeMap.put(host + ":" + port, dbSize); } long keyCounter = 0; int factor = 1; for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } long sleepCounter = factor * SCANKEY_SLEEP_BASE; String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long dbSize = redisServerDbSizeMap.get(host + ":" + port); keyCounter += dbSize; long childTaskId = taskService.addInstanceScanKeyTask(appId, auditId, host, port, pattern, size, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} redis scanKeyTask create successfully", appId, host, port); // 超额就sleep if (keyCounter > sleepCounter) { factor++; sleepSeconds(120); } } catch (Exception e) { logger.error(marker, "appId {} {}:{} redis scanKeyTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待scankey子任务完成 * * @return */ public TaskFlowStatusEnum waitAppScanKeyTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceScanKeyTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceScanKeyTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s)的scan key完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/AppSlotAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 17:36 */ @Component("AppSlotAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class AppSlotAnalysisTask extends BaseTask { private long appId; private long auditId; private List redisServerNodes; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 1. 检查集群参数 taskStepList.add("checkAppParam"); // 2.1 创建 appSlotAnalysisTask taskStepList.add("createAppSlotAnalysisTask"); // 2.2 等到 ppSlotAnalysisTask完成 taskStepList.add("waitAppSlotAnalysisTaskFinish"); // 4. 工单审批 taskStepList.add("updateAudit"); return taskStepList; } /** * 0.初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } //redis server list String redisServerNodesStr = MapUtils.getString(paramMap, TaskConstants.REDIS_SERVER_NODES_KEY); if (StringUtils.isNotBlank(redisServerNodesStr)) { redisServerNodes = JSONArray.parseArray(redisServerNodesStr, RedisServerNode.class); if (CollectionUtils.isEmpty(redisServerNodes)) { logger.error(marker, "task {} redisServerNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } logger.info(marker, "user paramMap node: {}", redisServerNodesStr); } return TaskFlowStatusEnum.SUCCESS; } /** * 1.检查应用参数 * * @return */ public TaskFlowStatusEnum checkAppParam() { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error(marker, "appId {} appDesc is null", appId); return TaskFlowStatusEnum.ABORT; } if (!appDesc.isOnline()) { logger.error(marker, "appId {} is must be online, ", appId); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 2.1.创建appSlotAnalysisTask子任务 */ public TaskFlowStatusEnum createAppSlotAnalysisTask() { redisServerNodes = buildRedisServerNodes(redisServerNodes, appId); paramMap.put(TaskConstants.REDIS_SERVER_NODES_KEY, redisServerNodes); for (RedisServerNode redisServerNode : redisServerNodes) { //跳过已经执行完毕的节点 if (redisServerNode.getTaskId() > 0) { continue; } String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); try { long childTaskId = taskService.addInstanceSlotAnalysisTask(appId, host, port, auditId, taskId); redisServerNode.setTaskId(childTaskId); logger.info(marker, "appId {} {}:{} instanceSlotAnalysisTask create successfully", appId, host, port); } catch (Exception e) { logger.error(marker, "appId {} {}:{} instanceSlotAnalysisTask create fail", appId, host, port); logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } return TaskFlowStatusEnum.SUCCESS; } /** * 2.2.等待appSlotAnalysisTask子任务完成 * * @return */ public TaskFlowStatusEnum waitAppSlotAnalysisTaskFinish() { for (RedisServerNode redisServerNode : redisServerNodes) { String host = redisServerNode.getIp(); int port = redisServerNode.getPort(); long childTaskId = redisServerNode.getTaskId(); TaskFlowStatusEnum taskFlowStatusEnum = waitTaskFinish(childTaskId, TaskConstants.REDIS_SERVER_DIAGNOSTIC_TIMEOUT); if (taskFlowStatusEnum.equals(TaskFlowStatusEnum.ABORT)) { logger.error(marker, "appId {} {}:{} instanceSlotAnalysisTask execute fail", appId, host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "appId {} {}:{} instanceSlotAnalysisTask execute successfully", appId, host, port); } } return TaskFlowStatusEnum.SUCCESS; } /** * 3.通过初审:资源分配 */ public TaskFlowStatusEnum updateAudit() { try { AppDesc appDesc = appService.getByAppId(appId); appAuditDao.updateAppAudit(auditId, AppCheckEnum.APP_PASS.value()); StringBuffer content = new StringBuffer(); content.append(String.format("应用(%s-%s)slotAnalysisTask完成", appDesc.getAppId(), appDesc.getName())); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceBigKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.redis.util.PipelineUtil; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.Pair; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceBigKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceBigKeyTask extends BaseTask { private String host; private int port; private long appId; private long fromBytes; private long toBytes; private int size; private long auditId; private long parentTaskId; private final static int SCAN_COUNT = 100; private final static String CONDITION_TEMPLATE = "fromBytes:{0}K;size:{1}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // delete key taskStepList.add("bigKey"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } fromBytes = MapUtils.getLongValue(paramMap, "fromBytes"); if (fromBytes <= 0) { logger.info(marker, "task {} fromBytes is empty", taskId); } size = MapUtils.getIntValue(paramMap, "size"); if (size <= -2) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskFlowStatusEnum bigKey() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); String condition = MessageFormat.format(CONDITION_TEMPLATE, String.valueOf(fromBytes), size); record.setDiagnosticCondition(condition); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.BIG_KEY.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); /** * 扫描bigkey,计时开始*/ long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); long count = 0; int totalSplit = 10; int curSplit = 1; Map result = new HashMap<>(); while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); Pipeline pipeline = jedis.pipelined(); if (CollectionUtils.isNotEmpty(keyList)) { List keyStrList = keyList.stream().map(byteKey -> new String(byteKey)).collect(Collectors.toList()); keyStrList.stream().forEach(keyStr -> PipelineUtil.memoryUsage(pipeline, keyStr)); List memObjectList; try { memObjectList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue; // ignore } List memUsedList = memObjectList; Map keyMemMap = IntStream.range(0, keyList.size()) .filter(i -> !"none".equalsIgnoreCase(String.valueOf(memUsedList.get(i))) && (memUsedList.get(i) instanceof Long) && Long.valueOf(String.valueOf(memUsedList.get(i))) >= fromBytes * 1024) .mapToObj(i -> new Pair<>(keyStrList.get(i), String.valueOf(memUsedList.get(i)))) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); result.putAll(keyMemMap); } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already scan&check key {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(10); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if ((size > 0 ? result.size() >= size : false) || Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } //结果存redis String redisBigKey = ConstUtils.getInstanceBigKey(taskId, hostPost); assistRedisService.del(redisBigKey); assistRedisService.hmset(redisBigKey, result); long cost = System.currentTimeMillis() - startTime; /** * 计时结束*/ //更新记录 diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, redisBigKey, 1, cost); logger.info(marker, "{} {}:{} instanceBigKeyTask successfully, cost time is {} ms, total key is {}", appId, host, port, cost, count); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "instanceBigKeyTask appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceDelKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.constant.SymbolConstant; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum; import com.sohu.cache.util.StringUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceDelKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceDelKeyTask extends BaseTask { private String host; private int port; private long appId; private String pattern; /** * 支持多个pattern,将pattern按照逗号分隔 */ private List patterns; private long auditId; private long parentTaskId; private final static int SCAN_COUNT = 100; private final static String CONDITION_TEMPLATE = "pattern:{0}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // delete key taskStepList.add("delKey"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskStepFlowEnum.TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, "pattern"); patterns = new ArrayList<>(); if (StringUtils.isBlank(pattern)) { logger.info(marker, "task {} pattern is empty", taskId); } else { if(pattern.contains(SymbolConstant.COMMA)){ patterns = Arrays.asList(pattern.split(",")); }else{ patterns.add(pattern); } } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskStepFlowEnum.TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskStepFlowEnum.TaskFlowStatusEnum delKey() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); record.setDiagnosticCondition(MessageFormat.format(CONDITION_TEMPLATE, patterns)); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.DEL_KEY.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); /** * 扫描删除,计时开始*/ long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); long count = 0; int totalSplit = 10; int curSplit = 1; int needScanTimes = 1; if(patterns.size() > 0){ needScanTimes = patterns.size(); } for(int i = 0; i < needScanTimes; i++){ String curPattern = null; if(patterns.size() > 0){ curPattern = patterns.get(i); } ScanParams scanParams = StringUtil.isBlank(curPattern) ? new ScanParams().count(SCAN_COUNT) : new ScanParams().match(curPattern).count(SCAN_COUNT); while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); //pipeline unlink Pipeline pipeline = jedis.pipelined(); keyList.stream().forEach(key -> pipeline.unlink(key)); List unlinkList; try { unlinkList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue;// ignoreu } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already delete {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(10); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } } long cost = System.currentTimeMillis() - startTime; /** * 计时结束*/ //更新记录 diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, String.valueOf(count), 1, cost); logger.info(marker, "{} {}:{} del key successfully, cost time is {} ms, total key is {}", appId, host, port, cost, count); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "del key appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceHotKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceHotKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceHotKeyTask extends BaseTask { private String host; private int port; private long appId; private String command; private long auditId; private long parentTaskId; private final static String CONDITION_TEMPLATE = "command:{0}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // delete key taskStepList.add("hotKey"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskStepFlowEnum.TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } command = MapUtils.getString(paramMap, "command"); if (StringUtils.isBlank(command)) { logger.error(marker, "task {} command {} is wrong", taskId, command); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskStepFlowEnum.TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskStepFlowEnum.TaskFlowStatusEnum hotKey() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); record.setDiagnosticCondition(MessageFormat.format(CONDITION_TEMPLATE, command)); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.HOT_KEY.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); /** * 扫描删除,计时开始*/ long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); String result = redisCenter.executeAdminCommand(appId, host, port, command, 60000 * 6); //结果存redis String redisHotKey = ConstUtils.getInstanceHotKey(taskId, hostPost); assistRedisService.del(redisHotKey); assistRedisService.set(redisHotKey, result); long cost = System.currentTimeMillis() - startTime; /** * 计时结束*/ //更新记录 diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, redisHotKey, 1, cost); logger.info(marker, "{} {}:{} hotkey successfully, cost time is {} ms", appId, host, port, cost); return TaskStepFlowEnum.TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "del key appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskStepFlowEnum.TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceIdleKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.redis.util.PipelineUtil; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.*; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceIdleKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceIdleKeyTask extends BaseTask { private String host; private int port; private long appId; private long idleTime; private int size; private long auditId; private long parentTaskId; private final static int SCAN_COUNT = 100; private final static String CONDITION_TEMPLATE = "idleDay:{0};size{1}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // delete key taskStepList.add("idleKey"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } idleTime = MapUtils.getIntValue(paramMap, "idleTime"); if (idleTime <= 0) { logger.error(marker, "task {} idleTime {} is wrong", taskId, idleTime); return TaskFlowStatusEnum.ABORT; } size = MapUtils.getIntValue(paramMap, "size"); if (size <= -2) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskFlowStatusEnum idleKey() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); record.setDiagnosticCondition(MessageFormat.format(CONDITION_TEMPLATE, idleTime, size)); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.IDLE_KEY.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); /** * 扫描删除,计时开始*/ long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); ScanParams scanParams = new ScanParams().count(SCAN_COUNT); long count = 0; int totalSplit = 10; int curSplit = 1; Map result = new HashMap<>(); while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); Pipeline pipeline = jedis.pipelined(); if (CollectionUtils.isNotEmpty(keyList)) { List keyStrList = keyList.stream().map(byteKey -> new String(byteKey)).collect(Collectors.toList()); keyStrList.stream().forEach(keyStr -> PipelineUtil.objectIdletime(pipeline, keyStr)); List idletimeList; try { idletimeList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { continue; // ignore } List idletimeResList = new ArrayList<>(); if(CollectionUtils.isNotEmpty(idletimeList)){ idletimeList.stream().filter(idleTime -> (idleTime instanceof Long)).forEach(idleTime -> idletimeResList.add((Long)idleTime)); } Map keyIdleMap = new HashMap<>(); IntStream.range(0, keyStrList.size()) .filter(i -> idletimeResList.get(i) != null) .forEach(i -> { if(idletimeResList.get(i) > idleTime * 3600 * 24){ keyIdleMap.put(keyStrList.get(i), String.valueOf(idletimeResList.get(i))); } }); result.putAll(keyIdleMap); } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already anlysis {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(10); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if ((size > 0 ? result.size() >= size : false) || Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } //结果存redis String redisIdleKey = ConstUtils.getInstanceIdleKey(taskId, hostPost); assistRedisService.del(redisIdleKey); assistRedisService.hmset(redisIdleKey, result); long cost = System.currentTimeMillis() - startTime; /** * 计时结束*/ //更新记录 diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, redisIdleKey, 1, cost); logger.info(marker, "{} {}:{} instanceIdleKeyTask successfully, cost time is {} ms, total key is {}", appId, host, port, cost, count); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "instanceIdleKeyTask appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceScanCleanKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.ScanCleanConstants; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.assertj.core.util.Lists; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.*; import redis.clients.jedis.util.JedisClusterCRC16; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: zengyizhao * @Date: 2022/5/25 */ @Component("InstanceScanCleanKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceScanCleanKeyTask extends BaseTask { private long appId; private long auditId; private long parentTaskId; private String host; private int port; private String operateType; private String pattern; private int perCount; private Long ttlLess; private Long ttlMore; private Integer ttlResetMore; private Integer ttlResetLess; private Integer index; private Integer compareType; private Long compareValue; private String authPwd; private String hostPort; private String condition; private Random random; private Pattern patternExp = Pattern.compile("[0-9]+"); @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); //检查匹配分析 if(ScanCleanConstants.OPERATE_ANALYSE.equals(paramMap.get(ScanCleanConstants.OPERATE_TYPE))){ taskStepList.add("analyseKeyMatch"); } //分析清理 if(ScanCleanConstants.OPERATE_CLEAN.equals(paramMap.get(ScanCleanConstants.OPERATE_TYPE))){ taskStepList.add("scanClean"); } //分析重置ttl if(ScanCleanConstants.OPERATE_TTL_RESET.equals(paramMap.get(ScanCleanConstants.OPERATE_TYPE))){ taskStepList.add("scanResetTtl"); } return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } operateType = MapUtils.getString(paramMap, ScanCleanConstants.OPERATE_TYPE); if (!(ScanCleanConstants.OPERATE_ANALYSE.equals(operateType) || ScanCleanConstants.OPERATE_CLEAN.equals(operateType) || ScanCleanConstants.OPERATE_TTL_RESET.equals(operateType))) { logger.error(marker, "task {} isClean {} is wrong", taskId, operateType); return TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, ScanCleanConstants.PATTERN); if (StringUtils.isBlank(pattern)) { logger.error(marker, "task {} pattern is empty", taskId); return TaskFlowStatusEnum.ABORT; } this.compilePatternAndSet(); AppDesc appDesc = appService.getByAppId(appId); authPwd = appDesc.getAppPassword(); ttlLess = MapUtils.getLong(paramMap, ScanCleanConstants.TTL_LESS); ttlMore = MapUtils.getLong(paramMap, ScanCleanConstants.TTL_MORE); if(ttlLess != null && ttlMore != null && ttlLess < ttlMore){ logger.error(marker, "task {} ttl filter value more/less condition fault", taskId); return TaskFlowStatusEnum.ABORT; } ttlResetLess = MapUtils.getInteger(paramMap, ScanCleanConstants.TTL_RESET_LESS); ttlResetMore = MapUtils.getInteger(paramMap, ScanCleanConstants.TTL_RESET_MORE); if(ttlResetLess != null && ttlResetMore != null && ttlResetLess < ttlResetMore){ logger.error(marker, "task {} ttl reset value more and less condition fault", taskId); return TaskFlowStatusEnum.ABORT; } if(ttlResetLess != null && ttlResetMore != null){ random = new Random(); } perCount = MapUtils.getIntValue(paramMap, ScanCleanConstants.PER_COUNT, 100); parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); hostPort = host + ":" + port; getCondition(); return TaskFlowStatusEnum.SUCCESS; } private void compilePatternAndSet(){ Pattern lessMatchPattern = Pattern.compile("@Less\\{[0-9]+\\}Less@"); Matcher lessMatcher = lessMatchPattern.matcher(pattern); boolean foundFlag = lessMatcher.find(); if(foundFlag){ int start = lessMatcher.start(); int end = lessMatcher.end(); compareType = ScanCleanConstants.COMPARE_TYPE_LESS_THAN; compareValue = Long.valueOf(pattern.substring(start + 6, end - 6)); pattern = pattern.substring(0, start) + "[0-9]*[0-9]" + pattern.substring(end); index = start; }else{ Pattern moreMatchPattern = Pattern.compile("@More\\{[0-9]+\\}More@"); Matcher moreMatcher = moreMatchPattern.matcher(pattern); foundFlag = moreMatcher.find(); if(foundFlag){ int start = moreMatcher.start(); int end = moreMatcher.end(); compareType = ScanCleanConstants.COMPARE_TYPE_MORE_THAN; compareValue = Long.valueOf(pattern.substring(start + 6, end - 6)); pattern = pattern.substring(0, start) + "[0-9]*[0-9]" + pattern.substring(end); index = start; } } } private void getCondition(){ StringBuffer stringBuffer = new StringBuffer(); if(ScanCleanConstants.OPERATE_ANALYSE.equals(operateType)){ stringBuffer.append("扫描分析: "); }else if(ScanCleanConstants.OPERATE_CLEAN.equals(operateType)){ stringBuffer.append("分析清理: "); }else if(ScanCleanConstants.OPERATE_TTL_RESET.equals(operateType)){ stringBuffer.append("重置ttl: "); } stringBuffer.append("匹配键=").append(pattern); stringBuffer.append(",每次扫描数量=").append(perCount); if(compareValue != null){ stringBuffer.append(",精确筛选条件=(").append("key从第").append(index).append("字符起数字匹配值"); if(ScanCleanConstants.COMPARE_TYPE_LESS_THAN.equals(compareType)){ stringBuffer.append(" < "); }else { stringBuffer.append(" > "); } stringBuffer.append(compareValue).append(")"); } if(ttlLess != null || ttlMore != null){ if(ttlLess != null && ttlMore != null){ stringBuffer.append(",ttl剩余筛选条件=(").append("ttl").append(" > ").append(ttlMore).append(" and ttl < ").append(ttlLess).append(")"); }else if(ttlLess != null){ stringBuffer.append(",ttl剩余筛选条件=(").append("ttl").append(" < ").append(ttlLess).append(")"); }else if(ttlMore != null){ stringBuffer.append(",ttl剩余筛选条件=(").append("ttl").append(" > ").append(ttlMore).append(")"); } } if(ttlResetLess != null || ttlResetMore != null){ stringBuffer.append(",ttl重置时间配置=(").append("ttl").append(" > ").append(ttlResetMore).append(" and ttl < ").append(ttlResetLess).append(")"); } condition = stringBuffer.toString(); } /** * 2.analyseKeyMatch * * @return */ public TaskFlowStatusEnum analyseKeyMatch() { long recordId = saveSubTaskRecord(); long startTime = System.currentTimeMillis(); String instanceScanKey = ConstUtils.getInstanceScanClean(taskId, hostPort); Jedis slaveJedis = null; Jedis masterJedis = null; try { slaveJedis = redisCenter.getJedis(host, port, authPwd); HostAndPort master = redisCenter.getMaster(host, port, authPwd); if(master != null){ masterJedis = redisCenter.getJedis(master.getHost(), master.getPort(), authPwd); }else{ masterJedis = slaveJedis; } scanAnalyse(slaveJedis, masterJedis, instanceScanKey); //更新记录 long cost = System.currentTimeMillis() - startTime; diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 1, cost); logger.info(marker, "analyse key match successfully, appId:{} hostport:{} cost time is {} ms", appId, hostPort, cost); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, "analyse key match error, appId:{} hostport:{} error:" + e.getMessage(), appId, hostPort, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (slaveJedis != null) { slaveJedis.close(); } if (masterJedis != null) { masterJedis.close(); } } } /** * 3.scanCleanMatch * * @return */ public TaskFlowStatusEnum scanClean() { long recordId = saveSubTaskRecord(); long startTime = System.currentTimeMillis(); String instanceScanKey = ConstUtils.getInstanceScanClean(taskId, hostPort); Jedis jedis = null; try { jedis = redisCenter.getJedis(host, port, authPwd); scanTtlClean(jedis, instanceScanKey); //更新记录 long cost = System.currentTimeMillis() - startTime; diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 1, cost); logger.info(marker, "scan clean successfully, appId:{} hostport:{} cost time is {} ms", appId, cost); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, "scan clean key error, appId:{} hostport:{} error:" + e.getMessage(), appId, hostPort, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } /** * 4.scanResetTtl * * @return */ public TaskFlowStatusEnum scanResetTtl() { long recordId = saveSubTaskRecord(); long startTime = System.currentTimeMillis(); String instanceScanKey = ConstUtils.getInstanceScanClean(taskId, hostPort); Jedis jedis = null; try { jedis = redisCenter.getJedis(host, port, authPwd); scanResetTtl(jedis, instanceScanKey); //更新记录 long cost = System.currentTimeMillis() - startTime; diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 1, cost); logger.info(marker, "scan reset ttl successfully, appId:{} hostport:{} cost time is {} ms", appId, cost); return TaskFlowStatusEnum.SUCCESS; } catch (Exception e) { logger.error(marker, "scan reset ttl error, appId:{} hostport:{} error:" + e.getMessage(), appId, hostPort, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, instanceScanKey, 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } private long saveSubTaskRecord(){ DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); record.setNode(hostPort); record.setDiagnosticCondition(condition); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.SCAN_CLEAN.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); return record.getId(); } private void scanAnalyse(Jedis slaveJedis, Jedis masterJedis, String instanceScanKey) throws InterruptedException { //结果存redis assistRedisService.del(instanceScanKey); assistRedisService.rpush(instanceScanKey, String.format("实例%s——键分析开始", instanceScanKey)); long startTime = System.currentTimeMillis(); ScanParams scanParams = new ScanParams(); scanParams.count(perCount); scanParams.match(pattern); ScanResult scanResult = null; String cursor = "0"; Boolean flag = true; List keyList = new LinkedList<>(); List matchKeyList = new LinkedList<>(); long totalCount = 0; long count = 0; long notTtlCount = 0; long notValueMatchCount = 0; long times = 0; while (flag) { keyList.clear(); scanResult = slaveJedis.scan(cursor, scanParams); cursor = scanResult.getCursor(); totalCount += scanResult.getResult().size(); for (String key : scanResult.getResult()) { if(compareValue == null){ keyList.add(key); }else { if(checkMatchByCompareValue(key)){ keyList.add(key); }else{ notValueMatchCount++; } } } int originalSize = keyList.size(); if(ttlLess != null || ttlMore != null){ checkTtlByPipeline(masterJedis, keyList); } int filterSize = keyList.size(); notTtlCount += originalSize -filterSize; count += keyList.size(); times++; //取样 this.sampleMatchKey(matchKeyList, keyList, times); if(times % 10 == 0){ logger.info("实例{}——键分析进行中,当前精确匹配键数量:{},排除键数量:{},(值去除({})/ttl去除({})),pattern匹配总数量:{},当前cursor:{}, 匹配键示例:{}", instanceScanKey, count, (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount, cursor, (matchKeyList.size() > 10 ? matchKeyList.subList(0, 10) : matchKeyList)); } if (cursor.equals("0")) { flag = false; logger.info("实例{}——键分析结束-----------scan over!--------", instanceScanKey); } } //memoryUsageByPipeline long avgMemoryUsage = memoryUsage(masterJedis, matchKeyList); assistRedisService.rpush(instanceScanKey, String.format("实例键分析结束, 精确匹配键数量:%s, 取样平均内存占用:%s(B), 总内存占用:%s(B), 排除键数量:%s(值去除(%s)/ttl去除(%s)), pattern匹配总数量:%s", count, avgMemoryUsage, (count * avgMemoryUsage), (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount)); this.printMatchKey(instanceScanKey, matchKeyList); assistRedisService.rpush(instanceScanKey, String.format("实例%s——键分析结束, 总耗时%sms", instanceScanKey, (System.currentTimeMillis() - startTime))); } private void scanTtlClean(Jedis masterJedis, String instanceScanKey) throws InterruptedException { //结果存redis assistRedisService.del(instanceScanKey); assistRedisService.rpush(instanceScanKey, String.format("实例%s——键清理开始", instanceScanKey)); ScanParams scanParams = new ScanParams(); scanParams.count(perCount); scanParams.match(pattern); ScanResult scanResult = null; String cursor = "0"; long startTime = System.currentTimeMillis(); Boolean flag = true; List keyList = new LinkedList<>(); List matchKeyList = new LinkedList<>(); long totalCount = 0; long count = 0; long notTtlCount = 0; long notValueMatchCount = 0; long times = 0; while (flag) { keyList.clear(); scanResult = masterJedis.scan(cursor, scanParams); cursor = scanResult.getCursor(); totalCount += scanResult.getResult().size(); for (String key : scanResult.getResult()) { if(compareValue == null){ keyList.add(key); }else { if(checkMatchByCompareValue(key)){ keyList.add(key); }else{ notValueMatchCount++; } } } int originalSize = keyList.size(); if(ttlLess != null || ttlMore != null){ checkTtlByPipeline(masterJedis, keyList); } int filterSize = keyList.size(); notTtlCount += originalSize -filterSize; count += keyList.size(); times++; //取样 this.sampleMatchKey(matchKeyList, keyList, times); if(times % 10 == 0){ logger.info("实例:{},键清理进行中,当前精确匹配键数量:{},排除键数量:{},(值去除({})/ttl去除({})),pattern匹配总数量:{},当前cursor:{}, 匹配键示例:{}", instanceScanKey, count, (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount, cursor, (matchKeyList.size() > 10 ? matchKeyList.subList(0, 10) : matchKeyList)); } if(keyList.size() > 0){ unlinkByPipeline(masterJedis, keyList); if(times % 10 == 0){ logger.info("实例:{},键清理进行中,删除键:{}", instanceScanKey, (keyList.size() > 10 ? keyList.subList(0, 10) : keyList)); } } if (cursor.equals("0")) { flag = false; logger.info("实例{}——键清理结束------------scan over!--------", instanceScanKey); } } assistRedisService.rpush(instanceScanKey, String.format("实例——键清理结束, 精确匹配清理键数量:%s, 排除键数量:%s(值去除(%s)/ttl去除(%s)), pattern匹配总数量:%s", count, (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount)); this.printMatchKey(instanceScanKey, matchKeyList); assistRedisService.rpush(instanceScanKey, String.format("实例%s——键清理结束, 总耗时%sms", instanceScanKey, (System.currentTimeMillis() - startTime))); } private void scanResetTtl(Jedis masterJedis, String instanceScanKey) throws InterruptedException { //结果存redis assistRedisService.del(instanceScanKey); assistRedisService.rpush(instanceScanKey, String.format("实例%s—键重置ttl开始", instanceScanKey)); ScanParams scanParams = new ScanParams(); scanParams.count(perCount); scanParams.match(pattern); ScanResult scanResult = null; String cursor = "0"; long startTime = System.currentTimeMillis(); Boolean flag = true; List keyList = new LinkedList<>(); List matchKeyList = new LinkedList<>(); long totalCount = 0; long count = 0; long notTtlCount = 0; long notValueMatchCount = 0; long times = 0; while (flag) { keyList.clear(); scanResult = masterJedis.scan(cursor, scanParams); cursor = scanResult.getCursor(); totalCount += scanResult.getResult().size(); for (String key : scanResult.getResult()) { if(compareValue == null){ keyList.add(key); }else { if(checkMatchByCompareValue(key)){ keyList.add(key); }else{ notValueMatchCount++; } } } int originalSize = keyList.size(); if(ttlLess != null || ttlMore != null){ checkTtlByPipeline(masterJedis, keyList); } int filterSize = keyList.size(); notTtlCount += originalSize -filterSize; count += keyList.size(); times++; //取样 this.sampleMatchKey(matchKeyList, keyList, times); if(times % 10 == 0){ logger.info("实例:{},键重置ttl进行中,当前精确匹配键数量:{},排除键数量:{},(值去除({})/ttl去除({})),pattern匹配总数量:{},当前cursor:{}, 匹配键示例:{}", instanceScanKey, count, (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount, cursor, (matchKeyList.size() > 10 ? matchKeyList.subList(0, 10) : matchKeyList)); } if(keyList.size() > 0){ resetTtlByPatch(masterJedis, keyList); if(times % 10 == 0){ logger.info("实例:{},键重置ttl进行中,重置ttl键:{}", instanceScanKey, (keyList.size() > 10 ? keyList.subList(0, 10) : keyList)); } } if (cursor.equals("0")) { flag = false; logger.info("实例{}——键重置ttl结束------------scan over!--------", instanceScanKey); } } assistRedisService.rpush(instanceScanKey, String.format("实例——键重置ttl结束, 精确匹配重置键数量:%s, 排除键数量:%s(值去除(%s)/ttl去除(%s)), pattern匹配总数量:%s", count, (notValueMatchCount + notTtlCount), notValueMatchCount, notTtlCount , totalCount)); this.printMatchKey(instanceScanKey, matchKeyList); assistRedisService.rpush(instanceScanKey, String.format("实例%s——键重置ttl结束, 总耗时%sms", instanceScanKey, (System.currentTimeMillis() - startTime))); } private boolean checkMatchByCompareValue(String key){ if(index == null || compareType == null || compareValue == null){ return false; } String subKey = key.substring(index); Matcher matcher = patternExp.matcher(subKey); boolean foundFlag = matcher.find(); if(foundFlag){ int end = matcher.end(); try{ Long id = Long.valueOf(subKey.substring(0, end)); if(ScanCleanConstants.COMPARE_TYPE_MORE_THAN.equals(compareType)){ return id > compareValue; }else if(ScanCleanConstants.COMPARE_TYPE_LESS_THAN.equals(compareType)){ return id < compareValue; } }catch (Exception e){ logger.error("checkMatchByCompareValue key {}, error,", key, e.getMessage()); } } return false; } private void checkTtlByPipeline(Jedis jedis, List keyList){ Pipeline pipelined = jedis.pipelined(); for (String key : keyList){ pipelined.ttl(key); } List ttlList = pipelined.syncAndReturnAll(); int j = 0; for(int i = 0; i < ttlList.size(); i++){ Object ttlObj = ttlList.get(i); if(ttlObj instanceof Number){ if(((Long) ttlObj > 0)){ if(ttlLess != null && ttlMore != null && ((Long) ttlObj > ttlLess || (Long) ttlObj < ttlMore)) { keyList.remove(j); j--; }else if(ttlLess != null && (Long) ttlObj > ttlLess){ keyList.remove(j); j--; }else if(ttlMore != null && (Long) ttlObj < ttlMore){ keyList.remove(j); j--; } } }else{ keyList.remove(j); j--; } j++; } } private long memoryUsage(Jedis jedis, List keyList){ if(CollectionUtils.isEmpty(keyList)){ return 0; } int totalCount = keyList.size(); long sumMemUsage = 0; for (String key : keyList){ Long memoryUsage = jedis.memoryUsage(key); if(memoryUsage == null || memoryUsage < 0){ totalCount--; }else{ sumMemUsage += memoryUsage; } } return sumMemUsage/totalCount; } private void sampleMatchKey(List matchKeyList, List keyList, long times){ if(CollectionUtils.isNotEmpty(keyList)){ if(matchKeyList.size() < 500){ int num = perCount/keyList.size() * 2; num = num > 50 ? 50 : (num > 5 ? num: 5); matchKeyList.addAll(keyList.size() > num ? keyList.subList(0, num) : keyList); return; } if(times%50 == 0){ matchKeyList.addAll(keyList.size() > 10 ? keyList.subList(0, 10) : keyList); if(matchKeyList.size() > 500){ for(int i = 0; i < matchKeyList.size() - 500;){ int toRem = new Random().nextInt(500); matchKeyList.remove(toRem); } } } } } private void printMatchKey(String instanceScanKey, List matchKeyList){ if(CollectionUtils.isNotEmpty(matchKeyList)){ if(matchKeyList.size() > 100){ Collections.shuffle(matchKeyList); matchKeyList = matchKeyList.subList(0, 100); } List matchResultList = new ArrayList<>(); boolean first = true; for(int i = 0; i < matchKeyList.size() / 20; ){ if(first){ matchResultList.add("匹配键示例:[" + matchKeyList.subList(0, 20).stream().collect(Collectors.joining(","))); first = false; }else{ if(matchKeyList.size() != 20){ matchResultList.add(matchKeyList.subList(0, 20).stream().collect(Collectors.joining(","))); }else{ matchResultList.add(matchKeyList.subList(0, 20).stream().collect(Collectors.joining(",")) + "]"); } } matchKeyList = matchKeyList.subList(20, matchKeyList.size()); } if(matchKeyList.size() > 0){ if(first){ matchResultList.add("匹配键示例:[" + matchKeyList.stream().collect(Collectors.joining(",")) + "]"); }else{ matchResultList.add(matchKeyList.stream().collect(Collectors.joining(",")) + "]"); } } assistRedisService.rpushList(instanceScanKey, matchResultList); }else{ assistRedisService.rpush(instanceScanKey, "匹配键示例:[]"); } } private void unlinkByPatch(Jedis jedis, List keyList){ jedis.unlink(keyList.toArray(new String[keyList.size()])); } private void unlinkByPipeline(Jedis jedis, List keyList){ Pipeline pipelined = jedis.pipelined(); for (String key : keyList){ pipelined.unlink(key); } pipelined.sync(); } private void unlinkBySlotAndPatch(Map slotJedisMap, List keyList){ Map> keyToJedisMap = new HashMap<>(); for (String key : keyList){ int slot = JedisClusterCRC16.getSlot(key); Jedis jedis = slotJedisMap.get(slot); if(keyToJedisMap.containsKey(jedis)){ keyToJedisMap.get(jedis).add(key); }else{ keyToJedisMap.put(jedis, Lists.newArrayList(key)); } } Set jedisSet = keyToJedisMap.keySet(); for (Jedis jedis : jedisSet){ jedis.unlink(keyToJedisMap.get(jedis).toArray(new String[keyToJedisMap.get(jedis).size()])); } } private void resetTtlByPatch(Jedis jedis, List keyList){ Pipeline pipelined = jedis.pipelined(); for (String key : keyList){ pipelined.expire(key, ttlResetMore + random.nextInt(ttlResetLess - ttlResetMore)); } pipelined.sync(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceScanKeyTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.StringUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceScanKeyTask") @Scope(SCOPE_PROTOTYPE) public class InstanceScanKeyTask extends BaseTask { private String host; private int port; private long appId; private String pattern; private long auditId; private int size; private long parentTaskId; private final static int SCAN_COUNT = 100; private final static String CONDITION_TEMPLATE = "pattern:{0};size:{1}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // scan taskStepList.add("scanKey"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } pattern = MapUtils.getString(paramMap, "pattern"); if (StringUtils.isBlank(pattern)) { logger.info(marker, "task {} pattern is empty", taskId); } size = MapUtils.getIntValue(paramMap, "size"); if (size <= 0) { logger.error(marker, "task {} size {} is wrong", taskId, size); return TaskFlowStatusEnum.ABORT; } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskFlowStatusEnum scanKey() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); String condition = MessageFormat.format(CONDITION_TEMPLATE, pattern, size); record.setDiagnosticCondition(condition); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.SCAN_KEY.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); ScanParams scanParams = StringUtil.isBlank(pattern) ? new ScanParams().count(Math.min(SCAN_COUNT, size)) : new ScanParams().match(pattern).count(Math.min(SCAN_COUNT, size)); long count = 0; int totalSplit = 10; int curSplit = 1; List result = new ArrayList<>(); while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); if (CollectionUtils.isNotEmpty(keyList)) { result.addAll(keyList.stream().map(byteKey -> new String(byteKey)).collect(Collectors.toList())); } count += keyList.size(); if (count > dbSize / totalSplit * curSplit) { logger.info(marker, "{} {}:{} has already scan {}% {} key ", appId, host, port, curSplit * 10, count); curSplit++; } // @TODO暂时写死 TimeUnit.MILLISECONDS.sleep(10); } catch (Exception e) { logger.error(marker, e.getMessage(), e); } finally { //防止无限循环 if (result.size() >= size || Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } //结果存redis String redisScanKey = ConstUtils.getInstanceScanKey(taskId, hostPost); assistRedisService.del(redisScanKey); assistRedisService.rpushList(redisScanKey, result); //更新记录 long cost = System.currentTimeMillis() - startTime; diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, redisScanKey, 1, cost); logger.info(marker, "{} {}:{} scan key successfully, cost time is {} ms, total key is {}", appId, host, port, cost, count); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "scan key appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/diagnosticTask/InstanceSlotAnalysisTask.java ================================================ package com.sohu.cache.task.tasks.diagnosticTask; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.entity.InstanceSlotModel; import com.sohu.cache.redis.util.PipelineUtil; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.Pair; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.exceptions.JedisRedirectionException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * @Author: rucao * @Date: 2020/6/9 15:53 */ @Component("InstanceSlotAnalysisTask") @Scope(SCOPE_PROTOTYPE) public class InstanceSlotAnalysisTask extends BaseTask { private String host; private int port; private long appId; private long auditId; private long parentTaskId; private static double ERROR_FACTOR = 1; private static String COUNT_ERROR_FORMAT = "countkeys:{0}; error:{1}; benchmark:{2}"; @Override public List getTaskSteps() { List taskStepList = new ArrayList<>(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); // 检查实例是否运行 taskStepList.add("checkIsRun"); // slotAnalysis taskStepList.add("slotAnalysis"); return taskStepList; } /** * 1.初始化参数 */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } auditId = MapUtils.getLongValue(paramMap, TaskConstants.AUDIT_ID_KEY); if (auditId <= 0) { logger.error(marker, "task {} auditId {} is wrong", taskId, auditId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } parentTaskId = MapUtils.getLongValue(paramMap, "parentTaskId"); return TaskFlowStatusEnum.SUCCESS; } /** * 2.检查run以及slave * * @return */ public TaskFlowStatusEnum checkIsRun() { if (!redisCenter.isRun(appId, host, port)) { logger.error(marker, "{} {}:{} is not run", appId, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * 3.scanKey * * @return */ public TaskFlowStatusEnum slotAnalysis() { DiagnosticTaskRecord record = new DiagnosticTaskRecord(); record.setAppId(appId); record.setAuditId(auditId); String hostPost = host + ":" + port; record.setNode(hostPost); record.setTaskId(taskId); record.setParentTaskId(parentTaskId); record.setType(DiagnosticTypeEnum.SLOT_ANALYSIS.getType()); record.setStatus(0); diagnosticTaskRecordDao.insertDiagnosticTaskRecord(record); long recordId = record.getId(); /** * 扫描删除,计时开始*/ long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { logger.info(marker, "{} {}:{} dbsize is {}", appId, host, port, dbSize); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 1, System.currentTimeMillis() - startTime); return TaskFlowStatusEnum.SUCCESS; } logger.info(marker, "{} {}:{} total key is {} ", appId, host, port, dbSize); Map result = new HashMap<>(); Pipeline pipeline = jedis.pipelined(); InstanceSlotModel instanceSlotModel = (InstanceSlotModel) MapUtils.getObject(redisCenter.getClusterSlotsMap(appId), hostPost); if (instanceSlotModel != null) { List slotList = instanceSlotModel.getSlotList(); //set benchmark long benchmark = 0l; for (Integer slot : slotList) { benchmark = jedis.clusterCountKeysInSlot(slot); if (benchmark > 0) { break; } } slotList.stream().forEach(slot -> PipelineUtil.clusterCountKeysInSlot(pipeline, slot)); List objectList = new ArrayList<>(); try { objectList = pipeline.syncAndReturnAll(); } catch (JedisRedirectionException e) { logger.error(marker, "redisSlotAnalysis appId {} {}:{} JedisRedirectionException:" + e.getMessage(), appId, host, port, e); } List countObjectList = objectList; long finalBenchmark = benchmark; result = IntStream.range(0, slotList.size()) .filter(i -> (countObjectList.get(i) != null) && (countObjectList.get(i) instanceof Long)) .mapToObj(i -> new Pair<>(String.valueOf(slotList.get(i)), getCountAndError((Long) countObjectList.get(i), finalBenchmark))) .collect(Collectors.toMap(Pair::getKey, Pair::getValue)); } //结果存redis String redisSlotAnalysis = ConstUtils.getInstanceSlotAnalysis(taskId, hostPost); assistRedisService.del(redisSlotAnalysis); assistRedisService.hmset(redisSlotAnalysis, result); long cost = System.currentTimeMillis() - startTime; /** * 计时结束*/ //更新记录 diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, redisSlotAnalysis, 1, cost); logger.info(marker, "{} {}:{} redisSlotAnalysis successfully, cost time is {} ms", appId, host, port, cost); return TaskFlowStatusEnum.SUCCESS; } catch (RuntimeException e) { diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); throw e; } catch (Exception e) { logger.error(marker, "redis-cli -h {} -p {} admin auth error", host, port); logger.error(marker, "redisSlotAnalysis appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); diagnosticTaskRecordDao.updateDiagnosticStatus(recordId, "", 2, 0); return TaskFlowStatusEnum.ABORT; } finally { if (jedis != null) { jedis.close(); } } } private double getRealError(long count, long benchmark) { if (benchmark <= 0) { return count == benchmark ? 0 : 100; } return Math.abs(count - benchmark) * 1.0 / benchmark; } private String getCountAndError(long count, long benchmark) { double err = getRealError(count, benchmark); return err > ERROR_FACTOR ? MessageFormat.format(COUNT_ERROR_FORMAT, String.valueOf(count), String.format("%.2f", err), String.valueOf(benchmark)) : "countkeys:" + count; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/install/RedisSentinelInstallTask.java ================================================ package com.sohu.cache.task.tasks.install; import com.alibaba.fastjson.JSONArray; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** *

* Description: Redis sentinel安装 *

* * @author chenshi * @version 1.0 * @date 2019/1/11 */ @Component("RedisSentinelInstallTask") @Scope(SCOPE_PROTOTYPE) public class RedisSentinelInstallTask extends BaseTask { private long appId; private String host; private int port; private int quorum; SystemResource redisResource; private List masterRedisServerNodes; /** * 当前实例类型 */ private final InstanceInfoEnum.InstanceTypeEnum currentInstanceTypeEnum = InstanceInfoEnum.InstanceTypeEnum.REDIS_SENTINEL; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); taskStepList.add("checkIsExist"); taskStepList.add("prepareRelateDir"); taskStepList.add("prepareRelateBin"); taskStepList.add("pushService"); taskStepList.add("pushConfig"); taskStepList.add("startServer"); taskStepList.add("checkIsRun"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } quorum = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SENTINEL_QUORUM_KEY); if (quorum <= 0) { logger.error(marker, "task {} quorum {} is wrong", taskId, quorum); return TaskFlowStatusEnum.ABORT; } //parse String masterRedisNodeStr = MapUtils.getString(paramMap, TaskConstants.MASTER_REDIS_SERVER_NODES); masterRedisServerNodes = JSONArray.parseArray(masterRedisNodeStr, RedisServerNode.class); if (CollectionUtils.isEmpty(masterRedisServerNodes)) { logger.error(marker, "task {} masterRedisNodes is empty", taskId); return TaskFlowStatusEnum.ABORT; } redisResource = resourceService.getResourceById(appService.getByAppId(appId).getVersionId()); return TaskFlowStatusEnum.SUCCESS; } /** * 检查实例是否已经存在 * * @return */ public TaskFlowStatusEnum checkIsExist() { return checkInstanceIsExist(appId, host, port, currentInstanceTypeEnum); } /** * 准备相关目录 * * @return */ public TaskFlowStatusEnum prepareRelateDir() { return prepareRelateDir(appId, host, port, currentInstanceTypeEnum); } /** * 准备二进制执行文件 * * @return */ public TaskFlowStatusEnum prepareRelateBin() { return prepareRelateBin(appId, host, port, currentInstanceTypeEnum, redisResource.getName()); } /** * 启动服务 * * @return */ public TaskFlowStatusEnum pushService() { //远程和本地目录 /*String instanceRemoteBasePath = machineCenter.getInstanceRemoteBasePath(appId, port, currentInstanceTypeEnum); String instanceLocalTmpPath = machineCenter.getInstanceLocalTempBasePath(appId, host, port, currentInstanceTypeEnum); //相关参数 int cpuidx = MachineProtocol.getCpuIdx(port); String startCmd = RedisProtocol.getRedisSentinelStartCmd(); String runCmd = RedisProtocol.getRedisSentinelRunCmd(port); String serviceShellFileName = RedisProtocol.getServiceShellFileName(currentInstanceTypeEnum); logger.info(marker, "cpuidx is {}", cpuidx); logger.info(marker, "startCmd is {}", startCmd); logger.info(marker, "runCmd is {}", runCmd); return pushService(appId, currentInstanceTypeEnum, host, port, instanceRemoteBasePath, instanceLocalTmpPath, cpuidx, startCmd, runCmd, serviceShellFileName); */ return TaskFlowStatusEnum.SUCCESS; } /** * 推配置 * * @return */ public TaskFlowStatusEnum pushConfig() { //资源是否存在 redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); String instanceRemoteBasePath = ConstUtils.CACHECLOUD_BASE_DIR; AppDesc appDesc = appService.getByAppId(appId); List masterSentinelConfigs; // 获取masterName if (masterRedisServerNodes.size() == 1) { RedisServerNode redisServerNode = masterRedisServerNodes.get(0); List> customConfigs = new ArrayList<>(); customConfigs.add(Pair.of("sentinel auth-pass " + redisServerNode.getMasterName() + ConstUtils.SPACE, appDesc.getAppPassword())); masterSentinelConfigs = this.handleSentinelConfig(redisServerNode.getMasterName(), redisServerNode.getIp(), redisServerNode.getPort(), host, port, appDesc.getVersionId(), customConfigs); logger.info("sentinel configs :" + masterSentinelConfigs); } else { logger.error(marker, "appId {} masterRedisServerNodes {} is empty", appId, masterRedisServerNodes); return TaskFlowStatusEnum.ABORT; } if (CollectionUtils.isEmpty(masterSentinelConfigs)) { logger.error(marker, "appId {} host:{} port:{} versionId:{} instanceRemoteBasePath {} configList is empty", appId, host, port, appDesc.getVersionId(), instanceRemoteBasePath); return TaskFlowStatusEnum.ABORT; } String masterSentinelFileName = RedisProtocol.getConfig(port, false); String sentinelPathFile = machineCenter .createRemoteFile(host, masterSentinelFileName, masterSentinelConfigs); if (StringUtils.isBlank(sentinelPathFile)) { return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } private String getMasterName(String host, int port) { String masterSentinelName = String.format("sentinel-%s-%s", host, port); return masterSentinelName; } private void printConfig(List masterConfigs) { logger.info("==================redis-{}-config==================", masterConfigs); for (String line : masterConfigs) { logger.info(line); } } /** * 启动服务 * * @return */ public TaskFlowStatusEnum startServer() { redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); String sentinelShell = redisDeployCenter.getSentinelRunShell(host, port, redisDir); logger.info(marker, "sentinelMasterShell:{}", sentinelShell); boolean isSentinelMasterShell = machineCenter.startProcessAtPort(host, port, sentinelShell); if (!isSentinelMasterShell) { logger.error(marker, "sentinelMasterShell={} error", sentinelShell); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } /** * @return */ public TaskFlowStatusEnum checkIsRun() { //检测是否启动成功前,先休息3秒,否则可能会服务未启动完成,出现不能正确创建socket连接异常 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } if (!redisCenter.isRun(host, port)) { logger.error(marker, "sentinel {}:{} is not run", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "sentinel {}:{} is run", host, port); return TaskFlowStatusEnum.SUCCESS; } } /** *

* Description: 获取sentinel config *

* * @author chenshi * @version 1.0 * @date 2019/1/11 */ private List handleSentinelConfig(String masterName, String host, int port, String sentinelHost, int sentinelPort, int versionId, List> customConfigs) { try { // todo masterHost return redisConfigTemplateService.handleSentinelConfig(masterName, host, port, sentinelHost, sentinelPort, versionId, customConfigs); } catch (Exception e) { logger.error(marker, e.getMessage(), e); return Collections.emptyList(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/install/RedisServerInstallTask.java ================================================ package com.sohu.cache.task.tasks.install; import com.sohu.cache.constant.AppDescEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.protocol.RedisProtocol; import com.sohu.cache.redis.enums.RedisConfigEnum; import com.sohu.cache.redis.util.AuthUtil; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import static org.springframework.beans.factory.config.ConfigurableBeanFactory.SCOPE_PROTOTYPE; /** * redis server安装 */ @Component("RedisServerInstallTask") @Scope(SCOPE_PROTOTYPE) public class RedisServerInstallTask extends BaseTask { private long appId; private String host; private int port; private int maxMemory; private Boolean isCluster; SystemResource redisResource; /** * 当前实例类型 */ private final InstanceTypeEnum currentInstanceTypeEnum = InstanceTypeEnum.REDIS_SERVER; /** * 密码 */ private String password; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); taskStepList.add(TaskConstants.INIT_METHOD_KEY); /** * 1.检查实例是否存在 * 2.检查服务器安装环境 dir / env param * 3.appid | redis version版本验证 * 4.push config * 5.start redis instance * 6.validate instance is run */ taskStepList.add("checkIsExist"); taskStepList.add("prepareRelateDir"); taskStepList.add("prepareRelateBin"); taskStepList.add("pushConfig"); taskStepList.add("pushService"); taskStepList.add("startServer"); taskStepList.add("checkIsRun"); return taskStepList; } /** * 初始化参数 * * @return */ @Override public TaskFlowStatusEnum init() { super.init(); appId = MapUtils.getLongValue(paramMap, TaskConstants.APPID_KEY); if (appId <= 0) { logger.error(marker, "task {} appId {} is wrong", taskId, appId); return TaskFlowStatusEnum.ABORT; } host = MapUtils.getString(paramMap, TaskConstants.HOST_KEY); if (StringUtils.isBlank(host)) { logger.error(marker, "task {} host is empty", taskId); return TaskFlowStatusEnum.ABORT; } port = MapUtils.getIntValue(paramMap, TaskConstants.PORT_KEY); if (port <= 0) { logger.error(marker, "task {} port {} is wrong", taskId, port); return TaskFlowStatusEnum.ABORT; } maxMemory = MapUtils.getIntValue(paramMap, TaskConstants.REDIS_SERVER_MAX_MEMORY_KEY); if (maxMemory <= 0) { logger.error(marker, "task {} maxMemory {} is wrong", taskId, maxMemory); return TaskFlowStatusEnum.ABORT; } redisResource = resourceService.getResourceById(appService.getByAppId(appId).getVersionId()); isCluster = MapUtils.getBoolean(paramMap, TaskConstants.IS_CLUSTER_KEY); return TaskFlowStatusEnum.SUCCESS; } /** * 检查实例是否已经存在 * * @return */ public TaskFlowStatusEnum checkIsExist() { return checkInstanceIsExist(appId, host, port, currentInstanceTypeEnum); } /** * 准备相关目录 * * @return */ public TaskFlowStatusEnum prepareRelateDir() { return prepareRelateDir(appId, host, port, currentInstanceTypeEnum); } /** * 准备二进制执行文件 * * @return */ public TaskFlowStatusEnum prepareRelateBin() { return prepareRelateBin(appId, host, port, currentInstanceTypeEnum, redisResource.getName()); } /** * 推配置 * * @return */ public TaskFlowStatusEnum pushConfig() { redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); //实例基准目录 String instanceRemoteBasePath = ConstUtils.CACHECLOUD_BASE_DIR; AppDesc appDesc = appService.getByAppId(appId); password = getAppPwd(appDesc); List> customConfigs = new ArrayList<>(); customConfigs.add(Pair.of(RedisConfigEnum.REQUIREPASS.getKey(), password)); customConfigs.add(Pair.of(RedisConfigEnum.MASTERAUTH.getKey(), password)); List configList = handleCommonConfig(host, port, maxMemory, appDesc.getMaxmemoryPolicy(), appDesc.getVersionId(), isCluster, customConfigs); if (CollectionUtils.isEmpty(configList)) { logger.error(marker, "appId {} port {} maxmemory {} versionId:{} instanceRemoteBasePath {} configList is empty", appId, port, maxMemory, appDesc.getVersionId(), instanceRemoteBasePath); return TaskFlowStatusEnum.ABORT; } String fileName; if (isCluster) { fileName = RedisProtocol.getConfig(port, true); } else { fileName = RedisProtocol.getConfig(port, false); } //todo String pathFile = machineCenter.createRemoteFile(host, fileName, configList); if (StringUtils.isBlank(pathFile)) { logger.error(marker, "appId {} port {} maxmemory {} instanceRemoteBasePath:{} pathFile:{} is empty", appId, port, maxMemory, instanceRemoteBasePath,pathFile); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } private String getAppPwd(AppDesc appDesc){ String newPassword = null; boolean customPwdFlag = appDesc.isSetCustomPassword(); if(customPwdFlag){ newPassword = appDesc.getCustomPassword(); }else{ String newPkey = String.valueOf(appId); newPassword = AuthUtil.getAppIdMD5(newPkey); } if(newPassword == null){ newPassword = ""; } return newPassword; } /** * 启动服务 * * @return */ public TaskFlowStatusEnum pushService() { //远程和本地目录 //String instanceRemoteBasePath = machineCenter.getInstanceRemoteBasePath(appId, port, currentInstanceTypeEnum); // String instanceLocalTmpPath = machineCenter.getInstanceLocalTempBasePath(appId, host, port, currentInstanceTypeEnum); //相关参数 // int cpuidx = MachineProtocol.getCpuIdx(port); /*String startCmd = RedisProtocol.getRedisServerStartCmd(); String runCmd = RedisProtocol.getRedisServerRunCmd(port); String serviceShellFileName = RedisProtocol.getServiceShellFileName(currentInstanceTypeEnum); logger.info(marker, "cpuidx is {}", cpuidx); logger.info(marker, "startCmd is {}", startCmd); logger.info(marker, "runCmd is {}", runCmd); return pushService(appId, currentInstanceTypeEnum, host, port, instanceRemoteBasePath, instanceLocalTmpPath, cpuidx, startCmd, runCmd, serviceShellFileName); */ return TaskFlowStatusEnum.SUCCESS; } /** * 启动服务 * * @return */ public TaskFlowStatusEnum startServer() { //资源是否存在 redisConfigTemplateService.checkAndInstallRedisResource(host, redisResource); String redisDir = redisResource == null ? ConstUtils.REDIS_DEFAULT_DIR : ConstUtils.getRedisDir(redisResource.getName()); String runShell; if (isCluster) { runShell = redisDeployCenter.getRedisRunShell(true, host, port, redisDir); } else { runShell = redisDeployCenter.getRedisRunShell(false, host, port, redisDir); } //启动实例 logger.info(marker, "masterShell:host={};shell={}", host, runShell); boolean isMasterShell = machineCenter.startProcessAtPort(host, port, runShell); if (!isMasterShell) { logger.error(marker, "runShell={} error,{}:{}", runShell, host, port); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkIsRun() { //检测是否启动成功前,先休息3秒,否则可能会服务未启动完成,出现不能正确创建socket连接异常 try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { logger.error(e.getMessage(), e); } if (!redisCenter.isRun(host, port, password)) { logger.error(marker, "redis server {}:{} is not run", host, port); return TaskFlowStatusEnum.ABORT; } else { logger.info(marker, "redis server {}:{} is run", host, port); return TaskFlowStatusEnum.SUCCESS; } } /** *

* Description:获取redis config *

* * @author chenshi * @version 1.0 * @date 2019/1/9 */ private List handleCommonConfig(String host, int port, int maxMemory, Integer maxMemoryPolicyType, int versionId, boolean isCluster, List> customConfigs) { try { String maxMemoryPolicy = null; if(maxMemoryPolicyType != null){ AppDescEnum.MaxmemoryPolicyType policyType = AppDescEnum.MaxmemoryPolicyType.getByType(maxMemoryPolicyType); if(policyType != null){ maxMemoryPolicy = policyType.getName(); } } return redisConfigTemplateService.handleRedisConfig(host, port, versionId, maxMemory, maxMemoryPolicy, isCluster, customConfigs, Collections.emptyMap()); } catch (Exception e) { logger.error(marker, e.getMessage(), e); return Collections.emptyList(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/tasks/resource/PackCompileTask.java ================================================ package com.sohu.cache.task.tasks.resource; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.exception.SSHException; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.PushEnum; import com.sohu.cache.task.constant.TaskConstants; import com.sohu.cache.task.constant.TaskStepFlowEnum.TaskFlowStatusEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.enums.SshAuthTypeEnum; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Date; import java.util.List; import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** * Created by chenshi on 2020/7/13. */ @Component("PackCompileTask") @Scope(SCOPE_PROTOTYPE) public class PackCompileTask extends BaseTask { /** * 编译容器ip */ private String containerIp; /** * 资源id */ private Integer resourceId; /** * 仓库id */ private Integer repositoryId; // 操作人 private String username; // 资源包 private SystemResource resource; // 仓库资源 private SystemResource repository; // 编译 private static String COMPILE_SH = " mkdir -p %s && cd %s && " + " wget -O resource.tar.gz %s && tar zxvf resource.tar.gz --strip-component=1 &&" + " rm -f resource.tar.gz && make"; // 备份 private static String BACKUP_SH = "mkdir -p %s && cp -r %s %s "; // 上传 private static String PRIVATEKEY_UPLOAD_SH = "cd %s && tar -cvf %s %s && scp -i %s -oStrictHostKeyChecking=no -r %s %s@%s:%s"; private static String PASSWD_UPLOAD_SH = "cd %s && tar -cvf %s %s && sshpass -p %s scp -oStrictHostKeyChecking=no -r %s %s@%s:%s"; private static String PACKAGE_SUFFIX = "-make.tar.gz"; private static String PRIVATE_KEY = "/opt/cachecloud/ssh/id_rsa"; private static int COMPILE_TIME = 10 * 60 * 1000; @Override public List getTaskSteps() { List taskStepList = new ArrayList(); //1. 参数初始化 taskStepList.add(TaskConstants.INIT_METHOD_KEY); //2. 检查容器ssh环境&私钥文件&gcc taskStepList.add("checkSshEnv"); //3. 远程仓库下载资源包&解压编译 taskStepList.add("compile"); //4. 备份资源 taskStepList.add("bakResource"); //5. 二进制包上传到仓库 taskStepList.add("uploadResource"); //6. 编译完成 taskStepList.add("compileOver"); return taskStepList; } @Override public TaskFlowStatusEnum init() { super.init(); // 1.资源id resourceId = MapUtils.getInteger(paramMap, TaskConstants.RESOURCE_ID); if (resourceId == null) { logger.error(marker, "task {} source machine ip {} is empty", taskId, resourceId); return TaskFlowStatusEnum.ABORT; } // 2.目标宿主机 repositoryId = MapUtils.getInteger(paramMap, TaskConstants.REPOSITORY_ID); if (repositoryId == null) { logger.error(marker, "task {} target machine ip {} is empty", taskId, repositoryId); return TaskFlowStatusEnum.ABORT; } // 3.容器ip containerIp = MapUtils.getString(paramMap, TaskConstants.CONTAINER_IP); if (StringUtils.isEmpty(containerIp)) { logger.error(marker, "task {} container ip {} is empty", taskId, containerIp); return TaskFlowStatusEnum.ABORT; } // 4.操作人/资源/仓库信息 username = MapUtils.getString(paramMap, TaskConstants.USER_INFO_KEY); resource = resourceDao.getResourceById(resourceId); repository = resourceDao.getResourceById(repositoryId); return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum checkSshEnv() { try { //1. 资源状态更新:编译中 if (resource != null) { resource.setIspush(PushEnum.COMPILEING.getValue()); resourceDao.update(resource); } else { logger.error(marker, "resource id:{} is empty,resource {}", resourceId, resource); return TaskFlowStatusEnum.ABORT; } if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PASSWORD.getValue()) { // 2.1 用户名密码 logger.info(marker, "check ssh use username/passwd"); return TaskFlowStatusEnum.SUCCESS; } else if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PUBLIC_KEY.getValue()) { // 2.2 检查私钥文件 String check_cmd = String.format("ls -l %s", PRIVATE_KEY); SSHTemplate.Result result = sshService.executeWithResult(containerIp, check_cmd, COMPILE_TIME); if (result.isSuccess() && !StringUtil.isBlank(result.getResult())) { logger.info(marker, "check private key exists ,cmd:{} result : {}", check_cmd, result); return TaskFlowStatusEnum.SUCCESS; } else { // 下载私钥文件到机器 logger.error(marker, "check private key ,cmd:{} result : {}", check_cmd, result); return TaskFlowStatusEnum.ABORT; } } } catch (Exception e) { return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum compile() { String respositoryUrl = resourceService.getRespositoryUrl(resourceId, repositoryId); //1. 资源编译 String compile_dir = ConstUtils.REDIS_COMPILE_BASE_DIR + resource.getName(); String compile_cmd = String.format(COMPILE_SH, compile_dir, compile_dir, resource.getUrl()); logger.info(marker, "download from url:{}", respositoryUrl); logger.info(marker, "compile cmd : {}", compile_cmd); try { SSHTemplate.Result result = sshService.executeWithResult(containerIp, compile_cmd, COMPILE_TIME); if (result.isSuccess()) { logger.info(marker, "compile cmd:{} result : {}", compile_cmd, result); } else { logger.error(marker, "compile cmd:{} result error: {}", compile_cmd, result.getExcetion()); return TaskFlowStatusEnum.ABORT; } } catch (SSHException e) { logger.error(marker, "compile error :{}", e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum bakResource() { if (repository != null) { try { String resouceFile = repository.getDir() + resource.getDir() + "/" + resource.getName() + PACKAGE_SUFFIX; String bakPath = repository.getDir() + resource.getDir() + "/bak/"; String backupFile = bakPath + resource.getName() + PACKAGE_SUFFIX + "-" + DateUtil.formatYYYYMMddHHMMss(new Date()) + "-" + username; String bakcmd = String.format(BACKUP_SH, bakPath, resouceFile, backupFile); String repository_ip = repository.getName();//远程仓库ip // 源文件如果存在,需要先备份 SSHTemplate.Result existResult = sshService.executeWithResult(repository_ip, String.format("ls -l %s", resouceFile)); logger.info(marker, "resouceFile result:{}", existResult.isSuccess(), existResult); if (existResult.isSuccess() && !StringUtil.isBlank(existResult.getResult())) { SSHTemplate.Result result = sshService.executeWithResult(repository_ip, bakcmd); if (result.isSuccess()) { logger.info(marker, "bakResource success cmd:{} ,result :{}", bakcmd, result.getResult()); } else { logger.error(marker, "bakResource error cmd:{} ,result: {}", bakcmd, result); return TaskFlowStatusEnum.ABORT; } } } catch (SSHException e) { logger.error(marker, "bakResource error :{}", e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } } else { logger.error(marker, "repository id:{} is empty,repository {}", repositoryId, repository); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum uploadResource() { // 1.源资源文件和打包资源文件 String compile_resourceName = ConstUtils.REDIS_COMPILE_BASE_DIR + resource.getName() + PACKAGE_SUFFIX; String upload_path = repository.getDir() + resource.getDir(); // 2.上传文件 String upload_cmd = ""; if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PASSWORD.getValue()) { // 2.1 用户名密码 upload_cmd = String.format(PASSWD_UPLOAD_SH, ConstUtils.REDIS_COMPILE_BASE_DIR, compile_resourceName, resource.getName(), ConstUtils.PASSWORD, compile_resourceName, ConstUtils.USERNAME, repository.getName(), upload_path); } else if (ConstUtils.SSH_AUTH_TYPE == SshAuthTypeEnum.PUBLIC_KEY.getValue()) { upload_cmd = String.format(PRIVATEKEY_UPLOAD_SH, ConstUtils.REDIS_COMPILE_BASE_DIR, compile_resourceName, resource.getName(), PRIVATE_KEY, compile_resourceName, ConstUtils.USERNAME, repository.getName(), upload_path); } try { SSHTemplate.Result result = sshService.executeWithResult(containerIp, upload_cmd, COMPILE_TIME); if (result.isSuccess()) { logger.info(marker, "upload cmd {} success : result:{} ", upload_cmd, result); } else { logger.error(marker, "upload cmd {} fail : result:{} ", upload_cmd, result); } } catch (SSHException e) { logger.error(marker, "uploadResource error :{}", e.getMessage(), e); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } public TaskFlowStatusEnum compileOver() { if (resource != null) { //1.清理远程目录 try { String clear_cmd = String.format("rm -rf %s", ConstUtils.REDIS_COMPILE_BASE_DIR + resource.getName() + "*"); logger.info(marker, "clear resource :" + sshService.executeWithResult(containerIp, clear_cmd)); } catch (SSHException e) { e.printStackTrace(); } //2.更新资源状态 resource.setIspush(PushEnum.YES.getValue()); resource.setLastmodify(new Date()); resource.setUsername(username); resourceDao.update(resource); } else { logger.error(marker, "resource id:{} is empty,resource {}", resourceId, resource); return TaskFlowStatusEnum.ABORT; } return TaskFlowStatusEnum.SUCCESS; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/util/AppWechatUtil.java ================================================ package com.sohu.cache.task.util; import com.sohu.cache.alert.WeChatComponent; import com.sohu.cache.dao.MachineRoomDao; import com.sohu.cache.entity.AppAudit; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.EnvUtil; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserService; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.Set; /** * 微信通知 */ @Component public class AppWechatUtil { private Logger logger = LoggerFactory.getLogger(AppWechatUtil.class); @Autowired(required = false) private WeChatComponent weChatComponent; @Autowired private UserService userService; @Autowired private MachineRoomDao machineRoomDao; @Autowired private AppService appService; @Autowired private AppStatsCenter appStatsCenter; @Autowired private Environment environment; /** * 应用状态通知 * * @param appDesc * @param appAudit */ public void noticeAppResult(AppDesc appDesc, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } try { long userId = appDesc.getUserId(); AppUser appUser = userService.get(userId); long applyUserId = appAudit.getUserId(); AppUser applyAppUser = userService.get(applyUserId); StringBuffer appCreateWeChatContent = new StringBuffer(); appCreateWeChatContent .append(String.format("申请类型: %s \n", appAudit.getTypeDesc())); appCreateWeChatContent.append(String.format("申请描述: %s \n", appAudit.getInfo())); appCreateWeChatContent.append(String.format("申请时间: %s \n", appAudit.getCreateTimeFormat())); appCreateWeChatContent.append(String.format("申请人员: %s \n", applyAppUser.getChName())); appCreateWeChatContent .append(String.format("申请状态: %s \n", appAudit.getStatusDesc())); appCreateWeChatContent.append(String.format("集群名称: %s\n", appDesc.getName())); //appCreateWeChatContent.append(String.format("集群容量: %s GB
", appDesc.getForecastMem())); //appCreateWeChatContent.append(String.format("集群机房: %s(%s)
", machineRoomName, machineLogicName)); if (StringUtils.isNotBlank(appAudit.getRefuseReason())) { appCreateWeChatContent .append(String.format("处理描述: %s \n", appAudit.getRefuseReason())); } Set weChatSet = new HashSet(); //weChatSet.addAll(ConstUtils.getAdminWeChatList()); weChatSet.add(appUser.getName()); weChatSet.add(applyAppUser.getName()); weChatComponent.sendWeChat(ConstUtils.NOTICE_TITLE, appCreateWeChatContent.toString(), new ArrayList(weChatSet)); } catch (Exception e) { logger.error(e.getMessage(), e); } } /** * 集群认领 * * @param appDesc * @param operateUser */ public void noticeAppClaim(AppDesc appDesc, AppUser operateUser) { if (EnvUtil.isDev(environment)) { return; } try { // String machineRoomName = appDesc.getMachineRoom(); // String machineLogicName; // MachineRoom machineRoom = machineRoomDao.getByName(machineRoomName); // if (appDesc.isMemcached()) { // machineLogicName = machineRoomName; // } else { // machineLogicName = machineRoom.getLogicName(); // } StringBuffer appCreateWeChatContent = new StringBuffer(); appCreateWeChatContent.append(String.format("事件类型: %s \n", "集群认领")); appCreateWeChatContent.append(String.format("认领人员: %s
", operateUser.getChName())); appCreateWeChatContent.append(String .format("认领时间: %s \n", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))); appCreateWeChatContent.append(String.format("集群名称: %s \n", appDesc.getName())); //appCreateWeChatContent.append(String.format("集群类型: %s
", appDesc.getDbTypeDesc())); //appCreateWeChatContent.append(String.format("集群机房: %s(%s)
", machineRoomName, machineLogicName)); Set weChatSet = new HashSet(); //weChatSet.addAll(ConstUtils.getAdminWeChatList()); weChatSet.add(operateUser.getName()); weChatComponent.sendWeChat(ConstUtils.NOTICE_TITLE, appCreateWeChatContent.toString(), new ArrayList(weChatSet)); } catch (Exception e) { logger.error(e.getMessage(), e); } } public void noticeRmtSyncFinish(long sourceAppId, long targetAppId) { if (EnvUtil.isDev(environment)) { return; } try { AppDesc sourceAppDesc = appService.getByAppId(sourceAppId); AppDesc targetAppDesc = appService.getByAppId(targetAppId); StringBuffer content = new StringBuffer(); content.append("扩容同步完成\n"); content.append(String.format("源集群 : %s \n", sourceAppDesc.getName())); content.append(String.format("目集群 : %s \n", targetAppDesc.getName())); content.append("可以执行redis.sh --update"); weChatComponent.sendWeChatToAdmin(ConstUtils.NOTICE_TITLE, content.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } public void noticeTaskAbort(long taskId, String stepName) { if (EnvUtil.isDev(environment)) { return; } try { StringBuffer content = new StringBuffer(); content.append(String.format("任务id=%s,stepName=%s中断,请查看", taskId, stepName)); weChatComponent.sendWeChatToAdmin(ConstUtils.NOTICE_TITLE, content.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } public void noticeAppScaleStop(long sourceAppId, long targetAppId) { if (EnvUtil.isDev(environment)) { return; } try { AppDesc sourceAppDesc = appService.getByAppId(sourceAppId); AppDesc targetAppDesc = appService.getByAppId(targetAppId); StringBuffer content = new StringBuffer(); content.append(String.format("集群%s->%s的rmt被强制中断,请查看cc任务日志", sourceAppDesc.getName(), targetAppDesc.getName())); weChatComponent.sendWeChatToAdmin(ConstUtils.NOTICE_TITLE, content.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } public void noticeRmtUseMaster(long sourceAppId, long targetAppId) { if (EnvUtil.isDev(environment)) { return; } try { StringBuffer content = new StringBuffer(); content.append(String.format("集群迁移%s->%s,使用了master做source", sourceAppId, targetAppId)); weChatComponent.sendWeChatToAdmin(ConstUtils.NOTICE_TITLE, content.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } /** * 野生实例 * * @param ip * @param port */ public void noticeWildInstance(String ip, int port) { if (EnvUtil.isDev(environment)) { return; } try { StringBuffer content = new StringBuffer(); content.append(String.format("%s:%s is not in instance_info", ip, port)); weChatComponent.sendWeChatToAdmin(ConstUtils.NOTICE_TITLE, content.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/task/util/SpringContextUtil.java ================================================ package com.sohu.cache.task.util; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextUtil implements ApplicationContextAware { private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public ApplicationContext getApplicationContext() { return applicationContext; } public Object getBeanById(String id) { return applicationContext.getBean(id); } public Object getBeanByClass(Class c) { return applicationContext.getBean(c); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/AppKeyUtil.java ================================================ package com.sohu.cache.util; import org.springframework.util.DigestUtils; import java.nio.charset.Charset; import java.util.Arrays; /** * appkey计算工具 * * @author leifu * @Date 2016-7-9 * @Time 下午9:23:59 */ public class AppKeyUtil { public static String genSecretKey(long appId) { StringBuilder key = new StringBuilder(); // 相关参数 key.append(appId).append(ConstUtils.APP_SECRET_BASE_KEY); // 转成char[] char[] strs = key.toString().toCharArray(); // 排序 Arrays.sort(strs); // md5 return MD5(new String(strs)); } private static String MD5(String s) { return DigestUtils.md5DigestAsHex(s.getBytes(Charset.forName("UTF-8"))); } public static void main(String[] args) { System.out.println(genSecretKey(10010)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/ConstUtils.java ================================================ package com.sohu.cache.util; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.web.enums.SshAuthTypeEnum; import java.util.HashMap; import java.util.List; import java.util.Map; /** * cachecloud常量 */ public class ConstUtils { public static final String NOTICE_TITLE = "【CacheCloud】状态通知"; /** * 应用类型区分 * 2: Redis Cluster * 6: Redis Standalone * 5: Redis+Sentinel * 7: Redis+Twemproxy * 8: Pika+Sentinel * 9: Pika+Twemproxy */ public static final int CACHE_TYPE_REDIS_CLUSTER = 2; public static final int CACHE_REDIS_SENTINEL = 5; public static final int CACHE_REDIS_STANDALONE = 6; public static final int CACHE_REDIS_TWEMPROXY = 7; public static final int CACHE_PIKA_SENTINEL = 8; public static final int CACHE_PIKA_TWEMPROXY = 9; // 数据源名称 public static final String REDIS = "redis"; public static final String MACHINE = "machine"; //mysql收集数据的时间字段 public static final String COLLECT_TIME = "CollectTime"; // 容量转换 public static final int _1024 = 1024; // 表示空字符串 public static final String EMPTY = ""; //SSO clientId public static final String SSO_CLIENT = "clientId"; /** * 服务端版本 */ public static final String CACHECLOUD_VERSION = "3.2.0"; /** * 逗号 */ public static final String COMMA = ","; /** * 换行 */ public static final String NEXT_LINE = "\n"; /** * 空格 */ public static final String SPACE = " "; /** * 冒号 */ public static final String COLON = ":"; /** * 井号 */ public static final String POUND = "#"; /** * 分号 */ public static final String SEMICOLON = ";"; /** * at @ */ public static final String AT = "@"; /** * 内部错误 */ public static final String INNER_ERROR = "cachecloud_inner_error"; /** * 登录跳转参数 */ public final static String RREDIRECT_URL_PARAM = "redirectUrl"; /** * redis默认启动路径 */ public final static String REDIS_DEFAULT_DIR = "/opt/cachecloud/redis"; /** * redis安装基准目录 */ public static final String REDIS_INSTALL_BASE_DIR = "/opt/cachecloud"; public static final String REDIS_COMPILE_BASE_DIR = "/opt/cachecloud/compile/"; /** * pika 安装基准目录,挂载ssd */ public static final String PIKA_INSTALL_BASE_DIR = "/opt/cachecloud/pika"; /** * nutcracker当期版本 */ public static final String DEFAULT_NUTCRACKER_CUR_VERSION = "0.4.1"; /** * redis migrate tool当期版本 */ public static final String DEFAULT_RMT_CUR_VERSION = "1.0"; /** * codis当期版本 */ public static final String DEFAULT_CODIS_CUR_VERSION = "3.2.2"; /** * pika当期版本 */ public static final String DEFAULT_PIKA_CUR_VERSION = "3.0.3"; /** * slave相对于master节点端口增值 */ public static final int SLAVE_PORT_INCREASE = 1000; /** * 机器报警阀值 */ public static final double DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD = 85.0; /** * 机器磁盘报警阀值 */ public static final double DEFAULT_DISK_USAGE_RATIO_THRESHOLD = 70.0; /** * 应用客户端连接数报警阀值 */ public static final int DEFAULT_APP_CLIENT_CONN_THRESHOLD = 2000; /** * 机器统一的用户名、密码、端口 */ public static final String DEFAULT_USERNAME = "cachecloud"; public static final String DEFAULT_PASSWORD = "cachecloud"; public static final String DEFAULT_USER_LOGIN_ENCRY_KEY = "97c9d9de0a2dbd64"; public static final String DEFAULT_USER_PASSWORD = "89750bfb62c09ba4f7dfe8b7e45ca31f"; public static final int DEFAULT_SSH_PORT_DEFAULT = 22; /** * ssh授权方式:参考SshAuthTypeEnum */ public static final int DEFAULT_SSH_AUTH_TYPE = SshAuthTypeEnum.PUBLIC_KEY.getValue(); /** * public key pem */ public static final String DEFAULT_PUBLIC_KEY_PEM = "/opt/ssh/id_rsa"; public static final String DEFAULT_PUBLIC_USERNAME = "cachecloud"; public static final String MEMCACHE_USER = "memcached_server"; public static final String MEMCACHE_KEY_PEM = "/home/redis_server/cachecloud/cachecloud/memcache_server_key/id_rsa"; /** * 管理员相关 */ public static final String DEFAULT_SUPER_ADMIN_NAME = "admin"; public static final String DEFAULT_SUPER_ADMIN_PASS = "admin"; public static final String DEFAULT_SUPER_ADMINS = "admin"; /** * redis-migrate-tool端口 */ public static final int DEFAULT_REDIS_MIGRATE_TOOL_PORT = 8888; /** * redis server基准端口 */ public static final int DEFAULT_REDIS_SERVER_BASE_PORT = 6400; /** * redis sentinel基准端口 */ public static final int DEFAULT_REDIS_SENTINEL_BASE_PORT = 26379; /** * 1是session,2是cookie(参考UserLoginTypeEnum) */ public static final int DEFAULT_USER_LOGIN_TYPE = 2; /** * cachecloud根目录,这个要与cachecloud-init.sh脚本中的目录一致 */ public static final String DEFAULT_CACHECLOUD_BASE_DIR = "/opt"; /** * 是否定期清理各种统计数据:(详见CleanUpStatisticsJob) */ public static final boolean DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA = true; /** * appkey秘钥 */ public static final String DEFAULT_APP_SECRET_BASE_KEY = "cachecloud-2014"; /** * 机器性能统计周期(分钟) */ public static final int DEFAULT_MACHINE_STATS_CRON_MINUTE = 1; //应用自动扩容与内存审计(判断是否可缩容)相关 start /** * 后台自动处理用户 */ public static final long DEFAULT_BOT_USER_ID = 0; public static long BOT_USER_ID = ConstUtils.DEFAULT_BOT_USER_ID; /** * 自动扩容最大允许分片内存大小 */ public static final long DEFAULT_REDIS_EXPAND_CAPACITY_LIMIT = 8L * 1024 * 1024 * 1024; public static long REDIS_EXPAND_CAPACITY_LIMIT = ConstUtils.DEFAULT_REDIS_EXPAND_CAPACITY_LIMIT; /** * 应用上线多少天之后,可判断缩容 */ public static final int DEFAULT_REDIS_REDUCE_CAPACITY_BUFFER_TIME = 15; public static int REDIS_REDUCE_CAPACITY_BUFFER_TIME = ConstUtils.DEFAULT_REDIS_REDUCE_CAPACITY_BUFFER_TIME; /** * 应用缩容预计处理时间 */ public static final int DEFAULT_REDIS_REDUCE_CAPACITY_SCHEDULE_TIME = 15; public static int REDIS_REDUCE_CAPACITY_SCHEDULE_TIME = ConstUtils.DEFAULT_REDIS_REDUCE_CAPACITY_SCHEDULE_TIME; /** * 应用缩容审计告警,是否发送应用负责人 */ public static final boolean DEFAULT_REDIS_REDUCE_CAPACITY_SENDMAIL = false; public static boolean REDIS_REDUCE_CAPACITY_SENDMAIL = ConstUtils.DEFAULT_REDIS_REDUCE_CAPACITY_SENDMAIL; /** * 应用扩容告警,是否发送应用负责人 */ public static final boolean DEFAULT_REDIS_EXPAND_CAPACITY_SENDMAIL = false; public static boolean REDIS_EXPAND_CAPACITY_SENDMAIL = ConstUtils.DEFAULT_REDIS_EXPAND_CAPACITY_SENDMAIL; /** * 应用内存使用近几天最大值,用于判断是否有峰值 */ public static final int DEFAULT_REDIS_MEM_USED_MAX_DAYS = 3; public static int REDIS_MEM_USED_MAX_DAYS = ConstUtils.DEFAULT_REDIS_MEM_USED_MAX_DAYS; /** * 分片内存缩容最小值(低于不可缩容) */ public static final long DEFAULT_REDIS_REDUCE_CAPACITY_SHARDING_MEM = 125L * 1024 * 1024 * 1024 / 1000 ; public static long REDIS_REDUCE_CAPACITY_SHARDING_MEM = ConstUtils.DEFAULT_REDIS_REDUCE_CAPACITY_SHARDING_MEM ; /** * 分片内存缩容——报警内存最小缩容容量 */ public static final long DEFAULT_REDIS_REDUCE_CAPACITY_MEM_MIN = 5L * 1024 * 1024 * 1024 / 10; public static long REDIS_REDUCE_CAPACITY_MEM_MIN = ConstUtils.DEFAULT_REDIS_REDUCE_CAPACITY_MEM_MIN; /** * 分片内存扩容步长 */ public static final long DEFAULT_REDIS_EXPAND_CAPACITY_STEP = 125L * 1024 * 1024 * 1024 / 1000 ; public static long REDIS_EXPAND_CAPACITY_STEP = ConstUtils.DEFAULT_REDIS_EXPAND_CAPACITY_STEP ; /** * 应用内存扩容AppAutoCapacityServiceImpl.ExpandConfig */ public static final String DEFAULT_REDIS_EXPAND_CAPACITY_CONFIG = "0,3,0,85,20,1000;3,5,10,85,20,200;5,10,10,85,15,200;10,20,10,85,10,150;20,40,5,90,10,50;40,80,5,95,5,30;80,120,3,95,5,20;120,1000,1,95,0,0"; public static String REDIS_EXPAND_CAPACITY_CONFIG = ConstUtils.DEFAULT_REDIS_EXPAND_CAPACITY_CONFIG; /** * 应用内存扩容开关 */ public static final boolean DEFAULT_REDIS_EXPAND_CAPACITY_OPEN_FLAG = false; public static boolean REDIS_EXPAND_CAPACITY_OPEN_FLAG = ConstUtils.DEFAULT_REDIS_EXPAND_CAPACITY_OPEN_FLAG; //应用自动扩容与内存审计(判断是否可缩容)相关 end /** * rdb文件物理机存储路径 */ public static final String DEFAULT_RDB_MACHINE_DIR = "/data/redis/data/"; public static String RDB_MACHINE_DIR = ConstUtils.DEFAULT_RDB_MACHINE_DIR; /** * redis 版本 */ public static Map REDIS_RESOURCE = new HashMap<>(); /** * 应用持久化主从特殊配置 */ public static final String DEFAULT_APP_PERSISTENCE_CONFIG_MAP = "[" + "{" + "\"isMaster\":\"true\"," + "\"persistenceMap\":{" + "\"0\":{" + "\"appendonly\":\"yes\"," + "\"appendfsync\":\"everysec\"" + "}," + "\"1\":{" + "\"appendonly\":\"yes\"," + "\"appendfsync\":\"no\"" + "}," + "\"2\":{" + "\"appendonly\":\"no\"" + "}," + "\"3\":{" + "\"appendonly\":\"no\"" + "}" + "}" + "}," + "{" + "\"isMaster\":\"false\"," + "\"persistenceMap\":{" + "\"0\":{" + "\"appendonly\":\"yes\"," + "\"appendfsync\":\"everysec\"" + "}," + "\"1\":{" + "\"appendonly\":\"yes\"," + "\"appendfsync\":\"everysec\"" + "}," + "\"2\":{" + "\"appendonly\":\"yes\"," + "\"appendfsync\":\"everysec\"" + "}," + "\"3\":{" + "\"appendonly\":\"no\"" + "}" + "}" + "}" + "]"; public static String APP_PERSISTENCE_CONFIG_MAP = ConstUtils.DEFAULT_APP_PERSISTENCE_CONFIG_MAP; /** * big key阈值 */ public static final int DEFAULT_STRING_MAX_LENGTH = 100 * 1024; public static final int DEFAULT_HASH_MAX_LENGTH = 50000; public static final int DEFAULT_LIST_MAX_LENGTH = 50000; public static final int DEFAULT_SET_MAX_LENGTH = 50000; public static final int DEFAULT_ZSET_MAX_LENGTH = 50000; public static double MEMORY_USAGE_RATIO_THRESHOLD = DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD; public static double DISK_USAGE_RATIO_THRESHOLD = DEFAULT_DISK_USAGE_RATIO_THRESHOLD; public static int APP_CLIENT_CONN_THRESHOLD = DEFAULT_APP_CLIENT_CONN_THRESHOLD; public static String USERNAME = DEFAULT_USERNAME; public static String PASSWORD = DEFAULT_PASSWORD; public static int SSH_PORT_DEFAULT = DEFAULT_SSH_PORT_DEFAULT; public static int SSH_AUTH_TYPE = DEFAULT_SSH_AUTH_TYPE; public static int SSH_CONNECTION_TIMEOUT = 5000; public static String PUBLIC_KEY_PEM = DEFAULT_PUBLIC_KEY_PEM; public static String PUBLIC_USERNAME = DEFAULT_PUBLIC_USERNAME; public static String SUPER_ADMIN_NAME = DEFAULT_SUPER_ADMIN_NAME; public static String SUPER_ADMIN_PASS = DEFAULT_SUPER_ADMIN_PASS; public static String SUPER_ADMINS = DEFAULT_SUPER_ADMINS; public static String USER_LOGIN_ENCRY_KEY = DEFAULT_USER_LOGIN_ENCRY_KEY; public static List SUPER_MANAGER; /** * 联系人 */ public static String CONTACT; /** * redis-migrate-tool相关路径 */ public static String REDIS_MIGRATE_TOOL_HOME; /** * redis-shake相关路径 */ public static String REDIS_SHAKE_HOME; /** * redis-full-check相关 */ public static String REDIS_FULL_CHECK_HOME; public static int REDIS_MIGRATE_TOOL_PORT = DEFAULT_REDIS_MIGRATE_TOOL_PORT; public static int REDIS_SERVER_BASE_PORT = DEFAULT_REDIS_SERVER_BASE_PORT; public static int REDIS_SENTINEL_BASE_PORT = DEFAULT_REDIS_SENTINEL_BASE_PORT; public static int USER_LOGIN_TYPE = DEFAULT_USER_LOGIN_TYPE; /** * cookie登录方式所需要的域 */ public static String CACHECLOUD_BASE_DIR = DEFAULT_CACHECLOUD_BASE_DIR; public static boolean WHETHER_SCHEDULE_CLEAN_DATA = DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA; public static String APP_SECRET_BASE_KEY = DEFAULT_APP_SECRET_BASE_KEY; public static int MACHINE_STATS_CRON_MINUTE = DEFAULT_MACHINE_STATS_CRON_MINUTE; /** * 领导邮件 */ public static List LEADER_EMAIL_LIST; public static String NUTCRACKER_CUR_VERSION = DEFAULT_NUTCRACKER_CUR_VERSION; public static String RMT_CUR_VERSION = DEFAULT_RMT_CUR_VERSION; public static String CODIS_CUR_VERSION = DEFAULT_CODIS_CUR_VERSION; public static String PIKA_CUR_VERSION = DEFAULT_PIKA_CUR_VERSION; /** * 内部redis配置 */ public static volatile String CACHECLOUD_INTERNAL_REDIS_SENTINELS = ""; public static volatile String CACHECLOUD_INTERNAL_REDIS_MASTERNAME = ""; public static volatile String CACHECLOUD_INTERNAL_REDIS_PASSWORD = ""; public static int STRING_MAX_LENGTH = DEFAULT_STRING_MAX_LENGTH; public static int HASH_MAX_LENGTH = DEFAULT_HASH_MAX_LENGTH; public static int LIST_MAX_LENGTH = DEFAULT_LIST_MAX_LENGTH; public static int SET_MAX_LENGTH = DEFAULT_SET_MAX_LENGTH; public static int ZSET_MAX_LENGTH = DEFAULT_ZSET_MAX_LENGTH; public static String getRedisMigrateToolCmd(String name) { return ConstUtils.getRedisToolDir(name) + "src/redis-migrate-tool"; } public static String getRedisShakeStartCmd() { return "sh " + REDIS_SHAKE_HOME + "start.sh"; } public static String getRedisShakeLinuxCmd(String name) { return ConstUtils.getRedisToolDir(name) + "redis-shake.linux"; } public static String getRedisShakeStopCmd() { return "sh " + REDIS_SHAKE_HOME + "stop.sh"; } public static String getRedisFullCheckDir() { return REDIS_FULL_CHECK_HOME; } public static String getRedisFullCheckResultDir() { return REDIS_FULL_CHECK_HOME + "data/"; } public static String getRedisFullCheckMetricDir() { return REDIS_FULL_CHECK_HOME + "metric/"; } public static String getRedisFullCheckLogDir() { return REDIS_FULL_CHECK_HOME + "logs/"; } public static String getRedisFullCheckCmd() { return REDIS_FULL_CHECK_HOME + "redis-full-check"; } public static String getRedisMigrateToolDir() { return REDIS_MIGRATE_TOOL_HOME + "data/"; } public static String getRedisShakeDir() { return REDIS_SHAKE_HOME; } public static String getRedisShakePidDir(String name) { return ConstUtils.getRedisToolDir(name) + "pid/"; } public static String getRedisShakeLogsDir(String name) { return ConstUtils.getRedisToolDir(name) + "logs/"; } public static String getRedisShakeConfDir(String name) { return ConstUtils.getRedisToolDir(name) + "conf/"; } public static String getRedisShakeHttpPort() { return "9320"; } /** * 空闲key * * @param appId * @param auditId * @return */ public static String getRedisServerIdleKey(long appId, long auditId) { return String.format("cc:key:idle:%s:%s", appId, auditId); } /** * key类型 * * @param appId * @param auditId * @return */ public static String getRedisServerTypeKey(long appId, long auditId) { return String.format("cc:key:type:%s:%s", appId, auditId); } /** * key ttl * * @param appId * @param auditId * @return */ public static String getRedisServerTtlKey(long appId, long auditId) { return String.format("cc:key:ttl:%s:%s", appId, auditId); } /** * value size * * @param appId * @param auditId * @return */ public static String getRedisServerValueSizeKey(long appId, long auditId) { return String.format("cc:key:valueSize:%s:%s", appId, auditId); } /** * 生成taskflowId * * @param taskFlowId * @return */ public static String getTaskFlowRedisKey(String taskFlowId) { return "cc:taskflow:" + taskFlowId; } public static String getInstanceScanKey(long taskId, String hostPort) { return String.format("cc:key:scan:%s:%s", taskId, hostPort); } public static String getInstanceDelKey(long taskId, String hostPort) { return String.format("cc:key:del:%s:%s", taskId, hostPort); } public static String getInstanceBigKey(long taskId, String hostPort) { return String.format("cc:key:bigkey:%s:%s", taskId, hostPort); } public static String getInstanceIdleKey(long taskId, String hostPort) { return String.format("cc:key:idlekey:%s:%s", taskId, hostPort); } public static String getInstanceHotKey(long taskId, String hostPort) { return String.format("cc:key:hotkey:%s:%s", taskId, hostPort); } public static String getInstanceSlotAnalysis(long taskId, String hostPort) { return String.format("cc:key:slotAnalysis:%s:%s", taskId, hostPort); } public static String getInstanceScanClean(long taskId, String hostPort) { return String.format("cc:key:scanClean:%s:%s", taskId, hostPort); } public static String getScanClean(long taskId) { return String.format("cc:key:scanClean:%s", taskId); } public static String getRedisDir(String versionName){ return String.format("%s/%s", REDIS_INSTALL_BASE_DIR, versionName); } public static String getRedisToolDir(String versionName){ return String.format("%s/%s/", REDIS_INSTALL_BASE_DIR, versionName); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/DemoCodeUtil.java ================================================ package com.sohu.cache.util; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * Created by hym */ public class DemoCodeUtil { public static final List redisCluster; public static final List redisSentinel; public static final List redisStandalone; public static final List redisSentinelSpring; public static final List redisClusterSpring; private static final String springAppId = "${your appId}"; static { List tmpRedisCluster = new ArrayList<>(); tmpRedisCluster.add("PipelineCluster redisCluster = null; "); tmpRedisCluster.add("// 使用默认配置 "); tmpRedisCluster.add("//redisCluster = ClientBuilder.redisCluster(appId).build(); "); tmpRedisCluster.add("/** "); tmpRedisCluster.add(" * 使用自定义配置: "); tmpRedisCluster.add(" * 1. setTimeout:redis操作的超时设置,默认2000毫秒。 "); tmpRedisCluster.add(" * 2. setMaxRedirections:节点重定向的最大次数,不建议修改。 "); tmpRedisCluster.add(" */ "); tmpRedisCluster.add("JedisPoolConfig poolConfig = new JedisPoolConfig(); "); tmpRedisCluster.add("redisCluster = ClientBuilder.redisCluster(appId) "); tmpRedisCluster.add("    .setJedisPoolConfig(poolConfig) "); tmpRedisCluster.add("    .setTimeout(Protocol.DEFAULT_TIMEOUT) "); tmpRedisCluster.add("    .setMaxRedirections(5) "); tmpRedisCluster.add("    .build(); "); tmpRedisCluster.add("//1.字符串value"); tmpRedisCluster.add("redisCluster.set(\"key1\", \"value1\"); "); tmpRedisCluster.add("assertEquals(\"value1\", redisCluster.get(\"key1\")); "); tmpRedisCluster.add("//2.实体型value"); tmpRedisCluster.add("//高效的序列化工具(spring中要配置成单例)"); tmpRedisCluster.add("ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();"); tmpRedisCluster.add("long vid = 120;"); tmpRedisCluster.add("String videoName = \"屌丝男士\";"); tmpRedisCluster.add("String videoKey = \"video:\" + vid;"); tmpRedisCluster.add("//long vid; String videoName"); tmpRedisCluster.add("Video video = new Video(vid, videoName);"); tmpRedisCluster.add("redisCluster.set(videoKey, protostuffSerializer.serialize(video));"); tmpRedisCluster.add("byte[] resultBytes = redisCluster.getBytes(videoKey);"); tmpRedisCluster.add("// 反序列化获取结果"); tmpRedisCluster.add("Video resultVideo = protostuffSerializer.deserialize(resultBytes);"); tmpRedisCluster.add("assertEquals(videoName, resultVideo.getName());"); redisCluster = Collections.unmodifiableList(tmpRedisCluster); List tmpRedisSentinel = new ArrayList<>(); tmpRedisSentinel.add("JedisSentinelPool sentinelPool = null; "); tmpRedisSentinel.add("// 使用默认配置 "); tmpRedisSentinel.add("//sentinelPool = ClientBuilder.redisSentinel(appId).build(); "); tmpRedisSentinel.add("/** "); tmpRedisSentinel.add(" * 自定义配置:setTimeout 连接和操作超时时间,默认2000毫秒。 "); tmpRedisSentinel.add(" */ "); tmpRedisSentinel.add("JedisPoolConfig poolConfig = new JedisPoolConfig(); "); tmpRedisSentinel.add("sentinelPool = ClientBuilder.redisSentinel(appId) "); tmpRedisSentinel.add("    .setTimeout(Protocol.DEFAULT_TIMEOUT) "); tmpRedisSentinel.add("    .setPoolConfig(poolConfig) "); tmpRedisSentinel.add("    .build(); "); tmpRedisSentinel.add("Jedis jedis = null; "); tmpRedisSentinel.add("try { "); tmpRedisSentinel.add("    jedis = sentinelPool.getResource(); "); tmpRedisSentinel.add("    //1.字符串value "); tmpRedisSentinel.add("    jedis.set(\"key1\", \"1\"); "); tmpRedisSentinel.add("    "); tmpRedisSentinel.add("    //2.实体型value"); tmpRedisSentinel.add("    //高效的序列化工具(spring中要配置成单例),已经内置在cachecloud的客户端中直接引入即可."); tmpRedisSentinel.add("    ProtostuffSerializer protostuffSerializer = new ProtostuffSerializer();"); tmpRedisSentinel.add("    long vid = 120;"); tmpRedisSentinel.add("    String videoName = \"屌丝男士\";"); tmpRedisSentinel.add("    String videoKey = \"video:\" + vid;"); tmpRedisSentinel.add("    //long vid; String videoName"); tmpRedisSentinel.add("    Video video = new Video(vid, videoName);"); tmpRedisSentinel.add("    jedis.set(videoKey.getBytes(), protostuffSerializer.serialize(video));"); tmpRedisSentinel.add("    byte[] resultBytes = jedis.get(videoKey.getBytes());"); tmpRedisSentinel.add("    //反序列化获取结果"); tmpRedisSentinel.add("    Video resultVideo = protostuffSerializer.deserialize(resultBytes);"); tmpRedisSentinel.add("    assertEquals(videoName, resultVideo.getName());"); tmpRedisSentinel.add("} catch (Exception e) { "); tmpRedisSentinel.add("    logger.error(e.getMessage(), e); "); tmpRedisSentinel.add("} finally { "); tmpRedisSentinel.add("    if(jedis!=null) "); tmpRedisSentinel.add("      jedis.close(); "); tmpRedisSentinel.add("} "); redisSentinel = Collections.unmodifiableList(tmpRedisSentinel); List tmpRedisStandalone = new ArrayList<>(); tmpRedisStandalone.add("JedisPool jedisPool = null; "); tmpRedisStandalone.add("// 使用默认配置 "); tmpRedisStandalone.add("//jedisPool = ClientBuilder.redisStandalone(appId).build(); "); tmpRedisStandalone.add("/** "); tmpRedisStandalone.add(" * 自定义配置:setTimeout 连接和操作超时时间,默认2000毫秒。 "); tmpRedisStandalone.add(" */ "); tmpRedisStandalone.add("JedisPoolConfig poolConfig = new JedisPoolConfig(); "); tmpRedisStandalone.add("poolConfig.setMaxWaitMillis(Protocol.DEFAULT_TIMEOUT); "); tmpRedisStandalone.add("jedisPool = ClientBuilder.redisStandalone(appId) "); tmpRedisStandalone.add("    .setTimeout(Protocol.DEFAULT_TIMEOUT) "); tmpRedisStandalone.add("    .setPoolConfig(poolConfig) "); tmpRedisStandalone.add("    .build(); "); tmpRedisStandalone.add("Jedis jedis = jedisPool.getResource(); "); tmpRedisStandalone.add("jedis.setnx(\"key2\", \"5\"); "); tmpRedisStandalone.add("assertEquals(\"10\", jedis.incrBy(\"key2\", 5)); "); tmpRedisStandalone.add("jedis.close(); "); redisStandalone = Collections.unmodifiableList(tmpRedisStandalone); //redis-sentinel的spring配置 List tmpRedisSentinelSpring = new ArrayList<>(); tmpRedisSentinelSpring.add("//spring 配置"); tmpRedisSentinelSpring.add("<bean id=\"redisSentinelFactory\" class=\"com.sohu.tv.mobil.common.data.RedisSentinelFactory\" init-method=\"init\">"); tmpRedisSentinelSpring.add("    <property name=\"appId\" value=\"" + springAppId + "\"/>"); tmpRedisSentinelSpring.add("</bean>"); tmpRedisSentinelSpring.add("<bean id=\"redisSentinelPool\" factory-bean=\"redisSentinelFactory\" factory-method=\"getJedisSentinelPool\"/>"); tmpRedisSentinelSpring.add("<!--高效的序列化工具--/>"); tmpRedisSentinelSpring.add("<bean id=\"protostuffSerializer\" class=\"redis.clients.jedis.serializable.ProtostuffSerializer\"/>"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("package xx.xx;"); tmpRedisSentinelSpring.add("import com.sohu.tv.builder.ClientBuilder;"); tmpRedisSentinelSpring.add("import redis.clients.jedis.JedisPoolConfig;"); tmpRedisSentinelSpring.add("import org.slf4j.Logger;"); tmpRedisSentinelSpring.add("import org.slf4j.LoggerFactory;"); tmpRedisSentinelSpring.add("import redis.clients.jedis.JedisSentinelPool;"); tmpRedisSentinelSpring.add("import redis.clients.jedis.Protocol;"); tmpRedisSentinelSpring.add("public class RedisSentinelFactory {"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    private final Logger logger = LoggerFactory.getLogger(this.getClass());"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    private JedisSentinelPool jedisSentinelPool;"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    private int appId;"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    public void init(){"); tmpRedisSentinelSpring.add("        //根据自己需要设置poolConfig"); tmpRedisSentinelSpring.add("        JedisPoolConfig poolConfig = new JedisPoolConfig();"); tmpRedisSentinelSpring.add("        poolConfig.setMaxWaitMillis(Protocol.DEFAULT_TIMEOUT);"); tmpRedisSentinelSpring.add("        try {"); tmpRedisSentinelSpring.add("            //根据自己需要设置超时时间"); tmpRedisSentinelSpring.add("            jedisSentinelPool = ClientBuilder.redisSentinel(appId)"); tmpRedisSentinelSpring.add("                .setPoolConfig(poolConfig)"); tmpRedisSentinelSpring.add("                .build();"); tmpRedisSentinelSpring.add("        } catch (Exception e) {"); tmpRedisSentinelSpring.add("            logger.error(e.getMessage(), e);"); tmpRedisSentinelSpring.add("        }"); tmpRedisSentinelSpring.add("    }"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    public JedisSentinelPool getJedisSentinelPool() {"); tmpRedisSentinelSpring.add("        return jedisSentinelPool;"); tmpRedisSentinelSpring.add("    }"); tmpRedisSentinelSpring.add(""); tmpRedisSentinelSpring.add("    public void setAppId(int appId) {"); tmpRedisSentinelSpring.add("        this.appId = appId;"); tmpRedisSentinelSpring.add("    }"); tmpRedisSentinelSpring.add("}"); redisSentinelSpring = Collections.unmodifiableList(tmpRedisSentinelSpring); // redis-cluster的spring配置 List tmpRedisClusterSpring = new ArrayList<>(); tmpRedisClusterSpring.add("//spring 配置"); tmpRedisClusterSpring.add("<bean id=\"redisClusterFactory\" class=\"xx.xx.RedisClusterFactory\" init-method=\"init\">"); tmpRedisClusterSpring.add("    <property name=\"appId\" value=\"" + springAppId + "\"/>"); tmpRedisClusterSpring.add("</bean>"); tmpRedisClusterSpring.add("<bean id=\"redisCluster\" factory-bean=\"redisClusterFactory\" factory-method=\"getRedisCluster\"/>"); tmpRedisClusterSpring.add("<!--高效的序列化工具--/>"); tmpRedisClusterSpring.add("<bean id=\"protostuffSerializer\" class=\"redis.clients.jedis.serializable.ProtostuffSerializer\"/>"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("package xx.xx;"); tmpRedisClusterSpring.add("import com.sohu.tv.builder.ClientBuilder;"); tmpRedisClusterSpring.add("import redis.clients.jedis.JedisPoolConfig;"); tmpRedisClusterSpring.add("import org.slf4j.Logger;"); tmpRedisClusterSpring.add("import org.slf4j.LoggerFactory;"); tmpRedisClusterSpring.add("import redis.clients.jedis.PipelineCluster;"); tmpRedisClusterSpring.add("import redis.clients.jedis.Protocol;"); tmpRedisClusterSpring.add("public class RedisClusterFactory {"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    private final Logger logger = LoggerFactory.getLogger(this.getClass());"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    private PipelineCluster redisCluster;"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    private int appId;"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    public void init() {"); tmpRedisClusterSpring.add("        //根据自己需要设置poolConfig"); tmpRedisClusterSpring.add("        JedisPoolConfig poolConfig = new JedisPoolConfig();"); tmpRedisClusterSpring.add("        poolConfig.setMaxWaitMillis(Protocol.DEFAULT_TIMEOUT);"); tmpRedisClusterSpring.add("        try {"); tmpRedisClusterSpring.add("            //根据自己需要修改参数"); tmpRedisClusterSpring.add("            redisCluster = ClientBuilder.redisCluster(appId)"); tmpRedisClusterSpring.add("                .setJedisPoolConfig(poolConfig)"); tmpRedisClusterSpring.add("                .build();"); tmpRedisClusterSpring.add("        } catch (Exception e) {"); tmpRedisClusterSpring.add("            logger.error(e.getMessage(), e);"); tmpRedisClusterSpring.add("        }"); tmpRedisClusterSpring.add("    }"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    public PipelineCluster getRedisCluster() {"); tmpRedisClusterSpring.add("        return redisCluster;"); tmpRedisClusterSpring.add("    }"); tmpRedisClusterSpring.add(""); tmpRedisClusterSpring.add("    public void setAppId(int appId) {"); tmpRedisClusterSpring.add("        this.appId = appId;"); tmpRedisClusterSpring.add("    }"); tmpRedisClusterSpring.add("}"); redisClusterSpring = Collections.unmodifiableList(tmpRedisClusterSpring); } /** * 获取依赖 * * @return */ public static List getDependencyRedis() { List dependencyRedis = new ArrayList(); // 依赖 dependencyRedis.add("<dependency> "); dependencyRedis.add("    <groupId>com.sohu.tv</groupId> "); dependencyRedis.add("    <artifactId>cachecloud-client-redis</artifactId> "); dependencyRedis.add("</dependency> "); dependencyRedis.add("<repositories> "); dependencyRedis.add("    <repository> "); dependencyRedis.add("        <id>sohu.nexus</id> "); dependencyRedis.add("    </repository> "); dependencyRedis.add("</repositories> "); return dependencyRedis; } public static List getCode(int appType, long appId) { List list = null; switch (appType) { case ConstUtils.CACHE_REDIS_SENTINEL: { list = new ArrayList(redisSentinel); break; } case ConstUtils.CACHE_REDIS_STANDALONE: { list = new ArrayList(redisStandalone); break; } case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: { list = new ArrayList(redisCluster); break; } default: break; } if (list != null && list.size() > 0) { if (!list.get(0).contains("appId =")) { list.add(0, "long appId = " + appId + ";"); } } return list; } public static List getSpringConfig(int appType, long appId) { List list = new ArrayList(); switch (appType) { case ConstUtils.CACHE_REDIS_SENTINEL: { list.addAll(redisSentinelSpring); break; } case ConstUtils.CACHE_REDIS_STANDALONE: { break; } case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: { list.addAll(redisClusterSpring); break; } default: break; } if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { String line = list.get(i); if (line != null && line.contains(springAppId)) { line = line.replace(springAppId, String.valueOf(appId)); list.set(i, line); } } } return list; } public static String getRestAPI(int appType, long appId) { String appTypePath = ""; switch (appType) { case ConstUtils.CACHE_REDIS_SENTINEL: { appTypePath = "sentinel"; break; } case ConstUtils.CACHE_REDIS_STANDALONE: { appTypePath = "standalone"; break; } case ConstUtils.CACHE_TYPE_REDIS_CLUSTER: { appTypePath = "cluster"; break; } default: break; } return "http://${domain}/cache/client/redis/" + appTypePath + "/" + appId + ".json"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/EnvUtil.java ================================================ package com.sohu.cache.util; import com.google.common.collect.Sets; import org.springframework.core.env.Environment; import java.util.Set; /** * Created by yijunzhang */ public class EnvUtil { public static Set getProfiles(Environment environment) { return Sets.newHashSet(environment.getActiveProfiles()); } public static boolean isOnline(Environment environment) { return getProfiles(environment).contains("online"); } public static boolean isDev(Environment environment) { Set profiles = getProfiles(environment); return profiles.contains("test") || profiles.contains("test-sohu") || profiles.contains("local") || profiles.contains("local-sohu"); } public static boolean isLocal(Environment environment) { Set profiles = getProfiles(environment); return profiles.contains("local") || profiles.contains("local-sohu"); } public static boolean isTest(Environment environment) { Set profiles = getProfiles(environment); return profiles.contains("test") || profiles.contains("test-sohu"); } public static boolean isOpen(Environment environment) { Set profiles = getProfiles(environment); return profiles.contains("open") || profiles.contains("open-sohu"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/IdempotentConfirmer.java ================================================ package com.sohu.cache.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 幂等操作器 * Created by yijunzhang on 14-10-22. */ public abstract class IdempotentConfirmer { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private int retry = 3; protected IdempotentConfirmer(int retry) { this.retry = retry; } public IdempotentConfirmer() { } public abstract boolean execute(); public boolean run() { while (retry-- > 0) { try { boolean isOk = execute(); if (isOk){ return true; } } catch (Exception e) { logger.error(e.getMessage(), e); continue; } } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/IntegerUtil.java ================================================ package com.sohu.cache.util; /** * Integer 工具类 * * @author 银时:yinshi.nc / yinshi.nc@taobao.com * @Date Jan 13, 2012 */ public class IntegerUtil { /** * 如果为0,则返回默认值 * * @param originalInt * @param defaultInt * 默认Integer * @return */ public static Integer defaultIfZero( Integer originalInt, Integer defaultInt ) { if ( 0 == originalInt ) { return defaultInt; } return originalInt; } /** * 如果为0,则返回默认值 * * @param originalInt * @param defaultInt * 默认Integer * @return */ public static Integer defaultIfError( String originalStr, Integer defaultInt ) { try { return Integer.parseInt( StringUtil.trimToEmpty( originalStr ) ); } catch ( Exception e ) { return defaultInt; } } /** * 如果是一个不合法的整型,那么返回一个默认值 * * @param originalInt * @param defaultInt * 默认Integer * @return */ public static Integer defaultIfError( Integer originalStr, Integer defaultInt ) { try { return originalStr; } catch ( Exception e ) { return defaultInt; } } /** * 如果非正,则返回默认值
* @param originalInt * @param defaultInt * 默认Integer * @return originalInt if originalInt>0, return defaultInt if originalInt<=0 */ public static Integer defaultIfSmallerThan0( Integer originalInt, Integer defaultInt ) { if ( 0 >= originalInt ) { return defaultInt; } return originalInt; } /** 将String 转化成 Integer,如果小于等于0,将抛异常 */ public static Integer exceptionIfSmallerThan0( String originalStr )throws Exception{ try { int num = Integer.parseInt( StringUtil.trimToEmpty( originalStr ) ); if( num > 0 ) return num; else throw new Exception(); } catch ( Exception e ) { throw new Exception( originalStr + " is smaller than 0, or it is a invalid parameter " ); } } /** * 判断是否大余0 * @return false if num <=0 , true if num >0 */ public static boolean isBiggerThan0( int num ){ if( 0>= num ) return false; return true; } /** * Return maxInt if too big, else return original. * * @param originalInt * @param maxInt * max int * @return */ public static Integer maxIfTooBig( Integer originalInt, Integer maxInt ) { if ( originalInt >= maxInt ) { originalInt = maxInt; } return originalInt; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/JsonUtil.java ================================================ package com.sohu.cache.util; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; /** * jackson转换工具 * @author leifu * @Date 2016年3月23日 * @Time 上午10:47:57 */ public class JsonUtil { private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class); // 采用jackson private static ObjectMapper mapper = new ObjectMapper(); /** * 将对象转换为json * * @param entity * @return */ public static String toJson(Object entity) { if (entity == null) { return null; } try { return mapper.writeValueAsString(entity); } catch (IOException e) { logger.error("parse entity=" + entity + " to json error!", e); } return null; } /** * 从json解析出对象 * * @param * @param content * @param valueType * @return */ public static T fromJson(String content, Class valueType) { if (content == null) { return null; } try { return mapper.readValue(content, valueType); } catch (IOException e) { logger.error("parse content=" + content + " error!", e); } return null; } private static ObjectMapper getObjectMapper() { return mapper; } public static ObjectNode createObjectNode() { return getObjectMapper().createObjectNode(); } public static ArrayNode createArrayNode() { return getObjectMapper().createArrayNode(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/MD5Util.java ================================================ package com.sohu.cache.util; import java.security.MessageDigest; /** * @Author: zengyizhao * @DateTime: 2022/1/26 12:05 * @Description: */ public class MD5Util { /** * @Description: MD5加码 生成32位md5码 * @Author: caoru * @CreateDate: 2018/8/9 14:21 */ public static String string2MD5(String inStr){ MessageDigest md5 = null; try{ md5 = MessageDigest.getInstance("MD5"); }catch (Exception e){ System.out.println(e.toString()); e.printStackTrace(); return ""; } char[] charArray = inStr.toCharArray(); byte[] byteArray = new byte[charArray.length]; for (int i = 0; i < charArray.length; i++) byteArray[i] = (byte) charArray[i]; byte[] md5Bytes = md5.digest(byteArray); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++){ int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } return hexValue.toString(); } /** * @Description: 加密解密算法 执行一次加密,两次解密 * @Author: caoru * @CreateDate: 2018/8/9 14:21 */ public static String convertMD5(String inStr){ char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++){ a[i] = (char) (a[i] ^ 't'); } String s = new String(a); return s; } public static void main(String args[]) { String s = new String("10566"); String encryptStr=convertMD5(s); System.out.println("原始:" + s); System.out.println("MD5后:" + string2MD5(s)); System.out.println("加密的:" + encryptStr); System.out.println("解密的:" + convertMD5(encryptStr)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/MapUtil.java ================================================ package com.sohu.cache.util; import org.apache.commons.beanutils.BeanUtils; import java.util.Map; /** * Created by rucao on 2019/12/16 */ public class MapUtil { public static Object mapToObject(Map map, Class beanClass) throws Exception { if (map == null){ return null; } Object obj = beanClass.newInstance(); BeanUtils.populate(obj, map); return obj; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/NMONFileFactory.java ================================================ package com.sohu.cache.util; import com.sohu.cache.server.data.OS; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.security.CodeSource; import java.util.HashMap; import java.util.Map; /** * nmon文件存储工厂 */ public class NMONFileFactory { private static final Logger logger = LoggerFactory.getLogger(NMONFileFactory.class); public static final String NMON_PATH = "/nmon"; public static final String NMON_DIR_PATH = "nmon.dir"; public static final String FILE = "file"; //nmon文件存储 key为OSType_ProcessorArchitecture_DistributionType private static final Map nmonFileMap = new HashMap(); static { init(); } /** * 初始化nmon文件 */ private static void init() { try { String path = System.getProperty(NMON_DIR_PATH); if(path == null) { String classpath = null; try { CodeSource codeSource = NMONFileFactory.class.getProtectionDomain().getCodeSource(); classpath = codeSource.getLocation().getPath(); if(classpath.startsWith(FILE)) { //like that: file:/opt/app/cachecloud/cachecloud-web-1.0-SNAPSHOT.war!/WEB-INF/classes!/ classpath = classpath.substring(FILE.length()+1); } if(new File(classpath).isDirectory()) { path = classpath+"../.."+NMON_PATH; } else { //like that: /opt/app/cachecloud/cachecloud-web-1.0-SNAPSHOT.war!/WEB-INF/classes!/ String[] tmp = classpath.split("!/", 2); path = tmp[0].substring(0, tmp[0].lastIndexOf("/"))+NMON_PATH; } } catch (Exception e) { logger.error(classpath, e); } } if(path == null){ return; } File nmonDir = new File(path); if(!nmonDir.exists()) { logger.error("{} path not exist", nmonDir.getAbsolutePath()); return; } //获取操作系统目录 File[] osDirs = nmonDir.listFiles(); if(osDirs == null) { logger.error("{} not contains OS folders", nmonDir.getAbsolutePath()); return; } for(File osDir : osDirs) { //获取处理器架构目录 File[] archFiles = osDir.listFiles(); if(archFiles == null) { logger.info("{} not contains architecture folders", osDir.getName()); continue; } for(File archDir : archFiles) { //获取nmon文件目录 File[] nmonFiles = archDir.listFiles(); if(nmonFiles == null) { logger.info("{} not contains nomon files", archDir.getName()); continue; } for(File nmonFile : nmonFiles) { nmonFileMap.put(osDir.getName() + "_" + archDir.getName() + "_" + nmonFile.getName() , nmonFile); } logger.info("init {} {} nmon file size="+nmonFiles.length, osDir.getName(), archDir.getName()); } } logger.info("init {} finished, os size={}", nmonDir.getAbsolutePath(), osDirs.length); } catch (Exception e) { logger.error("init nmon factory", e); } } /** * 根据OS信息获取对应版本的NMON文件 * @param os * @return File */ public static File getNMONFile(OS os) { String key = os.getOsType().getValue() + "_" + os.getProcessorArchitecture().getValue() + "_" + os.getDistributionType().getNmonName() + os.getDistributionVersion().getValue(); return nmonFileMap.get(key); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/NamedArg.java ================================================ package com.sohu.cache.util; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * Annotation that provides information about argument's name. * * @since JavaFX 8.0 */ @Retention(RUNTIME) @Target(PARAMETER) public @interface NamedArg { /** * The name of the annotated argument. * @return the name of the annotated argument */ public String value(); /** * The default value of the annotated argument. * @return the default value of the annotated argument */ public String defaultValue() default ""; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/NumberUtil.java ================================================ package com.sohu.cache.util; /** * 从commons-lang抄的 * @author leifu */ public class NumberUtil { public static int toInt(String str, int defaultValue) { if (str == null) { return defaultValue; } try { return Integer.parseInt(str); } catch (NumberFormatException nfe) { return defaultValue; } } public static int toInt(String str) { return toInt(str, 0); } public static long toLong(String str, long defaultValue) { if (str == null) { return defaultValue; } try { return Long.parseLong(str); } catch (NumberFormatException nfe) { return defaultValue; } } public static long toLong(String str) { return toLong(str, 0L); } public static double toDouble(final String str) { return toDouble(str, 0.0d); } public static double toDouble(final String str, final double defaultValue) { if (str == null) { return defaultValue; } try { return Double.parseDouble(str); } catch (final NumberFormatException nfe) { return defaultValue; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/OSFactory.java ================================================ package com.sohu.cache.util; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.server.data.OS; import com.sohu.cache.server.data.OSInfo; import com.sohu.cache.server.data.OSInfo.DistributionType; import com.sohu.cache.server.data.OSInfo.DistributionVersion; import com.sohu.cache.server.data.OSInfo.OSType; import com.sohu.cache.server.data.OSInfo.ProcessorArchitecture; /** * 根据操作系统原生信息解析出OS */ public class OSFactory { private static final Logger logger = LoggerFactory.getLogger(OSFactory.class); //获取发行版本号的主版本和次版本 private static final Pattern VERSION_PATTERN = Pattern.compile("([1-9]+(\\.[0-9]+)?)"); public static OS getDefaultOS(OSInfo osInfo) { String uname = osInfo.getUname(); //无法获取系统位数 if(uname == null) { return null; } uname = uname.toLowerCase(); ProcessorArchitecture defaultArch = ProcessorArchitecture.X86_64; //其次获取操作系统位数 if(!uname.contains(defaultArch.getValue())) { defaultArch = ProcessorArchitecture.X86; } return new OS(OSType.LINUX, DistributionType.LINUX_OLD, DistributionVersion.DEFAULT, defaultArch); } /** * 采用uname -a信息和/etc/issue解析出目前能够支持的操作系统 * @param osInfo * @return OS */ public static OS getOS(OSInfo osInfo) { String uname = osInfo.getUname(); String issue = osInfo.getIssue(); OSType osType = OSType.LINUX; ProcessorArchitecture defaultArch = ProcessorArchitecture.X86_64; DistributionType defaultDist = DistributionType.LINUX_OLD; DistributionVersion version = DistributionVersion.DEFAULT; //无法获取系统类型,位数 版本,采用默认 if(uname == null || issue == null) { OS os = new OS(osType, defaultDist, version, defaultArch); return os; } uname = uname.toLowerCase(); //首先获取操作系统类型 if(!uname.contains(OSType.LINUX.getValue())) { logger.error("os={} is temporarily not supported", uname); return null; } //其次获取操作系统位数 if(!uname.contains(defaultArch.getValue())) { defaultArch = ProcessorArchitecture.X86; } //再次解析操作系统发行版本 issue = issue.toLowerCase(); DistributionType findType = DistributionType.findByContains(issue); //没有找到匹配的版本,使用默认 if(findType == null) { logger.warn("dist cannot matched, {}", issue); OS os = new OS(osType, defaultDist, version, defaultArch); return os; } //最后解析版本号 Matcher matcher = VERSION_PATTERN.matcher(issue); //没有版本好用默认的 if(!matcher.find()) { logger.warn("version not matched, {}", issue); OS os = new OS(osType, defaultDist, version, defaultArch); return os; } String ver = matcher.group(); ver = ver.replaceAll("\\.", ""); logger.info("version matched, {} - {}", ver, issue); DistributionVersion versionResult = findVersion(findType.getVersions(), ver); //没有具体的版本能匹配上 if(versionResult == null) { logger.info("version {} not found, {}", ver, issue); OS os = new OS(osType, defaultDist, version, defaultArch); return os; } OS os = new OS(osType, findType, versionResult, defaultArch); logger.info("find OS={}", os); return os; } private static DistributionVersion findVersion(DistributionVersion[] versions, String target) { for(DistributionVersion dv : versions) { if(dv.getValue().equals(target)){ return dv; } } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/ObjectConvert.java ================================================ package com.sohu.cache.util; import com.sohu.cache.entity.InstanceInfo; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; /** * 对象转换工具类 * * User: lingguo * Date: 14-5-29 * Time: 下午6:17 */ public class ObjectConvert { private static Logger logger = LoggerFactory.getLogger(ObjectConvert.class); /** * 将ip和port连接起来 * * @param ip * @param port * @return */ public static String linkIpAndPort(String ip, int port) { return ip + ":" + port; } /** * 将实例列表转化为ip1:port1 ip2:port2 * * @param instanceList * @return */ public static String assembleInstance(List instanceList) { if (instanceList.isEmpty()) { return null; } StringBuilder instanceBuilder = new StringBuilder(); for (int i = 0; i < instanceList.size(); i++) { InstanceInfo instanceInfo = instanceList.get(i); if (instanceInfo.isOffline()) { continue; } if (i > 0) { instanceBuilder.append(" "); } instanceBuilder.append(instanceInfo.getIp()).append(":").append(instanceInfo.getPort()); } return StringUtils.trim(instanceBuilder.toString()); } /** * 将百分比的比值转换为对应浮点数 * * @param value 百分比表示 * @param defaultVal 默认值 * @return 转换后的浮点表示 */ public static double percentToDouble(String value, double defaultVal) { double result = defaultVal; if (value == null || value.isEmpty()) { return result; } try { result = Double.valueOf(value.substring(0, value.length() - 1)); } catch (NumberFormatException e) { logger.error(e.getMessage(), e); } return result; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/Pair.java ================================================ /* * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package com.sohu.cache.util; import java.io.Serializable; /** *

A convenience class to represent name-value pairs.

* @since JavaFX 2.0 */ public class Pair implements Serializable{ /** * Key of this Pair. */ private K key; /** * Gets the key for this pair. * @return key for this pair */ public K getKey() { return key; } /** * Value of this this Pair. */ private V value; /** * Gets the value for this pair. * @return value for this pair */ public V getValue() { return value; } /** * Creates a new pair * @param key The key for this pair * @param value The value to use for this pair */ public Pair(@NamedArg("key") K key, @NamedArg("value") V value) { this.key = key; this.value = value; } /** *

String representation of this * Pair.

* *

The default name/value delimiter '=' is always used.

* * @return String representation of this Pair */ @Override public String toString() { return key + "=" + value; } /** *

Generate a hash code for this Pair.

* *

The hash code is calculated using both the name and * the value of the Pair.

* * @return hash code for this Pair */ @Override public int hashCode() { // name's hashCode is multiplied by an arbitrary prime number (13) // in order to make sure there is a difference in the hashCode between // these two parameters: // name: a value: aa // name: aa value: a return key.hashCode() * 13 + (value == null ? 0 : value.hashCode()); } /** *

Test this Pair for equality with another * Object.

* *

If the Object to be tested is not a * Pair or is null, then this method * returns false.

* *

Two Pairs are considered equal if and only if * both the names and values are equal.

* * @param o the Object to test for * equality with this Pair * @return true if the given Object is * equal to this Pair else false */ @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof Pair) { Pair pair = (Pair) o; if (key != null ? !key.equals(pair.key) : pair.key != null) return false; if (value != null ? !value.equals(pair.value) : pair.value != null) return false; return true; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/PandectUtil.java ================================================ package com.sohu.cache.util; import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; /** *

* Description: 总览统计 *

* @author chenshi * @version 1.0 * @date 2017/8/14 * @param * @return */ public class PandectUtil { private static Logger logger = LoggerFactory.getLogger(PandectUtil.class); //最后一次从mysql获取map时间 public final static String KEY_LASTTIME = "lastTime"; private static Map PANDECT_MAP = new HashMap(); /** *

* Description:1小时自动失效,重新从数据库获取 *

* @author chenshi * @version 1.0 * @date 2017/8/14 * @param * @return true:从sql获取 false:从map获取 */ public static Boolean getFromMysql(){ if(!MapUtils.isEmpty(PANDECT_MAP)){ Long lastTime = MapUtils.getLong(PANDECT_MAP, KEY_LASTTIME, 0l); long expire = System.currentTimeMillis()-lastTime; logger.info("expire = {}ms",expire); if(expire >= 2*60*1000){ return true; } return false; } return true; } // 清除map public static void clearMap(){ PANDECT_MAP.clear(); } public static Map getPandectMap() { return PANDECT_MAP; } public static void setPandectMap(Map pandectMap) { PANDECT_MAP = pandectMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/RedisConstUtils.java ================================================ package com.sohu.cache.util; /** * Created by chenshi */ public class RedisConstUtils { /** * Redis版本安装脚本路径 */ public static final String REDIS_SHELL_DIR = "/opt/cachecloud/sh/"; /** * Redis安装包后缀 */ public static final String REDIS_INSTALL_PACKAGE_SUFFIX = ".tar.gz"; /** * Redis make包后缀 */ public static final String REDIS_INSTALL_MAKE_PACKAGE_SUFFIX = "-make.tar.gz"; /** * Redis版本名称前缀 */ public static final String REDIS_VERSION_PREFIX = "redis-"; /** * Redis单版本安装日志 */ public static final String REDIS_INSTALL_LOG = "/opt/cachecloud/sh/install.log.%s"; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/ScheduleUtil.java ================================================ package com.sohu.cache.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Random; /** * 调度相关的工具类 *

* Created by yijunzhang on 14-6-10. */ public class ScheduleUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleUtil.class); private static final String COLLECT_TIME_FORMAT = "yyyyMMddHHmm"; private static final String DATE_FORMAT = "yyyyMMdd"; /** * cron表达式:每分钟,根据appId计算分钟的秒数 * * @param appId * @return */ public static String getMinuteCronByAppId(long appId) { String baseCron = (appId % 50) + " 0/1 * ? * *"; return baseCron; } public static String getMachineStatsCron(long hostId) { String baseCron = (hostId % 50) + " 0/" + ConstUtils.MACHINE_STATS_CRON_MINUTE + " * ? * *"; return baseCron; } public static String getFiveMinuteCronByHostId(long hostId) { String baseCron = (hostId % 50) + " 0/5 * ? * *"; return baseCron; } public static String getRedisSlowLogCron(long appId) { Random random = new Random(); String baseCron = random.nextInt(60) + " 0/20 * ? * *"; return baseCron; } /** * cron表达式:每小时,根据hostId计算小时的分钟数 * * @param hostId * @return */ public static String getHourCronByHostId(long hostId) { String hourCron = "0 %s 0/1 ? * *"; Random random = new Random(); long minute = (hostId + random.nextInt(Integer.MAX_VALUE)) % 60; return String.format(hourCron, minute); } /** * 计算前一分钟的时间,并格式化 * * @param collectTime 基准时间 * @return */ public static long getLastCollectTime(long collectTime) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(COLLECT_TIME_FORMAT); try { Date date = simpleDateFormat.parse(String.valueOf(collectTime)); Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.MINUTE, -1); Date lastDate = calendar.getTime(); return Long.parseLong(simpleDateFormat.format(lastDate)); } catch (ParseException e) { LOGGER.error(e.getMessage(), e); return 0L; } } /** * 格式化时间 * * @param date * @return */ public static long getCollectTime(Date date) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(COLLECT_TIME_FORMAT); return Long.parseLong(simpleDateFormat.format(date)); } /** * 返回某一天的起始时间,如:201406300000 * * @param date 当前日期 * @param offset 针对当前日期的偏移 * @return 日期的long形式,如201406300000 */ public static long getBeginTimeOfDay(Date date, int offset) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DAY_OF_YEAR, offset); date = calendar.getTime(); SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT); return Long.parseLong(dateFormat.format(date) + "0000"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/StringUtil.java ================================================ package com.sohu.cache.util; import com.sohu.cache.constant.BaseConstant; import com.sohu.cache.constant.EmptyObjectConstant; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.sohu.cache.constant.EmptyObjectConstant.EMPTY_STRING; /** * Description: String Utils * * @author nileader / nileader@gmail.com * @Date Feb 10, 2012 */ public class StringUtil { /** * Check String is equals. targetStr compare with compareStrArray, and * return true if equals one or more * * @param targetStr 寰呮瘮杈冪殑瀛楃涓� * @param compareStrArray 瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯 * @return */ public static boolean containsIgnoreCase(final String originalStr, final CharSequence targetStr) { if (null == originalStr) { return false; } String originalStrCaps = originalStr.toUpperCase(); String targetStrCaps = targetStr.toString().toUpperCase(); return originalStrCaps.contains(targetStrCaps); } /** * Description: Remove {_, -, @, $, #, /, &} in string and make letter after * this uppercase.
* e.g. ni_lea-der@gmail./com -> niLeaDerGmail.Com * * @param @param inputString * @param @param firstCharacterUppercase The first letter is need uppercase. * @return String * @throws */ public static String convertToCamelCaseString(String inputString, boolean firstCharacterUppercase) { if (null == inputString) { return null; } StringBuilder sb = new StringBuilder(); boolean nextUpperCase = false; for (int i = 0; i < inputString.length(); i++) { char c = inputString.charAt(i); switch (c) { case '_': case '-': case '@': case '$': case '#': case ' ': case '/': case '&': if (sb.length() > 0) { nextUpperCase = true; } break; default: if (nextUpperCase) { sb.append(Character.toUpperCase(c)); nextUpperCase = false; } else { sb.append(c); } break; } } if (firstCharacterUppercase) { sb.setCharAt(0, Character.toUpperCase(sb.charAt(0))); } else { sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); } return sb.toString(); } /** * Return Default if originalStr is empty. * * @param originalStr 寰呯‘璁ゅ� * @param defaultStr 榛樿鍊� * @return 濡傛灉originalStr涓虹┖锛岄偅涔堝氨杩斿洖defaultStr */ public static String defaultIfBlank(String originalStr, String defaultStr) { if (StringUtil.isBlank(originalStr)) { return defaultStr; } return originalStr; } /** * Check String is equals Ignore Case. targetStr compare with * compareStrArray, and return true if equals all * * @param targetStr 寰呮瘮杈冪殑瀛楃涓� * @param compareStrArray 瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯 * @return true if targetStr same with every string in compareStrArray */ public static boolean equalsIgnoreCaseAll(String targetStr, String... compareStrArray) { if (StringUtil.isBlank(targetStr) || null == compareStrArray || 0 == compareStrArray.length) { return false; } for (int i = 0; i < compareStrArray.length; i++) { if (!targetStr.equalsIgnoreCase(compareStrArray[i])) { return false; } } return true; } /** * Check String is equals. targetStr compare with compareStrArray, and * return true if equals one or more * * @param targetStr 寰呮瘮杈冪殑瀛楃涓� * @param compareStrArray 瑕佹瘮杈冪殑涓�釜鎴栧涓瓧绗︿覆鏍囧噯 * @return true if targetStr same with string in compareStrArray one at * least */ public static boolean equalsIgnoreCaseOne(String targetStr, String... compareStrArray) { if (StringUtil.isBlank(targetStr) || null == compareStrArray || 0 == compareStrArray.length) { return false; } for (int i = 0; i < compareStrArray.length; i++) { if (targetStr.equalsIgnoreCase(compareStrArray[i])) { return true; } } return false; } /** * 閫氳繃姝e垯琛ㄨ揪鏂瑰紡锛屾壘鍑轰竴涓瓧绗︿覆涓墍鏈夋寚瀹氱殑瀛愪覆 * * @param @param originalStr 瀛楃涓� * @param @param regex 寰呮煡鎵惧瓙涓茬殑姝e垯琛ㄨ揪寮� * @return List 瀛愪覆闆嗗悎 *

*

     *  瀵�/1.1.1.1:sid=0x2337c7074dofj02e,37775[1](queued=0,recved=6,sent=7,sid=0x2337c7074f1102e,sdlfjle,dsfe鐨勭粨鏋滄槸锛�
     * [sid=0x2337c7074dofj02e, , sid=0x2337c7074f1102e, ]
     * 
*/ public static List findAllByRegex(String originalStr, String regex) { if (StringUtil.isBlank(originalStr) || StringUtil.isBlank(regex)) return null; List targetStrList = new ArrayList(); final Pattern patternOfTargetStr = Pattern.compile(regex, Pattern.CANON_EQ); final Matcher matcherOfTargetStr = patternOfTargetStr.matcher(originalStr); /** 寮�瑙f瀽 */ while (matcherOfTargetStr.find()) { targetStrList.add(StringUtil.trimToEmpty(matcherOfTargetStr.group())); } return targetStrList; } /** * 閫氳繃姝e垯琛ㄨ揪鏂瑰紡锛屾壘鍑轰竴涓瓧绗︿覆涓涓�釜鎸囧畾鐨勫瓙涓� * * @param @param originalStr 瀛楃涓� * @param @param regex 寰呮煡鎵惧瓙涓茬殑姝e垯琛ㄨ揪寮� * @return List 瀛愪覆闆嗗悎 *

*

     *  瀵�/1.1.1.1:sid=0x2337c7074dofj02e,37775[1](queued=0,recved=6,sent=7,sid=0x2337c7074f1102e,sdlfjle,dsfe鐨勭粨鏋滄槸锛�
     * sid=0x2337c7074dofj02e,
     * 
*/ public static String findFirstByRegex(String originalStr, String regex) { if (StringUtil.isBlank(originalStr) || StringUtil.isBlank(regex)) return EMPTY_STRING; final Pattern patternOfTargetStr = Pattern.compile(regex, Pattern.CANON_EQ); final Matcher matcherOfTargetStr = patternOfTargetStr.matcher(originalStr); /** 寮�瑙f瀽 */ if (matcherOfTargetStr.find()) { return StringUtil.trimToEmpty(matcherOfTargetStr.group()); } return EMPTY_STRING; } /** * 鐢熸垚绌虹櫧琛� * * @param lines 琛屾暟 */ public static String generateLineBlank(int lines) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < lines; i++) { sb.append("\n"); } return sb.toString(); } /** * make first letter lower case for str * * @return Same letter, but the first letter is lower case. */ public static String makeFirstLetterLowerCase(String str) { String firstLetter = str.substring(0, 1); return firstLetter.toLowerCase() + str.substring(1, str.length()); } /*** * check if orginalStr is null or empty.
* If have more than one originalStr, use isBlank(String... * originalStrArray) * * @param originalStr * 寰呯‘璁ゅ� * @return true or false; */ public static boolean isBlank(String originalStr) { if (null == originalStr) { return true; } if (originalStr.contains(BaseConstant.WORD_SEPARATOR)) { return false; } return trimToEmpty(originalStr).isEmpty(); } /*** * check if orginalStr is null or empty * * @param String * ... originalStrArray * @return true if have one blank at least. */ public static boolean isBlank(String... originalStrArray) { if (null == originalStrArray || 0 == originalStrArray.length) return true; for (int i = 0; i < originalStrArray.length; i++) { if (isBlank(originalStrArray[i])) return true; } return false; } /** * check the originalStr is contain the whitespace * * @param originalStr * @return true if contain whitespace */ public static boolean isContainWhitespace(String originalStr) { if (StringUtil.isBlank(originalStr)) { return true; } int strLen = originalStr.length(); for (int i = 0; i < strLen; i++) { char ch = originalStr.charAt(i); if (Character.isWhitespace(ch)) { return true; } } return false; } /** * 字符串连接,使用指定分隔符 * * @param subStr * @return */ public static String join(String... subStrs) { if (null == subStrs || 0 == subStrs.length) { return EMPTY_STRING; } StringBuilder sb = new StringBuilder(); for (String subStr : subStrs) { sb.append(subStr).append(BaseConstant.WORD_SEPARATOR); } String sbStr = sb.toString(); if (sbStr.endsWith(BaseConstant.WORD_SEPARATOR)) { sbStr = StringUtil.replaceLast(sbStr, BaseConstant.WORD_SEPARATOR, ""); } return sbStr; } /** * Description: Replaces last substring of this string that matches the * given regular expression with the given replacement.
* Do not worry about null pointer * * @param @param regex * @param @param replacement * @return String * @throws */ public static String replaceAll(String originalStr, String replacement, String regex) { return StringUtil.trimToEmpty(originalStr).replaceAll(regex, replacement); } public static String replaceAll(String originalStr, String replacement, String... regexArray) { if (0 == regexArray.length) return originalStr; for (String regex : regexArray) { originalStr = StringUtil.replaceAll(originalStr, replacement, regex); } return originalStr; } /** * Description: Replaces last substring of this string that matches the * given regular expression with the given replacement. * * @param @param regex * @param @param replacement * @param @return * @return String * @throws */ public static String replaceLast(String originalStr, String regex, String replacement) { if (StringUtil.isBlank(originalStr)) return EMPTY_STRING; int index = originalStr.lastIndexOf(regex); if (-1 == index) return originalStr; // 鍏堝瓨鍌ㄨ繖涓猧ndex涔嬪墠鐨勬墍鏈塻tr String temp = originalStr.substring(0, index); String temp2 = originalStr.substring(index, originalStr.length()); temp2 = temp2.replaceFirst(regex, replacement); originalStr = temp + temp2; return originalStr; } /** * Description: Replaces all {n} placeholder use params * * @param originalStr a string such as : * "select * from table where id={0}, name={1}, gender={3}" * @param replacementParams real params: 1,yinshi.nc,male * @note n start with 0 */ public static String replaceSequenced(String originalStr, Object... replacementParams) { if (StringUtil.isBlank(originalStr)) return EMPTY_STRING; if (null == replacementParams || 0 == replacementParams.length) return originalStr; for (int i = 0; i < replacementParams.length; i++) { String elementOfParams = replacementParams[i] + EmptyObjectConstant.EMPTY_STRING; if (StringUtil.trimToEmpty(elementOfParams).equalsIgnoreCase("null")) elementOfParams = EmptyObjectConstant.EMPTY_STRING; originalStr = originalStr.replace("{" + i + "}", StringUtil.trimToEmpty(elementOfParams)); } return originalStr; } /** * 璁剧疆鍓嶇紑锛屽鏋滆繖涓瓧绗︿覆宸茬粡鏄繖涓墠缂�簡锛岄偅涔堝氨涓嶄綔浠讳綍鎿嶄綔銆� TODO none test */ public static String setPrefix(String originalStr, String prefix) { originalStr = StringUtil.trimToEmpty(originalStr); prefix = StringUtil.trimToEmpty(prefix); if (!originalStr.startsWith(prefix)) { originalStr = prefix + originalStr; } return originalStr; } /** * /** * 鍒ゆ柇瀛楃涓叉槸鍚﹁秴杩囨寚瀹氶暱搴︼紝濡備綍瓒呰繃锛屾坊鍔犳寚瀹氬悗缂� * * @param originalStr "閾舵椂鐨� * @param maxLength 2 * @param suffix ... * @return "閾舵椂..." */ public static String subStringIfTooLong(String originalStr, int maxLength, String suffix) { if (StringUtil.isBlank(originalStr)) return EmptyObjectConstant.EMPTY_STRING; if (maxLength < 0) maxLength = 0; if (originalStr.length() > maxLength) return originalStr.substring(0, maxLength) + StringUtil.trimToEmpty(suffix); return originalStr; } /** * Returns a copy of the string, with leading and trailing whitespace * omitted. Don't worry the NullPointerException. Will never return Null. * * @param originalStr * @return "" or String without empty str. */ public static String trimToEmpty(String originalStr) { if (null == originalStr || originalStr.isEmpty()) return EMPTY_STRING; if (originalStr.equals(BaseConstant.WORD_SEPARATOR)) return originalStr; return originalStr.trim(); } /** * URL编码 * * @param s String to be translated. * @param enc The name of a supported character encoding. * @return */ public static String urlEncode(String s, String enc) { if (StringUtil.isBlank(s)) return StringUtil.trimToEmpty(s); try { return java.net.URLEncoder.encode(trimToEmpty(s), enc); } catch (UnsupportedEncodingException e) { return s; } } /** * URL编码,使用UTF-8编码 * * @param s String to be translated. * @param enc The name of a supported character encoding. * @return */ public static String urlEncode(String s) { if (StringUtil.isBlank(s)) return StringUtil.trimToEmpty(s); return urlEncode(trimToEmpty(s), "UTF-8"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/util/TypeUtil.java ================================================ package com.sohu.cache.util; /** * Created by yijunzhang on 14-9-26. */ public class TypeUtil { public static boolean isRedisType(int type) { if (type == ConstUtils.CACHE_REDIS_SENTINEL || type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER || type == ConstUtils.CACHE_REDIS_STANDALONE || type == ConstUtils.CACHE_REDIS_TWEMPROXY || type == ConstUtils.CACHE_PIKA_TWEMPROXY || type == ConstUtils.CACHE_PIKA_SENTINEL) { return true; } return false; } public static boolean isRedisCluster(int type) { if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { return true; } return false; } public static boolean isRedisSentinel(int type) { if (type == ConstUtils.CACHE_REDIS_SENTINEL) { return true; } return false; } public static boolean isRedisStandalone(int type) { if (type == ConstUtils.CACHE_REDIS_STANDALONE) { return true; } return false; } public static boolean isRedisTwemproxy(int type) { if (type == ConstUtils.CACHE_REDIS_TWEMPROXY) { return true; } return false; } public static boolean isPikaSentinel(int type) { if (type == ConstUtils.CACHE_PIKA_SENTINEL) { return true; } return false; } public static boolean isPikaTwemproxy(int type) { if (type == ConstUtils.CACHE_PIKA_TWEMPROXY) { return true; } return false; } public static boolean isRedisDataType(int type) { if (type == ConstUtils.CACHE_TYPE_REDIS_CLUSTER || type == ConstUtils.CACHE_REDIS_STANDALONE) { return true; } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/key/ChartKeysUtil.java ================================================ package com.sohu.cache.web.chart.key; /** * Created by hym on 14-7-27. */ public class ChartKeysUtil { public enum ChartKey { RENDER_TO("renderTo"), TYPE("type"); private String key; ChartKey(String key) { this.key = key; } public String getKey() { return key; } } public enum TitleKey { TEXT("text"); private String key; TitleKey(String key) { this.key = key; } public String getKey() { return key; } } public enum SubTitleKey { TEXT("text"); private String key; SubTitleKey(String key) { this.key = key; } public String getKey() { return key; } } public enum XAxisKey { CATEGORIES("categories"), LABELS("labels"),LABELS_STEP("step"),LABELS_ROTATION("rotation"), LABELS_Y("y"), MAX_STAGGER_LINES("maxStaggerLines"); private String key; XAxisKey(String key) { this.key = key; } public String getKey() { return key; } } public enum YAxisKey { TITLE("title"), TITLE_TEXT("text"), PLOTLINES("plotLines"), PLOTLINES_VALUE("value"), PLOTLINES_WIDTH("width"), PLOTLINES_COLOR("color"); private String key; YAxisKey(String key) { this.key = key; } public String getKey() { return key; } } public enum TooltipKey { VALUESUFFIX("valueSuffix"),CROSSHAIRS("crosshairs"),SHARED("shared"); private String key; TooltipKey(String key) { this.key = key; } public String getKey() { return key; } } public enum LegendKey { LAYOUT("layout"), ALIGN("align"), VERTICALALIGN("verticalAlign"), BORDERWIDTH("borderWidth"); private String key; LegendKey(String key) { this.key = key; } public String getKey() { return key; } } public enum SeriesKey { DATA("data"), NAME("name"); private String key; SeriesKey(String key) { this.key = key; } public String getKey() { return key; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/AreaChartEntity.java ================================================ package com.sohu.cache.web.chart.model; import com.sohu.cache.web.chart.key.ChartKeysUtil; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class AreaChartEntity extends ChartEntity { public AreaChartEntity() { super(); putChartType(); setTooltipShared(true); } @Override protected void putChartType() { this.getChart().put(ChartKeysUtil.ChartKey.TYPE.getKey(), "area"); } public void setXAxisCategories(List xAxisCategories) { setXAxisCategories(xAxisCategories, 14); } public void setXAxisCategories(List xAxisCategories, int totalLabels) { setXAxisCategories(xAxisCategories, totalLabels, 0, -5); } public void setXAxisCategories(List xAxisCategories, int totalLabels, int rotation, int y) { putXAxis(ChartKeysUtil.XAxisKey.CATEGORIES.getKey(), xAxisCategories); if (xAxisCategories.size() >= totalLabels) { Map m = null; if (this.getxAxis().containsKey(ChartKeysUtil.XAxisKey.LABELS.getKey())) { m = (Map) this.getxAxis().get(ChartKeysUtil.XAxisKey.LABELS.getKey()); } if (m == null) { m = new LinkedHashMap(); } m.put(ChartKeysUtil.XAxisKey.LABELS_STEP.getKey(), xAxisCategories.size() / totalLabels + 1); m.put(ChartKeysUtil.XAxisKey.LABELS_ROTATION.getKey(), rotation); m.put(ChartKeysUtil.XAxisKey.LABELS_Y.getKey(), y); m.put(ChartKeysUtil.XAxisKey.MAX_STAGGER_LINES.getKey(), 1); putXAxis(ChartKeysUtil.XAxisKey.LABELS.getKey(), m); } } public void setYAxisTitle(String title) { if (this.getyAxis().containsKey(ChartKeysUtil.YAxisKey.TITLE.getKey())) { ((Map) this.getyAxis().get(ChartKeysUtil.YAxisKey.TITLE.getKey())).put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title); } else { Map map = new HashMap(); map.put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title); putYAxis(ChartKeysUtil.YAxisKey.TITLE.getKey(), map); } } public void setTooltipCrosshairs(boolean crosshairs) { putTooltip(ChartKeysUtil.TooltipKey.CROSSHAIRS.getKey(), crosshairs); } public void setTooltipShared(boolean shared) { putTooltip(ChartKeysUtil.TooltipKey.SHARED.getKey(), shared); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/ChartEntity.java ================================================ package com.sohu.cache.web.chart.model; import com.sohu.cache.web.chart.key.ChartKeysUtil; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; public abstract class ChartEntity { private Map chart; private Map title; private Map subtitle; private Map xAxis; private Map yAxis; private Map tooltip; private Map legend; private List> series; public ChartEntity() { // 初始化chart Map chart = new LinkedHashMap(); chart.put(ChartKeysUtil.ChartKey.RENDER_TO.getKey(), "container"); this.setChart(chart); // 初始化title Map title = new LinkedHashMap(); title.put(ChartKeysUtil.TitleKey.TEXT.getKey(), "请设置图表title"); this.setTitle(title); // 初始化subtitle Map subtitle = new LinkedHashMap(); this.setSubtitle(subtitle); // 初始化xAxis Map xAxis = new LinkedHashMap(); this.setxAxis(xAxis); // 初始化yAxis Map yAxis = new LinkedHashMap(); this.setyAxis(yAxis); // 初始化tooltip Map tooltip = new LinkedHashMap(); this.setTooltip(tooltip); // 初始化legend Map legend = new LinkedHashMap(); this.setLegend(legend); //初始化series List> series = new LinkedList>(); this.setSeries(series); } /** * 所有曲线类型必须设置曲线类型 */ protected abstract void putChartType(); /** * 指定容器,即页面div的id * 默认为container,用户可以覆盖 * * @param container 页面div的id */ public void renderTo(String container) { this.putChart(ChartKeysUtil.ChartKey.RENDER_TO.getKey(), container); } /** * 设置chart属性 * * @param key * @param value */ public void putChart(String key, Object value) { this.getChart().put(key, value); } /** * 设置title属性 * * @param key * @param value */ public void putTitle(String key, Object value) { this.getTitle().put(key, value); } /** * 设置subTitle属性 * * @param key * @param value */ public void putSubTitle(String key, Object value) { this.getSubtitle().put(key, value); } /** * @param key * @param value */ public void putXAxis(String key, Object value) { this.getxAxis().put(key, value); } /** * @param key * @param value */ public void putYAxis(String key, Object value) { this.getyAxis().put(key, value); } /** * @param key * @param value */ public void putTooltip(String key, Object value) { this.getTooltip().put(key, value); } /** * @param key * @param value */ public void putLegend(String key, Object value) { this.getLegend().put(key, value); } /** * @param series */ public void putSeries(Map series) { this.getSeries().add(series); } // 以下是get set 方法 public Map getChart() { return chart; } private void setChart(Map chart) { this.chart = chart; } public Map getTitle() { return title; } private void setTitle(Map title) { this.title = title; } public Map getSubtitle() { return subtitle; } private void setSubtitle(Map subtitle) { this.subtitle = subtitle; } public Map getxAxis() { return xAxis; } private void setxAxis(Map xAxis) { this.xAxis = xAxis; } public Map getyAxis() { return yAxis; } private void setyAxis(Map yAxis) { this.yAxis = yAxis; } public Map getTooltip() { return tooltip; } private void setTooltip(Map tooltip) { this.tooltip = tooltip; } public Map getLegend() { return legend; } private void setLegend(Map legend) { this.legend = legend; } public List> getSeries() { return series; } private void setSeries(List> series) { this.series = series; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/HighchartDoublePoint.java ================================================ package com.sohu.cache.web.chart.model; import com.sohu.cache.entity.AppDailyData; import com.sohu.cache.entity.AppStats; import com.sohu.cache.web.util.DateUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.time.DateUtils; import java.text.DecimalFormat; import java.text.ParseException; import java.util.Date; /** * highchart最简单的点 double y * * @author leifu * @Date 2016年8月1日 * @Time 下午12:59:29 */ @Slf4j public class HighchartDoublePoint { /** * 时间戳 */ private Long x; /** * 用于表示y轴数量 */ private Double y; /** * 日期 */ private String date; public HighchartDoublePoint() { } public HighchartDoublePoint(Long x, Double y, String date) { this.x = x; this.y = y; this.date = date; } public Long getX() { return x; } public void setX(Long x) { this.x = x; } public Double getY() { return y; } public void setY(Double y) { this.y = y; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public static HighchartDoublePoint getFromAppStats(AppStats appStat, String statName, Date currentDate, int diffDays) throws ParseException { Date collectDate = getDateTime(appStat.getCollectTime()); if (!DateUtils.isSameDay(currentDate, collectDate)) { return null; } //显示用的时间 String date = null; try { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH:mm"); } catch (Exception e) { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH"); } DecimalFormat df = new DecimalFormat("##.##"); // y坐标 double count = 0D; if ("memFragRatio".equals(statName)) { long rss = appStat.getUsedMemoryRss(); long mem = appStat.getUsedMemory(); count = Double.parseDouble(df.format(rss * 1.0D / mem)); } //为了显示在一个时间范围内 if (diffDays > 0) { collectDate = DateUtils.addDays(collectDate, diffDays); } return new HighchartDoublePoint(collectDate.getTime(), count, date); } public static HighchartDoublePoint getFromAppDailyDatas(AppDailyData appDailyData, String statName) throws ParseException { Date collectDate = appDailyData.getDate(); //显示用的时间 String date = DateUtil.formatDate(collectDate, "yyyy-MM-dd"); // y坐标 double count = 0D; if ("avg_hit_ratio".equals(statName)) { count = appDailyData.getAvgHitRatio(); } else if ("min_minute_hit_ratio".equals(statName)) { count = appDailyData.getMinMinuteHitRatio(); } else if ("max_minute_hit_ratio".equals(statName)) { count = appDailyData.getMaxMinuteHitRatio(); } return new HighchartDoublePoint(collectDate.getTime(), count, date); } private static Date getDateTime(long collectTime) throws ParseException { try { return DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime)); } catch (Exception e) { return DateUtil.parseYYYYMMddHH(String.valueOf(collectTime)); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/HighchartPoint.java ================================================ package com.sohu.cache.web.chart.model; import java.text.ParseException; import java.util.Date; import org.apache.commons.lang.time.DateUtils; import com.sohu.cache.entity.AppCommandStats; import com.sohu.cache.entity.AppStats; import com.sohu.cache.web.util.DateUtil; /** * highchart最简单的点 * * @author leifu * @Date 2016年8月1日 * @Time 下午12:59:29 */ public class HighchartPoint { /** * 时间戳 */ private Long x; /** * 用于表示y轴数量 */ private Long y; /** * 日期 */ private String date; public HighchartPoint() { } public HighchartPoint(Long x, Long y, String date) { this.x = x; this.y = y; this.date = date; } public Long getX() { return x; } public void setX(Long x) { this.x = x; } public Long getY() { return y; } public void setY(Long y) { this.y = y; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public static HighchartPoint getFromAppCommandStats(AppCommandStats appCommandStats, Date currentDate, int diffDays) throws ParseException { Date collectDate = getDateTime(appCommandStats.getCollectTime()); if (!DateUtils.isSameDay(currentDate, collectDate)) { return null; } //显示用的时间 String date = null; try { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH:mm"); } catch (Exception e) { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH"); } // y坐标 long commandCount = appCommandStats.getCommandCount(); // x坐标 //为了显示在一个时间范围内 if (diffDays > 0) { collectDate = DateUtils.addDays(collectDate, diffDays); } return new HighchartPoint(collectDate.getTime(), commandCount, date); } public static HighchartPoint getFromAppStats(AppStats appStat, String statName, Date currentDate, int diffDays) throws ParseException { Date collectDate = getDateTime(appStat.getCollectTime()); if (!DateUtils.isSameDay(currentDate, collectDate)) { return null; } //显示用的时间 String date = null; try { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH:mm"); } catch (Exception e) { date = DateUtil.formatDate(collectDate, "yyyy-MM-dd HH"); } // y坐标 long count = 0; if ("hits".equals(statName)) { count = appStat.getHits(); } else if ("misses".equals(statName)) { count = appStat.getMisses(); } else if ("usedMemory".equals(statName)) { count = appStat.getUsedMemory() / 1024 / 1024; } else if ("usedMemoryRss".equals(statName)) { count = appStat.getUsedMemoryRss() / 1024 / 1024; } else if ("netInput".equals(statName)) { count = appStat.getNetInputByte(); } else if ("netOutput".equals(statName)) { count = appStat.getNetOutputByte(); } else if ("connectedClient".equals(statName)) { count = appStat.getConnectedClients(); } else if ("objectSize".equals(statName)) { count = appStat.getObjectSize(); } else if ("hitPercent".equals(statName)) { count = appStat.getHitPercent(); } else if ("cpuSys".equals(statName)) { count = appStat.getCpuSys(); } else if ("cpuUser".equals(statName)) { count = appStat.getCpuUser(); } else if ("cpuSysChildren".equals(statName)) { count = appStat.getCpuSysChildren(); } else if ("cpuUserChildren".equals(statName)) { count = appStat.getCpuUserChildren(); } else if ("expiredKeys".equals(statName)) { count = appStat.getExpiredKeys(); } else if ("evictedKeys".equals(statName)) { count = appStat.getEvictedKeys(); } else if ("usedDisk".equals(statName)) { count = appStat.getUsedDisk() / 1024 / 1024; } //为了显示在一个时间范围内 if (diffDays > 0) { collectDate = DateUtils.addDays(collectDate, diffDays); } return new HighchartPoint(collectDate.getTime(), count, date); } private static Date getDateTime(long collectTime) throws ParseException { try { return DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime)); } catch (Exception e) { return DateUtil.parseYYYYMMddHH(String.valueOf(collectTime)); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/SimpleChartData.java ================================================ package com.sohu.cache.web.chart.model; import java.text.ParseException; import java.util.Date; import java.util.concurrent.TimeUnit; import com.sohu.cache.entity.AppCommandGroup; import com.sohu.cache.entity.AppCommandStats; import com.sohu.cache.entity.AppStats; import com.sohu.cache.web.util.DateUtil; /** * 用于显示chart的简单对象 * * @author leifu * @Time 2014年8月31日 */ public class SimpleChartData { /** * 时间戳 */ private Long x; /** * 用于表示y轴数量 */ private Long y; /** * 命令名 */ private String commandName; /** * 日期 */ private String date; public Long getX() { return x; } public void setX(Long x) { this.x = x; } public Long getY() { return y; } public void setY(Long y) { this.y = y; } public String getCommandName() { return commandName; } public void setCommandName(String commandName) { this.commandName = commandName; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } /** * AppCommandStats转换为SimpleChartData * * @param appCommandStats * @return * @throws ParseException */ public static SimpleChartData getFromAppCommandStats( AppCommandStats appCommandStats, Integer addDay) throws ParseException { SimpleChartData chartData = new SimpleChartData(); long collectTime = appCommandStats.getCollectTime(); String commandName = appCommandStats.getCommandName(); long commandCount = appCommandStats.getCommandCount(); Date dateTime = null; try { dateTime = DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime)); } catch (Exception e) { dateTime = DateUtil.parseYYYYMMddHH(String.valueOf(collectTime)); } Long x = dateTime.getTime(); if(addDay != null){ x += TimeUnit.DAYS.toMillis(1) * addDay; } Long y = commandCount; String date = null; try { date = DateUtil.formatDate(dateTime, "yyyy-MM-dd HH:mm"); } catch (Exception e) { date = DateUtil.formatDate(dateTime, "yyyy-MM-dd HH"); } chartData.setX(x); chartData.setY(y); chartData.setDate(date); chartData.setCommandName(commandName); return chartData; } /** * AppStats转换为SimpleChartData * * @param appStat * @param statName * 命中数、丢失数的字段 * @return * @throws ParseException */ public static SimpleChartData getFromAppStats(AppStats appStat, String statName) throws ParseException { SimpleChartData chartData = new SimpleChartData(); long collectTime = appStat.getCollectTime(); long count = 0; if ("hits".equals(statName)) { count = appStat.getHits(); } else if ("misses".equals(statName)) { count = appStat.getMisses(); } else if ("usedMemory".equals(statName)){ count = appStat.getUsedMemory() / 1024 / 1024; } else if ("netInput".equals(statName)) { count = appStat.getNetInputByte(); } else if ("netOutput".equals(statName)) { count = appStat.getNetOutputByte(); } else if ("hitPercent".equals(statName)) { count = appStat.getHitPercent(); } Date dateTime = null; try { dateTime = DateUtil.parseYYYYMMddHHMM(String.valueOf(collectTime)); } catch (Exception e) { dateTime = DateUtil.parseYYYYMMddHH(String.valueOf(collectTime)); } Long x = dateTime.getTime(); Long y = count; String date = null; try { date = DateUtil.formatDate(dateTime, "yyyy-MM-dd HH:mm"); } catch (Exception e) { date = DateUtil.formatDate(dateTime, "yyyy-MM-dd HH"); } chartData.setX(x); chartData.setY(y); chartData.setDate(date); return chartData; } /** * AppCommandGroup转换为SimpleChartData用于显示pie图 * * @param appCommandGroup * @return */ public static SimpleChartData getFromAppCommandGroup( AppCommandGroup appCommandGroup) { SimpleChartData chartData = new SimpleChartData(); chartData.setCommandName(appCommandGroup.getCommandName()); chartData.setY(appCommandGroup.getCount()); return chartData; } @Override public String toString() { return "SimpleChartData [x=" + x + ", y=" + y + ", commandName=" + commandName + "]"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/chart/model/SplineChartEntity.java ================================================ package com.sohu.cache.web.chart.model; import com.sohu.cache.web.chart.key.ChartKeysUtil; import java.util.*; public class SplineChartEntity extends ChartEntity { public SplineChartEntity() { super(); putChartType(); setTooltipShared(true); } @Override protected void putChartType() { this.getChart().put(ChartKeysUtil.ChartKey.TYPE.getKey(), "spline"); } public void setXAxisCategories(List xAxisCategories) { setXAxisCategories(xAxisCategories, 14); } public void setXAxisCategories(List xAxisCategories, int totalLabels) { setXAxisCategories(xAxisCategories, totalLabels, 0, -5); } public void setXAxisCategories(List xAxisCategories, int totalLabels, int rotation, int y) { putXAxis(ChartKeysUtil.XAxisKey.CATEGORIES.getKey(), xAxisCategories); if (xAxisCategories.size() >= totalLabels) { Map m = null; if (this.getxAxis().containsKey(ChartKeysUtil.XAxisKey.LABELS.getKey())) { m = (Map) this.getxAxis().get(ChartKeysUtil.XAxisKey.LABELS.getKey()); } if (m == null) { m = new LinkedHashMap(); } m.put(ChartKeysUtil.XAxisKey.LABELS_STEP.getKey(), xAxisCategories.size() / totalLabels + 1); m.put(ChartKeysUtil.XAxisKey.LABELS_ROTATION.getKey(), rotation); m.put(ChartKeysUtil.XAxisKey.LABELS_Y.getKey(), y); m.put(ChartKeysUtil.XAxisKey.MAX_STAGGER_LINES.getKey(), 1); putXAxis(ChartKeysUtil.XAxisKey.LABELS.getKey(), m); } } public void setYAxisTitle(String title) { if (this.getyAxis().containsKey(ChartKeysUtil.YAxisKey.TITLE.getKey())) { ((Map) this.getyAxis().get(ChartKeysUtil.YAxisKey.TITLE.getKey())).put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title); } else { Map map = new HashMap(); map.put(ChartKeysUtil.YAxisKey.TITLE_TEXT.getKey(), title); putYAxis(ChartKeysUtil.YAxisKey.TITLE.getKey(), map); } } public void setTooltipCrosshairs(boolean crosshairs) { putTooltip(ChartKeysUtil.TooltipKey.CROSSHAIRS.getKey(), crosshairs); } public void setTooltipShared(boolean shared) { putTooltip(ChartKeysUtil.TooltipKey.SHARED.getKey(), shared); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AnalysisController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppAuditType; import com.sohu.cache.dao.AppAuditDao; import com.sohu.cache.dao.InstanceBigKeyDao; import com.sohu.cache.entity.AppAudit; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.ParamCount; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.constant.IdleTimeDistriEnum; import com.sohu.cache.task.constant.TtlTimeDistriEnum; import com.sohu.cache.task.constant.ValueSizeDistriEnum; import com.sohu.cache.task.entity.InstanceBigKey; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.AppEmailUtil; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import redis.clients.jedis.Tuple; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; import java.util.Set; /** * Created by yijunzhang */ @Controller public class AnalysisController extends BaseController { @Autowired private AssistRedisService assistRedisService; @Autowired private InstanceBigKeyDao instanceBigKeyDao; @Autowired private TaskService taskService; @Autowired private AppAuditDao appAuditDao; @Autowired private AppEmailUtil appEmailUtil; /** * key分析 */ @RequestMapping("/admin/app/key") public ModelAndView appKey(Model model, Long appId) { AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); List appAuditList = appService.getAppAudits(appId, AppAuditType.KEY_ANALYSIS.getValue()); model.addAttribute("appAuditList", appAuditList); return new ModelAndView("analysis/appKey"); } /** * 提交前置键值分析申请 * * @param appId 应用id */ @RequestMapping(value = "/admin/app/keyAnalysis") public ModelAndView submitKeyAnalysis(HttpServletRequest request, HttpServletResponse response, Long appId, String nodeInfo, String appAnalysisReason) { try { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService.saveAppKeyAnalysis(appDesc, appUser, appAnalysisReason, nodeInfo); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { logger.error(e.getMessage(), e); write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * key分析结果 */ @RequestMapping("/admin/app/keyAnalysisResult") public ModelAndView keyAnalysisResult(Model model, Long appId, long auditId) { AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //idle String idleKeyResultKey = ConstUtils.getRedisServerIdleKey(appId, auditId); Set idleKeyTuples = assistRedisService.zrangeWithScores(idleKeyResultKey, 0, -1); List idleKeyParamCountList = new ArrayList(); for (Tuple tuple : idleKeyTuples) { String element = tuple.getElement(); IdleTimeDistriEnum idleTimeDistriEnum = IdleTimeDistriEnum.getByValue(element); ParamCount paramCount = new ParamCount(idleTimeDistriEnum.getInfo(), tuple.getScore(), ""); idleKeyParamCountList.add(paramCount); } model.addAttribute("idleKeyParamCountList", idleKeyParamCountList); model.addAttribute("idleKeyDistri", JSONObject.toJSONString(idleKeyParamCountList)); //type String keyTypeResultKey = ConstUtils.getRedisServerTypeKey(appId, auditId); Set keyTypeTuples = assistRedisService.zrangeWithScores(keyTypeResultKey, 0, -1); List keyTypeParamCountList = new ArrayList(); for (Tuple tuple : keyTypeTuples) { ParamCount paramCount = new ParamCount(tuple.getElement(), tuple.getScore(), ""); keyTypeParamCountList.add(paramCount); } model.addAttribute("keyTypeParamCountList", keyTypeParamCountList); model.addAttribute("keyTypeDistri", JSONObject.toJSONString(keyTypeParamCountList)); //ttl String keyTtlResultKey = ConstUtils.getRedisServerTtlKey(appId, auditId); Set keyTtlTuples = assistRedisService.zrangeWithScores(keyTtlResultKey, 0, -1); List keyTtlParamCountList = new ArrayList(); for (Tuple tuple : keyTtlTuples) { String element = tuple.getElement(); TtlTimeDistriEnum ttlTimeDistriEnum = TtlTimeDistriEnum.getByValue(element); ParamCount paramCount = new ParamCount(ttlTimeDistriEnum.getInfo(), tuple.getScore(), ""); keyTtlParamCountList.add(paramCount); } model.addAttribute("keyTtlParamCountList", keyTtlParamCountList); model.addAttribute("keyTtlDistri", JSONObject.toJSONString(keyTtlParamCountList)); //key value size String keyValueSizeResultKey = ConstUtils.getRedisServerValueSizeKey(appId, auditId); Set keyValueSizeTuples = assistRedisService.zrangeWithScores(keyValueSizeResultKey, 0, -1); List keyValueSizeParamCountList = new ArrayList(); for (Tuple tuple : keyValueSizeTuples) { String element = tuple.getElement(); ValueSizeDistriEnum valueSizeDistriEnum = ValueSizeDistriEnum.getByValue(element); ParamCount paramCount = new ParamCount(valueSizeDistriEnum.getInfo(), tuple.getScore(), ""); keyValueSizeParamCountList.add(paramCount); } model.addAttribute("keyValueSizeParamCountList", keyValueSizeParamCountList); model.addAttribute("keyValueSizeDistri", JSONObject.toJSONString(keyValueSizeParamCountList)); //big List instanceBigKeyList = instanceBigKeyDao.getAppBigKeyList(appId, auditId, null); model.addAttribute("instanceBigKeyCount", instanceBigKeyList.size()); instanceBigKeyList = instanceBigKeyList.subList(0, Math.min(instanceBigKeyList.size(), 100)); model.addAttribute("instanceBigKeyList", instanceBigKeyList); return new ModelAndView("analysis/keyAnalysis"); } /** * 审批执行键值分析 */ @RequestMapping(value = "/manage/app/startKeyAnalysis") public ModelAndView startKeyAnalysis(HttpServletRequest request) { long appId = NumberUtils.toLong(request.getParameter("appId")); long auditId = NumberUtils.toLong(request.getParameter("appAuditId")); appAuditDao.updateAppAuditOperateUser(auditId, getUserInfo(request).getId()); long taskId = taskService.addAppKeyAnalysisTask(appId, auditId, 0); return new ModelAndView("redirect:/manage/task/flow?taskId=" + taskId); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppAutomationApiController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.*; import com.sohu.cache.entity.*; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.StringUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.sql.Timestamp; import java.util.*; /** * Created by chenshi on 2018/10/29. */ @RestController @RequestMapping("/api/automation") public class AppAutomationApiController extends BaseController { // httpcode:500异常信息 private static String ERROR_EXCEPTION = "系统异常:%s"; private static String ERROR_APP_NAME_REPEATE = "应用名称:%s重复"; private static String ERROR_APP_REDISVERSION_NOEXIST = "Redis版本:%s不存在"; private static String ERROR_APP_USER_NOEXIST = "用户信息不完整:%s"; private static String ERROR_MACHINE_CLUSTER_NOTENOUGH = "RedisCluster集群机器:%s数量少于3台"; private static String ERROR_MACHINE_SENTINEL_NOTENOUGH = "RedisSentinel集群机器:%s数量少于2台"; private static String ERROR_MACHINE_IPINFO = "机器列表iplist:%s,非法机器ip:%s"; private static String ERROR_RESOURCE_INSUFFICENT = "机器:%s实例资源分配不足"; private static String ERROR_MEM_ASSIGN = "申请内存:%s M, 机器剩余总内存:%s M,内存分配不足(至少%s M)"; private static String ERROR_CPU_ASSIGN = "实例数:%s , 机器总核数:%s, cpu分配不足"; private static String ERROR_REDIS_FORMAT = "部署格式检查异常:%s "; private static String ERROR_SETNIENL_NOTENOUGH = "RedisSentinel机器分配不足"; private static String ERROR_APP_TOKEN = "token校验异常:%s,没有权限调用"; private static String ERROR_INSTANCE_NUM = "%s应用部署异常,当前实例数:%s"; // info信息 private static String ERROR_APP_SAVE_INFO = "应用信息保存异常"; private static String ERROR_REDIS_DEPLOY_INFO = "Redis应用部署异常"; private static String ERROR_REDISCLUSTER_INTEGRITY_INFO = "RedisCluster slots不等于16384, slots num="; private static String ERROR_APP_SETPASSWD_INFO = "应用设置密码异常"; private static String SUCCESS_INFO = "创建成功"; // 内存分配上限 private static double MEM_MAX_RATIO = 0.85;// 85%留给应用使用 private static int MAX_INSTANCE_MEM = 2;// 最大分片2G // app token private static String APP_TOKEN = "appAdd"; /** *

* Description: 应用状态检测接口 *

* * @author chenshi * @version 1.0 * @date 2018/11/14 */ @RequestMapping(value = "/app/inspect", method = {RequestMethod.POST, RequestMethod.GET}) public ResponseEntity>> appInspect( @RequestHeader(value = "token") String token, @RequestBody List appIds) { // 1.token 校验 if (token.isEmpty() || !token.equals(APP_TOKEN)) { logger.error("error token:{}", String.format(ERROR_APP_TOKEN, token)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } // 2.appids 校验 if (CollectionUtils.isEmpty(appIds)) { logger.error("error param: appIds:{}", appIds); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } // 3.获取appid 状态 try { List appDescs = appService.checkAppStatus(appIds); List> lists = new ArrayList>(); for (AppDesc appDesc : appDescs) { Map map = new HashMap(); map.put("appid", appDesc.getAppId()); map.put("status", appDesc.getStatus()); if (appDesc.getStatus() == 4) { List appAudits = appService.getAppAudits(appDesc.getAppId(), AppAuditType.APP_AUDIT.getValue()); if (!CollectionUtils.isEmpty(appAudits)) { map.put("message", appAudits.get(0).getRefuseReason()); } } lists.add(map); } return ResponseEntity.status(HttpStatus.OK).body(lists); } catch (Exception e) { logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); } } /** *

* Description: api自动创建集群 *

* * @author chenshi * @version 1.0 * @date 2018/11/14 */ @RequestMapping(value = "/app", method = {RequestMethod.POST}) public ResponseEntity addApp( @RequestHeader(value = "token") String token, @RequestBody AppInfoApi appInfoApi) { // 接口执行时间 long startTime = System.currentTimeMillis(); JSONObject response = new JSONObject(); /** * 1.token权限校验 */ if (token.isEmpty() || !token.equals(APP_TOKEN)) { logger.error("error:{}", String.format(ERROR_APP_TOKEN, token)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_APP_TOKEN, token)); } /** * 2.默认属性设置 */ setDefaultConfig(appInfoApi); /** * 3. 基础信息检查 */ RedisVersion redisVersion = null; AppUser appUser = null; try { //1.1 应用名 AppDesc appByName = appService.getAppByName(appInfoApi.getName()); if (appByName != null && appByName.getAppId() > 0) { logger.error("error:{}", String.format(ERROR_APP_NAME_REPEATE, appInfoApi.getName())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_APP_NAME_REPEATE, appInfoApi.getName())); } // 1.2 redisVersion SystemResource redisResource = redisConfigTemplateService.getRedisVersionByName(appInfoApi.getRedisVersion()); if (redisResource != null && redisResource.getId() > 0) { logger.error("error:{}", String.format(ERROR_APP_REDISVERSION_NOEXIST, appInfoApi.getRedisVersion())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_APP_REDISVERSION_NOEXIST, appInfoApi.getRedisVersion())); } logger.info("redisVersion:{}", redisVersion); // 1.3 获取用户信息 AppUser user = appInfoApi.getUser(); if (user == null || StringUtils.isEmpty(user.getName())) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_APP_USER_NOEXIST, appInfoApi.getUser())); } if (!StringUtils.isEmpty(user.getName())) { appUser = userService.getByName(appInfoApi.getUser().getName()); logger.info("get user:{}", appUser); } // 如果不是cc用户 自动创建 if (appUser == null) { appUser = new AppUser(user.getName(), user.getChName(), user.getEmail(), user.getMobile(), user.getWeChat(), AppUserTypeEnum.REGULAR_USER.value(), AppUserAlertEnum.YES.value()); userService.save(appUser); logger.info("create new appUser:{}", appUser); } if (appUser.getId() == null) { logger.error("error:{}", String.format(ERROR_APP_USER_NOEXIST, appInfoApi.getUser().getName())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_APP_USER_NOEXIST, appInfoApi.getUser().getName())); } // 1.4 机器ip合法性验证 if (!CollectionUtils.isEmpty(appInfoApi.getIplist())) { // 非法机器ip信息 List invalidIps = new ArrayList(); for (String ip : appInfoApi.getIplist()) { if (!StringUtils.isEmpty(ip)) { MachineInfo machineinfo = machineCenter.getMachineInfoByIp(ip); if (machineinfo == null) { invalidIps.add(ip); } } } // 存在非法机器信息 返回异常信息 if (!CollectionUtils.isEmpty(invalidIps) && invalidIps.size() > 0) { logger.error("iplist:{} exist invalid ipinfo:{}", appInfoApi.getIplist(), invalidIps); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_MACHINE_IPINFO, appInfoApi.getIplist(), invalidIps)); } } else { logger.error("iplist is empty ,error:{}", appInfoApi.getIplist()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_MACHINE_IPINFO, appInfoApi.getIplist(), "无可用机器ip")); } // 1.5 集群 机器数>=3 sentinel 机器数>=2 sentinel单独分配 if (appInfoApi.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER && appInfoApi.getIplist().size() < 3) { logger.error("error:{}", String.format(ERROR_MACHINE_CLUSTER_NOTENOUGH, appInfoApi.getIplist())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_MACHINE_CLUSTER_NOTENOUGH, appInfoApi.getIplist())); } else if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL && appInfoApi.getIplist().size() < 2) { logger.error("error:{}", String.format(ERROR_MACHINE_SENTINEL_NOTENOUGH, appInfoApi.getIplist())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_MACHINE_SENTINEL_NOTENOUGH, appInfoApi.getIplist())); } } catch (Exception e) { // exception 系统异常 500 logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 4.自动分配实例 * 4.1 自动计算实例个数 instanceNum * 4.2 实例分配完成合理性验证 */ List deployInfoList = new ArrayList(); List machineMems = new ArrayList(); String sentinelMachines = "";//setnienl节点列表 String appDeployText = "";//部署实例信息 StringBuilder appDeployTextBuilder = new StringBuilder(); try { String ips = String.join(",", appInfoApi.getIplist()); logger.info("ips :" + ips); if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { //从机器列表获取sentinel节点 sentinelMachines = autoSelectSentinel(appInfoApi); if (sentinelMachines == null) { logger.error(String.format(ERROR_SETNIENL_NOTENOUGH)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_SETNIENL_NOTENOUGH)); } } String result = appService.generateDeployInfo(appInfoApi.getType(), appInfoApi.getHasSlave(), appInfoApi.getRoom(), Double.parseDouble(appInfoApi.getMemTotalSize() * 1024 + ""), appInfoApi.getIplist().size(), appInfoApi.getInstanceNum(), 0, ips, "", sentinelMachines, deployInfoList, machineMems); logger.info("assign redis instance result :" + result); // 4.2 拆解实例 if (!CollectionUtils.isEmpty(deployInfoList)) { for (DeployInfo deployInfo : deployInfoList) { if (appInfoApi.getHasSlave() == 1) { if (deployInfo.getMasterIp() != null) { //appDeployText += deployInfo.getMasterIp() + ConstUtils.COLON + deployInfo.getMemSize() + ConstUtils.COLON + deployInfo.getSlaveIp() + "\n"; appDeployTextBuilder.append(deployInfo.getMasterIp()) .append(ConstUtils.COLON) .append(deployInfo.getMemSize()) .append(ConstUtils.COLON) .append(deployInfo.getSlaveIp()) .append("\n"); } if (deployInfo.getSentinelIp() != null) { //appDeployText += deployInfo.getSentinelIp() + "\n"; appDeployTextBuilder.append(deployInfo.getSentinelIp()).append("\n"); } } else { if (deployInfo.getMasterIp() != null) { //appDeployText += deployInfo.getMasterIp() + ConstUtils.COLON + deployInfo.getMemSize() + "\n"; appDeployTextBuilder.append(deployInfo.getMasterIp()) .append(ConstUtils.COLON) .append(deployInfo.getMemSize()) .append("\n"); } if (deployInfo.getSentinelIp() != null) { //appDeployText += deployInfo.getSentinelIp() + "\n"; appDeployTextBuilder.append(deployInfo.getSentinelIp()).append("\n"); } } } } else { logger.error(String.format(ERROR_RESOURCE_INSUFFICENT, ips)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_RESOURCE_INSUFFICENT, ips)); } appDeployText = appDeployTextBuilder.toString(); logger.info("deployInfo : {}", appDeployText); } catch (Exception e) { // exception 系统异常 500 logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 5. 应用信息部署前 实例格式检查 * 5.1 内存/cpu核数检查 * 5.2 实例格式检查 */ try { // cpu和mem检查 Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); if (!CollectionUtils.isEmpty(machineMems)) { long remainMem = 0; int remianCpu = 0; for (MachineMemStatInfo machineMemStatInfo : machineMems) { remainMem += (machineMemStatInfo.getMem() * 1024 - machineMemStatInfo.getApplyMem() / 1024 / 1024); int machineCpu = machineInstanceCountMap.get(machineMemStatInfo.getIp()) == null ? 0 : machineInstanceCountMap.get(machineMemStatInfo.getIp()); remianCpu += machineMemStatInfo.getCpu() - machineCpu; } // 1)机器剩余内存量 long applyMem = appInfoApi.getHasSlave() == 0 ? appInfoApi.getMemTotalSize() * 1024 : appInfoApi.getMemTotalSize() * 2 * 1024; if (remainMem * MEM_MAX_RATIO < applyMem) { logger.error(String.format(ERROR_MEM_ASSIGN, applyMem, remainMem, applyMem * 1.25)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_MEM_ASSIGN, applyMem, remainMem, applyMem * 1.25)); } // 2).机器剩余cpu核数,应用部署实例数,需要判断是否有主从 int instanceNumber = 1; //standalone if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { instanceNumber = 2; } else if (appInfoApi.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { instanceNumber = appInfoApi.getHasSlave() == 1 ? appInfoApi.getInstanceNum() * 2 + 1 : appInfoApi.getInstanceNum() + 1; } if (instanceNumber > remianCpu) { // cpu核数不够 logger.error(String.format(ERROR_CPU_ASSIGN, instanceNumber, remianCpu)); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_CPU_ASSIGN, instanceNumber, remianCpu)); } logger.info("remain cpuNum:{},app instanceNum:{},applyMemTotal:{}M, remian machineMemTotal:{}M", remianCpu, instanceNumber, applyMem, remainMem); } } catch (Exception e) { logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } // 实例格式检查 try { DataFormatCheckResult dataFormatCheckResult = appDeployCenter.checkAppDeployDetail4Api(appInfoApi, appDeployText, redisVersion); if (!dataFormatCheckResult.isSuccess()) { //检查异常 logger.error(String.format(ERROR_REDIS_FORMAT, dataFormatCheckResult.getMessage())); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_REDIS_FORMAT, dataFormatCheckResult.getMessage())); } } catch (Exception e) { // exception 系统异常 500 logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 6.appDesc 和 appAudit 应用信息保存 */ AppAudit appAudit = saveAppInfoAndLog(redisVersion, appUser, appInfoApi); if (appAudit == null) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, ERROR_APP_SAVE_INFO)); } Long appId = appAudit.getAppId(); Long appAuditId = appAudit.getId(); if (appId == null || appAuditId == null) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, ERROR_APP_SAVE_INFO)); } // 获取应用信息 AppDesc appDesc = appService.getByAppId(appId); /** * 7.异步提交创建应用任务 */ asyncExecuteAppDeployTask(appId, appAuditId, appDeployText, appUser, appInfoApi); /** * 8.发邮件通知管理员 */ if (appDesc != null) { appEmailUtil.noticeAppResultByApi(appDesc, appAudit); } logger.info("api create appdesc cost time :{} ms", (System.currentTimeMillis() - startTime)); response.put("cost", System.currentTimeMillis() - startTime); response.put("status", appDesc.getStatus()); response.put("appId", appId); return ResponseEntity.status(HttpStatus.OK).body(response.toString()); } /** *

* Description: 创建集群异步任务 *

* * @author chenshi * @version 1.0 * @date 2018/11/14 */ public void asyncExecuteAppDeployTask(final Long appId, final Long appAuditId, final String appDeployText, final AppUser appUser, final AppInfoApi appInfoApi) { String key = "app-automation-" + appId; asyncService.submitFuture(AsyncThreadPoolFactory.APP_POOL, new KeyCallable(key) { public Boolean execute() { try { long start = System.currentTimeMillis(); ResponseEntity result = deployApp(appId, appAuditId, appDeployText, appUser, appInfoApi); logger.info("async execute task :{} , cost time:{} ms", result, System.currentTimeMillis() - start); if (result.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) { // 记录异常原因 appAuditDao.updateRefuseReason(appAuditId, result.getBody()); } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); } /** *

* Description: 部署应用 *

* * @author chenshi * @version 1.0 * @date 2018/11/14 */ public ResponseEntity deployApp(Long appId, Long appAuditId, String appDeployText, AppUser appUser, AppInfoApi appInfoApi) { /** * 1.开始部署redis */ try { boolean isSuccess = false; if (appAuditId != null && StringUtils.isNotBlank(appDeployText)) { String[] appDetails = appDeployText.split("\n"); // 部署service isSuccess = appDeployCenter.allocateResourceApp(appAuditId, Arrays.asList(appDetails), appUser); } // 部署失败 直接返回 if (!isSuccess) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, ERROR_REDIS_DEPLOY_INFO)); } logger.info("deploy rediscluster :" + isSuccess); } catch (Exception e) { // exception 系统异常 500 logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 2.集群完整性验证 */ int slotsNum = 0; try { if (appInfoApi.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { //等待集群握手,有时api获取会不完整 Thread.sleep(2000); logger.info("wait 2 seocnds for cluster meet success!"); Map clusterSlotsMap = redisCenter.getClusterSlotsMap(appId); logger.info("==================clusterSlots validate =================="); for (Map.Entry InstanceSlot : clusterSlotsMap.entrySet()) { slotsNum += InstanceSlot.getValue().getSlotList().size(); } logger.info("cluster slots assign num =" + slotsNum); if (slotsNum != 16384) { logger.info("==================cluster is not ok ! =================="); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, ERROR_REDISCLUSTER_INTEGRITY_INFO + slotsNum)); } } } catch (Exception e) { logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 3.部署节点个数验证 */ AppDesc appDesc = appService.getByAppId(appId); try { // 部署节点数验证 List instancelist = instanceDao.getEffectiveInstListByAppId(appId); if (CollectionUtils.isEmpty(instancelist)) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_INSTANCE_NUM, appDesc.getTypeDesc(), 0)); } logger.info("appid :{} ,type:{}, redis instanceNum ={}", appId, appDesc.getTypeDesc(), instancelist.size()); // cluster/standalone/sentinel节点数验证 if (appInfoApi.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER && instancelist.size() < 3) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_INSTANCE_NUM, appDesc.getTypeDesc(), instancelist.size())); } else if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL && instancelist.size() < 5) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_INSTANCE_NUM, appDesc.getTypeDesc(), instancelist.size())); } else if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_STANDALONE && instancelist.size() != 1) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_INSTANCE_NUM, appDesc.getTypeDesc(), instancelist.size())); } } catch (Exception e) { logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, e.getMessage())); } /** * 4.设置验证密码 */ try { if (appId > 0) { // 设置密码 redisDeployCenter.fixPassword(appId, null, null, true); // 密码校验逻辑 boolean checkFlag = redisDeployCenter.checkAuths(appId); logger.info("check app passwd:" + checkFlag); } } catch (Exception e) { logger.error(e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(String.format(ERROR_EXCEPTION, ERROR_APP_SETPASSWD_INFO)); } return ResponseEntity.status(HttpStatus.OK).body("应用创建成功"); } /** * 保存应用和审核信息 * * @param redisVersion 版本信息 * @param appUser 用户信息 * @return 审核对象 */ public AppAudit saveAppInfoAndLog(RedisVersion redisVersion, AppUser appUser, AppInfoApi appInfoApi) { try { AppDesc appDesc = new AppDesc(); appDesc.setName(appInfoApi.getName()); appDesc.setIntro(appInfoApi.getDesc() == null ? "" : appInfoApi.getDesc()); appDesc.setClientMachineRoom(appInfoApi.getRoom() == null ? "" : appInfoApi.getRoom()); appDesc.setType(appInfoApi.getType()); appDesc.setIsTest(appInfoApi.getIsTest()); appDesc.setTypeDesc(appDesc.getTypeDesc()); appDesc.setVersionId(redisVersion.getId()); appDesc.setUserId(appUser.getId()); appDesc.setOfficer(String.valueOf(appUser.getId())); appDesc.setClientConnAlertValue(2000); appDesc.setForecaseQps(1000); appDesc.setForecastObjNum(100000); appDesc.setMemAlertValue(85); appDesc.setVerId(1);//获取版本id appDesc.setStatus((short) AppStatusEnum.STATUS_ALLOCATED.getStatus()); // 设置命中率报警0,默认不监控 appDesc.setHitPrecentAlertValue(0); // 客户端默认关闭监控 appDesc.setIsAccessMonitor(AppUserAlertEnum.NO.value()); Timestamp now = new Timestamp(new Date().getTime()); appDesc.setCreateTime(now); appDesc.setPassedTime(now); appService.save(appDesc); // 保存应用和用户的关系 appService.saveAppToUser(appDesc.getAppId(), appDesc.getUserId()); // 更新appKey long appId = appDesc.getAppId(); appService.updateAppKey(appId); // 保存应用审批信息 AppAudit appAudit = new AppAudit(); appAudit.setAppId(appId); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); appAudit.setParam1(String.valueOf(appInfoApi.getMemTotalSize())); appAudit.setParam2(appDesc.getTypeDesc()); appAudit.setInfo("类型:" + appDesc.getTypeDesc() + ";初始申请空间:" + appInfoApi.getMemTotalSize() + "G (API创建)"); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(AppAuditType.APP_AUDIT.getValue()); appAuditDao.insertAppAudit(appAudit); logger.info("appAudit :" + appAudit); // 保存申请日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_DESC_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } /** *

* Description:初始化设置 *

* * @author chenshi * @version 1.0 * @date 2018/10/31 */ public void setDefaultConfig(AppInfoApi appInfoApi) { //1.实例数量 if (appInfoApi.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { int memTotalSize = appInfoApi.getMemTotalSize(); int maxInstanceMem = MAX_INSTANCE_MEM;//2G int machineNum = appInfoApi.getIplist().size(); int instanceNum = 3; // 1.正式应用 /测试计算实例数量 if (machineNum < 3) { logger.info(" machine is not enough !"); } if (maxInstanceMem * 3 <= memTotalSize) { instanceNum = memTotalSize / maxInstanceMem; //取整 } if (maxInstanceMem * 3 > memTotalSize) { instanceNum = machineNum >= 3 ? machineNum : 3; //取默认值 } Double instanceMem = Double.parseDouble(memTotalSize + "") / instanceNum * 1024; logger.info("集群申请内存量:{}G,机器数:{},分配实例数:{},实例内存:{}", memTotalSize, machineNum, instanceNum, instanceMem.intValue()); appInfoApi.setInstanceNum(instanceNum); } else if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { appInfoApi.setInstanceNum(2); } else if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_STANDALONE) { appInfoApi.setInstanceNum(1); } // 2.默认值 sentinel 有slave | 设置sentinel数量 if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_SENTINEL) { appInfoApi.setHasSlave(1);//sentinel节点需要设置主从 if (appInfoApi.getSentinelNum() < 3 || appInfoApi.getSentinelNum() % 2 == 0) { appInfoApi.setSentinelNum(3);//设置默认sentinel节点数量 } } if (appInfoApi.getType() == ConstUtils.CACHE_REDIS_STANDALONE) { appInfoApi.setHasSlave(0);//standalone节点不设置从节点 } // 3.版本默认值 redis-3.0.7 if (StringUtil.isBlank(appInfoApi.getRedisVersion())) { appInfoApi.setRedisVersion("redis-3.0.7"); } } /** *

* Description:自动获取sentinel节点 *

* * @author chenshi * @version 1.0 * @date 2018/11/1 */ public String autoSelectSentinel(AppInfoApi appInfoApi) { String sentinelMachines = ""; StringBuilder sentinelMachinesBuilder = new StringBuilder(); try { //1. 默认sentinel节点数 int sentinelNum = appInfoApi.getSentinelNum(); List machineMemStatInfoList = machineCenter.getAllValidMachineMem(new ArrayList(), null, 3); List machineCandi = new ArrayList(); for (MachineMemStatInfo memStatInfo : machineMemStatInfoList) { memStatInfo.setInstanceNum(instanceDao.getInstListByIp(memStatInfo.getIp()).size()); appService.getMachineCandiList(memStatInfo, 0d, 1, 0, machineCandi); } // 2.优先挑选空闲机器,否则走随机挑选 if (machineCandi.size() < sentinelNum) { logger.warn("machineCandi size = {},default random sentinel ip!", machineCandi.size()); machineCandi = machineMemStatInfoList; } if (machineCandi.size() < 3) { logger.warn("machineCandi size = {} is not enough!", machineCandi.size()); return null; } // 3.按机房分类 (跨机房部署) List roomList = machineCenter.getEffectiveRoom(); Map> sentinelMachineMap = new HashMap>(); for (MachineRoom room : roomList) { List list = new ArrayList(); sentinelMachineMap.put(room.getName(), list); } for (MachineMemStatInfo memStatInfo : machineCandi) { sentinelMachineMap.get(memStatInfo.getRoom()).add(memStatInfo); } Set sentinelMachineSet = new HashSet(); // 4.for select while (sentinelMachineSet.size() < sentinelNum && sentinelMachineMap.size() >= 3) { for (Map.Entry> entry : sentinelMachineMap.entrySet()) { getResMachines(entry.getValue(), 1, sentinelMachineSet); if (sentinelMachineSet.size() == sentinelNum) { break; } } } logger.info("sentinelMachineSet:{}", sentinelMachineSet); if (sentinelMachineSet.size() >= 3) { for (MachineMemStatInfo sentinelMachine : sentinelMachineSet) { //sentinelMachines += sentinelMachine.getIp() + ","; sentinelMachinesBuilder.append(sentinelMachine.getIp()).append(","); } sentinelMachines = sentinelMachinesBuilder.toString(); sentinelMachines = sentinelMachines.substring(0, sentinelMachines.lastIndexOf(",")); logger.info("sentinelMachines:{}", sentinelMachines); return sentinelMachines; } return null; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } private void getResMachines(List machineCandi, Integer machineNum, Set resMachines) { if (machineCandi == null) { return; } Map map = new HashMap(); if (machineCandi.size() < machineNum) { return; } else { while (map.size() < machineNum) { int random = (int) (Math.random() * machineCandi.size()); if (!map.containsKey(random)) { map.put(random, ""); resMachines.add(machineCandi.get(random)); } } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppClientDataShowController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.client.service.*; import com.sohu.cache.dao.AppClientStatisticGatherDao; import com.sohu.cache.entity.*; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.util.NumberUtil; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.Page; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.TimeUnit; /** * 应用客户端统计相关 * * @author leifu * @Time 2014年8月31日 */ @Controller @RequestMapping("/client/show") public class AppClientDataShowController extends BaseController { /** * 收集数据时间format */ private final static String COLLECT_TIME_FORMAT = "yyyyMMddHHmmss"; @Autowired private AppClientReportCommandService appClientReportCommandService; @Autowired private AppClientReportExceptionService appClientReportExceptionService; /** * 客户端异常服务 */ @Resource(name = "clientReportExceptionService") private ClientReportExceptionService clientReportExceptionService; /** * 应用基本服务 */ @Resource(name = "appService") private AppService appService; /** * 实例信息 */ @Resource(name = "instanceStatsCenter") private InstanceStatsCenter instanceStatsCenter; @Autowired private AppClientStatisticGatherDao appClientStatisticGatherDao; /** * 应用客户端统计首页 */ @RequestMapping("/index") public ModelAndView doIndex(HttpServletRequest request, HttpServletResponse response, Model model) { Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId == null || appId <= 0) { return new ModelAndView(""); } AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appId", appId); model.addAttribute("appDesc", appDesc); model.addAttribute("tabTag", request.getParameter("tabTag")); model.addAttribute("type", request.getParameter("type")); model.addAttribute("searchDate", request.getParameter("searchDate")); model.addAttribute("commandStatisticsStartDate", request.getParameter("commandStatisticsStartDate")); model.addAttribute("commandStatisticsEndDate", request.getParameter("commandStatisticsEndDate")); model.addAttribute("exceptionStartDate", request.getParameter("exceptionStartDate")); model.addAttribute("exceptionEndDate", request.getParameter("exceptionEndDate")); model.addAttribute("valueDistriStartDate", request.getParameter("valueDistriStartDate")); model.addAttribute("valueDistriEndDate", request.getParameter("valueDistriEndDate")); model.addAttribute("costDistriStartDate", request.getParameter("costDistriStartDate")); model.addAttribute("costDistriEndDate", request.getParameter("costDistriEndDate")); model.addAttribute("clientIp", request.getParameter("clientIp")); model.addAttribute("pageNo", request.getParameter("pageNo")); model.addAttribute("firstCommand", request.getParameter("firstCommand")); model.addAttribute("timeDimensionality", request.getParameter("timeDimensionality")); return new ModelAndView("client/appClientIndex"); } /** * 客户端异常查询 */ @RequestMapping("/exception") public ModelAndView doException(HttpServletRequest request, HttpServletResponse response, Model model) { // 1.1 应用信息 Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId <= 0) { return new ModelAndView(""); } AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 1.2 异常类型 int type = NumberUtil.toInt(request.getParameter("type")); model.addAttribute("type", type); // 1.3 客户端ip String clientIp = request.getParameter("clientIp"); model.addAttribute("clientIp", clientIp); // 1.4 日期格式转换 TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithClientExceptionTime(request, model); } catch (ParseException e) { logger.error(e.getMessage(), e); } // 2. 分页查询异常 int totalCount = clientReportExceptionService.getAppExceptionCount(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10); Page page = new Page(pageNo, pageSize, totalCount); model.addAttribute("page", page); List appClientExceptionList = clientReportExceptionService.getAppExceptionList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), type, clientIp, page); model.addAttribute("appClientExceptionList", appClientExceptionList); return new ModelAndView("client/clientException"); } /** * 异常查询日期格式 */ private TimeBetween fillWithClientExceptionTime(HttpServletRequest request, Model model) throws ParseException { final String exceptionDateFormat = "yyyy-MM-dd"; String exceptionStartDateParam = request.getParameter("exceptionStartDate"); String exceptionEndDateParam = request.getParameter("exceptionEndDate"); Date startDate; Date endDate; if (StringUtils.isBlank(exceptionStartDateParam) || StringUtils.isBlank(exceptionEndDateParam)) { // 如果为空默认取昨天和今天 SimpleDateFormat sdf = new SimpleDateFormat(exceptionDateFormat); startDate = sdf.parse(sdf.format(new Date())); endDate = DateUtils.addDays(startDate, 1); exceptionStartDateParam = DateUtil.formatDate(startDate, exceptionDateFormat); exceptionEndDateParam = DateUtil.formatDate(endDate, exceptionDateFormat); } else { endDate = DateUtil.parse(exceptionEndDateParam, exceptionDateFormat); startDate = DateUtil.parse(exceptionStartDateParam, exceptionDateFormat); //限制不能超过7天 if (endDate.getTime() - startDate.getTime() > TimeUnit.DAYS.toMillis(7)) { startDate = DateUtils.addDays(endDate, -7); } } // 前端需要 model.addAttribute("exceptionStartDate", exceptionStartDateParam); model.addAttribute("exceptionEndDate", exceptionEndDateParam); // 查询后台需要 long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } @RequestMapping("/commandStatistics") public ModelAndView doCommandStatistics(HttpServletRequest request, HttpServletResponse response, Model model) { // 1.应用信息 Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId <= 0) { return new ModelAndView(""); } AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 2.获取时间区间 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); searchDate = timeBetween.getFormatStartDate(); model.addAttribute("searchDate", searchDate); try { List> appClientGatherStatList = appClientStatisticGatherDao.getAppClientStatisticByGatherTime(appId, searchDate); model.addAttribute("appClientGatherStat", CollectionUtils.isNotEmpty(appClientGatherStatList) && appClientGatherStatList.size() > 0 ? appClientGatherStatList.get(0) : null); } catch (Exception e) { logger.error(e.getMessage(), e); } // 3.客户端的统计信息 Map>> appClientCommandStatisticsMap = appClientReportCommandService.getAppCommandClientStatistics(appId, null, startTime, endTime, null); model.addAttribute("appClientCommandStatisticsJson", JSONObject.toJSONString(appClientCommandStatisticsMap)); return new ModelAndView("client/clientCommandStatistics"); } @RequestMapping("/commandStatistics/client") public ModelAndView getCommandStatisticsByClient(HttpServletRequest request, HttpServletResponse response, Model model) { // 1.应用信息 Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId <= 0) { return new ModelAndView(""); } model.addAttribute("appId", appId); // 2.获取时间区间 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); model.addAttribute("searchDate", timeBetween.getFormatStartDate()); List clientList = appClientReportCommandService.getAppDistinctClients(appId, startTime, endTime); model.addAttribute("clientList", clientList); List commandList = appClientReportCommandService.getAppDistinctCommand(appId, startTime, endTime); model.addAttribute("commandList", commandList); String firstClient = request.getParameter("firstClient"); if (StringUtils.isBlank(firstClient) && CollectionUtils.isNotEmpty(clientList)) { firstClient = clientList.get(0); } model.addAttribute("firstClient", firstClient); String firstCommand = request.getParameter("firstCommand"); if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(commandList)) { firstCommand = commandList.get(0); } model.addAttribute("firstCommand", firstCommand); if ("all".equals(firstClient)) { List> sumCommandStatList = appClientReportCommandService.getSumCmdStatByCmd(appId, startTime, endTime, firstCommand); model.addAttribute("sumCommandStatJson", JSONObject.toJSONString(sumCommandStatList)); } else if ("all".equals(firstCommand)) { List> sumClientStatList = appClientReportCommandService.getSumCmdStatByClient(appId, startTime, endTime, firstClient); model.addAttribute("sumClientStatJson", JSONObject.toJSONString(sumClientStatList)); } else { Map>> appClientCommandStatisticsMap = appClientReportCommandService.getAppCommandClientStatistics(appId, firstCommand, startTime, endTime, firstClient); model.addAttribute("appClientCommandStatisticsJson", JSONObject.toJSONString(appClientCommandStatisticsMap)); } return new ModelAndView("client/commandStatisticsByClient"); } @RequestMapping("/exceptionStatistics") public ModelAndView doExceptionStatistics(HttpServletRequest request, HttpServletResponse response, Model model) { // 1.应用信息 Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId <= 0) { return new ModelAndView(""); } AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 2.获取时间区间 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); searchDate = timeBetween.getFormatStartDate(); model.addAttribute("searchDate", searchDate); try { List> appClientGatherStatList = appClientStatisticGatherDao.getAppClientStatisticByGatherTime(appId, searchDate); model.addAttribute("appClientGatherStat", CollectionUtils.isNotEmpty(appClientGatherStatList) && appClientGatherStatList.size() > 0 ? appClientGatherStatList.get(0) : null); } catch (Exception e) { logger.error(e.getMessage(), e); } // 3.客户端的统计信息 Map>> appClientExceptionStatisticsMap = appClientReportExceptionService.getAppExceptionStatisticsMap(appId, null, startTime, endTime, null); model.addAttribute("appClientExceptionStatisticsJson", JSONObject.toJSONString(appClientExceptionStatisticsMap)); return new ModelAndView("client/clientExceptionStatistics"); } @RequestMapping("/exceptionStatistics/client") public ModelAndView getExceptionStatisticsByClient(HttpServletRequest request, HttpServletResponse response, Model model) { // 1.应用信息 Long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId <= 0) { return new ModelAndView(""); } model.addAttribute("appId", appId); Integer type = NumberUtils.toInt(request.getParameter("exceptionType")); String viewName = type == 0 ? "connExceptionStatisticsByClient" : "cmdExceptionStatisticsByClient"; // 2.获取时间区间 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); model.addAttribute("searchDate", timeBetween.getFormatStartDate()); Map> clientConfigMap = appClientReportExceptionService.getAppClientConfigs(appId, type, startTime, endTime); model.addAttribute("clientConfigMap", clientConfigMap); String firstClient = request.getParameter("firstClient"); if (StringUtils.isBlank(firstClient) && CollectionUtils.isNotEmpty(clientConfigMap.keySet())) { firstClient = clientConfigMap.keySet().iterator().next(); } model.addAttribute("firstClient", firstClient); Map>> appClientExceptionStatisticsMap = appClientReportExceptionService.getAppExceptionStatisticsMap(appId, firstClient, startTime, endTime, type); model.addAttribute("appClientExceptionStatisticsJson", JSONObject.toJSONString(appClientExceptionStatisticsMap)); List> appNodeExceptionStatisticsList = appClientReportExceptionService.getDistinctClientNodeStatistics(appId, firstClient, startTime, endTime, type); model.addAttribute("appNodeExceptionStatisticsList", appNodeExceptionStatisticsList); return new ModelAndView("client/" + viewName); } @RequestMapping(value = "/sumCommandStat/command") public void getSumCmdStatByCmd(HttpServletRequest request, HttpServletResponse response) { Long appId = NumberUtils.toLong(request.getParameter("appId")); String command = request.getParameter("command"); String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); JSONObject json = new JSONObject(); String result = "success"; List> sumCommandStatMap = appClientReportCommandService.getSumCmdStatByCmd(appId, startTime, endTime, command); if (CollectionUtils.isEmpty(sumCommandStatMap)) { result = "sumCommandStatMap is empty"; } json.put("result", result); json.put("sumCommandStatMap", sumCommandStatMap); sendMessage(response, json.toString()); } @RequestMapping(value = "/latencyCommandDetails") public ModelAndView getLatencyCommandDetails(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); model.addAttribute("appId", appId); long timestamp = NumberUtils.toLong(request.getParameter("searchTime")); //毫秒 Date date = new Date(timestamp); SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmm00"); long searchTime = NumberUtils.toLong(format.format(date)); model.addAttribute("searchTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:00").format(date)); Map> sumCmdExpStatMap = appClientReportExceptionService.getSumCmdExpStatGroupByNode(appId, searchTime); model.addAttribute("sumCmdExpStatMap", sumCmdExpStatMap); Set nodeSet = sumCmdExpStatMap.keySet(); Map>> latencyCommandDetailMap = appClientReportExceptionService.getLatencyCommandDetails(nodeSet, searchTime); model.addAttribute("latencyCommandDetailMap", latencyCommandDetailMap); return new ModelAndView("/client/cmdExceptionCommandDetail"); } @RequestMapping(value = "/latencyCommandDetail/node") public void getLatencyCommandDetailByNode(HttpServletRequest request, HttpServletResponse response) { JSONObject json = new JSONObject(); String result = "success"; String client = request.getParameter("client"); String node = request.getParameter("node"); String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); List> latencyCommandDetailList = appClientReportExceptionService.getLatencyCommandDetailByNode(client, node, startTime, endTime); if (CollectionUtils.isEmpty(latencyCommandDetailList)) { result = "latencyCommandDetailList is empty"; } json.put("result", result); json.put("latencyCommandDetailList", latencyCommandDetailList); sendMessage(response, json.toString()); } private TimeBetween fillWithDateFormat(String searchDate) throws ParseException { final String dateFormat = "yyyy-MM-dd"; Date startDate; Date endDate; if (StringUtils.isBlank(searchDate)) { // 如果为空默认取今天 SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); startDate = sdf.parse(sdf.format(new Date())); } else { startDate = DateUtil.parse(searchDate, dateFormat); } endDate = DateUtils.addDays(startDate, 1); // 查询后台需要 long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Maps; import com.google.common.collect.Table; import com.sohu.cache.constant.*; import com.sohu.cache.dao.AppUserDao; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.enums.InstanceAlertCheckCycleEnum; import com.sohu.cache.redis.enums.InstanceAlertCompareTypeEnum; import com.sohu.cache.redis.enums.InstanceAlertTypeEnum; import com.sohu.cache.redis.util.Command; import com.sohu.cache.stats.app.AppDailyDataCenter; import com.sohu.cache.stats.app.AppDeployCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceAlertConfigService; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.chart.model.HighchartDoublePoint; import com.sohu.cache.web.chart.model.HighchartPoint; import com.sohu.cache.web.chart.model.SimpleChartData; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.Page; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import redis.clients.jedis.commands.ProtocolCommand; import redis.clients.jedis.util.SafeEncoder; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; /** * 应用统计相关 * * @author leifu * @Time 2014年8月31日 */ @Controller @RequestMapping("/admin/app") public class AppController extends BaseController { private Logger logger = LoggerFactory.getLogger(AppController.class); @Resource(name = "appStatsCenter") private AppStatsCenter appStatsCenter; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; @Resource(name = "appDeployCenter") private AppDeployCenter appDeployCenter; @Resource(name = "instanceStatsCenter") private InstanceStatsCenter instanceStatsCenter; @Resource(name = "appDailyDataCenter") private AppDailyDataCenter appDailyDataCenter; @Resource(name = "instanceAlertConfigService") private InstanceAlertConfigService instanceAlertConfigService; @Autowired private ResourceService resourceService; @Resource private MachineCenter machineCenter; @Resource private UserService userService; @Autowired private AppUserDao appUserDao; @Autowired protected RedisCenter redisCenter; /** * 初始化贡献者页面 * * @return */ @RequestMapping("/initBecomeContributor") public ModelAndView doInitBecomeContributor(HttpServletRequest request, HttpServletResponse response, Model model) { model.addAttribute("currentUser", getUserInfo(request)); return new ModelAndView("app/initBecomeContributor"); } /** * 成为cachecloud贡献者 * * @param groupName 项目组 * @param applyReason 申请理由 * @return */ @RequestMapping("/addBecomeContributor") public ModelAndView doAddBecomeContributor(HttpServletRequest request, HttpServletResponse response, Model model, String groupName, String applyReason) { appEmailUtil.noticeBecomeContributor(groupName, applyReason, getUserInfo(request)); model.addAttribute("success", SuccessEnum.SUCCESS.value()); return new ModelAndView(""); } /** * 单个应用首页 * * @param appId * @param tabTag 标签名 * @param firstCommand 第一条命令 * @return * @throws ParseException */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String tabTag, String firstCommand, String condition) throws ParseException { // 如果应用id为空,取第一个应用id if (appId == null) { return new ModelAndView("redirect:/admin/app/list"); } // 日期转换 String searchDate = request.getParameter("searchDate"); String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date startDate = new Date(); startDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); endDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), "yyyy-MM-dd"); } //慢查询 String slowLogStartDateParam = request.getParameter("slowLogStartDate"); String slowLogEndDateParam = request.getParameter("slowLogEndDate"); if (StringUtils.isBlank(slowLogStartDateParam) || StringUtils.isBlank(slowLogEndDateParam)) { Date startDate = new Date(); slowLogStartDateParam = DateUtil.formatDate(startDate, "yyyy-MM-dd"); slowLogEndDateParam = DateUtil.formatDate(DateUtils.addDays(startDate, 1), "yyyy-MM-dd"); } //日报 String dailyDateParam = request.getParameter("dailyDate"); if (StringUtils.isBlank(dailyDateParam)) { dailyDateParam = DateUtil.formatDate(DateUtils.addDays(new Date(), -1), "yyyy-MM-dd"); } int conditionInt = StringUtils.isEmpty(condition) ? 0 : Integer.parseInt(condition); model.addAttribute("condition", conditionInt); model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); model.addAttribute("searchDate", searchDate); model.addAttribute("slowLogStartDate", slowLogStartDateParam); model.addAttribute("slowLogEndDate", slowLogEndDateParam); model.addAttribute("dailyDate", dailyDateParam); model.addAttribute("appId", appId); model.addAttribute("tabTag", tabTag); model.addAttribute("firstCommand", firstCommand); return new ModelAndView("app/userAppsIndex"); } /** * 应用统计相关 */ @RequestMapping("/stat") public ModelAndView appStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { AppUser appUser = getUserInfo(request); // 1.获取app的VO AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); // 2. 时间 TimeBetween timeBetween = getTimeBetween(request, model, "startDate", "endDate"); long beginTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); // 3.是否超过1天 if (endTime - beginTime > TimeUnit.DAYS.toMillis(1)) { model.addAttribute("betweenOneDay", 0); } else { model.addAttribute("betweenOneDay", 1); } // 4. top5命令 // 对于top5 只展示搜索当天的 TimeBetween oneDaytimeBetween = getTimeBetweenOneDay(request,"startDate"); long top5BeginTime = oneDaytimeBetween.getStartTime(); long top5EndTime = oneDaytimeBetween.getEndTime(); List top5Commands = appStatsCenter .getTopLimitAppCommandStatsList(appId, top5BeginTime, top5EndTime, 5); model.addAttribute("top5Commands", top5Commands); // 5.峰值 List top5ClimaxList = new ArrayList(); if (CollectionUtils.isNotEmpty(top5Commands)) { for (AppCommandStats appCommandStats : top5Commands) { AppCommandStats temp = appStatsCenter .getCommandClimax(appId, top5BeginTime, top5EndTime, appCommandStats.getCommandName()); if (temp != null) { top5ClimaxList.add(temp); } } } if(CollectionUtils.isNotEmpty(top5ClimaxList)){ top5ClimaxList.sort(Comparator.comparingLong(AppCommandStats::getCommandCount).reversed()); } model.addAttribute("top5ClimaxList", top5ClimaxList); if (appDetail != null && StringUtils.isNotBlank(appDetail.getAppDesc().getAppPassword())) { model.addAttribute("md5password", appDetail.getAppDesc().getAppPassword()); } // 7. 当天命令调用总量 Long commandCount = appStatsCenter .getAppCommandCount(appId, oneDaytimeBetween.getStartTime(), oneDaytimeBetween.getEndTime()); model.addAttribute("commandCount", commandCount); // 8. 是否为管理员 boolean isMaster = false; if(appUser != null && AppUserTypeEnum.ADMIN_USER.value().equals(appUser.getType())){ isMaster = true; } model.addAttribute("isMaster", isMaster); model.addAttribute("appId", appId); return new ModelAndView("app/appStat"); } /** * 命令曲线 * * @param firstCommand 第一条命令 */ @RequestMapping("/commandAnalysis") public ModelAndView appCommandAnalysis(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String firstCommand) throws ParseException { // 1.获取app的VO AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); // 2.返回日期 TimeBetween timeBetween = getTimeBetween(request, model, "startDate", "endDate"); // 3.是否超过1天 if(timeBetween.getStartDate() != null && timeBetween.getEndDate() != null && (timeBetween.getEndDate().getTime() - timeBetween.getStartDate().getTime() > TimeUnit.DAYS.toMillis(1))){ model.addAttribute("betweenOneDay", 0); } else { model.addAttribute("betweenOneDay", 1); } // 4.获取top命令 List allCommands = appStatsCenter .getTopLimitAppCommandStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), 20); model.addAttribute("allCommands", allCommands); if (StringUtils.isBlank(firstCommand) && CollectionUtils.isNotEmpty(allCommands)) { model.addAttribute("firstCommand", allCommands.get(0).getCommandName()); } else { model.addAttribute("firstCommand", firstCommand); } model.addAttribute("appId", appId); // 返回标签名 return new ModelAndView("app/appCommandAnalysis"); } /** * 应用故障 */ @RequestMapping("/fault") public ModelAndView appFault(HttpServletRequest request, HttpServletResponse response, Model model) { return new ModelAndView("app/appFault"); } /** * 应用拓扑图 * * @param appId * @return */ @RequestMapping("/topology") public ModelAndView statTopology(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { AppUser userInfo = this.getUserInfo(request); int isAdmin = 0; if(userInfo.getType() == AppUserTypeEnum.ADMIN_USER.value()){ isAdmin = 1; } model.addAttribute("isAdmin", isAdmin); //应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //实例相关信息(包含统计) fillAppInstanceStats(appId, model); return new ModelAndView("app/appTopology"); } @RequestMapping("/appDesc") public ModelAndView appDesc(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { JSONObject json = new JSONObject(); AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { json.put("status", String.valueOf(SuccessEnum.FAIL.value())); } else { json.put("appDesc", appDesc); json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); } sendMessage(response, json.toString()); return null; } /** * 应用机器拓扑图 * * @param appId * @return */ @RequestMapping("/machineInstancesTopology") public ModelAndView machineInstancesTopology(HttpServletRequest request, HttpServletResponse response, Long appId, Model model) { //应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //拓扑 fillAppMachineInstanceTopology(appId, model); return new ModelAndView("app/appMachineInstancesTopology"); } /** * 应用基本信息 * * @param appId 应用id */ @RequestMapping("/detail") public ModelAndView appDetail(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { AppUser appUser = getUserInfo(request); // 获取应用vo AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); model.addAttribute("appDetail", appDetail); //增加全局监控 model.addAttribute("instanceAlertAllList", instanceAlertConfigService.getByType(InstanceAlertTypeEnum.ALL_ALERT.getValue())); model.addAttribute("instanceAlertCheckCycleEnumList", InstanceAlertCheckCycleEnum.getInstanceAlertCheckCycleEnumList()); model.addAttribute("instanceAlertCompareTypeEnumList", InstanceAlertCompareTypeEnum.getInstanceAlertCompareTypeEnumList()); if (appDetail != null && !StringUtils.isEmpty(appDetail.getAppDesc().getAppPassword())) { model.addAttribute("password", appDetail.getAppDesc().getAppPassword()); } else { model.addAttribute("password", ""); } // 用户管理权限 List userList = userService.getAllUser(); Map userMap = userList.stream().collect(Collectors.toMap(AppUser::getId, Function.identity())); model.addAttribute("userMap", userMap); // 业务组 List bizList = userService.getBizList(); model.addAttribute("bizList", bizList); Boolean hasAuth = false; String officer = appDetail.getAppDesc().getOfficer(); List officers = new ArrayList(); if (!StringUtils.isEmpty(officer)) { officers.addAll(Arrays.asList(officer.split(","))); } if (appUser != null && (appUser.getType() == AppUserTypeEnum.ADMIN_USER.value() || officers.contains(String.valueOf(appUser.getId())))) { hasAuth = true; } model.addAttribute("hasAuth", hasAuth); return new ModelAndView("app/appDetail"); } /** * 应用客户端连接 * * @param request * @param response * @param model * @param appId * @return */ @RequestMapping("/clientList") public ModelAndView clientList(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, int condition) { //应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("condition", condition); List instanceInfoList = appService.getAppOnlineInstanceInfo(appId); Map instanceMap = instanceInfoList.stream().collect(Collectors.toMap( InstanceInfo::getId, InstanceInfo::getHostPort)); model.addAttribute("instanceMap", instanceMap); List> addrInstanceList = redisCenter.getAppClientList(appId, condition); model.addAttribute("addrInstanceList", addrInstanceList); return new ModelAndView("app/appClientList"); } /** * 获取某个命令时间分布图 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/getCommandStats") public ModelAndView getCommandStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); long beginTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); // 命令参数 String commandName = request.getParameter("commandName"); List appCommandStatsList; if (StringUtils.isNotBlank(commandName)) { appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime, commandName); } else { appCommandStatsList = appStatsCenter.getCommandStatsList(appId, beginTime, endTime); } String result = assembleJson(appCommandStatsList); write(response, result); return null; } /** * 获取某个命令时间分布图 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/getMutiDatesCommandStats") public ModelAndView getMutiDatesCommandStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); // 命令参数 String commandName = request.getParameter("commandName"); List appCommandStatsList; if (StringUtils.isNotBlank(commandName)) { appCommandStatsList = appStatsCenter .getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE, commandName); } else { appCommandStatsList = appStatsCenter .getCommandStatsListV2(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); } String result = assembleMutilDateAppCommandJsonMinute(appCommandStatsList, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取命中率、丢失率等分布 * * @param appId 应用id * @param statName 统计项(hit,miss等) * @throws ParseException */ @RequestMapping("/getAppStats") public ModelAndView getAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String statName) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List appStats = appStatsCenter .getAppStatsListByMinuteTime(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleAppStatsJson(appStats, statName); write(response, result); return null; } /** * 多命令 * * @param appId * @return * @throws ParseException */ @RequestMapping("/getMutiStatAppStats") public ModelAndView getMutiStatAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { String statNames = request.getParameter("statName"); List statNameList = Arrays.asList(statNames.split(ConstUtils.COMMA)); TimeBetween timeBetween = getJsonTimeBetween(request); List appStats = appStatsCenter .getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); String result = assembleMutiStatAppStatsJsonMinute(appStats, statNameList, timeBetween.getStartDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取命中率、丢失率等分布 * * @param appId 应用id * @param statName 统计项(hit,miss等) * @throws ParseException */ @RequestMapping("/getMutiDatesAppStats") public ModelAndView getMutiDatesAppStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String statName, Integer addDay) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List appStats = appStatsCenter .getAppStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), TimeDimensionalityEnum.MINUTE); String result = assembleMutilDateAppStatsJsonMinute(appStats, statName, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("data", result); return new ModelAndView(""); } /** * 跳转到获取命中率分布页面 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/getAppHitRatioInfo") public ModelAndView getMutiDatesAppHitRatioStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { Date yesterDay = DateUtils.addDays(new Date(), -1); model.addAttribute("appId", appId); model.addAttribute("searchDate", DateUtil.formatDate(yesterDay, "yyyy-MM-dd")); return new ModelAndView("app/appHitRatio"); } /** * 获取命中率分布 * * @param appId 应用id * @param statName 统计项(hit,miss等) * @throws ParseException */ @RequestMapping("/getMutiDatesAppHitRatioStats") public ModelAndView getMutiDatesAppHitRatioStats(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String statName) throws ParseException { String endDateParam = request.getParameter("endDate"); String startDateParam = request.getParameter("startDate"); Date endDate = DateUtil.parseYYYY_MM_dd(endDateParam); Date startDate = null; if (StringUtils.isBlank(startDateParam)) { startDate = DateUtils.addDays(endDate, -30); } else { startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate)); List appDailyDatas = appStatsCenter .getAppHitRatioList(appId, beginTime, endTime); String result = assembleMutilDateAppHitRatio(appDailyDatas, statName); model.addAttribute("data", result); return new ModelAndView(""); } /** * 获取指定时间内某个应用全部实例的统计信息 * * @param appId */ @RequestMapping("/appInstanceNetStat") public ModelAndView appInstanceNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 日期格式转换 getTimeBetween(request, model, "startDate", "endDate"); return new ModelAndView("app/appInstanceNetStat"); } /** * 获取指定时间内某个应用全部实例的CPU统计信息 * * @param appId */ @RequestMapping("/appInstanceCpuStat") public ModelAndView appInstanceCpuStat(HttpServletRequest request, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 日期格式转换 getTimeBetween(request, model, "startDate", "endDate"); return new ModelAndView("app/appInstanceCpuStat"); } /** * 获取指定时间内某个应用全部实例的统计信息 * * @param appId 应用流量 */ @RequestMapping("/getAppInstancesCpuStat") public void getAppInstancesCpuStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { //时间转换 TimeBetween timeBetween = getJsonTimeBetween(request); //缩减字段 String cpuSysCommand = "used_cpu_sys"; String cpuUserCommand = "used_cpu_user"; String cpuSysChildCommand = "used_cpu_sys_children"; String cpuUserChildCommand = "used_cpu_user_children"; Map commandMap = Maps.newHashMap(); commandMap.put(cpuSysCommand, "cs"); commandMap.put(cpuUserCommand, "cu"); commandMap.put(cpuSysChildCommand, "cs_child"); commandMap.put(cpuUserChildCommand, "cu_child"); //获取应用下所有实例网络流量统计 Map>> appInstancesNetStat = instanceStatsCenter .getStandardStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), Arrays.asList(cpuSysCommand, cpuUserCommand, cpuSysChildCommand, cpuUserChildCommand)); //解析成json数组 List> appInstancesNetStatList = new ArrayList>(); for (Entry>> entry : appInstancesNetStat.entrySet()) { Integer instanceId = entry.getKey(); //实例基本信息 Map instanceStatMap = new HashMap(); instanceStatMap.put("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); instanceStatMap.put("instanceInfo", instanceInfo.getIp() + ":" + instanceInfo.getPort()); //每个实例的统计信息 List> instanceCpuStatList = new ArrayList>(); instanceStatMap.put("instanceCpuStatMapList", instanceCpuStatList); appInstancesNetStatList.add(instanceStatMap); //记录输入和输出流量 Map> map = entry.getValue(); List instanceCommandStatsList = new ArrayList(); instanceCommandStatsList.addAll(map.get(cpuSysCommand)); instanceCommandStatsList.addAll(map.get(cpuUserCommand)); instanceCommandStatsList.addAll(map.get(cpuSysChildCommand)); instanceCommandStatsList.addAll(map.get(cpuUserChildCommand)); Map> total = new HashMap>(); for (InstanceCommandStats instanceCommandStat : instanceCommandStatsList) { //用timestamp作为key,保证输入和输出流量在一个Map统计里 long timestamp = instanceCommandStat.getTimeStamp(); long commandCount = instanceCommandStat.getCommandCount(); String command = instanceCommandStat.getCommandName(); //精简字段 command = commandMap.get(command); if (total.containsKey(timestamp)) { Map tmpMap = total.get(timestamp); tmpMap.put(command, commandCount); } else { Map tmpMap = new HashMap(); tmpMap.put("t", timestamp); tmpMap.put(command, commandCount); total.put(timestamp, tmpMap); instanceCpuStatList.add(tmpMap); } } } String result = JSONObject.toJSONString(appInstancesNetStatList); write(response, result); } /** * 获取指定时间内某个应用全部实例的CPU统计信息 * * @param appId */ @RequestMapping("/appInstanceMemFragRatioStat") public ModelAndView appInstanceMemFragRatioStat(HttpServletRequest request, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 日期格式转换 getTimeBetween(request, model, "startDate", "endDate"); return new ModelAndView("app/appInstanceMemFragRatioStat"); } /** * 获取指定时间内某个应用全部实例的统计信息 * * @param appId 应用流量 */ @RequestMapping("/getAppInstancesMemFragRatioStat") public void getAppInstancesMemFragRatioStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { //时间转换 TimeBetween timeBetween = getJsonTimeBetween(request); //缩减字段 String ratioCommand = "mem_fragmentation_ratio"; Map commandMap = Maps.newHashMap(); commandMap.put(ratioCommand, "ratio"); long start = System.currentTimeMillis(); //获取应用下所有实例碎片率统计 Table>> table = instanceStatsCenter .getInstanceMinuteStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), Arrays.asList(ratioCommand)); logger.warn("getInstanceMinuteStatsList cost:{} ms", (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); //解析成json数组 List> appInstancesMemFragRatioStatList = new ArrayList>(); for (Table.Cell>> cell : table.cellSet()) { Integer instanceId = cell.getRowKey(); //实例基本信息 Map instanceStatMap = new HashMap(); instanceStatMap.put("instanceId", instanceId); instanceStatMap.put("instanceInfo", cell.getColumnKey()); //每个实例的统计信息 List> instanceMemFragRatioStatList = new ArrayList>(); instanceStatMap.put("instanceMemFragRatioStatMapList", instanceMemFragRatioStatList); appInstancesMemFragRatioStatList.add(instanceStatMap); //记录碎片率 Map> map = cell.getValue(); List instanceCommandStatsList = new ArrayList<>(); instanceCommandStatsList.addAll(map.get(ratioCommand)); Map> total = new HashMap>(); for (InstanceMinuteStats instanceMinuteStats : instanceCommandStatsList) { //用timestamp作为key,保证在一个Map统计里 long timestamp = instanceMinuteStats.getTimeStamp(); double memFragRatio = instanceMinuteStats.getMemFragmentationRatio(); String command = instanceMinuteStats.getCommandName(); //精简字段 command = commandMap.get(command); if (total.containsKey(timestamp)) { Map tmpMap = total.get(timestamp); tmpMap.put(command, memFragRatio); } else { Map tmpMap = new HashMap(); tmpMap.put("t", timestamp); tmpMap.put(command, memFragRatio); total.put(timestamp, tmpMap); instanceMemFragRatioStatList.add(tmpMap); } } } String result = JSONObject.toJSONString(appInstancesMemFragRatioStatList); logger.warn("parse Json cost:{} ms", (System.currentTimeMillis() - start)); write(response, result); } /** * 获取指定时间内某个应用全部实例的过期/淘汰键统计信息 * * @param appId */ @RequestMapping("/appInstanceExpiredEvictedKeysStat") public ModelAndView appInstanceExpiredEvictedKeysStat(HttpServletRequest request, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); model.addAttribute("appId", appId); // 日期格式转换 getTimeBetween(request, model, "startDate", "endDate"); return new ModelAndView("app/appInstanceExpiredEvictedKeysStat"); } /** * 获取指定时间内某个应用全部实例的过期/淘汰键统计信息 * @param appId 应用流量 */ @RequestMapping("/getAppInstancesExpiredEvictedKeysStat") public void getAppInstancesExpiredEvictedKeysStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { //时间转换 TimeBetween timeBetween = getJsonTimeBetween(request); //缩减字段 String expiredKeysCommand = "expired_keys"; String evictedKeysCommand = "evicted_keys"; Map commandMap = Maps.newHashMap(); commandMap.put(expiredKeysCommand, "exkey"); commandMap.put(evictedKeysCommand, "evkey"); long start = System.currentTimeMillis(); //获取应用下所有实例过期/淘汰键 Table>> table = instanceStatsCenter .getInstanceMinuteStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), Arrays.asList(expiredKeysCommand, evictedKeysCommand)); logger.warn("getInstanceMinuteStatsList cost:{} ms", (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); //解析成json数组 List> appInstancesExpiredEvictedKeysStatList = new ArrayList>(); for (Table.Cell>> cell : table.cellSet()) { Integer instanceId = cell.getRowKey(); //实例基本信息 Map instanceStatMap = new HashMap(); instanceStatMap.put("instanceId", instanceId); instanceStatMap.put("instanceInfo", cell.getColumnKey()); //每个实例的统计信息 List> instanceExpiredEvictedKeysStatList = new ArrayList>(); instanceStatMap.put("instanceExpiredEvictedKeysStatMapList", instanceExpiredEvictedKeysStatList); appInstancesExpiredEvictedKeysStatList.add(instanceStatMap); //记录过期、淘汰键 Map> map = cell.getValue(); List instanceCommandStatsList = new ArrayList<>(); instanceCommandStatsList.addAll(map.get(expiredKeysCommand)); instanceCommandStatsList.addAll(map.get(evictedKeysCommand)); Map> total = new HashMap>(); for (InstanceMinuteStats instanceMinuteStats : instanceCommandStatsList) { //用timestamp作为key,保证在一个Map统计里 long timestamp = instanceMinuteStats.getTimeStamp(); double memFragRatio = instanceMinuteStats.getMemFragmentationRatio(); String command = instanceMinuteStats.getCommandName(); //精简字段 command = commandMap.get(command); if (total.containsKey(timestamp)) { Map tmpMap = total.get(timestamp); tmpMap.put(command, memFragRatio); } else { Map tmpMap = new HashMap(); tmpMap.put("t", timestamp); tmpMap.put(command, memFragRatio); total.put(timestamp, tmpMap); instanceExpiredEvictedKeysStatList.add(tmpMap); } } } String result = JSONObject.toJSONString(appInstancesExpiredEvictedKeysStatList); logger.warn("parse Json cost:{} ms", (System.currentTimeMillis() - start)); write(response, result); } /** * 获取指定时间内某个应用全部实例的统计信息 * * @param appId 应用流量 */ @RequestMapping("/getAppInstancesNetStat") public ModelAndView getAppInstancesNetStat(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { //时间转换 TimeBetween timeBetween = getJsonTimeBetween(request); //缩减字段 String netInCommand = "total_net_input_bytes"; String netOutCommand = "total_net_output_bytes"; Map commandMap = new HashMap(); commandMap.put(netInCommand, "i"); commandMap.put(netOutCommand, "o"); //获取应用下所有实例网络流量统计 Map>> appInstancesNetStat = instanceStatsCenter .getStandardStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime(), Arrays.asList(netInCommand, netOutCommand)); //解析成json数组 List> appInstancesNetStatList = new ArrayList>(); for (Entry>> entry : appInstancesNetStat.entrySet()) { Integer instanceId = entry.getKey(); //实例基本信息 Map instanceStatMap = new HashMap(); instanceStatMap.put("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); instanceStatMap.put("instanceInfo", instanceInfo.getIp() + ":" + instanceInfo.getPort()); //每个实例的统计信息 List> instanceNetStatMapList = new ArrayList>(); instanceStatMap.put("instanceNetStatMapList", instanceNetStatMapList); appInstancesNetStatList.add(instanceStatMap); //记录输入和输出流量 Map> map = entry.getValue(); List instanceCommandStatsList = new ArrayList(); instanceCommandStatsList.addAll(map.get(netInCommand)); instanceCommandStatsList.addAll(map.get(netOutCommand)); Map> total = new HashMap>(); for (InstanceCommandStats instanceCommandStat : instanceCommandStatsList) { //用timestamp作为key,保证输入和输出流量在一个Map统计里 long timestamp = instanceCommandStat.getTimeStamp(); long commandCount = instanceCommandStat.getCommandCount(); String command = instanceCommandStat.getCommandName(); //精简字段 command = commandMap.get(command); if (total.containsKey(timestamp)) { Map tmpMap = total.get(timestamp); tmpMap.put(command, commandCount); } else { Map tmpMap = new HashMap(); tmpMap.put("t", timestamp); tmpMap.put(command, commandCount); total.put(timestamp, tmpMap); instanceNetStatMapList.add(tmpMap); } } } String result = JSONObject.toJSONString(appInstancesNetStatList); write(response, result); return null; } /** * @param appId * @throws ParseException */ @RequestMapping("/getTop5Commands") public ModelAndView getAppTop5Commands(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getTimeBetweenOneDay(request,"startDate"); List appCommandStats = appStatsCenter .getTop5AppCommandStatsList(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleJson(appCommandStats); write(response, result); return null; } /** * 应用各个命令分布情况 * * @param appId 应用id * @throws ParseException */ @RequestMapping("/appCommandDistribute") public ModelAndView appCommandDistribute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { TimeBetween timeBetween = getJsonTimeBetween(request); List appCommandGroupList = appStatsCenter .getAppCommandGroup(appId, timeBetween.getStartTime(), timeBetween.getEndTime()); String result = assembleGroupJson(appCommandGroupList); write(response, result); return null; } /** * 应用列表 */ @RequestMapping(value = "/list") public ModelAndView doAppList(HttpServletRequest request, HttpServletResponse response, Model model, String appParam, AppSearch appSearch, String userId) { // 1.获取该用户能够读取的应用列表,没有返回申请页面 AppUser currentUser = getUserInfo(request); model.addAttribute("currentUser", currentUser); int userAppCount = appService.getUserAppCount(currentUser.getId()); if (userAppCount == 0 && !AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) { return new ModelAndView("redirect:/admin/app/init"); } // 2.0 默认只出运行中的 if (appSearch.getAppStatus() == null) { appSearch.setAppStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus()); } // 2.1 查询指定时间客户端异常 if (!StringUtils.isEmpty(appParam)) { if (StringUtils.isNumeric(appParam)) { appSearch.setAppId(Long.parseLong(appParam)); } else { appSearch.setAppName(appParam); } } if (StringUtils.isNotEmpty(userId)) { appSearch.setUserId(NumberUtils.toLong(userId)); } // 2.2 分页相关 int totalCount = appService.getAppDescCount(currentUser, appSearch); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 10); Page page = new Page(pageNo, pageSize, totalCount); model.addAttribute("page", page); appSearch.setPage(page); List apps = appService.getAppDescList(currentUser, appSearch); // 2.3 应用列表 List appDetailList = new ArrayList(); model.addAttribute("appDetailList", appDetailList); // 3.Redis版本信息 List resourcelist = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); // 4. 全局统计 long totalApplyMem = 0; long totalUsedMem = 0; long totalApps = 0; if (apps != null && apps.size() > 0) { for (AppDesc appDesc : apps) { AppDetailVO appDetail = appStatsCenter.getAppDetail(appDesc.getAppId()); appDetailList.add(appDetail); totalApplyMem += appDetail.getMem(); totalUsedMem += appDetail.getMemUsePercent() * appDetail.getMem() / 100.0; totalApps++; appDetail.getAppDesc().setBizGroup(appDesc.getBizGroup()); } } List userList = userService.getAllUser(); List bizList = userService.getBizList(); model.addAttribute("userList", userList); model.addAttribute("bizList", bizList); model.addAttribute("appParam", appParam); model.addAttribute("resourcelist", resourcelist); model.addAttribute("totalApps", totalApps); model.addAttribute("totalApplyMem", totalApplyMem); model.addAttribute("totalUsedMem", totalUsedMem); return new ModelAndView("app/appList"); } /** * 应用列表 */ @RequestMapping(value = "/listStats") @ResponseBody public Map doAppListStats(HttpServletRequest request) { Map resultMap = new HashMap<>(); // 1.获取该用户能够读取的应用列表,没有返回申请页面 AppUser currentUser = getUserInfo(request); // 4. 全局统计 Calendar instance = Calendar.getInstance(); Date now = instance.getTime(); instance.add(Calendar.DATE, -5); Date startTime = instance.getTime(); List monitorStatisticsResultList = appService.getAppMonitorStatistics(currentUser.getId(), AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType()), DateUtil.formatYYYY_MM_dd(startTime), DateUtil.formatYYYY_MM_dd(now)); Map capacityMap = appService.getAppCapacityStats(currentUser.getId(), AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())); resultMap.put("monitorList", monitorStatisticsResultList); resultMap.put("capacityMap", capacityMap); return resultMap; } /** * 初始化应用申请 */ @RequestMapping(value = "/init") public ModelAndView doAppInit(HttpServletRequest request, HttpServletResponse response, Model model) { List userList = userService.getAllUser(); List roomList = machineCenter.getEffectiveRoom(); List versionList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); versionList = versionList.stream().filter(systemResource -> (systemResource.getOrderNum() >= 100)).collect(Collectors.toList()); //获取插件信息 model.addAttribute("userList", userList); model.addAttribute("roomList", roomList); model.addAttribute("versionList", versionList); model.addAttribute("policyList", AppDescEnum.MaxmemoryPolicyType.getAll()); return new ModelAndView("app/jobIndex/appInitIndex"); } @RequestMapping(value = "/import") public ModelAndView doAppImport(HttpServletRequest request, HttpServletResponse response, Model model) { List userList = userService.getAllUser(); List roomList = machineCenter.getEffectiveRoom(); List versionList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); model.addAttribute("userList", userList); model.addAttribute("roomList", roomList); model.addAttribute("versionList", versionList); return new ModelAndView("app/jobIndex/appImportIndex"); } @RequestMapping(value = "/jobs") public ModelAndView doAppJobs(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Integer status, Integer type) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List jobList = appService.getAppAudits(4, type, null, currentUser.getId(), null); Map statusStatisMap = appService.getStatisticGroupByStatus(currentUser.getId(), null, null, null); Map typeStatisMap = appService.getStatisticGroupByType(currentUser.getId(), null, null, null); List adminList = appUserDao.getAdminList(); model.addAttribute("adminMap", adminList.stream().collect(Collectors.toMap(AppUser::getId, Function.identity()))); AppAuditType[] appAuditTypes = AppAuditType.values(); model.addAttribute("appAuditTypeMap", Arrays.stream(appAuditTypes).collect(Collectors.toMap(AppAuditType::getValue, Function.identity()))); model.addAttribute("statusStatisMap", statusStatisMap); model.addAttribute("typeStatisMap", typeStatisMap); model.addAttribute("jobList", jobList); model.addAttribute("status", status); model.addAttribute("type", type); return new ModelAndView("app/jobIndex/index"); } @RequestMapping(value = "/appKeyAnalysis") public ModelAndView doKeyAnalysis(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Integer status, Integer type) { model.addAttribute("appId", appId); if (appId != null) { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); model.addAttribute("appInstanceList", instanceInfos); } AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appKeyAnalysisIndex"); } @RequestMapping(value = "/appScale") public ModelAndView doAppScale(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appScaleIndex"); } @RequestMapping(value = "/appDiagnostic") public ModelAndView doAppDiagnostic(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); Map diagnosticTypeMap = new TreeMap<>(); for (DiagnosticTypeEnum diagnosticType : DiagnosticTypeEnum.values()) { diagnosticTypeMap.put(diagnosticType.getType(), diagnosticType.getDesc() + ": " + diagnosticType.getMore()); } model.addAttribute("diagnosticTypeMap", diagnosticTypeMap); return new ModelAndView("app/jobIndex/appDiagnosticIndex"); } @RequestMapping(value = "/appDel") public ModelAndView doAppDel(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appCleanIndex"); } @RequestMapping(value = "/appOffline") public ModelAndView doAppOffline(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appOfflineIndex"); } @RequestMapping(value = "/appDataMigrate") public ModelAndView doAppDataMigrate(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appDataMigrateIndex"); } @RequestMapping(value = "/appConfig") public ModelAndView doAppConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId) { model.addAttribute("appId", appId); int first_instanceId = -1; if (appId != null) { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); model.addAttribute("appInstanceList", instanceInfos); first_instanceId = CollectionUtils.isNotEmpty(instanceInfos) && instanceInfos.size() > 0 ? instanceInfos.get(0).getId() : -1; } if (instanceId != null) { model.addAttribute("instanceId", instanceId); first_instanceId = instanceId.intValue(); } Map redisConfigMap = redisCenter.getRedisConfigList(first_instanceId); model.addAttribute("redisConfigMap", redisConfigMap); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appConfigIndex"); } @RequestMapping("/redisConfig") public ModelAndView redisConfig(HttpServletRequest request, HttpServletResponse response, Long appId, Integer instanceId, Model model) { JSONObject json = new JSONObject(); if (instanceId == null) { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); instanceId = CollectionUtils.isNotEmpty(instanceInfos) && instanceInfos.size() > 0 ? instanceInfos.get(0).getId() : -1; } Map redisConfigMap = redisCenter.getRedisConfigList(instanceId.intValue()); if (MapUtils.isEmpty(redisConfigMap)) { json.put("status", String.valueOf(SuccessEnum.FAIL.value())); } else { json.put("redisConfigMap", redisConfigMap); json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); } sendMessage(response, json.toString()); return null; } @RequestMapping("/redisCommand") public ModelAndView redisCommand(HttpServletRequest request, HttpServletResponse response, Long appId, Integer instanceId, Model model) { JSONObject json = new JSONObject(); if (instanceId == null) { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); instanceId = CollectionUtils.isNotEmpty(instanceInfos) && instanceInfos.size() > 0 ? instanceInfos.get(0).getId() : -1; } List commandList = redisCenter.getRedisCommand(instanceId.intValue()); if (CollectionUtils.isEmpty(commandList)) { json.put("status", String.valueOf(SuccessEnum.FAIL.value())); } else { json.put("commandList", commandList); json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); } sendMessage(response, json.toString()); return null; } @RequestMapping("/redisRenameCommand") public ModelAndView redisRenameCommand(HttpServletRequest request, HttpServletResponse response, Long appId, Integer instanceId, Model model) { JSONObject json = new JSONObject(); if (instanceId == null) { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); instanceId = CollectionUtils.isNotEmpty(instanceInfos) && instanceInfos.size() > 0 ? instanceInfos.get(0).getId() : -1; } List> configs = redisCenter.getConfigsInConfigFile(instanceId.intValue(), "rename-command"); if (CollectionUtils.isEmpty(configs)) { json.put("status", String.valueOf(SuccessEnum.FAIL.value())); } else { json.put("renameCommands", configs); json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); } sendMessage(response, json.toString()); return null; } @RequestMapping(value = "/appAlterConfig") public ModelAndView doAppAlterConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appAlterConfigIndex"); } @RequestMapping(value = "/appScanClean") public ModelAndView doAppScanClean(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { model.addAttribute("appId", appId); AppUser currentUser = getUserInfo(request); List appDescList = appService.getAppDescList(currentUser, new AppSearch()); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); return new ModelAndView("app/jobIndex/appScanCleanIndex"); } @RequestMapping(value = "/job/submit") public ModelAndView submitJobApplication(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String nodeInfos, int jobType, String reason, String param) { try { AppUser appUser = getUserInfo(request); AppAudit appAudit = new AppAudit(); appAudit.setAppId(appId == null ? -1 : appId); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); String info = "申请原因: " + reason; if (StringUtils.isNotBlank(nodeInfos)) { info += ",节点: " + nodeInfos; appAudit.setParam1(nodeInfos); } if (StringUtils.isNotBlank(param)) { info += ",其他: " + param; appAudit.setParam2(param); } appAudit.setInfo(info); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(jobType); Date now = new Date(); appAudit.setCreateTime(now); appAudit.setModifyTime(now); appAuditDao.insertAppAudit(appAudit); // 保存日志 // AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), // AppAuditLogTypeEnum.KEY_VALUE_ANALYSIS); // if (appAuditLog != null) { // appAuditLogDao.save(appAuditLog); // } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { logger.error(e.getMessage(), e); write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } @RequestMapping(value = "import/submit", method = RequestMethod.POST) public ModelAndView doAppImportSubmit(HttpServletRequest request, HttpServletResponse response, Model model, AppDesc appDesc, String memSize) { AppUser appUser = getUserInfo(request); //创建appImport AppImport appImport = new AppImport(); //appDesc入库 if (appDesc != null) { Timestamp now = new Timestamp(new Date().getTime()); appDesc.setCreateTime(now); appDesc.setPassedTime(now); appDesc.setVerId(1); appDesc.setStatus((short) AppStatusEnum.STATUS_INITIALIZE.getStatus()); appDesc.setHitPrecentAlertValue(0); appDesc.setIsAccessMonitor(AppUserAlertEnum.NO.value()); appService.save(appDesc); // 保存应用和用户的关系 String officers = appDesc.getOfficer(); if (!StringUtils.isEmpty(officers)) { for (String officerId : officers.split(",")) { if (!StringUtils.isEmpty(officerId)) { appService.saveAppToUser(appDesc.getAppId(), Long.parseLong(officerId)); } } } // 更新appKey long appId = appDesc.getAppId(); appService.updateAppKey(appId); } appImport.setAppId(appDesc.getAppId()); appImport.setMemSize(NumberUtils.toInt(memSize)); appImport.setSourceType(NumberUtils.toInt(request.getParameter("sourceType"))); appImport.setInstanceInfo(request.getParameter("appInstanceInfo")); appImport.setRedisPassword(request.getParameter("password")); appImport.setStatus(0); appImportDao.save(appImport); //appAudit入库 AppAudit appAudit = new AppAudit(); appAudit.setAppId(appDesc.getAppId()); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setInfo("迁移到应用:" + appDesc.getAppId() + " " + appDesc.getName()); appAudit.setModifyTime(new Date()); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(AppAuditType.APP_IMPORT.getValue()); appAudit.setParam1(String.valueOf(appImport.getId())); Date now = new Date(); appAudit.setCreateTime(now); appAudit.setModifyTime(now); appAuditDao.insertAppAudit(appAudit); return new ModelAndView("redirect:/admin/app/jobs"); } /** * 添加应用 * * @param appDesc 应用实体 * @param memSize 申请容量(G) * @return */ @RequestMapping(value = "/add", method = RequestMethod.POST) public ModelAndView doAppAdd(HttpServletRequest request, HttpServletResponse response, Model model, AppDesc appDesc, String memSize) { AppUser appUser = getUserInfo(request); if (appDesc != null) { Timestamp now = new Timestamp(new Date().getTime()); appDesc.setCreateTime(now); appDesc.setPassedTime(now); appDesc.setVerId(1); appDesc.setStatus((short) AppStatusEnum.STATUS_ALLOCATED.getStatus()); // 设置命中率报警0,默认不监控 appDesc.setHitPrecentAlertValue(0); // 客户端默认关闭监控 appDesc.setIsAccessMonitor(AppUserAlertEnum.NO.value()); appDeployCenter.createApp(appDesc, appUser, memSize); } return new ModelAndView("redirect:/admin/app/jobs"); } /** * 查看应用名是否存在 * * @param appName * @return */ @RequestMapping(value = "/checkAppNameExist") public ModelAndView doCheckAppNameExist(HttpServletRequest request, HttpServletResponse response, Model model, String appName) { AppDesc appDesc = appService.getAppByName(appName); if (appDesc != null) { write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * 应用命令查询 * * @param appId * @return */ @RequestMapping("/command") public ModelAndView command(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { model.addAttribute("appId", appId); } return new ModelAndView("app/appCommand"); } /** * 执行应用命令 * * @param appId * @return */ @RequestMapping("/commandExecute") public ModelAndView commandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { AppUser currentUser = getUserInfo(request); if (appId != null && appId > 0) { model.addAttribute("appId", appId); String command = request.getParameter("command"); String result = appStatsCenter.executeCommand(appId, command, currentUser != null ? currentUser.getName() : null); model.addAttribute("result", result); } else { model.addAttribute("result", "error"); } return new ModelAndView("app/commandExecute"); } /** * 删除应用下的指定用户 * * @param userId * @param appId * @return */ @RequestMapping(value = "/deleteAppToUser") public ModelAndView doDeleteAppToUser(HttpServletRequest request, HttpServletResponse response, Model model, Long userId, Long appId) { if (userId != null && appId != null) { // 验证删除权限 AppUser currentUser = getUserInfo(request); List appToUsers = appService.getAppToUserList(appId); if (CollectionUtils.isNotEmpty(appToUsers)) { for (AppToUser appToUser : appToUsers) { if (appToUser.getUserId().equals(currentUser.getId())) { write(response, String.valueOf(SuccessEnum.FAIL.value())); } } } appService.deleteAppToUser(appId, userId); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * 更新用户 * * @param name * @param chName * @param email * @param mobile * @param weChat * @param type * @param userId * @return */ @RequestMapping(value = "/changeAppUserInfo") public ModelAndView doAddUser(HttpServletRequest request, HttpServletResponse response, Model model, String name, String chName, String email, String mobile, String weChat, Integer type, Integer isAlert, Long userId, String company, String purpose, Long bizId) { // 后台暂时不对参数进行验证 AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, weChat, type, isAlert, company, purpose, bizId); try { if (userId == null) { appUser.setPassword(ConstUtils.DEFAULT_USER_PASSWORD); userService.save(appUser); } else { userService.update(appUser); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { write(response, String.valueOf(SuccessEnum.FAIL.value())); logger.error(e.getMessage(), e); } return null; } /** * 扩容申请 * * @param appId 应用id * @param applyMemSize 申请容量 * @param appScaleReason 申请原因 * @return */ @RequestMapping(value = "/scale") public ModelAndView doScaleApp(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String applyMemSize, String appScaleReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService .saveAppScaleApply(appDesc, appUser, applyMemSize, appScaleReason, AppAuditType.APP_SCALE); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 应用修改配置申请 * * @param appId 应用id * @param appConfigKey 配置项 * @param appConfigValue 配置值 * @return */ @RequestMapping(value = "/changeAppConfig") public ModelAndView doChangeAppConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService .saveAppChangeConfig(appDesc, appUser, instanceId, appConfigKey, appConfigValue, appConfigReason, AppAuditType.APP_MODIFY_CONFIG); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** *

* Description: 全局报警项修改 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/9/25 */ @RequestMapping(value = "/changeAppMonitorConfig") public ModelAndView doChangeMonitorAppConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService .saveAppChangeConfig(appDesc, appUser, instanceId, appConfigKey, appConfigValue, appConfigReason, AppAuditType.APP_MODIFY_CONFIG); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 实例修改配置申请 * * @param appId 应用id * @param instanceConfigKey 配置项 * @param instanceConfigValue 配置值 * @return */ @RequestMapping(value = "/changeInstanceConfig") public ModelAndView doChangeInstanceConfig(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService .saveInstanceChangeConfig(appDesc, appUser, instanceId, instanceConfigKey, instanceConfigValue, instanceConfigReason, AppAuditType.INSTANCE_MODIFY_CONFIG); appEmailUtil.noticeAppResult(appDesc, appAudit); write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 添加应用和用户对应关系 * * @param appId 应用id * @param users 用户id(邮箱前缀) * @returns */ @RequestMapping(value = "/addAppToUser") public ModelAndView doAddAppToUser(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String users) { if (StringUtils.isNotBlank(users)) { List userIdList = Arrays.asList(users.split(",")); for (String userIdStr : userIdList) { if (!appService.saveAppToUser(appId, NumberUtils.toLong(userIdStr, -1l))) { write(response, String.valueOf(SuccessEnum.FAIL.value())); } } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } return null; } /** * 修改应用报警配置 */ @RequestMapping(value = "/changeAppAlertConfig") public ModelAndView doChangeAppAlertConfig(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId"), -1); int memAlertValue = NumberUtils.toInt(request.getParameter("memAlertValue"), -1); int clientConnAlertValue = NumberUtils.toInt(request.getParameter("clientConnAlertValue"), -1); int hitPrecentAlertValue = NumberUtils.toInt(request.getParameter("hitPrecentAlertValue"), 0); int isAccessMonitor = NumberUtils.toInt(request.getParameter("isAccessMonitor"), 0); SuccessEnum result = appService .changeAppAlertConfig(appId, memAlertValue, clientConnAlertValue, hitPrecentAlertValue, isAccessMonitor, getUserInfo(request)); write(response, String.valueOf(result.value())); return null; } /** * 修改应用信息 */ @RequestMapping(value = "/updateAppDetail") public ModelAndView doUpdateAppDetail(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId"), 0); AppUser appUser = getUserInfo(request); logger.warn("{} want to update appId={} info!", appUser.getName(), appId); String appDescName = request.getParameter("appDescName"); String appDescIntro = request.getParameter("appDescIntro"); String officer = request.getParameter("officer"); SuccessEnum successEnum = SuccessEnum.SUCCESS; if (appId <= 0 || StringUtils.isBlank(appDescName) || StringUtils.isBlank(appDescIntro) || StringUtils .isBlank(officer)) { successEnum = SuccessEnum.FAIL; } else { try { AppDesc appDesc = appService.getByAppId(appId); appDesc.setName(appDescName); appDesc.setIntro(appDescIntro); appDesc.setOfficer(officer); appService.update(appDesc); } catch (Exception e) { logger.error(e.getMessage(), e); successEnum = SuccessEnum.FAIL; } } write(response, String.valueOf(successEnum.value())); return null; } /** * 应用日报查询 */ @RequestMapping("/daily") public ModelAndView appDaily(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 1. 应用信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 2. 日期 String dailyDateParam = request.getParameter("dailyDate"); Date date; if (StringUtils.isBlank(dailyDateParam)) { date = DateUtils.addDays(new Date(), -1); } else { date = DateUtil.parseYYYY_MM_dd(dailyDateParam); } model.addAttribute("dailyDate", dailyDateParam); // 3. 日报 AppDailyData appDailyData = appDailyDataCenter.getAppDailyData(appId, date); model.addAttribute("appDailyData", appDailyData); return new ModelAndView("app/appDaily"); } /** * 应用历史慢查询 * * @param appId * @return * @throws ParseException */ @RequestMapping("/slowLog") public ModelAndView appSlowLog(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) throws ParseException { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 开始和结束日期 TimeBetween timeBetween = getTimeBetween(request, model, "slowLogStartDate", "slowLogEndDate"); Date startDate = timeBetween.getStartDate(); Date endDate = timeBetween.getEndDate(); // 应用慢查询日志 Map appInstanceSlowLogCountMap = appStatsCenter .getInstanceSlowLogCountMapByAppId(appId, startDate, endDate); model.addAttribute("appInstanceSlowLogCountMap", appInstanceSlowLogCountMap); List appInstanceSlowLogList = appStatsCenter .getInstanceSlowLogByAppId(appId, startDate, endDate); model.addAttribute("appInstanceSlowLogList", appInstanceSlowLogList); // 各个实例对应的慢查询日志 Map> instaceSlowLogMap = new HashMap>(); Map instanceHostPortIdMap = new HashMap(); for (InstanceSlowLog instanceSlowLog : appInstanceSlowLogList) { String hostPort = instanceSlowLog.getIp() + ":" + instanceSlowLog.getPort(); instanceHostPortIdMap.put(hostPort, instanceSlowLog.getInstanceId()); if (instaceSlowLogMap.containsKey(hostPort)) { instaceSlowLogMap.get(hostPort).add(instanceSlowLog); } else { List list = new ArrayList(); list.add(instanceSlowLog); instaceSlowLogMap.put(hostPort, list); } } model.addAttribute("instaceSlowLogMap", instaceSlowLogMap); model.addAttribute("instanceHostPortIdMap", instanceHostPortIdMap); return new ModelAndView("app/slowLog"); } @RequestMapping("/latencyMonitor") public ModelAndView appLatencyMonitor(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { // 应用基本信息 AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); // 获取时间区间 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = DateUtil.fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); searchDate = timeBetween.getFormatStartDate(); model.addAttribute("searchDate", searchDate); // 应用延迟监控数据 Map>> appLatencyStats = appStatsCenter.getAppLatencyStats(appId, startTime, endTime); model.addAttribute("appLatencyStatsJson", JSONObject.toJSONString(appLatencyStats)); Map appLatencyStatsGroupByInstance = appStatsCenter.getAppLatencyStatsGroupByInstance(appId, startTime, endTime); model.addAttribute("appLatencyStatsGroupByInstance", appLatencyStatsGroupByInstance); Set instanceSet = new HashSet<>(); instanceSet.addAll(appLatencyStatsGroupByInstance.keySet()); // 应用慢查询日志 Map appInstanceSlowLogCountMap = appStatsCenter .getInstanceSlowLogCountMapByAppId(appId, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("appInstanceSlowLogCountMap", appInstanceSlowLogCountMap); instanceSet.addAll(appInstanceSlowLogCountMap.keySet()); model.addAttribute("instanceSet", instanceSet); List appInstanceSlowLogList = appStatsCenter .getInstanceSlowLogByAppId(appId, timeBetween.getStartDate(), timeBetween.getEndDate()); model.addAttribute("appInstanceSlowLogList", appInstanceSlowLogList); // 各个实例对应的慢查询日志 Map> instaceSlowLogMap = new HashMap>(); Map instanceHostPortIdMap = new HashMap(); for (InstanceSlowLog instanceSlowLog : appInstanceSlowLogList) { String hostPort = instanceSlowLog.getIp() + ":" + instanceSlowLog.getPort(); instanceHostPortIdMap.put(hostPort, instanceSlowLog.getInstanceId()); if (instaceSlowLogMap.containsKey(hostPort)) { instaceSlowLogMap.get(hostPort).add(instanceSlowLog); } else { List list = new ArrayList(); list.add(instanceSlowLog); instaceSlowLogMap.put(hostPort, list); } } model.addAttribute("instaceSlowLogMap", instaceSlowLogMap); model.addAttribute("instanceHostPortIdMap", instanceHostPortIdMap); return new ModelAndView("app/slowLog"); } @RequestMapping(value = "/latencyInfoDetails") public ModelAndView getLatencyInfoDetails(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); model.addAttribute("appId", appId); long timestamp = NumberUtils.toLong(request.getParameter("searchTime")); //毫秒 Date startDate = new Date(timestamp); long startTime = NumberUtils.toLong(DateUtil.formatDate(startDate, "yyyyMMddHHmm00")); Date endDate = DateUtils.addMinutes(startDate, 1); long endTime = NumberUtils.toLong(DateUtil.formatDate(endDate, "yyyyMMddHHmm00")); model.addAttribute("searchTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:00").format(startDate)); Map sumInstanceLatencyStatMap = appStatsCenter.getAppLatencyStatsGroupByInstance(appId, startTime, endTime); model.addAttribute("sumInstanceLatencyStatMap", sumInstanceLatencyStatMap); Map>> latencyInfoDetailMap = appStatsCenter.getAppLatencyInfo(appId, startTime, endTime); model.addAttribute("latencyInfoDetailMap", latencyInfoDetailMap); return new ModelAndView("/app/appLatencyInfoDetail"); } @RequestMapping(value = "/latencyRelatedSlowLog") public ModelAndView getLatencyRelatedSlowLog(HttpServletRequest request, HttpServletResponse response, Model model) { long instanceId = NumberUtils.toLong(request.getParameter("instanceId")); String executeDate = request.getParameter("executeDate"); //秒 List instanceSlowLogList = appStatsCenter.getByInstanceExecuteTime(instanceId, executeDate); model.addAttribute("instanceSlowLogList", instanceSlowLogList); return new ModelAndView(""); } /** * 清理应用数据 */ @RequestMapping(value = "/cleanAppData") public ModelAndView doCleanAppData(HttpServletRequest request, HttpServletResponse response, Model model, long appId) { AppUser appUser = getUserInfo(request); logger.warn("{} start to clean appId={} data!", appUser.getName(), appId); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0) { //验证用户对应用的权限 以及数据清理的结果 if (checkAppUserProvilege(request, appId) && appDeployCenter.cleanAppData(appId, getUserInfo(request))) { successEnum = SuccessEnum.SUCCESS; } } logger.warn("{} end to clean appId={} data, result is {}", appUser.getName(), appId, successEnum.info()); write(response, String.valueOf(successEnum.value())); return null; } /** * AppCommandGroup列表组装成json串 */ private String assembleGroupJson(List appCommandGroupList) { if (appCommandGroupList == null || appCommandGroupList.isEmpty()) { return "[]"; } List list = new ArrayList(); for (AppCommandGroup appCommandGroup : appCommandGroupList) { SimpleChartData chartData = SimpleChartData .getFromAppCommandGroup(appCommandGroup); list.add(chartData); } return JSONObject.toJSONString(list); } /** * AppStats列表组装成json串 */ private String assembleAppStatsJson(List appStats, String statName) { if (appStats == null || appStats.isEmpty()) { return "[]"; } List list = new ArrayList(); for (AppStats stat : appStats) { try { SimpleChartData chartData = SimpleChartData.getFromAppStats(stat, statName); list.add(chartData); } catch (ParseException e) { logger.info(e.getMessage(), e); } } return JSONObject.toJSONString(list); } private String assembleMutilDateAppCommandJsonMinute(List appCommandStats, Date startDate, Date endDate) { if (appCommandStats == null || appCommandStats.isEmpty()) { return "[]"; } Map> map = new HashMap>(); Date currentDate = DateUtils.addDays(endDate, -1); int diffDays = 0; while (currentDate.getTime() >= startDate.getTime()) { List list = new ArrayList(); for (AppCommandStats stat : appCommandStats) { try { HighchartPoint highchartPoint = HighchartPoint.getFromAppCommandStats(stat, currentDate, diffDays); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } String formatDate = DateUtil.formatDate(currentDate, "yyyy-MM-dd"); map.put(formatDate, list); currentDate = DateUtils.addDays(currentDate, -1); diffDays++; } return JSONObject.toJSONString(map); } /** * 多命令组装 * * @param appStats * @param statNameList * @param startDate * @return */ private String assembleMutiStatAppStatsJsonMinute(List appStats, List statNameList, Date startDate) { if (appStats == null || appStats.isEmpty()) { return "[]"; } Map> map = new HashMap>(); for (String statName : statNameList) { List list = new ArrayList(); for (AppStats stat : appStats) { try { HighchartPoint highchartPoint = HighchartPoint.getFromAppStats(stat, statName, startDate, 0); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } map.put(statName, list); } return JSONObject.toJSONString(map); } /** * 多时间组装 * * @param appStats * @param statName * @param startDate * @param endDate * @return */ private String assembleMutilDateAppStatsJsonMinute(List appStats, String statName, Date startDate, Date endDate) { if (appStats == null || appStats.isEmpty()) { return "[]"; } Map> map = new HashMap>(); Date currentDate = DateUtils.addDays(endDate, -1); int diffDays = 0; while (currentDate.getTime() >= startDate.getTime()) { List list = new ArrayList(); for (AppStats stat : appStats) { try { HighchartPoint highchartPoint = HighchartPoint .getFromAppStats(stat, statName, currentDate, diffDays); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } String formatDate = DateUtil.formatDate(currentDate, "yyyy-MM-dd"); map.put(formatDate, list); currentDate = DateUtils.addDays(currentDate, -1); diffDays++; } return JSONObject.toJSONString(map); } /** * 多时间组装 * * @param appDailyDatas * @param statName * @return */ private String assembleMutilDateAppHitRatio(List appDailyDatas, String statName) { if (appDailyDatas == null || appDailyDatas.isEmpty()) { return "[]"; } List list = new ArrayList<>(); for (AppDailyData appDailyData : appDailyDatas) { try { HighchartDoublePoint highchartPoint = HighchartDoublePoint .getFromAppDailyDatas(appDailyData, statName); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } return JSONObject.toJSONString(list); } /** * 多时间组装 * * @param appStats * @param statName * @param startDate * @param endDate * @return */ private String assembleMutilDateAppStatsJsonMinuteDoublePoint(List appStats, String statName, Date startDate, Date endDate) { if (appStats == null || appStats.isEmpty()) { return "[]"; } Map> map = new HashMap<>(); Date currentDate = DateUtils.addDays(endDate, -1); int diffDays = 0; while (currentDate.getTime() >= startDate.getTime()) { List list = new ArrayList<>(); for (AppStats stat : appStats) { try { HighchartDoublePoint highchartPoint = HighchartDoublePoint .getFromAppStats(stat, statName, currentDate, diffDays); if (highchartPoint == null) { continue; } list.add(highchartPoint); } catch (ParseException e) { logger.info(e.getMessage(), e); } } String formatDate = DateUtil.formatDate(currentDate, "yyyy-MM-dd"); map.put(formatDate, list); currentDate = DateUtils.addDays(currentDate, -1); diffDays++; } return JSONObject.toJSONString(map); } /** * AppCommandStats列表组装成json串 */ private String assembleJson(List appCommandStatsList) { return assembleJson(appCommandStatsList, null); } private String assembleJson(List appCommandStatsList, Integer addDay) { if (appCommandStatsList == null || appCommandStatsList.isEmpty()) { return "[]"; } List list = new ArrayList(); for (AppCommandStats stat : appCommandStatsList) { try { SimpleChartData chartData = SimpleChartData .getFromAppCommandStats(stat, addDay); list.add(chartData); } catch (ParseException e) { logger.info(e.getMessage(), e); } } return JSONObject.toJSONString(list); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppDataMigrateController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.*; import com.sohu.cache.dao.AppUserDao; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.app.AppDataMigrateCenter; import com.sohu.cache.stats.app.RedisMigrateToolCenter; import com.sohu.cache.stats.app.RedisShakeCenter; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppImportService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.Page; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.stream.Collectors; /** * 应用数据迁移入口 * * @author leifu * @Date 2016-6-8 * @Time 下午11:10:34 */ @Controller @RequestMapping("/data/migrate") public class AppDataMigrateController extends BaseController { private static Set MIGRATE_SAMPLE_USEFUL_LINES = new HashSet(); static { MIGRATE_SAMPLE_USEFUL_LINES.add("Checked keys"); MIGRATE_SAMPLE_USEFUL_LINES.add("Inconsistent value keys"); MIGRATE_SAMPLE_USEFUL_LINES.add("Inconsistent expire keys"); MIGRATE_SAMPLE_USEFUL_LINES.add("Other check error keys"); MIGRATE_SAMPLE_USEFUL_LINES.add("Checked OK keys"); } @Autowired private AppDataMigrateCenter appDataMigrateCenter; @Resource(name = "redisMigrateToolCenter") private RedisMigrateToolCenter redisMigrateToolCenter; @Autowired private RedisShakeCenter redisShakeCenter; @Resource(name = "appService") private AppService appService; @Resource(name = "machineCenter") private MachineCenter machineCenter; @Autowired private ResourceDao resourceDao; @Autowired private AppUserDao appUserDao; @Autowired private ResourceService resourceService; @Autowired private AppImportService appImportService; @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag, AppDataMigrateSearch appDataMigrateSearch) { List adminList = appUserDao.getAdminList(); model.addAttribute("adminList", adminList); // 分页相关 int totalCount = appDataMigrateCenter.getMigrateTaskCount(appDataMigrateSearch); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); Page page = new Page(pageNo, 15, totalCount); appDataMigrateSearch.setPage(page); List appDataMigrateStatusList = appDataMigrateCenter.search(appDataMigrateSearch); model.addAttribute("page", page); model.addAttribute("appDataMigrateStatusList", appDataMigrateStatusList); model.addAttribute("appDataMigrateSearch", appDataMigrateSearch); model.addAttribute("tabTag", tabTag); model.addAttribute("appMigrateActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/migrate/list"); } /** * 初始化界面 * * @return */ @RequestMapping(value = "/init") public ModelAndView init(HttpServletRequest request, Model model) { List machineInfoList = machineCenter.getMachineInfoByType(MachineInfoEnum.TypeEnum.REDIS_MIGRATE_TOOL); Map machineInfoMap = machineInfoList.stream().collect(Collectors.toMap( machineInfo -> machineInfo.getIp(), machineInfo -> getMigrateMachineUsed(machineInfo.getIp()))); List resourcelist = resourceService.getResourceList(ResourceEnum.TOOL.getValue()); model.addAttribute("resourcelist", resourcelist); model.addAttribute("machineInfoMap", machineInfoMap); long importId = NumberUtils.toLong(request.getParameter("importId")); if (importId > 0) { AppImport appImport = appImportService.get(importId); model.addAttribute("importId", importId); model.addAttribute("targetAppId", appImport.getAppId()); model.addAttribute("sourceServers", appImport.getInstanceInfo()); model.addAttribute("redisSourcePass", appImport.getRedisPassword()); model.addAttribute("sourceType", appImport.getSourceType()); model.addAttribute("sourceDataType", 0); model.addAttribute("redisSourceVersion", appImport.getRedisVersionName()); } return new ModelAndView("migrate/init"); } private int getMigrateMachineUsed(String migrateMachineIp) { try { String cmd = "ps -ef | grep redis-shake | grep -v grep | grep -v tail"; String response = SSHUtil.execute(migrateMachineIp, cmd); if (StringUtils.isNotEmpty(response)) { String[] redis_shake_count = response.split(ConstUtils.NEXT_LINE); return redis_shake_count.length; } } catch (Exception e) { logger.error(e.getMessage(), e); } return 0; } /** * 检查配置 * * @return */ @RequestMapping(value = "/check") public ModelAndView check(HttpServletRequest request, Model model) { //相关参数 String migrateMachineIp = request.getParameter("migrateMachineIp"); String sourceRedisMigrateIndex = request.getParameter("sourceRedisMigrateIndex"); AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(sourceRedisMigrateIndex, -1)); String sourceServers = request.getParameter("sourceServers"); String targetRedisMigrateIndex = request.getParameter("targetRedisMigrateIndex"); AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(targetRedisMigrateIndex, -1)); String targetServers = request.getParameter("targetServers"); String redisSourcePass = request.getParameter("redisSourcePass"); String redisTargetPass = request.getParameter("redisTargetPass"); //检查返回结果 // int migrateTool = NumberUtils.toInt(request.getParameter("migrateTool"), 0); int versionid = NumberUtils.toInt(request.getParameter("versionid")); SystemResource resource = resourceService.getResourceById(versionid); if (resource == null) { return null; } // 检验机器安装环境 redisConfigTemplateService.checkAndInstallRedisTool(migrateMachineIp, resource); AppDataMigrateResult redisMigrateResult = null; if (resource.getName().indexOf("redis-shake") > -1) { redisMigrateResult = redisShakeCenter.check(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass, resource); } else if (resource.getName().indexOf("redis-migrate-tool") > -1) { redisMigrateResult = redisMigrateToolCenter.check(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass, resource); } model.addAttribute("status", redisMigrateResult.getStatus()); model.addAttribute("message", redisMigrateResult.getMessage()); /*AppDataMigrateResult redisMigrateResult = migrateTool == 1 ? redisMigrateToolCenter.check(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass) : redisShakeCenter.check(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, redisSourcePass, redisTargetPass); model.addAttribute("status", redisMigrateResult.getStatus()); model.addAttribute("message", redisMigrateResult.getMessage());*/ return new ModelAndView(""); } /** * 开始迁移 * * @return */ @RequestMapping(value = "/start") public ModelAndView start(HttpServletRequest request, Model model) { //相关参数 String migrateMachineIp = request.getParameter("migrateMachineIp"); String sourceRedisMigrateIndex = request.getParameter("sourceRedisMigrateIndex"); AppDataMigrateEnum sourceRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(sourceRedisMigrateIndex, -1)); String sourceServers = request.getParameter("sourceServers"); String targetRedisMigrateIndex = request.getParameter("targetRedisMigrateIndex"); AppDataMigrateEnum targetRedisMigrateEnum = AppDataMigrateEnum.getByIndex(NumberUtils.toInt(targetRedisMigrateIndex, -1)); String targetServers = request.getParameter("targetServers"); long sourceAppId = NumberUtils.toLong(request.getParameter("sourceAppId")); long targetAppId = NumberUtils.toLong(request.getParameter("targetAppId")); String redisSourcePass = request.getParameter("redisSourcePass"); String redisTargetPass = request.getParameter("redisTargetPass"); String redisSourceVersion = request.getParameter("redisSourceVersion"); String redisTargetVersion = request.getParameter("redisTargetVersion"); int source_rdb_parallel = NumberUtils.toInt(request.getParameter("source_rdb_parallel"), 8); int parallel = NumberUtils.toInt(request.getParameter("parallel"), 16); AppUser appUser = getUserInfo(request); long userId = appUser == null ? 0 : appUser.getId(); // 不需要对格式进行检验,check已经做过了,开始迁移 // int migrateTool = NumberUtils.toInt(request.getParameter("migrateTool"), 0); int versionid = NumberUtils.toInt(request.getParameter("versionid")); SystemResource resource = resourceService.getResourceById(versionid); if (resource == null) { return null; } AppDataMigrateStatus appDataMigrateStatus = new AppDataMigrateStatus(); if (resource.getName().indexOf("redis-shake") > -1) { appDataMigrateStatus = redisShakeCenter.migrate(migrateMachineIp, source_rdb_parallel, parallel, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, sourceAppId, targetAppId, redisSourcePass, redisTargetPass, redisSourceVersion, redisTargetVersion, userId, resource); } else if (resource.getName().indexOf("redis-migrate-tool") > -1) { appDataMigrateStatus = redisMigrateToolCenter.migrate(migrateMachineIp, sourceRedisMigrateEnum, sourceServers, targetRedisMigrateEnum, targetServers, sourceAppId, targetAppId, redisSourcePass, redisTargetPass, userId, resource); } model.addAttribute("status", 1); model.addAttribute("migrateId", appDataMigrateStatus.getMigrateId()); return new ModelAndView(""); } /** * 停掉迁移任务 * * @return */ @RequestMapping(value = "/stop") public ModelAndView stop(HttpServletRequest request, Model model) { //任务id:查到任务相关信息 long id = NumberUtils.toLong(request.getParameter("id")); int migrateTool = NumberUtils.toInt(request.getParameter("migrateTool"), 0); AppDataMigrateResult stopMigrateResult = migrateTool == 1 ? redisMigrateToolCenter.stopMigrate(id) : redisShakeCenter.stopMigrate(id); model.addAttribute("status", stopMigrateResult.getStatus()); model.addAttribute("message", stopMigrateResult.getMessage()); return new ModelAndView(""); } /** * 查看迁移日志 * * @return */ @RequestMapping(value = "/log") public ModelAndView log(HttpServletRequest request, Model model) { //任务id:查到任务相关信息 long id = NumberUtils.toLong(request.getParameter("id")); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 0); if (pageSize == 0) { pageSize = 100; } String log = appDataMigrateCenter.showDataMigrateLog(id, pageSize); model.addAttribute("logList", Arrays.asList(log.split(ConstUtils.NEXT_LINE))); return new ModelAndView("migrate/log"); } /** * 查看迁移配置 * * @return */ @RequestMapping(value = "/config") public ModelAndView config(HttpServletRequest request, Model model) { //任务id:查到任务相关信息 long id = NumberUtils.toLong(request.getParameter("id")); String config = appDataMigrateCenter.showDataMigrateConf(id); model.addAttribute("configList", Arrays.asList(config.split(ConstUtils.NEXT_LINE))); return new ModelAndView("migrate/config"); } /** * 查看迁移进度 * * @return */ @RequestMapping(value = "/process") public ModelAndView showProcess(HttpServletRequest request, Model model) { long id = NumberUtils.toLong(request.getParameter("id")); int migrateTool = NumberUtils.toInt(request.getParameter("migrateTool"), 0); if (migrateTool == 0) { String process = redisShakeCenter.showProcess(id); model.addAttribute("process", process); return new ModelAndView(""); } else { Map> migrateToolStatMap = appDataMigrateCenter.showMiragteToolProcess(id); model.addAttribute("migrateToolStatMap", migrateToolStatMap); return new ModelAndView("migrate/process"); } } /** * 数据校验 * * @return */ @RequestMapping(value = "/checkData") public ModelAndView checkData(HttpServletRequest request, Model model) { long id = NumberUtils.toLong(request.getParameter("id")); int migrateTool = NumberUtils.toInt(request.getParameter("migrateTool"), 0); int comparemode = NumberUtils.toInt(request.getParameter("comparemode"), 3); int nums = 1000 + new Random().nextInt(2000); CommandResult commandResult; List checkDataResultList = new ArrayList(); if (migrateTool == 1) { // redis-migrate-tool 采样校验 commandResult = redisMigrateToolCenter.sampleCheckData(id, nums); String message = commandResult.getResult(); checkDataResultList.add("一共随机检验了" + nums + "个key" + ",检查结果如下:"); String[] lineArr = message.split(ConstUtils.NEXT_LINE); for (String line : lineArr) { if (StringUtils.isBlank(line)) { continue; } // 行数太多显示会有问题 if (lineArr.length > 100 && !isUsefulLine(line)) { continue; } //message格式显示有点问题 line = line.replace("[0m", ""); line = line.replace("[31m", ""); line = line.replace("[33m", ""); checkDataResultList.add(line.trim()); } model.addAttribute("checkDataResultList", checkDataResultList); model.addAttribute("checkDataCommand", commandResult.getCommand()); } else { // redis-full-check commandResult = redisShakeCenter.checkData(id, 1000, comparemode); model.addAttribute("checkDataCommand", commandResult.getCommand()); } return new ModelAndView("migrate/checkData"); } /** * 查看迁移日志 * * @return */ @RequestMapping(value = "/checkData/log") public ModelAndView checkDatalog(HttpServletRequest request, Model model) { //任务id:查到任务相关信息 long id = NumberUtils.toLong(request.getParameter("id")); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 0); if (pageSize == 0) { pageSize = 100; } String log = appDataMigrateCenter.showCheckDataLog(id, pageSize); model.addAttribute("checkDatalogList", Arrays.asList(log.split(ConstUtils.NEXT_LINE))); return new ModelAndView("migrate/checkDataLog"); } private boolean isUsefulLine(String line) { for (String usefulLine : MIGRATE_SAMPLE_USEFUL_LINES) { if (line.contains(usefulLine)) { return true; } } return false; } /** * 通过应用id获取可用的Redis实例信息 * * @return */ @RequestMapping(value = "/appInstanceList") public ModelAndView appInstanceList(HttpServletRequest request, Model model) { String appIdStr = request.getParameter("appId"); String migrateToolStr = request.getParameter("migrateTool"); long appId = NumberUtils.toLong(appIdStr); int migrateTool = NumberUtils.toInt(migrateToolStr); AppDesc appDesc = appService.getByAppId(appId); String instances = migrateTool == 1 ? redisMigrateToolCenter.getAppInstanceListForRedisMigrateTool(appId) : redisShakeCenter.getAppInstanceListForRedisShake(appId); model.addAttribute("instances", instances); model.addAttribute("password", appDesc == null ? "" : appDesc.getAppPassword()); model.addAttribute("appType", appDesc == null ? -1 : appDesc.getType()); model.addAttribute("appName", appDesc == null ? "" : appDesc.getName()); model.addAttribute("redisVersion", appDesc == null ? "" : resourceDao.getResourceById(appDesc.getVersionId()).getName()); return new ModelAndView(""); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppManageController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.*; import com.sohu.cache.dao.InstanceReshardProcessDao; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.redis.util.AuthUtil; import com.sohu.cache.stats.app.AppDailyDataCenter; import com.sohu.cache.stats.app.AppDeployCenter; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.DeployInfoEnum; import com.sohu.cache.web.enums.NodeEnum; import com.sohu.cache.web.enums.RedisOperateEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.text.ParseException; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * 应用后台管理 * * @author leifu * @Time 2014年7月3日 */ @Controller @RequestMapping("manage/app") public class AppManageController extends BaseController { private Logger logger = LoggerFactory.getLogger(AppManageController.class); @Resource(name = "machineCenter") private MachineCenter machineCenter; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; @Resource(name = "appDeployCenter") private AppDeployCenter appDeployCenter; @Resource(name = "redisCenter") private RedisCenter redisCenter; @Resource(name = "redisDeployCenter") private RedisDeployCenter redisDeployCenter; @Resource(name = "appDailyDataCenter") private AppDailyDataCenter appDailyDataCenter; @Resource(name = "instanceReshardProcessDao") private InstanceReshardProcessDao instanceReshardProcessDao; @Resource(name = "appService") private AppService appService; @Autowired private AppScrollRestartService appScrollRestartService; @Resource private TaskService taskService; @RequestMapping("/appDaily") public ModelAndView appDaily(HttpServletRequest request, HttpServletResponse response, Model model) throws ParseException { AppUser userInfo = getUserInfo(request); logger.warn("user {} want to send appdaily", userInfo.getName()); if (ConstUtils.SUPER_MANAGER.contains(userInfo.getName())) { Date startDate; Date endDate; String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { endDate = new Date(); startDate = DateUtils.addDays(endDate, -1); } else { startDate = DateUtil.parseYYYY_MM_dd(startDateParam); endDate = DateUtil.parseYYYY_MM_dd(endDateParam); } long appId = NumberUtils.toLong(request.getParameter("appId")); if (appId > 0) { appDailyDataCenter.sendAppDailyEmail(appId, startDate, endDate); } else { appDailyDataCenter.sendAppDailyEmail(); } model.addAttribute("msg", "success!"); } else { model.addAttribute("msg", "no power!"); } return new ModelAndView(""); } /** * 审核列表 * * @param status 审核状态 * @param type 申请类型 */ @RequestMapping(value = "/auditList") public ModelAndView doAppAuditList(HttpServletRequest request, HttpServletResponse response, Model model, Integer status, Integer type, Long auditId, Long operateId, Long userId, String startDate, String endDate, Long adminId) { AppAuditType[] appAuditTypes = AppAuditType.values(); model.addAttribute("appAuditTypeMap", Arrays.stream(appAuditTypes).collect(Collectors.toMap(AppAuditType::getValue, Function.identity()))); List userList = userService.getAllUser(); model.addAttribute("userMap", userList.stream().collect(Collectors.toMap(AppUser::getId, Function.identity()))); //获取审核列表 List list = appService.getAppAudits(status, type, auditId, userId, operateId); //任务汇总 AppUser currentUser = getUserInfo(request); Date startTime = null; Date endTime = null; if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) { startTime = DateUtil.getDateByFormat(startDate, "yyyy-MM-dd"); endTime = DateUtil.getDateByFormat(endDate, "yyyy-MM-dd"); } Map statusStatisMap = appService.getStatisticGroupByStatus(null, adminId, startTime, endTime); Map typeStatisMap = appService.getStatisticGroupByType(null, adminId, startTime, endTime); model.addAttribute("statusStatisMap", statusStatisMap); model.addAttribute("typeStatisMap", typeStatisMap); model.addAttribute("list", list); model.addAttribute("userId", userId); model.addAttribute("operateId", operateId); model.addAttribute("status", status); model.addAttribute("type", type); model.addAttribute("auditId", auditId); model.addAttribute("checkActive", SuccessEnum.SUCCESS.value()); model.addAttribute("startDate", startDate); model.addAttribute("endDate", endDate); model.addAttribute("adminId", adminId); return new ModelAndView("manage/appAudit/list"); } @RequestMapping(value = "/audit/update") public ModelAndView updateAppAudit(HttpServletRequest request, HttpServletResponse response, Model model, Long auditId, int status, int type) { AppUser appUser = getUserInfo(request); return new ModelAndView("manage/appAudit/list"); } /** * 处理应用配置修改 * * @param appAuditId 审批id */ @RequestMapping(value = "/initAppConfigChange") public ModelAndView doInitAppConfigChange(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { // 申请原因 AppAudit appAudit = appService.getAppAuditById(appAuditId); model.addAttribute("appAudit", appAudit); // 用第一个参数存实例id Long instanceId = NumberUtils.toLong(appAudit.getParam1()); Map redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue()); model.addAttribute("redisConfigList", redisConfigList); model.addAttribute("instanceId", instanceId); // 实例列表 List instanceList = appService.getAppInstanceInfo(appAudit.getAppId()); model.addAttribute("instanceList", instanceList); model.addAttribute("appId", appAudit.getAppId()); model.addAttribute("appAuditId", appAuditId); // 修改配置的键值对 model.addAttribute("appConfigKey", appAudit.getParam2()); model.addAttribute("appConfigValue", appAudit.getParam3()); return new ModelAndView("manage/appAudit/initAppConfigChange"); } /** * 添加应用配置修改 * * @param appId 应用id * @param appConfigKey 配置项 * @param appConfigValue 配置值 * @param appAuditId 审批id */ @RequestMapping(value = "/addAppConfigChange") public ModelAndView doAddAppConfigChange(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String appConfigKey, String appConfigValue, Long appAuditId) { AppUser appUser = getUserInfo(request); logger.warn("user {} change appConfig:appId={};key={};value={},appAuditId:{}", appUser.getName(), appId, appConfigKey, appConfigValue, appAuditId); boolean isModify = false; if (appId != null && StringUtils.isNotBlank(appConfigKey)) { try { if(appAuditId != null ){ appAuditDao.updateAppAuditOperateUser(appAuditId, appUser.getId()); } isModify = appDeployCenter.modifyAppConfig(appId, appAuditId, appConfigKey, appConfigValue); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("user {} change appConfig:appId={};key={};value={},appAuditId:{},result is:{}", appUser.getName(), appId, appConfigKey, appConfigValue, appAuditId, isModify); return new ModelAndView("redirect:/manage/app/auditList"); } /** * 初始化水平扩容申请 */ @RequestMapping(value = "/initHorizontalScaleApply") public ModelAndView doInitHorizontalScaleApply(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { appAuditDao.updateAppAuditOperateUser(appAuditId, getUserInfo(request).getId()); AppAudit appAudit = appService.getAppAuditById(appAuditId); model.addAttribute("appAudit", appAudit); model.addAttribute("appId", appAudit.getAppId()); return new ModelAndView("manage/appAudit/initHorizontalScaleApply"); } /** * 添加水平扩容节点 * * @return */ @RequestMapping(value = "/addHorizontalNodes") public ModelAndView doAddHorizontalNodes(HttpServletRequest request, HttpServletResponse response, Model model, String masterSizeSlave, Long appAuditId) { AppUser appUser = getUserInfo(request); logger.warn("user {} addHorizontalNodes:{}", appUser.getName(), masterSizeSlave); boolean isAdd = false; AppAudit appAudit = appService.getAppAuditById(appAuditId); String[] nodes = masterSizeSlave.split(ConstUtils.NEXT_LINE); for (String node : nodes) { if (!StringUtils.isEmpty(node.trim())) { // 解析配置 String[] configArr = node.trim().split(ConstUtils.COLON); String masterHost = configArr[0]; String memSize = configArr[1]; int memSizeInt = NumberUtils.toInt(memSize); String slaveHost = null; if (configArr.length >= 3) { slaveHost = configArr[2]; } try { isAdd = appDeployCenter.addHorizontalNodes(appAudit.getAppId(), masterHost, slaveHost, memSizeInt); } catch (Exception e) { logger.error(e.getMessage(), e); } } } logger.warn("addAppClusterSharding:{}, result is {}", masterSizeSlave, isAdd); model.addAttribute("status", isAdd ? 1 : 0); return new ModelAndView(""); } /** * 检测水平扩容节点 * * @param masterSizeSlave * @param appAuditId * @return */ @RequestMapping(value = "/checkHorizontalNodes") public ModelAndView doCheckHorizontalNodes(HttpServletRequest request, HttpServletResponse response, Model model, String masterSizeSlave, Long appAuditId) { DataFormatCheckResult dataFormatCheckResult = null; try { dataFormatCheckResult = appDeployCenter.checkHorizontalNodes(appAuditId, masterSizeSlave); } catch (Exception e) { logger.error(e.getMessage(), e); dataFormatCheckResult = DataFormatCheckResult.fail(ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } model.addAttribute("status", dataFormatCheckResult.getStatus()); model.addAttribute("message", dataFormatCheckResult.getMessage()); return new ModelAndView(""); } /** * 水平扩容初始化 * * @param appAuditId */ @RequestMapping(value = "/handleHorizontalScale") public ModelAndView doHandleHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { // 1. 审批 AppAudit appAudit = appService.getAppAuditById(appAuditId); model.addAttribute("appAudit", appAudit); model.addAttribute("appId", appAudit.getAppId()); // 2. 进度 List instanceReshardProcessList = instanceReshardProcessDao.getByAuditId(appAudit.getId()); model.addAttribute("instanceReshardProcessList", instanceReshardProcessList); // 3. 实例列表和统计 fillAppInstanceStats(appAudit.getAppId(), model); // 4. 实例所在机器信息 fillAppMachineStat(appAudit.getAppId(), model); return new ModelAndView("manage/appAudit/handleHorizontalScale"); } /** * 显示reshard进度 */ @RequestMapping(value = "/showReshardProcess") public ModelAndView doShowReshardProcess(HttpServletRequest request, HttpServletResponse response, Model model) { long auditId = NumberUtils.toLong(request.getParameter("auditId")); List instanceReshardProcessList = instanceReshardProcessDao.getByAuditId(auditId); write(response, JSONObject.toJSONString(instanceReshardProcessList)); return null; } /** * 水平扩容配置检查 * * @param sourceId 源实例ID * @param targetId 目标实例ID * @param startSlot 开始slot * @param endSlot 结束slot * @param appId 应用id * @param appAuditId 审批id * @return */ @RequestMapping(value = "/checkHorizontalScale") public ModelAndView doCheckHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model, long sourceId, long targetId, int startSlot, int endSlot, long appId, long appAuditId, int migrateType) { HorizontalResult horizontalResult = appDeployCenter.checkHorizontal(appId, appAuditId, sourceId, targetId, startSlot, endSlot, migrateType); model.addAttribute("status", horizontalResult.getStatus()); model.addAttribute("message", horizontalResult.getMessage()); return new ModelAndView(""); } /** * 开始水平扩容 * * @param sourceId 源实例ID * @param targetId 目标实例ID * @param startSlot 开始slot * @param endSlot 结束slot * @param appId 应用id * @param appAuditId 审批id * @return */ @RequestMapping(value = "/startHorizontalScale") public ModelAndView doStartHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model, long sourceId, long targetId, int startSlot, int endSlot, long appId, long appAuditId, int migrateType) { AppUser appUser = getUserInfo(request); logger.warn("user {} horizontalScaleApply appId {} appAuditId {} sourceId {} targetId {} startSlot {} endSlot {}", appUser.getName(), appId, appAuditId, sourceId, targetId, startSlot, endSlot); HorizontalResult horizontalResult = appDeployCenter.startHorizontal(appId, appAuditId, sourceId, targetId, startSlot, endSlot, migrateType); model.addAttribute("status", horizontalResult.getStatus()); model.addAttribute("message", horizontalResult.getMessage()); return new ModelAndView(""); } /** * 重试水平扩容 * * @param instanceReshardProcessId * @return */ @RequestMapping(value = "/retryHorizontalScale") public ModelAndView retryHorizontalScale(HttpServletRequest request, HttpServletResponse response, Model model, int instanceReshardProcessId) { AppUser appUser = getUserInfo(request); logger.warn("user {} retryHorizontalScale id {}", appUser.getName(), instanceReshardProcessId); HorizontalResult horizontalResult = appDeployCenter.retryHorizontal(instanceReshardProcessId); model.addAttribute("status", horizontalResult.getStatus()); model.addAttribute("message", horizontalResult.getMessage()); return new ModelAndView(""); } /** * 处理应用扩容 * * @param appAuditId 审批id */ @RequestMapping(value = "/initAppScaleApply") public ModelAndView doInitAppScaleApply(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { // 申请原因 AppAudit appAudit = appService.getAppAuditById(appAuditId); model.addAttribute("appAudit", appAudit); // 实例列表和统计 fillAppInstanceStats(appAudit.getAppId(), model); // 实例所在机器信息 fillAppMachineStat(appAudit.getAppId(), model); long appId = appAudit.getAppId(); AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appAuditId", appAuditId); model.addAttribute("appId", appAudit.getAppId()); model.addAttribute("appDesc", appDesc); return new ModelAndView("manage/appAudit/initAppScaleApply"); } /** * 添加扩容配置 * * @param appScaleText 扩容配置 * @param appAuditId 审批id */ @RequestMapping(value = "/addAppScaleApply") public ModelAndView doAddAppScaleApply(HttpServletRequest request, HttpServletResponse response, Model model, String appScaleText, Long appAuditId, Long appId) { AppUser appUser = getUserInfo(request); logger.error("user {} appScaleApplay : appScaleText={},appAuditId:{}", appUser.getName(), appScaleText, appAuditId); boolean isSuccess = false; int mem = NumberUtils.toInt(appScaleText, 0); AppDesc appDesc = appService.getByAppId(appId); if (appAuditId != null && StringUtils.isNotBlank(appScaleText) && appDesc != null) { try { isSuccess = appDeployCenter.verticalExpansion(appId, appAuditId, appUser.getId(), mem); } catch (Exception e) { logger.error(e.getMessage(), e); } } else { logger.error("appScaleApplay error param: appScaleText={},appAuditId:{},appId:{}", appScaleText, appAuditId, appId); } logger.error("user {} appScaleApplay: appScaleText={},appAuditId:{}, result is {}", appUser.getName(), appScaleText, appAuditId, isSuccess); return new ModelAndView("redirect:/manage/app/auditList"); } /** * 初始化部署应用 * * @param appAuditId 审批id * @return */ @RequestMapping(value = "/initAppDeploy") public ModelAndView doInitAppDeploy(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { long appId; AppDesc appDesc; if (appAuditId == null) { appId = NumberUtils.toLong(request.getParameter("appId")); appDesc = appService.getByAppId(appId); } else { // 申请原因 AppAudit appAudit = appService.getAppAuditById(appAuditId); appId = appAudit.getAppId(); model.addAttribute("appAudit", appAudit); appDesc = appService.getByAppId(appId); } // 获取所有Redis版本 List allRedisVersion = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); // 机器列表 List machineList = machineCenter.getMachineStats(null, null, null, null, null, null, null); // 获取机器信息 Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); if (appDesc.getVersionId() > 0) { model.addAttribute("version", resourceService.getResourceById(appDesc.getVersionId())); } List roomList = machineCenter.getEffectiveRoom(); model.addAttribute("roomList", roomList); model.addAttribute("machineList", machineList); model.addAttribute("machineInstanceCountMap", machineInstanceCountMap); model.addAttribute("appAuditId", appAuditId); model.addAttribute("appId", appId); model.addAttribute("md5password", AuthUtil.getAppIdMD5(String.valueOf(appId))); model.addAttribute("appDesc", appService.getByAppId(appId)); model.addAttribute("versionList", allRedisVersion); model.addAttribute("importId", request.getParameter("importId")); return new ModelAndView("manage/appAudit/deploy/initAppDeploy"); } @RequestMapping(value = "/generateDeployInfo", method = {RequestMethod.POST, RequestMethod.GET}) public ModelAndView generateDeployInfo(HttpServletResponse response, int type, int hasSalve, int maxMemory, int redisNum, int sentinelNum, int pikaNum, int twemproxyNum, String appDeployInfo, String redisMachines, String sentinelMachines, String twemproxyMachines, String pikaMachines) { // 1.根据应用类型获取部署拓扑信息 logger.info("type:{} ,hasSalve:{} ,maxMemory:{}MB ", type, hasSalve, maxMemory); logger.info("redisMachines:{} ,num:{} ", redisMachines, redisNum); logger.info("sentinelMachines:{} ,num:{} ", sentinelMachines, sentinelNum); logger.info("twemproxyMachines:{} ,num:{} ", twemproxyMachines, twemproxyNum); logger.info("pikaMachines:{} ,num:{} ", pikaMachines, pikaNum); // 2.根据应用类型获取部署拓扑信息 List deployInfoList = new ArrayList(); Map machineDeployStatMap = new HashMap<>(); Map machineInstanceCountMap = new HashMap<>(); List machineMemStatInfo = new ArrayList<>(); Set ipList = new HashSet(); String deployStatus = DeployInfoEnum.SUCCESS.getValue(); try { List redisMachinelist = Arrays.asList(redisMachines.split(";")); List sentinelMachinelist = Arrays.asList(sentinelMachines.split(";")); List twemproxyMachinelist = Arrays.asList(twemproxyMachines.split(";")); List pikaMachinelist = Arrays.asList(pikaMachines.split(";")); switch (type) { case 2: // redis cluster appService.generateInstanceInfo(redisMachinelist, NodeEnum.REDIS_NODE.getValue(), type, redisMachinelist.size() * redisNum, maxMemory, hasSalve, deployInfoList); ipList.addAll(redisMachinelist); break; case 5: // sentinel + redis appService.generateInstanceInfo(redisMachinelist, NodeEnum.REDIS_NODE.getValue(), type, 1, maxMemory, hasSalve, deployInfoList); appService.generateProxyinfo(sentinelMachinelist, NodeEnum.SENTINEL_NODE.getValue(), type, sentinelMachinelist.size() * sentinelNum, deployInfoList); ipList.addAll(redisMachinelist); ipList.addAll(sentinelMachinelist); break; case 6:// standalone + redis deployInfoList.add(new DeployInfo(type, redisMachinelist.get(0), maxMemory)); ipList.addAll(redisMachinelist); break; case 7: //twemproxy + redis appService.generateInstanceInfo(redisMachinelist, NodeEnum.REDIS_NODE.getValue(), type, redisMachinelist.size() * redisNum, maxMemory, hasSalve, deployInfoList); appService.generateProxyinfo(sentinelMachinelist, NodeEnum.SENTINEL_NODE.getValue(), type, sentinelMachinelist.size() * sentinelNum, deployInfoList); appService.generateProxyinfo(twemproxyMachinelist, NodeEnum.TWEMPROXY_NODE.getValue(), type, twemproxyMachinelist.size() * twemproxyNum, deployInfoList); ipList.addAll(redisMachinelist); ipList.addAll(sentinelMachinelist); ipList.addAll(twemproxyMachinelist); break; case 8: //sentinel + pika appService.generateInstanceInfo(pikaMachinelist, NodeEnum.PIKA_NODE.getValue(), type, 1, maxMemory, hasSalve, deployInfoList); appService.generateProxyinfo(sentinelMachinelist, NodeEnum.SENTINEL_NODE.getValue(), type, sentinelMachinelist.size() * sentinelNum, deployInfoList); ipList.addAll(pikaMachinelist); ipList.addAll(sentinelMachinelist); break; case 9: //twemproxy + pika appService.generateInstanceInfo(pikaMachinelist, NodeEnum.PIKA_NODE.getValue(), type, pikaMachinelist.size() * pikaNum, maxMemory, hasSalve, deployInfoList); appService.generateProxyinfo(sentinelMachinelist, NodeEnum.SENTINEL_NODE.getValue(), type, sentinelMachinelist.size() * sentinelNum, deployInfoList); appService.generateProxyinfo(twemproxyMachinelist, NodeEnum.TWEMPROXY_NODE.getValue(), type, twemproxyMachinelist.size() * twemproxyNum, deployInfoList); ipList.addAll(pikaMachinelist); ipList.addAll(sentinelMachinelist); ipList.addAll(twemproxyMachinelist); break; default: break; } if (CollectionUtils.isEmpty(deployInfoList)) { deployStatus = DeployInfoEnum.EMPTY.getValue(); } // 收集机器资源信息 if (!CollectionUtils.isEmpty(ipList)) { machineDeployStatMap = appService.getMachineDeployStat(ipList, deployInfoList); machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); machineMemStatInfo = machineCenter.getValidMachineMemByIpList(new ArrayList(ipList)); } } catch (Exception e) { deployStatus = DeployInfoEnum.EXCEPTION.getValue(); logger.error(e.getMessage(), e); } // 3. response JSONObject json = new JSONObject(); json.put("result", deployStatus); json.put("deployInfoList", deployInfoList); json.put("resMachines", machineMemStatInfo); json.put("machineDeployStatMap", machineDeployStatMap); json.put("machineInstanceCountMap", machineInstanceCountMap); sendMessage(response, json.toString()); return null; } /** * 应用部署task * * @param request * @param appAuditId * @param type * @param maxMemory * @param redisNum * @param sentinelNum * @param pikaNum * @param twemproxyNum * @param redisMachines * @param sentinelMachines * @param twemproxyMachines * @param pikaMachines * @return */ @RequestMapping(value = "/addAppDeployTask", method = {RequestMethod.POST}) public ModelAndView doAddAppDeployTask(HttpServletRequest request, HttpServletResponse response, Long appAuditId, int isSetPasswd, int versionId, int importantLevel, long appid, int type, int maxMemory, int redisNum, int sentinelNum, int pikaNum, int twemproxyNum, @RequestParam(required = false) String appDeployInfo, String redisMachines, String sentinelMachines, String twemproxyMachines, String pikaMachines, String customPassword ) { JSONObject json = new JSONObject(); long taskid = -1;//任务流跳转 AppUser appUser = getUserInfo(request); logger.warn("user {} appid:{} ,appAuditId:{}, importantLevel:{} ,isSetPasswd:{},versionId:{},customPassword:{}", appUser.getName(), appid, appAuditId, importantLevel, isSetPasswd, versionId, customPassword); logger.info("type:{} ,maxMemory:{} MB ", type, maxMemory); logger.info("appDeployInfo :{} ", appDeployInfo); logger.info("redisMachines:{} ,num:{} ", redisMachines, redisNum); logger.info("sentinelMachines:{} ,num:{} ", sentinelMachines, sentinelNum); logger.info("twemproxyMachines:{} ,num:{} ", twemproxyMachines, twemproxyNum); logger.info("pikaMachines:{} ,num:{} ", pikaMachines, pikaNum); try { List appDeployInfolist = new ArrayList<>(); if(StringUtils.isNotEmpty(appDeployInfo)){ appDeployInfolist = Arrays.asList(appDeployInfo.split("\n")); } List redisMachinelist = Arrays.asList(redisMachines.split(";")); List sentinelMachinelist = Arrays.asList(sentinelMachines.split(";")); List twemproxyMachinelist = Arrays.asList(twemproxyMachines.split(";")); List pikaMachinelist = Arrays.asList(pikaMachines.split(";")); // 1.保存应用信息 AppDesc appDesc = appService.getByAppId(appid); if (appDesc != null) { appDesc.setImportantLevel(importantLevel); appDesc.setVersionId(versionId); appDesc.setType(type); if(StringUtils.isNotBlank(customPassword)){ appDesc.setCustomPassword(customPassword); } appService.updateWithCustomPwd(appDesc); } else { json.put("status", "fail"); json.put("message", "部署失败:获取应用信息为空,请检查服务日志!"); sendMessage(response, json.toString()); return null; } // 2.获取Redis版本信息 SystemResource redisResource = resourceService.getResourceById(versionId); if (redisResource == null) { json.put("status", "fail"); json.put("message", "部署失败:redis版本不存在,请检查服务日志!"); sendMessage(response, json.toString()); return null; } if (appAuditId != null) { appAuditDao.updateAppAuditOperateUser(appAuditId, appUser.getId()); } else { appAuditId = -1l; } //2.根据应用类型获取部署拓扑信息 switch (type) { case 2: // 部署task :redis cluster taskid = taskService.addRedisClusterAppTask(appid, appAuditId, maxMemory, appDeployInfolist, redisMachinelist, redisNum, redisResource.getName(), -1); break; case 5: // 部署task :sentinel + redis taskid = taskService.addRedisSentinelAppTask(appid, appAuditId, maxMemory, redisMachinelist, sentinelMachinelist, redisNum, sentinelNum, redisResource.getName(), -1); break; case 6:// 部署task :standalone taskid = taskService.addRedisStandaloneAppTask(appid, appAuditId, maxMemory, redisMachinelist, 1, redisResource.getName(), -1); break; case 7: // 部署task :twemproxy + redis taskid = taskService.addTwemproxyAppTask(appid, appAuditId, maxMemory, redisMachinelist, sentinelMachinelist, twemproxyMachinelist, redisNum, sentinelNum, twemproxyNum, false, redisResource.getName(), -1); break; case 8: // 部署task :sentinel + pika taskid = taskService.addPikaSentinelAppTask(appid, appAuditId, maxMemory, pikaMachinelist, sentinelMachinelist, pikaNum, sentinelNum, -1); break; case 9: // 部署task :twemproxy + pika taskid = taskService.addTwemproxyPikaTask(appid, appAuditId, maxMemory, pikaMachinelist, sentinelMachinelist, twemproxyMachinelist, pikaNum, sentinelNum, twemproxyNum, false, -1); break; default: break; } } catch (Exception e) { logger.error(e.getMessage(), e); json.put("status", "fail"); json.put("message", "部署失败:系统存在异常,请检查服务日志!"); sendMessage(response, json.toString()); return null; } json.put("status", "success"); json.put("taskid", taskid); // 用于跳转到任务流页面 json.put("message", "应用任务流开始构建,即将跳转任务流部署页面!"); sendMessage(response, json.toString()); return null; } /** * @Description: 生成部署信息 * @Author: caoru * @CreateDate: 2018/9/25 20:41 */ @RequestMapping(value = "/getDeployInfo", method = {RequestMethod.POST, RequestMethod.GET}) public ModelAndView getDeployInfo(HttpServletResponse response, Model model, Integer type, Integer isSalve, String room, Double size, Integer machineNum, Integer instanceNum, Integer useType, String machines, String excludeMachines, String sentinelMachines) { try { JSONObject json = new JSONObject(); String result; //参数校验是否为空 if (type == null || isSalve == null || room == null || size == null || machineNum == null || instanceNum == null || useType == null) { logger.info("参数为空"); result = "param is error or null"; json.put("result", result); sendMessage(response, json.toString()); return new ModelAndView(""); } size *= 1024; if (TypeUtil.isRedisSentinel(type)) { if (sentinelMachines.isEmpty()) { logger.info("sentinel类型,请指定sentinel机器"); result = "sentinel类型,请指定sentinel机器"; json.put("result", result); sendMessage(response, json.toString()); return new ModelAndView(""); } else { StringBuilder resultBuilder = new StringBuilder(); List sentinelMachineList = machineCenter.getValidMachineMemByIpList(Arrays.asList(sentinelMachines.split(","))); for (MachineMemStatInfo sentinelMachine : sentinelMachineList) { if (sentinelMachine.getCpu() - sentinelMachine.getInstanceNum() < 1) { //result += sentinelMachine.getIp() + ","; resultBuilder.append(sentinelMachine.getIp()).append(","); } } result = resultBuilder.toString(); if (result != null && !result.isEmpty()) { result = "sentinel机器:" + result; result += "cpu核数不足"; json.put("result", result); sendMessage(response, json.toString()); return new ModelAndView(""); } } } //存储部署信息 List deployInfoList = new ArrayList(); //存储满足条件的机器ip List resMachines = new ArrayList(); result = appService.generateDeployInfo(type, isSalve, room, size, machineNum, instanceNum, useType, machines, excludeMachines, sentinelMachines, deployInfoList, resMachines); if (!DeployInfoEnum.SUCCESS.getValue().equals(result)) { logger.info("result: {}", result); json.put("result", result); sendMessage(response, json.toString()); return new ModelAndView(""); } Set ipList = new HashSet(); Iterator iterator = resMachines.iterator(); while (iterator.hasNext()) { String ip = iterator.next().getIp(); if (ipList.contains(ip)) { iterator.remove(); } else { ipList.add(ip); } } Map machineDeployStatMap = appService.getMachineDeployStat(ipList, deployInfoList); Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); json.put("result", result); json.put("machineInstanceCountMap", machineInstanceCountMap); json.put("resMachines", resMachines); json.put("deployInfoList", deployInfoList); json.put("machineDeployStatMap", machineDeployStatMap); sendMessage(response, json.toString()); return new ModelAndView(""); } catch (Exception e) { logger.error(e.getMessage(), e); } return new ModelAndView(""); } /** * 通过,获取驳回申请 * * @param status 审批状态 * @param appAuditId 审批id * @param refuseReason 应用id * @return */ @RequestMapping(value = "/addAuditStatus") public ModelAndView doAddAuditStatus(HttpServletRequest request, HttpServletResponse response, Model model, Integer status, Long appAuditId, String refuseReason, Integer type) { AppUser appUser = getUserInfo(request); logger.warn("user {} addAuditStatus: status={},appAuditId:{},refuseReason:{}", appUser.getName(), status, appAuditId, refuseReason); AppAudit appAudit = appService.getAppAuditById(appAuditId); Long appId = appAudit.getAppId(); // 通过或者驳回并记录日志 appService.updateAppAuditStatus(appAuditId, appId, status, appUser); // 记录驳回原因 if (AppCheckEnum.APP_REJECT.value().equals(status)) { appAudit.setRefuseReason(refuseReason); appService.updateRefuseReason(appAudit, getUserInfo(request)); } // 发邮件统计 if (AppCheckEnum.APP_PASS.value().equals(status) || AppCheckEnum.APP_REJECT.value().equals(status)) { AppDesc appDesc = appService.getByAppId(appId); AppUser applyUser = userService.get(appAudit.getUserId()); if(appDesc != null){ appEmailUtil.noticeAppResultWithApplyUser(applyUser, appDesc, appService.getAppAuditById(appAuditId)); }else{ appEmailUtil.noticeAuditResult(applyUser, appService.getAppAuditById(appAuditId)); } } //没有传入type参数,只有在申请应用时会传入 if (type == null) { // 批准成功直接跳转 if (AppCheckEnum.APP_PASS.value().equals(status)) { return new ModelAndView("redirect:/manage/app/auditList"); } } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.APP_DIAGNOSTIC.getValue() == type) { return new ModelAndView("redirect:/manage/app/tool/index"); } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.APP_OFFLINE.getValue() == type) { return new ModelAndView("redirect:/manage/total/list?appParam=" + appId); } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.FLUSHALL_DATA.getValue() == type) { return new ModelAndView("redirect:/manage/app/tool/index?tabTag=deleteKey"); } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.APP_MIGRATE.getValue() == type) { return new ModelAndView("redirect:/data/migrate/init"); } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.APP_IMPORT.getValue() == type) { return new ModelAndView("redirect:/import/app/init?importId=" + appAudit.getParam1()); } if (AppCheckEnum.APP_ALLOCATE_RESOURCE.value().equals(status) && AppAuditType.SCAN_CLEAN.getValue() == type) { return new ModelAndView("redirect:/manage/app/tool/index?tabTag=scanClean"); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 下线应用 * * @param appId * @return */ @RequestMapping(value = "/offLine") public ModelAndView offLineApp(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long appAuditId) { AppUser userInfo = getUserInfo(request); logger.warn("user {} hope to offline appId: {}", userInfo.getName(), appId); long taskId = appDeployCenter.offLineApp(appId, userInfo, appAuditId); if (appAuditId != null) { appAuditDao.updateTaskId(appAuditId, taskId); } model.addAttribute("appId", appId); model.addAttribute("taskId", taskId); model.addAttribute("message", "下线任务已提交,即将跳转任务流页面, taskId:" + taskId); logger.warn("user {} offline appId: {}, taskId is {}", userInfo.getName(), appId, taskId); return new ModelAndView(); } /** * 实例机器信息 * * @param appId * @param model */ private void fillAppMachineStat(Long appId, Model model) { List instanceList = appService.getAppInstanceInfo(appId); Map machineStatsMap = new HashMap(); Map machineCanUseMem = new HashMap(); for (InstanceInfo instanceInfo : instanceList) { if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } String ip = instanceInfo.getIp(); if (machineStatsMap.containsKey(ip)) { continue; } MachineStats machineStats = machineCenter.getMachineMemoryDetail(ip); // 机器ip可能下线,查不到数据 if (machineStats != null) { machineStatsMap.put(ip, machineStats); machineCanUseMem.put(ip, machineStats.getMachineMemInfo().getLockedMem()); } } model.addAttribute("machineCanUseMem", machineCanUseMem); model.addAttribute("machineStatsMap", machineStatsMap); } /** * 应用运维 * * @param appId */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String tabTag) { model.addAttribute("appId", appId); model.addAttribute("tabTag", tabTag); return new ModelAndView("manage/appOps/appOpsIndex"); } /** * 应用机器运维 * * @param appId */ @RequestMapping("/machine") public ModelAndView appMachine(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { List appMachineList = appService.getAppMachineDetail(appId); model.addAttribute("appMachineList", appMachineList); AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); } return new ModelAndView("manage/appOps/appMachine"); } /** * 应用实例运维 * * @param appId */ @RequestMapping("/instance") public ModelAndView appInstance(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //实例信息和统计 fillAppInstanceStats(appId, model); model.addAttribute("k8sMachineMaps", machineCenter.getK8sMachineMap()); //只有cluster类型才需要计算slot相关 if (TypeUtil.isRedisCluster(appDesc.getType())) { // 计算丢失的slot区间 Map lossSlotsSegmentMap = redisCenter.getClusterLossSlots(appId); model.addAttribute("lossSlotsSegmentMap", lossSlotsSegmentMap); } } return new ModelAndView("manage/appOps/appInstance"); } /** * 应用详细信息和各种申请记录 * * @param appId */ @RequestMapping("/detail") public ModelAndView appInfoAndAudit(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { List appAuditList = appService.getAppAuditListByAppId(appId); AppDesc appDesc = appService.getByAppId(appId); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); model.addAttribute("appAuditList", appAuditList); model.addAttribute("appDesc", appDesc); } return new ModelAndView("manage/appOps/appInfoAndAudit"); } /** * redisCluster节点删除: forget + shutdown * * @param appId 应用id * @param delNodeInstanceId 需要被forget的节点 * @return */ @RequestMapping("/clusterDelNode") public ModelAndView clusterDelNode(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, int delNodeInstanceId) { AppUser appUser = getUserInfo(request); logger.warn("user {}, clusterForget: appId:{}, instanceId:{}", appUser.getName(), appId, delNodeInstanceId); // 检测forget条件 ClusterOperateResult checkClusterForgetResult = ClusterOperateResult.fail("checkClusterForget Exception"); try { checkClusterForgetResult = redisDeployCenter.checkClusterForget(appId, delNodeInstanceId); } catch (Exception e) { logger.error(e.getMessage(), e); } if (!checkClusterForgetResult.isSuccess()) { model.addAttribute("success", checkClusterForgetResult.getStatus()); model.addAttribute("message", checkClusterForgetResult.getMessage()); return new ModelAndView(""); } // 执行delnode:forget + shutdown ClusterOperateResult delNodeResult = ClusterOperateResult.fail("delNode Exception"); try { delNodeResult = redisDeployCenter.delNode(appId, delNodeInstanceId); } catch (Exception e) { logger.error(e.getMessage(), e); } model.addAttribute("success", delNodeResult.getStatus()); model.addAttribute("message", delNodeResult.getMessage()); logger.warn("user {}, clusterForget: appId:{}, instanceId:{}, result is {}", appUser.getName(), appId, delNodeInstanceId, delNodeResult.getStatus()); return new ModelAndView(""); } /** * redisCluster从节点failover * * @param appId 应用id * @param slaveInstanceId 从节点instanceId * @return */ @RequestMapping("/clusterSlaveFailOver") public void clusterSlaveFailOver(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, int slaveInstanceId) { boolean success = false; String failoverParam = request.getParameter("failoverParam"); logger.warn("clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}", appId, slaveInstanceId, failoverParam); if (appId != null && appId > 0 && slaveInstanceId > 0) { try { success = redisDeployCenter.clusterFailover(appId, slaveInstanceId, failoverParam); } catch (Exception e) { logger.error(e.getMessage(), e); } } else { logger.error("error param clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}", appId, slaveInstanceId, failoverParam); } logger.warn("clusterSlaveFailOver: appId:{}, slaveInstanceId:{}, failoverParam:{}, result is {}", appId, slaveInstanceId, failoverParam, success); write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } /** * @Description: 自动生成slave ip * @Author: caoru * @CreateDate: 2018/10/11 11:50 */ @RequestMapping(value = "/genSlaveIp") public void genSlaveIp(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int masterInstanceId) { String machineRes; String result = "success"; JSONObject json = new JSONObject(); if (appId > 0 && masterInstanceId > 0) { try { machineRes = redisDeployCenter.genSlaveIp(appId, masterInstanceId); if (StringUtils.isEmpty(machineRes)) { result = "没有满足条件的机器可用"; } json.put("result", result); json.put("machineRes", machineRes); sendMessage(response, json.toString()); } catch (Exception e) { logger.error(e.getMessage(), e); } } } /** * 添加slave节点 * * @param appId * @param masterInstanceId * @param slaveHost * @return */ @RequestMapping(value = "/addSlave") public void addSlave(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int masterInstanceId, String slaveHost) { AppUser appUser = getUserInfo(request); logger.warn("user {} addSlave: appId:{},masterInstanceId:{},slaveHost:{}", appUser.getName(), appId, masterInstanceId, slaveHost); boolean success = false; if (appId > 0 && StringUtils.isNotBlank(slaveHost) && masterInstanceId > 0) { try { success = redisDeployCenter.addSlave(appId, masterInstanceId, slaveHost); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("user {} addSlave: appId:{},masterInstanceId:{},slaveHost:{} result is {}", appUser.getName(), appId, masterInstanceId, slaveHost, success); write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } /** * 添加sentinel节点 * * @param appId * @param sentinelHost * @return */ @RequestMapping(value = "/addSentinel") public void addSentinel(HttpServletRequest request, HttpServletResponse response, Model model, long appId, String sentinelHost) { AppUser appUser = getUserInfo(request); logger.warn("user {} addSentinel: appId:{}, sentinelHost:{}", appUser.getName(), appId, sentinelHost); boolean success = false; if (appId > 0 && StringUtils.isNotBlank(sentinelHost)) { try { success = redisDeployCenter.addSentinel(appId, sentinelHost); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("user {} addSentinel: appId:{}, sentinelHost:{} result is {}", appUser.getName(), appId, sentinelHost, success); write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } /** * 为失联的slot添加master节点 * * @param appId */ @RequestMapping(value = "/addFailSlotsMaster") public void addFailSlotsMaster(HttpServletRequest request, HttpServletResponse response, Model model, long appId, String failSlotsMasterHost, int instanceId) { AppUser appUser = getUserInfo(request); logger.warn("user {} addFailSlotsMaster: appId:{}, instanceId {}, newMasterHost:{}", appUser.getName(), appId, instanceId, failSlotsMasterHost); RedisOperateEnum redisOperateEnum = RedisOperateEnum.FAIL; if (appId > 0 && StringUtils.isNotBlank(failSlotsMasterHost)) { try { redisOperateEnum = redisDeployCenter.addSlotsFailMaster(appId, instanceId, failSlotsMasterHost); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("user {} addFailSlotsMaster: appId:{}, instanceId {}, newMasterHost:{} result is {}", appUser.getName(), appId, instanceId, failSlotsMasterHost, redisOperateEnum.getValue()); write(response, String.valueOf(redisOperateEnum.getValue())); } /** * sentinelFailOver操作 * * @param appId * @return */ @RequestMapping("/sentinelFailOver") public void sentinelFailOver(HttpServletRequest request, HttpServletResponse response, Model model, long appId) { AppUser appUser = getUserInfo(request); logger.warn("user {} sentinelFailOver, appId:{}", appUser.getName(), appId); boolean success = false; if (appId > 0) { try { success = redisDeployCenter.sentinelFailover(appId); } catch (Exception e) { logger.error(e.getMessage(), e); } } else { logger.error("error param, sentinelFailOver: appId:{}", appId); } logger.warn("user {} sentinelFailOver, appId:{}, result is {}", appUser.getName(), appId, success); write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } @RequestMapping("/sentinelReset") public void sentinelReset(HttpServletRequest request, HttpServletResponse response, Model model, long appId) { AppUser appUser = getUserInfo(request); logger.warn("user {} sentinelReset, appId:{}", appUser.getName(), appId); boolean success = false; if (appId > 0) { try { success = redisDeployCenter.sentinelReset(appId); } catch (Exception e) { logger.error(e.getMessage(), e); } } else { logger.error("error param, sentinelReset: appId:{}", appId); } logger.warn("user {} sentinelReset, appId:{}, result is {}", appUser.getName(), appId, success); write(response, String.valueOf(success == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } /** * 应用重要性级别 */ @RequestMapping(value = "/updateAppImportantLevel") public ModelAndView doUpdateAppImportantLevel(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); int importantLevel = NumberUtils.toInt(request.getParameter("importantLevel")); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0 && importantLevel >= 0) { try { AppDesc appDesc = appService.getByAppId(appId); appDesc.setImportantLevel(importantLevel); appService.update(appDesc); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); } } model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 更新应用密码 */ @RequestMapping(value = "/updateAppPassword") public ModelAndView doUpdateAppPassword(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); String password = request.getParameter("password"); Boolean isSetPasswd = Boolean.valueOf(request.getParameter("isSetPasswd")); logger.info("modify appId:{},password:{}", appId, password); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0) { try { //增加版本校验,6.0.0-6.0.8不支持清除密码,即password为空的情况 AppDesc appDesc = appService.getByAppId(appId); if(appDesc != null){ if(StringUtils.isBlank(password)){ // Redis版本信息 SystemResource resource = resourceService.getResourceById(appDesc.getVersionId()); String name = resource.getName(); if(name != null){ String[] split = name.split("-"); if(split != null && split.length == 2){ String version = split[1].replace(".", ""); int versionNum = Integer.parseInt(version); if(versionNum <= 608 && versionNum >= 600){ model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } } } } // 修改密码逻辑 redisDeployCenter.fixPassword(appId, password, isSetPasswd, false); } successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); } } model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 更新应用 Redis版本 */ @RequestMapping(value = "/updateRedisVersion") public ModelAndView doUpdateAppRedisVersion(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); int versionId = NumberUtils.toInt(request.getParameter("versionId")); logger.info("modify appId:{},versionId:{}", appId, versionId); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0 && versionId > 0) { try { AppDesc appDesc = appService.getByAppId(appId); appDesc.setVersionId(versionId); appService.update(appDesc); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); } } model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** *

* Description: 应用密码初始化页面 *

* * @param * @return * @author chenshi * @version 1.0 * @date 2017/8/2 */ @RequestMapping(value = "/initAppPassword") public ModelAndView doInitAppPassword(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { if (appId != null && appId > 0) { AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appId", appDesc.getAppId()); model.addAttribute("pkey", appDesc.getPkey()); model.addAttribute("customPassword", appDesc.getCustomPassword()); } return new ModelAndView("manage/appOps/appCodeInit"); } @RequestMapping(value = "/checkAppPassword") public ModelAndView doCheckAppPassword(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId")); logger.info("check appid:{}", appId); SuccessEnum successEnum = SuccessEnum.FAIL; if (appId > 0) { try { // 密码校验逻辑 boolean check = redisDeployCenter.checkAuths(appId); // 返回true 则一致 if (check) { successEnum = SuccessEnum.SUCCESS; } } catch (Exception e) { logger.error(e.getMessage(), e); } } model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } @RequestMapping(value = "/updateAppPersistenceType") public void updateAppPersistenceType(HttpServletRequest request, HttpServletResponse response) { long appId = NumberUtils.toLong(request.getParameter("appId"), -1); Integer persistenceType = Integer.valueOf(request.getParameter("persistenceType")); if(AppDescEnum.AppPersistenceType.getByType(persistenceType) == null){ write(response, String.valueOf(SuccessEnum.FAIL.value())); return; } boolean executeFlag = appService.updateAppPersistenceType(appId, persistenceType); write(response, String.valueOf(executeFlag == true ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value())); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppMigrateController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.entity.*; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.enums.UseTypeEnum; import com.sohu.cache.web.vo.AppDetailVO; import com.sohu.cache.web.vo.RedisInfo; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.concurrent.TimeUnit; /** *

* Description: 应用在线迁移 *

* * @author chenshi * @version 1.0 * @date 2018/9/21 */ @Controller @RequestMapping("/manage/app/migrate") public class AppMigrateController extends BaseController { // 实例和日志信息 private static String INSTANCE_INFO_KEY = "instanceInfo"; private static String INSTANCE_LOG_KEY = "instanceLog"; // 下线实例信息 private static String DOWN_INSTANCE_IDS_KEY = "downInstanceIds"; private static String DOWN_INSTANCE_INFO_KEY = "downInstanceInfo"; @RequestMapping(value = "init", method = {RequestMethod.POST, RequestMethod.GET}) public ModelAndView init(Model model, long appId) { // 1.获取应用信息 AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); List machinelist = machineCenter.getMachineStats(null, null, null, null, null, null, null); // 获取机器信息 Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); // 2.获取当前redis实例信息 List instanceList = appService.getAppInstanceInfo(appId); String instanceRedisinfo = getInstanceInfo(instanceList, appId).get(INSTANCE_INFO_KEY); // 3.如果是sentinel,获取sentinel实例信息 String instanceSentinelinfo = getSentinelInstanceInfo(instanceList); List roomList = machineCenter.getEffectiveRoom(); model.addAttribute("roomList", roomList); model.addAttribute("appDetail", appDetail); model.addAttribute("instanceSentinelInfo", instanceSentinelinfo); model.addAttribute("instanceSourceInfo", instanceSentinelinfo + instanceRedisinfo); model.addAttribute("machinelist", machinelist); model.addAttribute("machineInstanceCountMap", machineInstanceCountMap); return new ModelAndView("/manage/appOps/appMigrate"); } @RequestMapping(value = "selectMachine", method = {RequestMethod.POST}) public ModelAndView autoSelectMachine(HttpServletResponse response, int type, int useType, String room, int machineNum, long mem, int masterNum, int slaveNum) { Map resultMap = new HashMap(); if (room == null || machineNum == 0 || masterNum == 0) { logger.info("可用机器数不足"); resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "参数输入错误"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } int masterMachineNum; Integer isSalve = slaveNum == 0 ? 0 : 1; if (TypeUtil.isRedisSentinel(type)) { masterMachineNum = 1 + slaveNum; } else if (TypeUtil.isRedisStandalone(type)) { masterMachineNum = 1; } else if (TypeUtil.isRedisCluster(type)) { masterMachineNum = machineNum; } else { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "type参数错误"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } Double reqSize = Math.ceil(mem * 1.0D / masterNum) * Math.ceil(masterNum * 1.0D / masterMachineNum); Integer reqCpu = masterNum % masterMachineNum == 0 ? masterNum / masterMachineNum : masterNum / masterMachineNum + 1; List machineMemStatInfoList = machineCenter.getAllValidMachineMem(new ArrayList(), room, useType); List machineCandi = new ArrayList(); for (MachineMemStatInfo memStatInfo : machineMemStatInfoList) { appService.getMachineCandiList(memStatInfo, reqSize, reqCpu, isSalve, machineCandi); } List resMachines = new ArrayList(); appService.getResMachines(machineCandi, masterMachineNum, resMachines); if (resMachines.size() == 0) { if (useType == UseTypeEnum.Machine_test.getValue()) { appService.getResMachines(machineMemStatInfoList, masterMachineNum, resMachines); } if (resMachines.size() == 0) { logger.info("可用机器数不足"); resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "可用机器数不足"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } } resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("resMachineList", resMachines); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "selectSentinelMachine", method = {RequestMethod.POST}) public ModelAndView selectSentinelMachine(HttpServletResponse response, long appId) { Map resultMap = new HashMap(); List instanceList = appService.getAppInstanceInfo(appId); String instanceSentinelInfo = getSentinelInstanceInfo(instanceList); if (instanceSentinelInfo.isEmpty()) { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "sentinel信息为空"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } List sentinelInfoList = Arrays.asList(instanceSentinelInfo.split("\n")); int sentinelNum = sentinelInfoList.size(); if (sentinelNum < 3 || sentinelNum % 2 == 0) { resultMap.put("message", "sentinel机器数为" + sentinelNum + "不满足条件,系统自动进行调整"); sentinelNum = sentinelNum < 3 ? 3 : sentinelNum + 1; } Integer reqCpu = 1; List machineMemStatInfoList = machineCenter.getAllValidMachineMem(new ArrayList(), null, 3); List machineCandi = new ArrayList(); for (MachineMemStatInfo memStatInfo : machineMemStatInfoList) { memStatInfo.setInstanceNum(instanceDao.getInstListByIp(memStatInfo.getIp()).size()); appService.getMachineCandiList(memStatInfo, 0d, reqCpu, 0, machineCandi); } if (machineCandi.size() < sentinelNum) { /*resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "可用sentinel机器数不足"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null;*/ // 可用sentinel机器不足 则默认挑选 logger.warn("machineCandi size = {},default random sentinel ip!", machineCandi.size()); machineCandi = machineMemStatInfoList; } //按机房分类 List roomList = machineCenter.getEffectiveRoom(); Map> sentinelMachineMap = new HashMap>(); for (MachineRoom room : roomList) { List list = new ArrayList(); sentinelMachineMap.put(room.getName(), list); } for (MachineMemStatInfo memStatInfo : machineCandi) { sentinelMachineMap.get(memStatInfo.getRoom()).add(memStatInfo); } Set sentinelMachineSet = new HashSet(); //select while (sentinelMachineSet.size() < sentinelNum) { for (Map.Entry> entry: sentinelMachineMap.entrySet()) { getResMachines(entry.getValue(), 1, sentinelMachineSet); if (sentinelMachineSet.size() == sentinelNum) { break; } } } resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("sentinelMachineList", new ArrayList(sentinelMachineSet)); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } private void getResMachines(List machineCandi, Integer machineNum, Set resMachines) { if (machineCandi == null) { return; } Map map = new HashMap(); if (machineCandi.size() < machineNum) { return; } else { while (map.size() < machineNum) { int random = (int) (Math.random() * machineCandi.size()); if (!map.containsKey(random)) { map.put(random, ""); resMachines.add(machineCandi.get(random)); } } } } @RequestMapping(value = "generateMachineInfo", method = {RequestMethod.POST}) public ModelAndView autoSelectMachine(HttpServletResponse response, String machineIps) { Map resultMap = new HashMap(); if (machineIps == null || machineIps.isEmpty()) { logger.info("所选sentinel机器为空"); resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "请选择sentinel机器"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } List resMachines = machineCenter.getValidMachineMemByIpList(Arrays.asList(machineIps.split(","))); resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("resMachineList", resMachines); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "checkPlan", method = {RequestMethod.POST}) public ModelAndView checkPlan(HttpServletResponse response, long appId, String machineInfo, String machineSentinelInfo, int type) { Map resultMap = new HashMap(); SuccessEnum successEnum = SuccessEnum.SUCCESS; logger.info(" appId:{},type:{},machineInfo:{},machineSentinelInfo:{}", appId, type, machineInfo, machineSentinelInfo); // param check if (StringUtils.isEmpty(machineInfo)) { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "迁移机器参数异常,machineInfo:" + machineInfo); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } AppDesc appDesc = appService.getByAppId(appId); List instanceList = appService.getAppInstanceInfo(appId); // 1.迁移机器ip连通性,系统环境安装env检查 // 2.迁移机器安装redis版本检查 // RedisVersion redisVersion = redisConfigTemplateService.getRedisVersionById(appDesc.getVersionId()); SystemResource redisResource = resourceService.getResourceById(appDesc.getVersionId()); try { Boolean flag = true; for (String machineIp : machineInfo.split(ConstUtils.SEMICOLON)) { if (!StringUtils.isEmpty(machineIp)) { // todo // flag = redisConfigTemplateService.checkMachineRedisVersion(machineIp, redisVersion); // if (!flag) { // resultMap.put("status", SuccessEnum.ERROR.value()); // resultMap.put("message", "" + // "迁移机器:" + machineIp + "未安装" + redisVersion.getName() + "版本,请先安装!"); // sendMessage(response, JSONObject.toJSONString(resultMap)); // return null; // } } } } catch (Exception e) { logger.error(e.getMessage(), e); resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "迁移机器Redis版本检查异常,请查看日志!"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } // 3.获取下线节点 Map mapInfo = getDownInstanceInfo(instanceList, appId, "slave"); // 4.获取新实例节点 List masterNodes = new ArrayList(); List sentinelNodes = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("master")) { masterNodes.add(instance); } if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("sentinel")) { sentinelNodes.add(instance); } } } Map redisInfoMap = getRedisInfo(masterNodes, machineInfo); String newInstanceInfo; StringBuilder newInstanceInfoBuilder = new StringBuilder("新增实例信息:\n"); for (Map.Entry redisInfo : redisInfoMap.entrySet()) { RedisInfo redisNode = redisInfo.getValue(); //newInstanceInfo += redisNode.getRedisInfo(redisNode); newInstanceInfoBuilder.append(redisNode.getRedisInfo(redisNode)); } // 5.如果是sentinel集群 if (type == ConstUtils.CACHE_REDIS_SENTINEL) { Map sentinelInfoMap = getSentinelInfo(sentinelNodes, machineSentinelInfo); for (Map.Entry sentinelInfo : sentinelInfoMap.entrySet()) { RedisInfo redisNode = sentinelInfo.getValue(); //newInstanceInfo += redisNode.getRedisInfo(redisNode); newInstanceInfoBuilder.append(redisNode.getRedisInfo(redisNode)); } // 获取需要下线的sentinel Map sentinelInfo = getDownInstanceInfo(instanceList, appId, "sentinel"); resultMap.put("downSentinelIds", sentinelInfo.get(DOWN_INSTANCE_IDS_KEY)); } newInstanceInfo = newInstanceInfoBuilder.toString(); resultMap.put("status", successEnum.value()); resultMap.put("downInstanceInfo", "下线实例信息:\n" + mapInfo.get(DOWN_INSTANCE_INFO_KEY)); resultMap.put("downInstanceIds", mapInfo.get(DOWN_INSTANCE_IDS_KEY)); resultMap.put("newInstanceInfo", newInstanceInfo); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "nodeReplace", method = {RequestMethod.POST}) public ModelAndView nodeReplace(HttpServletResponse response, long appId, String machineInfo, String machineSentinelInfo, String downInstanceIds, int type) { Map resultMap = new HashMap(); SuccessEnum successEnum = SuccessEnum.SUCCESS; logger.info("appid:{}, downInstanceIds:{}", appId, downInstanceIds); // 1.获取应用信息 List instanceList = appService.getAppInstanceInfo(appId); // 2.关闭指定下线slave节点 Boolean shutdownFlag = shutdownInstance(downInstanceIds, appId); if (!shutdownFlag) { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "关闭slave节点异常,请查看日志!"); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } // 3.启动新Redis实例 startInstance(instanceList, machineInfo, appId); if (type == ConstUtils.CACHE_REDIS_SENTINEL) { // 启动sentinel实例 startSentinelInstance(instanceList, machineSentinelInfo, appId); } // 4.获取迁移后最新实例信息 instanceList = appService.getAppInstanceInfo(appId); Map instanceInfo = getInstanceInfo(instanceList, appId); // 5.如果是sentinel,获取sentinel实例信息 String instanceSentinelinfo = ""; if (type == ConstUtils.CACHE_REDIS_SENTINEL) { instanceSentinelinfo = getSentinelInstanceInfo(instanceList); } resultMap.put("status", successEnum.value()); resultMap.put("instanceTargetInfo", instanceInfo.get(INSTANCE_INFO_KEY) + instanceSentinelinfo); resultMap.put("instanceTargetLog", instanceInfo.get(INSTANCE_LOG_KEY)); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "msFailover", method = {RequestMethod.POST}) public ModelAndView msFailover(HttpServletResponse response, Model model, long appId, int type) { // 1.从节点failover Map resultMap = redisConfigTemplateService.slaveFailover(appId); // 2.获取最新实例信息 List instanceList = appService.getAppInstanceInfo(appId); Map instanceInfo = getInstanceInfo(instanceList, appId); // 3.需要下线的slave实例信息 Map mapInfo = getDownInstanceInfo(instanceList, appId, "slave"); // 4.如果是sentinel,获取sentinel实例信息 String instanceSentinelinfo = ""; if (type == ConstUtils.CACHE_REDIS_SENTINEL) { instanceSentinelinfo = getSentinelInstanceInfo(instanceList); } resultMap.put("instanceTargetInfo", instanceInfo.get(INSTANCE_INFO_KEY) + instanceSentinelinfo); resultMap.put("instanceTargetLog", instanceInfo.get(INSTANCE_LOG_KEY)); resultMap.put("downInstanceInfo", "下线实例信息:\n" + mapInfo.get(DOWN_INSTANCE_INFO_KEY)); resultMap.put("downInstanceIds", mapInfo.get(DOWN_INSTANCE_IDS_KEY)); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "addSlave", method = {RequestMethod.POST}) public ModelAndView addNewSlave(HttpServletResponse response, long appId, String machineInfo, int type) { Map resultMap = new HashMap(); // 1.参数验证 if (StringUtils.isEmpty(machineInfo) && appId < 0) { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "参数异常:machineInfo:{" + machineInfo + "},appId:{" + appId + "}"); } // 2.获取实例信息 List instanceList = appService.getAppInstanceInfo(appId); // 3.添加新从节点 startInstance(instanceList, machineInfo, appId); // 4.日志 instanceList = appService.getAppInstanceInfo(appId); // 5.如果是sentinel,获取sentinel实例信息 String instanceSentinelinfo = ""; if (type == ConstUtils.CACHE_REDIS_SENTINEL) { instanceSentinelinfo = getSentinelInstanceInfo(instanceList); } Map instanceInfo = getInstanceInfo(instanceList, appId); resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("instanceTargetInfo", instanceInfo.get(INSTANCE_INFO_KEY) + instanceSentinelinfo); resultMap.put("instanceTargetLog", instanceInfo.get(INSTANCE_LOG_KEY)); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "appCheck", method = {RequestMethod.POST}) public ModelAndView appStatusCheck(HttpServletResponse response, long appId) { Map resultMap = new HashMap(); // 1.连接数检测 // 2.实例运行状态 resultMap.put("status", SuccessEnum.SUCCESS.value()); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "downSlave", method = {RequestMethod.POST}) public ModelAndView downSlave(HttpServletResponse response, long appId, String downInstanceIds, int type) { Map resultMap = new HashMap(); logger.info("appid:{}, downInstanceIds:{},type:{} ", appId, downInstanceIds, type); // 1.关闭指定下线slave节点 Boolean shutdownFlag = shutdownInstance(downInstanceIds, appId); if (!shutdownFlag) { resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", "关闭slave节点异常,请查看日志!"); } else { List instanceList = appService.getAppInstanceInfo(appId); Map instanceInfo = getInstanceInfo(instanceList, appId); // 2.如果是sentinel,获取sentinel实例信息 String instanceSentinelinfo = ""; if (type == ConstUtils.CACHE_REDIS_SENTINEL) { instanceSentinelinfo = getSentinelInstanceInfo(instanceList); } resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("instanceTargetInfo", instanceInfo.get(INSTANCE_INFO_KEY) + instanceSentinelinfo); resultMap.put("instanceTargetLog", instanceInfo.get(INSTANCE_LOG_KEY)); } sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @RequestMapping(value = "complete", method = {RequestMethod.POST}) public ModelAndView migrateComplete(HttpServletResponse response, long appId) { Map resultMap = new HashMap(); resultMap.put("status", SuccessEnum.SUCCESS.value()); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } /** *

* Description: 获取实例信息 *

* * @author chenshi * @version 1.0 * @date 2018/10/8 */ public Map getDownInstanceInfo(List instanceList, long appId, String role) { Map instanceMap = new HashMap(); String downInstanceInfo = ""; List downInstanceIds = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { // 遍历获取slave节点 for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals(role)) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); RedisInfo slaveInfo = new RedisInfo(instance.getIp(), instance.getPort(), redisVersion, instance.getRoleDesc()); downInstanceInfo += slaveInfo.getInfo(slaveInfo); downInstanceIds.add(instance.getId() + "#" + instance.getIp() + ":" + instance.getPort()); } } } instanceMap.put(DOWN_INSTANCE_INFO_KEY, downInstanceInfo); instanceMap.put(DOWN_INSTANCE_IDS_KEY, StringUtils.join(downInstanceIds, ",")); return instanceMap; } /** *

* Description: 下线实例 *

* * @author chenshi * @version 1.0 * @date 2018/10/8 */ public Boolean shutdownInstance(String downInstanceIds, long appId) { if (!StringUtils.isEmpty(downInstanceIds)) { try { // 遍历获取slave节点,关闭 for (String downInstance : downInstanceIds.split(",")) { int instanceId = Integer.parseInt(downInstance.split("#")[0]); String hostInfo = String.valueOf(downInstance.split("#")[1]); boolean closeOp = instanceDeployCenter.shutdownExistInstance(appId, instanceId); logger.info("appid:{} shutdown slave instance:[] :{}", appId, instanceId, hostInfo); } } catch (Exception e) { logger.info(e.getMessage(), e); return false; } } else { // 没有slave 可下线的slave节点 logger.info(" appid:{} ,has no slave node need to shutdown ,downInstanceIds:{}", appId, downInstanceIds); } return true; } /** *

* Description:添加实例 *

* * @param instanceList 实例列表 * @param machineInfo 机器信息 * @author chenshi * @version 1.0 * @date 2018/10/8 */ public void startInstance(List instanceList, String machineInfo, long appId) { // 1 当前master节点信息 List masterNodes = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { // 遍历获取slave节点,关闭slave节点 for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("master")) { masterNodes.add(instance); } } } // 2 启动新的slave实例 Map redisInfoMap = getRedisInfo(masterNodes, machineInfo); if (!CollectionUtils.isEmpty(masterNodes)) { for (InstanceInfo masterInstance : masterNodes) { if (masterInstance.getRoleDesc().equals("master")) { // 获取新slave节点 RedisInfo slaveNode = redisInfoMap.get(masterInstance.getHostPort()); boolean success = false; if (appId > 0 && StringUtils.isNotBlank(slaveNode.getIp())) { try { success = redisDeployCenter.addSlave(appId, masterInstance.getId(), slaveNode.getIp()); // sleep 15s for master psync TimeUnit.SECONDS.sleep(15); // todo 检测slave节点同步数据状态成功才发起下一个节点优化 long start = System.currentTimeMillis(); Boolean psyncFlag = redisConfigTemplateService.slaveIsPsync(appId, masterInstance.getIp(), masterInstance.getPort()); logger.info("appid:{} add slave wait psync cost :{}ms ,psyncFlag:{}", appId, (System.currentTimeMillis() - start), psyncFlag); } catch (Exception e) { logger.error(e.getMessage(), e); success = false; } } logger.warn("migrate addSlave: appId:{},masterInstanceId:{},slaveHost:{} result is {}", appId, masterInstance.getId(), slaveNode.getIp(), success); } } } } /** *

* Description: sentinel实例启动 *

* * @author chenshi * @version 1.0 * @date 2018/10/11 */ public void startSentinelInstance(List instanceList, String machineSentinelInfo, long appId) { // 1 当前sentinel节点信息 List sentinelNodes = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { // 遍历获取slave节点,关闭slave节点 for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("sentinel")) { sentinelNodes.add(instance); } } } // 2 启动新的slave实例 Map redisInfoMap = getSentinelInfo(sentinelNodes, machineSentinelInfo); if (!CollectionUtils.isEmpty(sentinelNodes) && !MapUtils.isEmpty(redisInfoMap)) { for (InstanceInfo sentnelNode : sentinelNodes) { // 获取新slave节点 RedisInfo sentinelInfo = redisInfoMap.get(sentnelNode.getHostPort()); boolean success = false; if (appId > 0 && StringUtils.isNotBlank(sentinelInfo.getIp())) { try { success = redisDeployCenter.addSentinel(appId, sentinelInfo.getIp()); } catch (Exception e) { logger.error(e.getMessage(), e); success = false; } } logger.warn("migrate addSentinel: appId:{},sentinelHost:{} result is {}", appId, sentnelNode.getHostPort(), success); } } } /** *

* Description: 获取迁移实例对应关系 *

* * @version 1.0 * @date 2018/10/9 */ public Map getRedisInfo(List masterNodes, String machineInfo) { Map redisInfoMap = new HashMap(); try { List machineIps = new ArrayList(); if (!StringUtils.isEmpty(machineInfo)) { machineIps = Arrays.asList(machineInfo.split(ConstUtils.SEMICOLON)); } logger.info("masterNodes num=" + masterNodes.size() + " ,machineNums =" + machineIps.size() + ",machine ips:" + machineIps); String role = "slave"; int pos = 0; for (InstanceInfo masterNode : masterNodes) { int tag = pos % machineIps.size(); int retryTimes = 0; // 挑选主从节点,如果只有重复则可以重复 while (masterNode.getIp().equals(machineIps.get(tag)) && retryTimes++ <= 3) { if (masterNodes.size() % machineIps.size() != 0) { tag = (tag + masterNodes.size() % machineIps.size()) % machineIps.size(); } else { tag = (tag + masterNodes.size() % machineIps.size() + 1) % machineIps.size(); } } redisInfoMap.put(masterNode.getHostPort(), new RedisInfo(machineIps.get(tag), role)); logger.info("masterNode:{} => {}", masterNode.getHostPort(), machineIps.get(tag)); pos++; } } catch (Exception e) { logger.error(e.getMessage(), e); } logger.info("redisInfoMap:{}", redisInfoMap); return redisInfoMap; } public Map getSentinelInfo(List sentinelNodes, String machineSentinelInfo) { Map sentinelInfoMap = new HashMap(); try { /** * 规则: * 1. 主从尽量在不同节点 (物理机节点) * 2. 如果节点不够可部署在同一节点 */ List machineIps = new ArrayList(); if (!StringUtils.isEmpty(machineSentinelInfo)) { machineIps = Arrays.asList(machineSentinelInfo.split(ConstUtils.SEMICOLON)); } String role = "sentinel"; for (InstanceInfo sentinelNode : sentinelNodes) { String host = sentinelNode.getIp(); // 获取随机节点 List ips = new ArrayList(); // 1.去重sentinelIp for (String ip : machineIps) { if (!ip.equals(host)) { ips.add(ip); } } // 2.获取随机节点 if (ips.size() > 0) { int random = Math.abs((sentinelNode.getHostPort()).hashCode()) % ips.size(); sentinelInfoMap.put(sentinelNode.getHostPort(), new RedisInfo(ips.get(random), role)); } else { sentinelInfoMap.put(sentinelNode.getHostPort(), new RedisInfo(host, role)); } } } catch (Exception e) { logger.error(e.getMessage(), e); } logger.info("sentinelInfoMap:{}", sentinelInfoMap); return sentinelInfoMap; } private Map getInstanceInfo(List instanceList, long appId) { Map resultMap = new HashMap(); //实例信息和日志信息 String instanceInfo = ""; String instanceLog = ""; StringBuilder instanceInfoBuilder = new StringBuilder(); StringBuilder instanceLogBuilder = new StringBuilder(); //建立slave-master实例关系 Map instanceMap = new HashMap(); if (instanceList != null && instanceList.size() > 0) { // 遍历获取slave节点 for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("slave")) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); RedisInfo slaveInfo = new RedisInfo(instance.getId(), instance.getIp(), instance.getPort(), redisVersion, instance.getRoleDesc()); RedisInfo masterInfo = new RedisInfo(instance.getMasterHost(), instance.getMasterPort()); instanceMap.put(masterInfo.getIpAndPortInfo(masterInfo) + "#" + slaveInfo.getIpAndPortInfo(slaveInfo), slaveInfo); } } // 遍历获取master节点 for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("master")) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); RedisInfo masterInfo = new RedisInfo(instance.getIp(), instance.getPort(), redisVersion, instance.getRoleDesc()); //instanceInfo += masterInfo.getInfo(masterInfo); //instanceLog += "
"; instanceInfoBuilder.append(masterInfo.getInfo(masterInfo)); instanceLogBuilder.append("
"); // 遍历map for (Map.Entry redisInfo : instanceMap.entrySet()) { if (redisInfo.getKey().indexOf(masterInfo.getIpAndPortInfo(masterInfo)) > -1) { //instanceInfo += "------" + redisInfo.getValue().getInfo(redisInfo.getValue()); //instanceLog += "日志
"; instanceInfoBuilder.append("------") .append(redisInfo.getValue().getInfo(redisInfo.getValue())); instanceLogBuilder.append("日志
"); } } } } } instanceLog = instanceLogBuilder.toString(); instanceInfo = instanceInfoBuilder.toString(); // 返回实例和日志信息 resultMap.put(INSTANCE_INFO_KEY, instanceInfo); resultMap.put(INSTANCE_LOG_KEY, instanceLog); return resultMap; } /** *

* Description:获取sentinel实例信息 *

* * @version 1.0 * @date 2018/10/11 */ private String getSentinelInstanceInfo(List instanceList) { //String instanceSentinelinfo = ""; StringBuilder instanceSentinelInfoBuilder = new StringBuilder(); List sentinelNodes = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && instance.getRoleDesc().equals("sentinel")) { sentinelNodes.add(instance); } } if (sentinelNodes != null && sentinelNodes.size() > 0) { for (InstanceInfo sentinelNode : sentinelNodes) { //instanceSentinelinfo += sentinelNode.getHostPort() + " " + sentinelNode.getTypeDesc() + " \n"; instanceSentinelInfoBuilder.append(sentinelNode.getHostPort()) .append(" ") .append(sentinelNode.getTypeDesc()) .append(" \n"); } } } return instanceSentinelInfoBuilder.toString(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppScrollRestartController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.ConfigRestartRecord; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.web.enums.AppTypeEnum; import com.sohu.cache.web.enums.ConfigRestartOperateEnum; import com.sohu.cache.web.enums.RestartStatusEnum; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.vo.AppRedisConfigVo; import com.sohu.cache.web.vo.ExecuteResult; import com.sohu.cache.web.vo.GeneralResponse; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** *

* Description: 应用滚动重启 *

* * @author zengyizhao * @version 1.0 * @date 2021/9/13 */ @Controller @RequestMapping("/manage/app/restart") public class AppScrollRestartController extends BaseController { @Autowired private AppService appService; @Autowired private AppScrollRestartService appScrollRestartService; @Autowired private AssistRedisService assistRedisService; private final static String RESTART_CONFIG_KEY = "restart:config:"; /** * 查询滚动重启记录 * @param model * @param appId * @return */ @RequestMapping(value = "getRestartRecord", method = RequestMethod.GET) public ModelAndView getRestartRecord(Model model, Long appId, Integer pageNo) { ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setAppId(appId); if(pageNo == null){ pageNo = 1; } int pageSize = 10; List configRestartRecordByCondition = appScrollRestartService.getConfigRestartRecordByCondition(model, configRestartRecord, pageNo, pageSize); List instanceInfoList = new ArrayList<>(); if(appId != null){ instanceInfoList = appService.getAppBasicInstanceInfo(appId); }else{ Set appIdSet = new HashSet<>(); for (ConfigRestartRecord record : configRestartRecordByCondition) { if(appIdSet.contains(record.getAppId())){ continue; } appIdSet.add(record.getAppId()); instanceInfoList.addAll(appService.getAppBasicInstanceInfo(record.getAppId())); } } Map instanceInfoMap = instanceInfoList.stream().collect(Collectors.toMap(InstanceInfo::getId, Function.identity(), (v1, v2) -> v1)); model.addAttribute("restartRecordList", configRestartRecordByCondition); model.addAttribute("appId", appId); model.addAttribute("instanceInfoMap", instanceInfoMap); return new ModelAndView("manage/appOps/appRestartList"); } /** * 滚动重启 * @param appRedisConfigVo * @return */ @RequestMapping(value = "scrollRestart", method = RequestMethod.POST) public void scrollRestart(HttpServletRequest request, HttpServletResponse response, @RequestBody AppRedisConfigVo appRedisConfigVo) { AppUser appUser = getUserInfo(request); if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "滚动重启/修改配置正在执行中,不允许重复操作。")); sendMessage(response, json); return; } // 1.获取应用信息 AppDesc appDesc = appService.getByAppId(appRedisConfigVo.getAppId()); //无有效应用时,或应用redis类型不符时,返回 if(appDesc == null || appDesc.getType() != AppTypeEnum.REDIS_SENTINEL.getType() && appDesc.getType() != AppTypeEnum.REDIS_CLUSTER.getType()){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "参数有误,请确认。")); sendMessage(response, json); return; } // 2.获取当前应用下redis实例信息 List instanceList = appService.getAppBasicInstanceInfo(appRedisConfigVo.getAppId()); //过滤出运行中的实例 instanceList = instanceList.stream().filter(instanceInfo -> instanceInfo.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()).collect(Collectors.toList()); if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "滚动重启/修改配置正在执行中,不允许重复操作。")); sendMessage(response, json); return; } //处理实例信息,封装主从信息 boolean executeFlag = appScrollRestartService.handleAppInstanceInfo(instanceList, appDesc); if(!executeFlag){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "未正确获取到实例主从信息,请重试。")); sendMessage(response, json); return; } if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "滚动重启/修改配置正在执行中,不允许重复操作。")); sendMessage(response, json); return; } //校验有效实例,并校验传入的instancId全部有效,无效直接返回 boolean check = this.checkPointedInstance(instanceList, appRedisConfigVo.getInstanceList()); if(!check){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "实例不满足此操作。")); sendMessage(response, json); return; } if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "滚动重启/修改配置正在执行中,不允许重复操作。")); sendMessage(response, json); return; } ExecuteResult executeResult = appScrollRestartService.handleRestart(appUser, appDesc, instanceList, appRedisConfigVo); String responseJson = null; if(executeResult.getMessage() != null){ responseJson = JSONObject.toJSONString(GeneralResponse.ok(executeResult.getMessage())); } sendMessage(response, responseJson); return; } /** * 停止滚动重启 * @param response * @param appId * @return */ @RequestMapping(value = "stopRestart", method = RequestMethod.GET) public void getRestartRecord(Model model, HttpServletResponse response, Long appId) { boolean existsStopRestartFlag = appScrollRestartService.existsStopRestartFlag(appId); if(existsStopRestartFlag){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "停止请求不允许重复发送,请通过日志查看重启进度。")); sendMessage(response, json); return; } ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setAppId(appId); int pageNo = 1; int pageSize = 10; List configRestartRecordByCondition = appScrollRestartService.getConfigRestartRecordByCondition(model, configRestartRecord, pageNo, pageSize); boolean existRestart = false; for (ConfigRestartRecord record : configRestartRecordByCondition) { if((record.getStatus() == RestartStatusEnum.RUNNING.getValue() && record.getOperateType() == ConfigRestartOperateEnum.RESTART.getValue()) || (record.getStatus() == RestartStatusEnum.RESTART_AFTER_CONFIG.getValue() && record.getOperateType() == ConfigRestartOperateEnum.CONFIG_RESTART.getValue())){ existRestart = true; break; } } if(existRestart){ boolean result = appScrollRestartService.addStopRestartFlag(appId); if(result){ String json = JSONObject.toJSONString(GeneralResponse.ok("停止请求已发送,但不确保停止,请通过日志查看重启进度。")); sendMessage(response, json); return; } }else{ String json = JSONObject.toJSONString(GeneralResponse.ok("重启任务不存在或已结束,请确认。")); sendMessage(response, json); return; } } /** * 修改配置 * @param appRedisConfigVo * @return */ @RequestMapping(value = "updateConfig", method = RequestMethod.POST) public void updateConfig(HttpServletRequest request, HttpServletResponse response, @RequestBody AppRedisConfigVo appRedisConfigVo) { AppUser appUser = getUserInfo(request); if (!assistRedisService.setNx(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId(), "1")) { String json = JSONObject.toJSONString(GeneralResponse.error(500, "滚动重启/修改配置正在执行中,不允许重复操作。")); sendMessage(response, json); return; } try { // 1.获取应用信息 AppDesc appDesc = appService.getByAppId(appRedisConfigVo.getAppId()); //无有效应用时,或应用redis类型不符时,返回 if (appDesc == null || appDesc.getType() != AppTypeEnum.REDIS_SENTINEL.getType() && appDesc.getType() != AppTypeEnum.REDIS_CLUSTER.getType() ) { String json = JSONObject.toJSONString(GeneralResponse.error(500, "参数有误,请确认。")); sendMessage(response, json); return; } //判断是否有配置信息 if (CollectionUtils.isEmpty(appRedisConfigVo.getConfigList())) { String json = JSONObject.toJSONString(GeneralResponse.error(500, "参数有误,请确认。")); sendMessage(response, json); return; } // 2.获取当前应用下redis实例信息 List instanceList = appService.getAppBasicInstanceInfo(appRedisConfigVo.getAppId()); //过滤出运行中的实例 instanceList = instanceList.stream().filter(instanceInfo -> instanceInfo.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()).collect(Collectors.toList()); //处理实例信息,封装主从信息 boolean executeFlag = appScrollRestartService.handleAppInstanceInfo(instanceList, appDesc); if(!executeFlag){ String json = JSONObject.toJSONString(GeneralResponse.error(500, "未正确获取到实例主从信息,请重试。")); sendMessage(response, json); return; } //校验有效实例,并校验传入的instancId全部有效,无效直接返回 boolean check = this.checkPointedInstance(instanceList, appRedisConfigVo.getInstanceList()); if (!check) { String json = JSONObject.toJSONString(GeneralResponse.error(500, "实例不满足此操作。")); sendMessage(response, json); return; } Map map = appScrollRestartService.handleConfig(appUser, appDesc, instanceList, appRedisConfigVo); String handleResult = (String) map.get("errorInfo"); String responseJson = null; if (StringUtils.isNotEmpty(handleResult)) { responseJson = JSONObject.toJSONString(GeneralResponse.error(500, handleResult)); } else { responseJson = JSONObject.toJSONString(GeneralResponse.ok(map)); } sendMessage(response, responseJson); return; }catch (Exception e){ logger.error("updateConfig error: ", e); }finally { assistRedisService.remove(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()); } } /** * 校验有效实例是否为空,并校验传入的instancId全部有效,无效直接返回 * @param instanceInfoList * @param instanceIdList * @return */ private boolean checkPointedInstance(List instanceInfoList, List instanceIdList){ if(CollectionUtils.isEmpty(instanceInfoList)){ return false; } if(CollectionUtils.isEmpty(instanceIdList)){ return true; } boolean existFlag = false; for(Integer instanceId : instanceIdList){ existFlag = false; for(InstanceInfo instanceInfo : instanceInfoList){ if(instanceId == instanceInfo.getId()){ existFlag = true; break; } } if(!existFlag){ return false; } } return true; } /** * 发送json消息 * * @param response * @param responseMessage */ public void sendMessage(HttpServletResponse response, GeneralResponse responseMessage) { response.reset(); response.setContentType("application/json;charset=UTF-8"); PrintWriter printWriter = null; try { printWriter = response.getWriter(); printWriter.write(JSONObject.toJSONString(responseMessage)); } catch (IOException e) { logger.error(ExceptionUtils.getFullStackTrace(e)); } finally { if (printWriter != null) { printWriter.flush(); printWriter.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppStatController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.dao.AppClientStatisticGatherDao; import com.sohu.cache.dao.AppDao; import com.sohu.cache.entity.AppClientStatisticGather; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.TimeBetween; import com.sohu.cache.task.tasks.daily.TopologyExamTask; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * 应用常用统计 * * @author leifu * @Time 2014年10月14日 */ @Controller @RequestMapping("manage/app/stat") public class AppStatController extends BaseController { @Resource(name = "appService") private AppService appService; @Resource private AppDao appDao; @Autowired private AppClientStatisticGatherDao appClientStatisticGatherDao; @Autowired TopologyExamTask topologyExamTask; @RequestMapping(value = "/list") public ModelAndView doAppStatsList(HttpServletRequest request, HttpServletResponse response, Model model) { //获取tab int tabId = NumberUtils.toInt(request.getParameter("tabId"), 0); model.addAttribute("tabId", tabId); //获取appId,判断有无 long appId = NumberUtils.toLong(request.getParameter("appId"), -1l); model.addAttribute("appId", appId == -1l ? "" : appId); if (appId != -1l) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return new ModelAndView("manage/appStat/list"); } } //获取searchDate,判断有无 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = DateUtil.fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } searchDate = timeBetween.getFormatStartDate(); model.addAttribute("searchDate", searchDate); //appDescList List appDescList = appDao.getOnlineApps(); model.addAttribute("list", appDescList); switch (tabId) { case 0: { //appClientGatherStatMap Map> appClientGatherStatMap = appService.getAppClientStatGather(appId, searchDate); model.addAttribute("appClientGatherStatMap", appClientGatherStatMap); break; } } model.addAttribute("appStatActive", SuccessEnum.SUCCESS.value()); model.addAttribute("collectAlert", "(请等待" + ConstUtils.MACHINE_STATS_CRON_MINUTE + "分钟)"); return new ModelAndView("manage/appStat/list"); } @RequestMapping(value = "/list/server") public ModelAndView doAppStatsListForServer(HttpServletRequest request, HttpServletResponse response, Model model) { //获取tab int tabId = NumberUtils.toInt(request.getParameter("tabId"), 1); model.addAttribute("tabId", tabId); //获取appId,判断有无 long appId = NumberUtils.toLong(request.getParameter("appId"), -1l); model.addAttribute("appId", appId == -1l ? "" : appId); if (appId != -1l) { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return new ModelAndView("manage/appStat/listServer"); } } //获取searchDate,判断有无 String searchDate = request.getParameter("searchDate"); TimeBetween timeBetween = new TimeBetween(); try { timeBetween = DateUtil.fillWithDateFormat(searchDate); } catch (ParseException e) { logger.error(e.getMessage(), e); } searchDate = timeBetween.getFormatStartDate(); model.addAttribute("searchDate", searchDate); if(tabId == 1 || tabId == 2 || tabId == 3){ //appDescList List appDescList = appDao.getOnlineApps(); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); model.addAttribute("appDescList", appDescList); //appDetailVOMap Map appDetailVOMap = appStatsCenter.getOnlineAppDetails(); model.addAttribute("appDetailVOMap", appDetailVOMap); //appClientGatherStatMap Map> appClientGatherStatMap = appService.getAppClientStatGather(appId, searchDate); model.addAttribute("appClientGatherStatMap", appClientGatherStatMap); } //机器环境检查 if(tabId == 4 ) { SimpleDateFormat searchFormat = new SimpleDateFormat("yyyy-MM-dd"); Map machineEnvMap = null; try { machineEnvMap = machineCenter.getAllMachineEnv(searchFormat.parse(searchDate), MachineInfoEnum.MachineTypeEnum.CONTAINER.getValue()); } catch (ParseException e) { logger.error("machineCenter get container date:{} error :{}",searchDate,e.getMessage()); } model.addAttribute("machineEnvMap", machineEnvMap); } // 宿主环境检查 if(tabId == 5) { SimpleDateFormat searchFormat = new SimpleDateFormat("yyyy-MM-dd"); Map machineEnvMap = null; try { machineEnvMap = machineCenter.getAllMachineEnv(searchFormat.parse(searchDate), MachineInfoEnum.MachineTypeEnum.HOST.getValue()); } catch (ParseException e) { logger.error("machineCenter get host date:{} error :{}",searchDate,e.getMessage()); } model.addAttribute("machineEnvMap", machineEnvMap); } model.addAttribute("appStatServerActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/appStat/listServer"); } @RequestMapping("/clientList") public ModelAndView clientList(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { List clientList = new ArrayList<>(); List instanceList = appService.getAppOnlineInstanceInfo(appId); for (InstanceInfo instance : instanceList) { if ("master".equals(instance.getRoleDesc())) { clientList = redisCenter.getClientList(instance.getId()); break; } } Set clientSet = clientList.stream() .filter(clientInfo -> StringUtils.isNotBlank(clientInfo)) .filter(clientInfo -> clientInfo.contains("flags=N")) // .filter(clientInfo -> !clientInfo.contains("cmd=client")) .map(clientInfo -> clientInfo.split(" |:")[1]) .collect(Collectors.toSet()); model.addAttribute("clientSet", clientSet.stream().collect(Collectors.joining("\n"))); return new ModelAndView(""); } @RequestMapping("/topologyUpdate") public ModelAndView topologyUpdate(HttpServletRequest request, HttpServletResponse response, Model model) { try { List topologyExamList = topologyExamTask.checkAppsTopology(new Date()); if (CollectionUtils.isNotEmpty(topologyExamList)) { appClientStatisticGatherDao.batchSaveTopologyExam(topologyExamList); } model.addAttribute("status", 1); } catch (Exception e) { logger.error(e.getMessage(), e); model.addAttribute("status", 0); } return new ModelAndView(""); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/AppToolController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.*; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.admin.CoreAppsStatCenter; import com.sohu.cache.task.TaskService; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.DiagnosticToolService; import com.sohu.cache.web.service.ToolService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * 应用诊断工具 * Created by rucao on 2018/11/9 */ @Controller @RequestMapping("/manage/app/tool") public class AppToolController extends BaseController { private Logger logger = LoggerFactory.getLogger(AppToolController.class); @Resource private RedisCenter redisCenter; @Resource private ToolService toolService; @Resource private AppDao appDao; @Resource private CoreAppsStatCenter coreAppsStatCenter; @Autowired private DiagnosticToolService diagnosticToolService; @Autowired private ResourceDao resourceDao; @Autowired private TaskService taskService; /** * 跳转到主页 * * @param request * @param response * @param model * @return */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag, Long appId, Long parentTaskId, Long auditId, Integer diagnosticStatus) { model.addAttribute("tabTag", tabTag); model.addAttribute("appId", appId); model.addAttribute("parentTaskId", parentTaskId); model.addAttribute("auditId", auditId); model.addAttribute("diagnosticStatus", diagnosticStatus); model.addAttribute("diagnosticActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/diagnosticTool/list"); } @RequestMapping(value = "/diagnostic/tool") public ModelAndView diagnosticToolIndex(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag, Long appId, Long parentTaskId, Long auditId, Integer diagnosticStatus) { List appDescList = appDao.getOnlineApps(); appDescList.forEach(appDesc -> { String versionName = Optional.ofNullable(resourceService.getResourceById(appDesc.getVersionId())).map(ver -> ver.getName()).orElse(""); appDesc.setVersionName(versionName); }); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); if (tabTag == null || "redis-cli".equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticTool"); } int type = DiagnosticTypeEnum.getDescKey(tabTag); List diagnosticTaskRecordList = diagnosticToolService.getDiagnosticTaskRecords(appId, parentTaskId, auditId, type, diagnosticStatus); model.addAttribute("diagnosticTaskRecordList", diagnosticTaskRecordList); model.addAttribute("appId", appId); model.addAttribute("parentTaskId", parentTaskId); model.addAttribute("auditId", auditId); model.addAttribute("type", type); model.addAttribute("diagnosticStatus", diagnosticStatus); if (DiagnosticTypeEnum.SCAN_KEY.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticScan"); } else if (DiagnosticTypeEnum.BIG_KEY.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticMemUsed"); } else if (DiagnosticTypeEnum.IDLE_KEY.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticIdleKey"); } else if (DiagnosticTypeEnum.HOT_KEY.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticHotKey"); } else if (DiagnosticTypeEnum.DEL_KEY.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticDelKey"); } else if (DiagnosticTypeEnum.SLOT_ANALYSIS.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticSlot"); } else if (DiagnosticTypeEnum.SCAN_CLEAN.getDesc().equals(tabTag)) { return new ModelAndView("manage/diagnosticTool/diagnosticScanClean"); } return new ModelAndView(""); } @RequestMapping(value = "/diagnostic/appInstances") public ModelAndView getAppInstances(HttpServletRequest request, HttpServletResponse response, Model model, Long appId) { JSONObject json = new JSONObject(); AppDesc appDesc = appService.getByAppId(appId); if (appDesc == null) { json.put("status", String.valueOf(SuccessEnum.FAIL.value())); } else { List instanceInfos = appService.getAppOnlineInstanceInfo(appId); json.put("appInstanceList", instanceInfos); json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); } sendMessage(response, json.toString()); return null; } @RequestMapping(value = "/diagnostic/submit") public ModelAndView submitDiagnostic(HttpServletRequest request, HttpServletResponse response, Model model, int type, Long auditId, Long appId, String nodes, String params) { if (auditId == null && appId != null && appId != -1L) { AppUser appUser = getUserInfo(request); AppDesc appDesc = appService.getByAppId(appId); AppAudit appAudit = appService.saveAppDiagnostic(appDesc, appUser, "应用诊断任务:" + DiagnosticTypeEnum.getKeyDesc(type)); auditId = appAudit.getId(); } AppUser appUser = getUserInfo(request); appAuditDao.updateAppAuditUser(auditId, AppCheckEnum.APP_ALLOCATE_RESOURCE.value(), appUser.getId()); long taskId = -1l; if (type == DiagnosticTypeEnum.SCAN_KEY.getType()) { String[] paramArray = params.split(","); String pattern = paramArray.length > 0 ? paramArray[0] : ""; int size = paramArray.length > 1 ? Integer.parseInt(paramArray[1]) : 20; taskId = taskService.addAppScanKeyTask(appId, auditId, nodes, pattern, size, 0); } else if (type == DiagnosticTypeEnum.BIG_KEY.getType()) { String[] paramArray = params.split(","); long fromBytes = paramArray.length > 0 ? Long.parseLong(paramArray[0]) : 10; int size = paramArray.length > 1 ? Integer.parseInt(paramArray[1]) : 20; taskId = taskService.addAppBigKeyTask(appId, nodes, fromBytes, -1, size, auditId, 0); } else if (type == DiagnosticTypeEnum.IDLE_KEY.getType()) { String[] paramArray = params.split(","); long idleTime = paramArray.length > 0 ? Integer.parseInt(paramArray[0]) : 7; int size = paramArray.length > 1 ? Integer.parseInt(paramArray[1]) : 20; taskId = taskService.addAppIdleKeyTask(appId, nodes, idleTime, size, auditId, 0); } else if (type == DiagnosticTypeEnum.HOT_KEY.getType()) { String[] paramArray = params.split(","); String command = paramArray.length > 0 ? paramArray[0] : "hotkey"; taskId = taskService.addAppHotKeyTask(appId, nodes, command, auditId, 0); } else if (type == DiagnosticTypeEnum.DEL_KEY.getType()) { String[] paramArray = params.split(","); String pattern = paramArray.length > 0 ? paramArray[0] : ""; taskId = taskService.addAppDelKeyTask(appId, nodes, pattern, auditId, 0); } else if (type == DiagnosticTypeEnum.SLOT_ANALYSIS.getType()) { taskId = taskService.addAppSlotAnalysisTask(appId, nodes, auditId, 0); } else if (type == DiagnosticTypeEnum.SCAN_CLEAN.getType()) { Map map = JSONObject.parseObject(params, Map.class); taskId = taskService.addAppScanCleanTask(appId, map, auditId, 0); } JSONObject json = new JSONObject(); json.put("status", "success"); json.put("taskId", taskId); sendMessage(response, json.toString()); return null; } @RequestMapping(value = "/diagnostic/result") public ModelAndView diagnosticResultList(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, Long parentTaskId, Long auditId, Integer type, Integer diagnosticStatus) { try { Map diagnosticTypeMap = new HashMap<>(); for (DiagnosticTypeEnum diagnosticType : DiagnosticTypeEnum.values()) { diagnosticTypeMap.put(diagnosticType.getType(), diagnosticType.getDesc()); } model.addAttribute("diagnosticTypeMap", diagnosticTypeMap); List appDescList = appDao.getOnlineApps(); Map appDescMap = appDescList.stream().collect(Collectors.toMap(AppDesc::getAppId, Function.identity())); model.addAttribute("appDescMap", appDescMap); List diagnosticTaskRecordList = diagnosticToolService.getDiagnosticTaskRecords(appId, parentTaskId, auditId, type, diagnosticStatus); model.addAttribute("diagnosticTaskRecordList", diagnosticTaskRecordList); model.addAttribute("appId", appId); model.addAttribute("parentTaskId", parentTaskId); model.addAttribute("auditId", auditId); model.addAttribute("type", type); model.addAttribute("diagnosticStatus", diagnosticStatus); model.addAttribute("diagnosticActive", SuccessEnum.SUCCESS.value()); } catch (Exception e) { logger.error(e.getMessage(), e); } return new ModelAndView("manage/diagnosticTool/resultList"); } @RequestMapping(value = "/diagnostic/data") public ModelAndView diagnosticResult(HttpServletRequest request, HttpServletResponse response, Model model, String redisKey, int type, boolean err) { JSONObject json = new JSONObject(); if (!StringUtil.isBlank(redisKey)) { if (type == DiagnosticTypeEnum.SCAN_KEY.getType()) { List result = diagnosticToolService.getScanDiagnosticData(redisKey); json.put("count", result.size()); json.put("result", result); } else if (type == DiagnosticTypeEnum.BIG_KEY.getType() || type == DiagnosticTypeEnum.IDLE_KEY.getType() || type == DiagnosticTypeEnum.SLOT_ANALYSIS.getType()) { Map result = diagnosticToolService.getDiagnosticDataMap(redisKey, type, err); json.put("count", result.size()); json.put("result", result); } else if (type == DiagnosticTypeEnum.HOT_KEY.getType()) { String result = diagnosticToolService.getHotkeyDiagnosticData(redisKey); json.put("result", result == null ? "" : result.replaceAll("(\\r\\n|\\n|\\n\\r)", "
")); } else if (type == DiagnosticTypeEnum.SCAN_CLEAN.getType()) { List result = diagnosticToolService.getScanCleanDiagnosticData(redisKey); json.put("result", result); } } json.put("status", String.valueOf(SuccessEnum.SUCCESS.value())); sendMessage(response, json.toString()); return null; } @RequestMapping(value = "/diagnostic/sampleCompareData") public ModelAndView diagnosticSampleCompareResult(HttpServletRequest request, HttpServletResponse response, Model model, String redisKey) { List result = new ArrayList<>(); try { if (!StringUtil.isBlank(redisKey)) { result = diagnosticToolService.getScanCleanDiagnosticData(redisKey); } model.addAttribute("diagnosticResultList", result); } catch (Exception e) { logger.error(e.getMessage(), e); } return new ModelAndView("manage/diagnosticTool/diagnosticSampleCompareResult"); } @RequestMapping("/commandExecute") public ModelAndView getCommandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String node, String command, Integer timeout) { String result = ""; if (appId != null && appId > 0 && !StringUtil.isBlank(node)) { model.addAttribute("appId", appId); model.addAttribute("node", node); String host = node.split(":")[0]; int port = Integer.parseInt(node.split(":")[1]); result = redisCenter.executeAdminCommand(appId, host, port, command, timeout); } else { result = "error"; } model.addAttribute("result", result); Map resultMap = new HashMap(); resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("result", result); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } @PostMapping(value = "/diagnostic/sampleScan") public ModelAndView getSampleScan(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String nodes, String pattern) { List sampleScanData = diagnosticToolService.getSampleScanData(appId, nodes, pattern); JSONObject json = new JSONObject(); json.put("count", sampleScanData.size()); json.put("result", sampleScanData); json.put("status", "success"); sendMessage(response, json.toString()); return null; } @PostMapping(value = "findInstancePatternKeys") public ModelAndView findInstancePatternKeys(Model model, long appId, String ip, int port, String pattern) { model.addAttribute("result", 1); return new ModelAndView(""); } @PostMapping(value = "findInstanceBigKey") public ModelAndView findInstanceBigKey(Model model, long appId, String ip, int port, long startBytes, long endBytes) { List instanceBigKeyList = redisCenter.findInstanceBigKey(appId, ip, port, startBytes, endBytes); model.addAttribute("instanceBigKeyList", instanceBigKeyList); return new ModelAndView(""); } @PostMapping(value = "findClusterBigKey") public ModelAndView findClusterBigKey(Model model, long appId, long startBytes, long endBytes) { List clusterBigKeyList = redisCenter.findClusterBigKey(appId, startBytes, endBytes); model.addAttribute("clusterBigKeyList", clusterBigKeyList); return new ModelAndView(""); } @PostMapping(value = "findInstanceIdleKeys") public ModelAndView findInstanceIdleKeys(Model model, long appId, String ip, int port, long idleDays) { List instanceIdleKeyList = redisCenter.findInstanceIdleKeys(appId, ip, port, idleDays); model.addAttribute("instanceIdleKeyList", instanceIdleKeyList); return new ModelAndView(""); } @PostMapping(value = "findClusterIdleKeys") public ModelAndView findClusterIdleKeys(Model model, long appId, long idleDays) { List clusterIdleKeyList = redisCenter.findClusterIdleKeys(appId, idleDays); model.addAttribute("clusterIdleKeyList", clusterIdleKeyList); return new ModelAndView(""); } @PostMapping(value = "delInstancePatternKeys") public ModelAndView delInstancePatternKeys(Model model, long appId, String ip, int port, String pattern) { redisCenter.delInstancePatternKeys(appId, ip, port, pattern); model.addAttribute("result", 1); return new ModelAndView(""); } @PostMapping(value = "delClusterPatternKey") public ModelAndView delClusterPatternKey(Model model, long appId, String pattern) { redisCenter.delClusterPatternKey(appId, pattern); model.addAttribute("result", 1); return new ModelAndView(""); } @GetMapping(value = "topologyExam/{appid}") public ModelAndView topologyExamByAppid(HttpServletRequest request, HttpServletResponse response, Model model, @PathVariable("appid") long appid) { List res = toolService.topologyExamByAppid(appid); model.addAttribute("result", res); write(response, res.toString()); return null; } @PostMapping(value = "topologyExam") public ModelAndView topologyExam(Model model, @RequestBody List appidList) { toolService.topologyExam(appidList); return null; } @PostMapping(value = "topologyExam/all") public ModelAndView topologyExamAll(@RequestParam Boolean examTest) { List appDescList = appDao.getOnlineApps(); List appidList = new ArrayList(); for (AppDesc appDesc : appDescList) { if (examTest == false) { if (appDesc.getIsTest() == 0) { appidList.add(appDesc.getAppId()); } } else { appidList.add(appDesc.getAppId()); } } toolService.topologyExam(appidList); return null; } @GetMapping("/restAppDescOfficer") public void restAppDescOfficer() { toolService.restAppDescOfficer(); } @GetMapping("/sendExpAppsStatDataEmail") public ModelAndView sendExpAppsStatDataEmail(@RequestParam("searchDate") String searchDate) { logger.info("begin-sendExpAppsStatDataEmail"); coreAppsStatCenter.sendExpAppsStatDataEmail(searchDate); logger.info("end-sendExpAppsStatDataEmail"); return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/BaseController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.async.AsyncService; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.dao.AppAuditDao; import com.sohu.cache.dao.AppAuditLogDao; import com.sohu.cache.dao.AppImportDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.stats.app.AppDeployCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.util.DateUtil; import com.vladsch.flexmark.ext.tables.TablesExtension; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.parser.ParserEmulationProfile; import com.vladsch.flexmark.util.ast.Document; import com.vladsch.flexmark.util.builder.Extension; import com.vladsch.flexmark.util.options.MutableDataSet; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.ui.Model; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.nio.charset.Charset; import java.text.ParseException; import java.util.*; import java.util.stream.Collectors; /** * 基类controller * * @author leifu * @Time 2014年10月16日 */ public class BaseController { protected final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired protected UserService userService; @Autowired protected AppService appService; @Autowired protected MachineCenter machineCenter; @Autowired protected UserLoginStatusService userLoginStatusService; @Autowired protected RedisCenter redisCenter; @Resource protected AppDeployCenter appDeployCenter; @Resource protected AppAuditDao appAuditDao; @Resource protected AppImportDao appImportDao; @Resource protected AppAuditLogDao appAuditLogDao; @Resource protected InstanceDao instanceDao; @Resource protected RedisDeployCenter redisDeployCenter; @Resource protected AppEmailUtil appEmailUtil; @Resource protected AsyncService asyncService; @Autowired protected AppStatsCenter appStatsCenter; @Autowired protected InstanceDeployCenter instanceDeployCenter; @Autowired AssistRedisService assistRedisService; @Resource protected RedisConfigTemplateService redisConfigTemplateService; @Resource protected ResourceService resourceService; public Boolean saveTempResource(String resourceId, String content) { try { assistRedisService.set(getResourceKey(resourceId), content); } catch (Exception e) { return false; } return true; } private String getResourceKey(String resourceId) { return String.format("resource_%s", resourceId); } public boolean clearTempResource(String resourceId) { try { assistRedisService.del(getResourceKey(resourceId)); } catch (Exception e) { return false; } return true; } public String getTempResource(String resourceId) { try { return assistRedisService.get(getResourceKey(resourceId)); } catch (Exception e) { return null; } } protected TimeBetween getJsonTimeBetween(HttpServletRequest request) throws ParseException { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); Date startDate = DateUtil.parseYYYY_MM_dd(startDateParam); Date endDate; if (StringUtils.isBlank(endDateParam)) { endDate = DateUtils.addDays(startDate, 1); } else { endDate = DateUtil.parseYYYY_MM_dd(endDateParam); } long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate)); return new TimeBetween(beginTime, endTime, startDate, endDate); } protected TimeBetween getTimeBetween(HttpServletRequest request, Model model, String startDateAtr, String endDateAtr) throws ParseException { String startDateParam = request.getParameter(startDateAtr); String endDateParam = request.getParameter(endDateAtr); Date startDate; Date endDate; if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { startDate = new Date(); endDate = DateUtils.addDays(startDate, 1); } else { endDate = DateUtil.parseYYYY_MM_dd(endDateParam); startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } Date yesterDay = DateUtils.addDays(startDate, -1); long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate)); model.addAttribute(startDateAtr, startDateParam); model.addAttribute(endDateAtr, endDateParam); model.addAttribute("yesterDay", DateUtil.formatDate(yesterDay, "yyyy-MM-dd")); return new TimeBetween(beginTime, endTime, startDate, endDate); } protected TimeBetween getTimeBetweenOneDay(HttpServletRequest request, String startDateAtr) throws ParseException { String startDateParam = request.getParameter(startDateAtr); Date startDate; Date endDate; if (StringUtils.isBlank(startDateParam)) { startDate = new Date(); } else { startDate = DateUtil.parseYYYY_MM_dd(startDateParam); } endDate = DateUtils.addDays(startDate, 1); long beginTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(startDate)); long endTime = NumberUtils.toLong(DateUtil.formatYYYYMMddHHMM(endDate)); return new TimeBetween(beginTime, endTime, startDate, endDate); } /** * 返回用户基本信息 * * @param request * @return */ public AppUser getUserInfo(HttpServletRequest request) { String userName = userLoginStatusService.getUserNameFromLoginStatus(request); return userService.getByName(userName); } /** * 发送json消息 * * @param response * @param message */ public void sendMessage(HttpServletResponse response, String message) { response.reset(); response.setContentType("application/json;charset=UTF-8"); PrintWriter printWriter = null; try { printWriter = response.getWriter(); printWriter.write(message); } catch (IOException e) { logger.error(ExceptionUtils.getFullStackTrace(e)); } finally { if (printWriter != null) { printWriter.flush(); printWriter.close(); } } } /** * @param response * @param result */ protected void write(HttpServletResponse response, String result) { try { response.setContentType("text/javascript"); response.setCharacterEncoding("UTF-8"); response.getWriter().print(result); response.getWriter().flush(); } catch (Exception e) { logger.error(e.getMessage(), e); } } /** * 查看用户对于app操作的权限 * * @param request * @param appId * @return */ protected boolean checkAppUserProvilege(HttpServletRequest request, long appId) { // 当前用户 AppUser currentUser = getUserInfo(request); if (currentUser == null) { logger.error("currentUser is empty"); return false; } if (AppUserTypeEnum.ADMIN_USER.value().equals(currentUser.getType())) { return true; } // 应用用户列表 List appToUsers = appService.getAppToUserList(appId); if (CollectionUtils.isEmpty(appToUsers)) { logger.error("appId {} userList is empty", appId); return false; } // 应用下用户id集合 Set appUserIdSet = new HashSet(); for (AppToUser appToUser : appToUsers) { appUserIdSet.add(appToUser.getUserId()); } //最终判断 if (!appUserIdSet.contains(currentUser.getId())) { logger.error("currentUser {} hasn't previlege in appId {}", currentUser.getId(), appId); return false; } return true; } /** * 实例统计信息 * * @param appId * @param model */ protected void fillAppInstanceStats(Long appId, Model model) { // 实例列表 List instanceList = appService.getAppInstanceInfo(appId); model.addAttribute("instanceList", instanceList); Map> instanceListMap = instanceGroupByMaster(instanceList); model.addAttribute("instanceListMap", instanceListMap); // 实例Map Map instanceInfoMap = new HashMap(); for (InstanceInfo instanceInfo : instanceList) { instanceInfoMap.put(instanceInfo.getId(), instanceInfo); } model.addAttribute("instanceInfoMap", instanceInfoMap); // 实例统计 List appInstanceStats = appService.getAppInstanceStats(appId); Map instanceStatsMap = new HashMap(); for (InstanceStats instanceStats : appInstanceStats) { instanceStatsMap.put(instanceStats.getIp() + ":" + instanceStats.getPort(), instanceStats); } model.addAttribute("instanceStatsMap", instanceStatsMap); //slot分布 Map clusterSlotsMap = redisCenter.getClusterSlotsMap(appId); model.addAttribute("clusterSlotsMap", clusterSlotsMap); //机器列表 long startTime = System.currentTimeMillis(); List machineList = machineCenter.getMachineStats(null, null, null, null, null, null, null); Map machineMap = machineList.stream().collect(Collectors.toMap(MachineStats::getIp, machineStats -> machineStats)); model.addAttribute("machineMap", machineMap); logger.info("getMachineStats cost: {}, appId: {}", System.currentTimeMillis() - startTime, appId); Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); model.addAttribute("machineInstanceCountMap", machineInstanceCountMap); } private Map> instanceGroupByMaster(List instanceList) { Map> resultMap = new HashMap>(); for (InstanceInfo info : instanceList) { String roleDesc = info.getRoleDesc(); if (roleDesc != null && roleDesc.equals("master")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getId(), new ArrayList()); list.add(info); resultMap.put(info.getId(), list); } else if (roleDesc != null && roleDesc.equals("slave")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getMasterInstanceId(), new ArrayList()); list.add(info); resultMap.put(info.getMasterInstanceId(), list); } else if (roleDesc != null && roleDesc.equals("sentinel")) { List list = (ArrayList) MapUtils.getObject(resultMap, -2, new ArrayList()); list.add(info); resultMap.put(-2, list); } else {//offline List list = (ArrayList) MapUtils.getObject(resultMap, -1, new ArrayList()); list.add(info); resultMap.put(-1, list); } } return resultMap; } /** * 应用机器实例分布图 * * @param appId * @param model */ protected void fillAppMachineInstanceTopology(Long appId, Model model) { List instanceList = appService.getAppInstanceInfo(appId); int groupId = 1; // 1.分组,同一个主从在一组 for (int i = 0; i < instanceList.size(); i++) { InstanceInfo instance = instanceList.get(i); // 有了groupId,不再设置 if (instance.getGroupId() > 0) { continue; } if (instance.isOffline()) { continue; } for (int j = i + 1; j < instanceList.size(); j++) { InstanceInfo instanceCompare = instanceList.get(j); if (instanceCompare.isOffline()) { continue; } // 寻找主从对应关系 if (instanceCompare.getMasterInstanceId() == instance.getId() || instance.getMasterInstanceId() == instanceCompare.getId()) { instanceCompare.setGroupId(groupId); } } instance.setGroupId(groupId++); } // 2.机器下的实例列表 Map> machineInstanceMap = new HashMap>(); for (InstanceInfo instance : instanceList) { String ip = instance.getIp(); if (machineInstanceMap.containsKey(ip)) { machineInstanceMap.get(ip).add(instance); } else { List tempInstanceList = new ArrayList(); tempInstanceList.add(instance); machineInstanceMap.put(ip, tempInstanceList); } } model.addAttribute("machineInstanceMap", machineInstanceMap); model.addAttribute("instancePairCount", groupId - 1); } /** * markdown to html */ public String markdown2html(String filename, String suffix) throws Exception { String templatePath = "static/" + filename + suffix; InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templatePath); if (inputStream == null) { return null; } String markdown = new String(read(inputStream), Charset.forName("UTF-8")); MutableDataSet options = new MutableDataSet(); options.setFrom(ParserEmulationProfile.MARKDOWN); options.set(Parser.EXTENSIONS, Arrays.asList(new Extension[]{TablesExtension.create()})); Document document = Parser.builder(options).build().parse(markdown); String html = HtmlRenderer.builder(options).build().render(document); return html; } public byte[] read(InputStream inputStream) throws IOException { byte[] buffer = new byte[1024]; int len = 0; ByteArrayOutputStream bos = null; try { bos = new ByteArrayOutputStream(); while ((len = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, len); } } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { } } } return bos.toByteArray(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ClientManageController.java ================================================ package com.sohu.cache.web.controller; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sohu.cache.web.service.UserService; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.sohu.cache.client.service.ClientReportExceptionService; import com.sohu.cache.client.service.ClientVersionService; import com.sohu.cache.entity.AppClientVersion; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.ClientInstanceException; import com.sohu.cache.web.enums.SuccessEnum; /** * 客户端管理 * * @author leifu * @Date 2016年2月18日 * @Time 下午4:55:32 */ @Controller @RequestMapping("manage/client") public class ClientManageController extends BaseController { /** * 客户端异常服务 */ @Resource(name = "clientReportExceptionService") private ClientReportExceptionService clientReportExceptionService; /** * 客户端版本服务 */ @Resource(name = "clientVersionService") private ClientVersionService clientVersionService; @Resource private UserService userService; /** * /manage/client/exception * @param request * @param response * @param model * @return */ @RequestMapping(value = "/exception") public ModelAndView doClientExceptionStat(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); model.addAttribute("ip", ip); //近一个月 long collectTime = NumberUtils.toLong(new SimpleDateFormat("yyyyMMdd000000").format(DateUtils.addMonths(new Date(), -1))); // 一段时间内客户端异常 List clientInstanceExceptionList = clientReportExceptionService.getInstanceExceptionStat(ip, collectTime); model.addAttribute("clientInstanceExceptionList", clientInstanceExceptionList); // 应用相关map fillAppInfoMap(model); model.addAttribute("clientExceptionActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/client/exception/list"); } private void fillAppInfoMap(Model model) { List appDescList = appService.getAllAppDesc(); // 所有应用id和负责人对应关系 Map appIdOwnerMap = new HashMap(); for (AppDesc appDesc : appDescList) { appIdOwnerMap.put(appDesc.getAppId(), userService.getOfficerName(appDesc.getOfficer())); } model.addAttribute("appIdOwnerMap", appIdOwnerMap); // 所有应用id和应用名对应关系 Map appIdNameMap = new HashMap(); for (AppDesc appDesc : appDescList) { appIdNameMap.put(appDesc.getAppId(), appDesc.getName()); } model.addAttribute("appIdNameMap", appIdNameMap); } /** * /manage/client/version * @param request * @param response * @param model * @return */ /*@RequestMapping(value = "/version") public ModelAndView doVersionStat(HttpServletRequest request, HttpServletResponse response, Model model) { long appId = NumberUtils.toLong(request.getParameter("appId"),-1); List appClientVersionList = clientVersionService.getAll(appId); // 应用相关map fillAppInfoMap(model); model.addAttribute("appClientVersionList", appClientVersionList); model.addAttribute("clientVersionActive", SuccessEnum.SUCCESS.value()); model.addAttribute("appId", request.getParameter("appId")); return new ModelAndView("manage/client/version/list"); }*/ } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ConfigManageController.java ================================================ package com.sohu.cache.web.controller; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.SystemConfig; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ConfigService; import com.sohu.cache.web.util.AppEmailUtil; /** * cachecloud配置管理 * * @author leifu * @Date 2016年5月23日 * @Time 上午10:31:16 */ @Controller @RequestMapping("manage/config") public class ConfigManageController extends BaseController { @Resource(name = "configService") private ConfigService configService; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; /** * 初始化配置 * * @param request * @param response * @param model * @return */ @RequestMapping(value = "/init") public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) { List configList = configService.getConfigList(1); model.addAttribute("configList", configList); model.addAttribute("success", request.getParameter("success")); model.addAttribute("configActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/config/init"); } /** * 修改配置 * * @param request * @param response * @param model * @return */ @RequestMapping(value = "/update") public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); logger.warn("user {} want to change config!", appUser.getName()); List oldConfigList = configService.getConfigList(1); SuccessEnum successEnum; Map configMap = new HashMap(); try { Map paramMap = request.getParameterMap(); for (Entry entry : paramMap.entrySet()) { String key = entry.getKey(); String value = entry.getValue()[0]; if (StringUtils.isNotBlank(key)) { configMap.put(key, value); } } if (MapUtils.isEmpty(configMap)) { logger.error("params {} may be empty!!", paramMap); } successEnum = configService.updateConfig(configMap); if (successEnum.equals(SuccessEnum.SUCCESS)) { configService.reloadSystemConfig(); } } catch (Exception e) { successEnum = SuccessEnum.FAIL; logger.error(e.getMessage(), e); } Map systemDifConfigMap = getDifConfigMap(oldConfigList, configMap); appEmailUtil.sendSystemConfigDifEmail(appUser, systemDifConfigMap, successEnum); logger.warn("user {} change config result is {}!", appUser.getName(), successEnum.value()); return new ModelAndView("redirect:/manage/config/init?success=" + successEnum.value()); } private Map getDifConfigMap(List oldConfigList, Map configMap) { Map systemDifConfigMap = new HashMap(); for (SystemConfig systemConfig : oldConfigList) { String key = systemConfig.getConfigKey(); String oldValue = systemConfig.getConfigValue(); String newValue = configMap.get(key); if (newValue != null && !oldValue.equals(newValue)) { systemDifConfigMap.put(systemConfig.getInfo(), String.format("old value: %s, new value: %s", oldValue, newValue)); } } return systemDifConfigMap; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ExamToolController.java ================================================ package com.sohu.cache.web.controller; import com.google.common.collect.Lists; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.tasks.daily.TopologyExamTask; import com.sohu.cache.web.enums.ExamToolEnum; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Created by rucao on 2019/1/25 */ @Controller @RequestMapping("/manage/tool") public class ExamToolController extends BaseController{ @Autowired private TaskService taskService; @Autowired private MachineDao machineDao; @Autowired TopologyExamTask topologyExamTask; @RequestMapping(value = "/topologyExam") public ModelAndView startTopologyExam(Model model, long appId){ ArrayList applist = new ArrayList(); AppDesc appDesc = appService.getByAppId(appId); if(appDesc.getAppId() > 0){ applist.add(appDesc); Map info = topologyExamTask.check(applist); model.addAttribute("checkInfo",info); } return new ModelAndView("manage/appTool/appKeysDealTool"); } @RequestMapping(value = "/topologyExam/online",method = RequestMethod.POST) public long startAllTopologyExam(){ long taskId=taskService.addAppTopologyExamTask(true, ExamToolEnum.EXAM_NON_TEST.getValue(),0,0); return taskId; } @RequestMapping(value = "/machineExam",method = RequestMethod.GET) public ModelAndView startMachineExam(Model model, @RequestParam Integer useType, @RequestParam String ipLike){ List machineIpList=Lists.newArrayList(); List machineInfoByCondition = machineDao.getMachineInfoByCondition(ipLike, useType, -1, null, -1, null); for (MachineInfo machineInfo:machineInfoByCondition){ machineIpList.add(machineInfo.getIp()); } taskService.addMachineExamTask(machineIpList,useType,0); return new ModelAndView(""); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ImportAppController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.constant.ImportAppResult; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.AppDataMigrateStatusDao; import com.sohu.cache.dao.TaskQueueDao; import com.sohu.cache.entity.*; import com.sohu.cache.stats.app.ImportAppCenter; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AppImportStatusEnum; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppImportService; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import redis.clients.jedis.Jedis; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; /** * 已经存在Redis导入 */ @Controller @RequestMapping("/import/app") public class ImportAppController extends BaseController { @Resource(name = "importAppCenter") private ImportAppCenter importAppCenter; @Autowired private AppImportService appImportService; @Autowired private AppDataMigrateStatusDao appDataMigrateStatusDao; @Autowired private TaskQueueDao taskQueueDao; @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag) { model.addAttribute("tabTag", tabTag); model.addAttribute("appImportActive", SuccessEnum.SUCCESS.value()); List appImportList = appImportService.getImportAppList(-1); model.addAttribute("appImportList", appImportList); model.addAttribute("appImportStatusMap", Arrays.stream(AppImportStatusEnum.values()).collect(Collectors.toMap(AppImportStatusEnum::getStatus, Function.identity()))); return new ModelAndView("manage/appImport/list"); } @RequestMapping(value = "init") public ModelAndView init(Model model, long importId) { //1.获取导入信息 AppImport appImport = appImportService.get(importId); if (appImport == null) { return new ModelAndView(""); } Long appId = appImport.getAppId(); AppDesc appDesc = appService.getByAppId(appId); int oldStatus = appImport.getStatus(); int status = oldStatus; if (status == AppImportStatusEnum.PREPARE.getStatus()) { //导入申请未处理阶段 if (appDesc.getVersionId() != -1) { appImport.setRedisVersionName(resourceService.getResourceById(appDesc.getVersionId()).getName()); } model.addAttribute("appDesc", appDesc); } if (status > 10 && status < 20) { //创建版本阶段 if (appDesc.getVersionId() == -1) { SystemResource resource = resourceService.getResourceByName(appImport.getRedisVersionName()); if (resource != null) { appDesc.setVersionId(resource.getId()); appService.update(appDesc); status = AppImportStatusEnum.VERSION_BUILD_END.getStatus(); model.addAttribute("hasRedisVersion", 1); } else { model.addAttribute("hasRedisVersion", 0); } } else { status = AppImportStatusEnum.VERSION_BUILD_END.getStatus(); model.addAttribute("hasRedisVersion", 1); } } if (status >= 20 && status < 30) { //创建应用阶段 long appBuildTaskId = appImport.getAppBuildTaskId(); if (appBuildTaskId > 0) { TaskQueue appBuildTask = taskQueueDao.getById(appBuildTaskId); if (appBuildTask != null && (appBuildTask.getStatus() == 2 || appBuildTask.getStatus() == 3)) { status = AppImportStatusEnum.APP_BUILD_ERROR.getStatus(); } else if (appBuildTask != null && appBuildTask.getStatus() == 4) { appDesc.setStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus()); appService.update(appDesc); status = AppImportStatusEnum.APP_BUILD_END.getStatus(); } else { status = AppImportStatusEnum.APP_BUILD_START.getStatus(); } } else { status = AppImportStatusEnum.APP_BUILD_INIT.getStatus(); } } if (status >= 30 && status < 40) { //数据迁移阶段 long migrateId = appImport.getMigrateId(); if (migrateId > 0) { AppDataMigrateStatus appDataMigrateStatus = appDataMigrateStatusDao.getByMigrateId(migrateId); int migrateStatus = appDataMigrateStatus.getStatus(); if (migrateStatus == 1) { status = AppImportStatusEnum.MIGRATE_END.getStatus(); } else if (migrateStatus == 2) { status = AppImportStatusEnum.MIGRATE_ERROR.getStatus(); } else { status = AppImportStatusEnum.MIGRATE_START.getStatus(); } } } if (status == AppImportStatusEnum.MIGRATE_END.getStatus()) { model.addAttribute("appId", appId); } if (oldStatus != status) { appImport.setStatus(status); appImportService.update(appImport); } model.addAttribute("appImport", appImport); model.addAttribute("appImportStatusMap", Arrays.stream(AppImportStatusEnum.values()).collect(Collectors.toMap(AppImportStatusEnum::getStatus, Function.identity()))); return new ModelAndView("/manage/appImport/appImport"); } @RequestMapping(value = "/preRebuildApp") public ModelAndView preRebuildApp(HttpServletRequest request, HttpServletResponse response, Model model) { long importId = NumberUtils.toLong(request.getParameter("importId")); long appId = NumberUtils.toLong(request.getParameter("appId")); AppImport appImport = appImportService.get(importId); appImport.setStatus(AppImportStatusEnum.APP_BUILD_INIT.getStatus()); appImport.setAppBuildTaskId(0); AppDesc appDesc = appService.getByAppId(appId); if (appDesc != null) { //offline instances List instanceInfos = instanceDao.getInstListByAppId(appId); int type = appDesc.getType(); if (instanceInfos != null) { instanceInfos.parallelStream().map(instanceInfo -> instanceOffline(appId, instanceInfo, type)).collect(Collectors.toList()); } appDesc.setStatus(AppStatusEnum.STATUS_INITIALIZE.getStatus()); if (appService.update(appDesc) > 0 && appImportService.update(appImport) > 0) { model.addAttribute("success", 1); } } appImportService.update(appImport); return new ModelAndView(""); } @RequestMapping(value = "/preReMigrate") public ModelAndView preReMigrate(HttpServletRequest request, HttpServletResponse response, Model model) { long importId = NumberUtils.toLong(request.getParameter("importId")); long appId = NumberUtils.toLong(request.getParameter("appId")); AppImport appImport = appImportService.get(importId); appImport.setStatus(AppImportStatusEnum.APP_BUILD_END.getStatus()); appImport.setMigrateId(0); AppDesc appDesc = appService.getByAppId(appId); if (appDesc != null) { //todo 清空数据可能耗时太长 if (cleanAppData(appId) && appImportService.update(appImport) > 0) { model.addAttribute("success", 1); } } appImportService.update(appImport); return new ModelAndView(""); } private boolean cleanAppData(long appId) { List instanceList = instanceDao.getInstListByAppId(appId); // 开始清除 for (InstanceInfo instance : instanceList) { if (instance.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } String host = instance.getIp(); int port = instance.getPort(); // master + 非sentinel节点 BooleanEnum isMater = redisCenter.isMaster(appId, host, port); if (isMater == BooleanEnum.TRUE && !TypeUtil.isRedisSentinel(instance.getType())) { //异步线程处理 AsyncThreadPoolFactory.DEFAULT_ASYNC_THREAD_POOL.execute(new Runnable() { @Override public void run() { Jedis jedis = redisCenter.getAdminJedis(appId, host, port); jedis.getClient().setConnectionTimeout(1000); jedis.getClient().setSoTimeout(60000); try { logger.warn("{}:{} start clear data", host, port); long start = System.currentTimeMillis(); String result = jedis.flushAll(); logger.warn("{}:{} finish clear data :{}, cost time:{} ms", host, port, result, (System.currentTimeMillis() - start)); } catch (Exception e) { logger.error("clear redis: " + e.getMessage(), e); } finally { jedis.close(); } } }); } } return true; } private boolean instanceOffline(long appId, InstanceInfo instanceInfo, int type) { final String ip = instanceInfo.getIp(); final int port = instanceInfo.getPort(); boolean isShutdown = TypeUtil.isRedisType(type) ? redisCenter.shutdown(appId, ip, port) : true; if(isShutdown){ isShutdown = redisCenter.checkShutdownSuccess(instanceInfo); } if (isShutdown) { instanceInfo.setStatus(InstanceStatusEnum.OFFLINE_STATUS.getStatus()); instanceDao.update(instanceInfo); } else { return false; } return true; } @RequestMapping(value = "/goOn") public ModelAndView goOn(HttpServletRequest request, HttpServletResponse response, Model model) { long importId = NumberUtils.toLong(request.getParameter("importId")); int status = NumberUtils.toInt(request.getParameter("status")); long migrateId = NumberUtils.toLong(request.getParameter("migrateId")); long appBuildTaskId = NumberUtils.toLong(request.getParameter("appBuildTaskId")); AppImport appImport = appImportService.get(importId); if (status > 0) { appImport.setStatus(status); } if (migrateId > 0) { appImport.setMigrateId(migrateId); } if (appBuildTaskId > 0) { appImport.setAppBuildTaskId(appBuildTaskId); } appImportService.update(appImport); model.addAttribute("success", 1); model.addAttribute("message", "成功"); return new ModelAndView(""); } @RequestMapping(value = "/check") public ModelAndView check(HttpServletRequest request, HttpServletResponse response, Model model) { int type = NumberUtils.toInt(request.getParameter("type")); String appInstanceInfo = request.getParameter("appInstanceInfo"); String password = request.getParameter("password"); ImportAppResult importAppResult = importAppCenter.check(type, appInstanceInfo, password); model.addAttribute("status", importAppResult.getStatus()); model.addAttribute("message", importAppResult.getMessage()); return new ModelAndView(""); } @RequestMapping(value = "/add") public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Model model) { AppDesc appDesc = genAppDesc(request); String appInstanceInfo = request.getParameter("appInstanceInfo"); logger.warn("appDesc:" + appDesc); logger.warn("appInstanceInfo: " + appInstanceInfo); // 不需要对格式进行检验,check已经做过了。 boolean isSuccess = importAppCenter.importAppAndInstance(appDesc, appInstanceInfo); logger.warn("import app result is {}", isSuccess); model.addAttribute("status", isSuccess ? 1 : 0); return new ModelAndView(""); } /** * 生成AppDesc * * @param request * @return */ private AppDesc genAppDesc(HttpServletRequest request) { // 当前用户 AppUser currentUser = getUserInfo(request); // 当前时间 Date date = new Date(); // 组装Appdesc AppDesc appDesc = new AppDesc(); appDesc.setName(request.getParameter("name")); appDesc.setIntro(request.getParameter("intro")); appDesc.setOfficer(request.getParameter("officer")); appDesc.setType(NumberUtils.toInt(request.getParameter("type"))); appDesc.setIsTest(NumberUtils.toInt(request.getParameter("isTest"))); appDesc.setMemAlertValue(NumberUtils.toInt(request.getParameter("memAlertValue"))); appDesc.setAppKey(request.getParameter("password")); appDesc.setUserId(currentUser.getId()); appDesc.setStatus(2); appDesc.setCreateTime(date); appDesc.setPassedTime(date); appDesc.setVerId(1); return appDesc; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/IndexController.java ================================================ package com.sohu.cache.web.controller; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 首页 * * @author leifu * @Date 2014年10月28日 * @Time 上午10:49:32 */ @Controller @RequestMapping("/") public class IndexController extends BaseController { @RequestMapping(value = "") public ModelAndView index(HttpServletRequest request, HttpServletResponse response) { String userName = userLoginStatusService.getUserNameFromTicket(request); String redirectUrl = request.getParameter("redirectUrl"); if(StringUtils.isBlank(redirectUrl)){ redirectUrl = "/admin/app/list"; } if (StringUtils.isNotBlank(userName)) { userLoginStatusService.addLoginStatus(request, response, userName); } return new ModelAndView("redirect:" + redirectUrl); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/InstanceAlertValueController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.ErrorMessageEnum; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceAlertConfig; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.enums.*; import com.sohu.cache.stats.instance.InstanceAlertConfigService; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.vo.AlertConfig; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.stream.Collectors; /** * 实例报警阀值 * * @author leifu * @Date 2016年8月24日 * @Time 下午1:24:25 */ @Controller @RequestMapping("manage/instanceAlert") public class InstanceAlertValueController extends BaseController { @Resource(name = "instanceAlertConfigService") private InstanceAlertConfigService instanceAlertConfigService; @Resource(name = "instanceDao") private InstanceDao instanceDao; /** * 初始化配置 */ @RequestMapping(value = "/init") public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) { int appType = 0; // String appTypeStr = request.getParameter("appType"); // if (StringUtils.isNotEmpty(appTypeStr)) { // appType = Integer.parseInt(appTypeStr); // } model.addAttribute("appType", appType); model.addAttribute("instanceAlertCheckCycleEnumList", InstanceAlertCheckCycleEnum.getInstanceAlertCheckCycleEnumList()); model.addAttribute("instanceAlertCompareTypeEnumList", InstanceAlertCompareTypeEnum.getInstanceAlertCompareTypeEnumList()); model.addAttribute("redisAlertConfigEnumList", RedisAlertConfigEnum.getRedisAlertConfigEnumList()); List globalAlertConfigList = instanceAlertConfigService.getByTypeAndAppType(InstanceAlertTypeEnum.ALL_ALERT.getValue(), appType); model.addAttribute("instanceAlertAllList", globalAlertConfigList); model.addAttribute("redisUsedGlobalAlertConfigList", distinctUsedGlobalAlert(globalAlertConfigList)); model.addAttribute("instanceAlertList", instanceAlertConfigService.getAll()); model.addAttribute("success", request.getParameter("success")); model.addAttribute("redisAlertValueActive", SuccessEnum.SUCCESS.value()); List instanceAlertSpecialList = instanceAlertConfigService.getByTypeAndAppType(InstanceAlertTypeEnum.INSTANCE_ALERT.getValue(), appType); List appAlertSpecialList = instanceAlertConfigService.getByTypeAndAppType(InstanceAlertTypeEnum.APP_ALERT.getValue(), appType); fillinstanceHostPort(instanceAlertSpecialList); List appAndInstanceAlertConfigList = addAppAlertConfigToInstanceSpecialList(appAlertSpecialList, instanceAlertSpecialList); model.addAttribute("instanceAlertSpecialList", appAndInstanceAlertConfigList); return new ModelAndView("manage/instanceAlert/init"); } /** * 筛选出使用的全局配置,唯一的 * @param globalAlertConfigList * @return */ private List distinctUsedGlobalAlert(List globalAlertConfigList) { if(CollectionUtils.isEmpty(globalAlertConfigList)){ return Collections.emptyList(); } List alertConfigList = new ArrayList<>(); globalAlertConfigList.stream().forEach(instanceAlertConfig -> { AlertConfig alertConfig = new AlertConfig(); alertConfig.setValue(instanceAlertConfig.getAlertConfig()); alertConfig.setInfo(instanceAlertConfig.getConfigInfo()); alertConfigList.add(alertConfig); }); return alertConfigList.stream().distinct().collect(Collectors.toList()); } /** * 填充hostport * * @param instanceAlertSpecialList */ private void fillinstanceHostPort(List instanceAlertSpecialList) { if (CollectionUtils.isEmpty(instanceAlertSpecialList)) { return; } for (InstanceAlertConfig instanceAlertConfig : instanceAlertSpecialList) { long instanceId = instanceAlertConfig.getInstanceId(); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); if (instanceInfo == null) { continue; } instanceAlertConfig.setInstanceInfo(instanceInfo); } } /** * 将应用报警封装为特殊实例报警进行返回 * @param appAlertSpecialList * @param instanceAlertSpecialList */ private List addAppAlertConfigToInstanceSpecialList(List appAlertSpecialList, List instanceAlertSpecialList) { if(CollectionUtils.isNotEmpty(appAlertSpecialList)){ if(CollectionUtils.isEmpty(instanceAlertSpecialList)){ return appAlertSpecialList; }else{ instanceAlertSpecialList.addAll(appAlertSpecialList); return instanceAlertSpecialList.stream().sorted(Comparator.comparing(instanceAlertConfig -> instanceAlertConfig.getId())).collect(Collectors.toList()); } } return instanceAlertSpecialList; } /** * 添加配置 */ @RequestMapping(value = "/add") public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); InstanceAlertConfig instanceAlertConfig = getInstanceAlertConfig(request); SuccessEnum successEnum; try { //如果未传重要程度,则查询已存在的全局配置获取 if(instanceAlertConfig.getImportantLevel() == null){ InstanceAlertConfig globalAlertConfig = instanceAlertConfigService.getGlobalAlertConfigByCondition(instanceAlertConfig.getAlertConfig(), instanceAlertConfig.getCompareType(), instanceAlertConfig.getAppType()); if(globalAlertConfig != null){ instanceAlertConfig.setImportantLevel(globalAlertConfig.getImportantLevel() == null ? 0 : globalAlertConfig.getImportantLevel()); }else{ instanceAlertConfig.setImportantLevel(0); } } logger.warn("user {} want to add instanceAlertConfig {}", appUser.getName(), instanceAlertConfig); instanceAlertConfigService.save(instanceAlertConfig); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} add instanceAlertConfig {}, result is {}", appUser.getName(), instanceAlertConfig, successEnum.value()); model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 添加应用配置,仅添加一条信息 */ @RequestMapping(value = "/addApp") public ModelAndView addApp(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); int appid = NumberUtils.toInt(request.getParameter("appid")); //判断此应用下是否有实例 List instancelist = instanceDao.getEffectiveInstListByAppId(appid); if(instancelist != null && instancelist.size()>0){ InstanceAlertConfig appAlertConfig = getAppAlertConfig(request); SuccessEnum successEnum; try { logger.warn("user {} want to add app instanceAlertConfig, size is {}", appUser.getName(), instancelist.size()); //如果未传重要程度,则查询已存在的全局配置获取 if(appAlertConfig.getImportantLevel() == null){ InstanceAlertConfig globalAlertConfig = instanceAlertConfigService.getGlobalAlertConfigByCondition(appAlertConfig.getAlertConfig(), appAlertConfig.getCompareType(), appAlertConfig.getAppType()); if(globalAlertConfig != null){ appAlertConfig.setImportantLevel(globalAlertConfig.getImportantLevel() == null ? 0 : globalAlertConfig.getImportantLevel()); }else{ appAlertConfig.setImportantLevel(0); } } instanceAlertConfigService.save(appAlertConfig); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} add app , result is {}", appUser.getName(), successEnum); model.addAttribute("status", successEnum.value()); } return new ModelAndView(""); } /** * 检查hostPort是否存在 */ @RequestMapping(value = "/checkInstanceHostPort") public ModelAndView checkInstanceHostPort(HttpServletRequest request, HttpServletResponse response, Model model) { String hostPort = request.getParameter("instanceHostPort"); if (StringUtils.isBlank(hostPort)) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", "参数为空"); return new ModelAndView(""); } String[] hostPortArr = hostPort.split(":"); if (hostPortArr.length != 2) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", "hostPort:" + hostPort + "格式错误"); return new ModelAndView(""); } String host = hostPortArr[0]; int port = NumberUtils.toInt(hostPortArr[1]); InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(host, port); if (instanceInfo == null) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", "hostPort:" + hostPort + "不存在"); } else { model.addAttribute("status", SuccessEnum.SUCCESS.value()); } return new ModelAndView(""); } /** * 初始化配置 */ @RequestMapping(value = "/monitor") public ModelAndView monitor(HttpServletRequest request, HttpServletResponse response, Model model) { instanceAlertConfigService.monitorLastMinuteAllInstanceInfo(); return null; } /** * 修改配置 */ @RequestMapping(value = "/update") public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); int id = NumberUtils.toInt(request.getParameter("id")); String alertValue = request.getParameter("alertValue"); int checkCycle = NumberUtils.toInt(request.getParameter("checkCycle")); int compareType = NumberUtils.toInt(request.getParameter("compareType")); int importantLevel = NumberUtils.toInt(request.getParameter("importantLevel")); logger.warn("user {} want to change instance alert id={}, alertValue={}, checkCycle={}, compareType={}", appUser.getName(), id, alertValue, checkCycle, compareType); SuccessEnum successEnum; try { InstanceAlertConfig orgInstAlertConfig = instanceAlertConfigService.get(id); instanceAlertConfigService.update(id, alertValue, checkCycle, compareType, importantLevel); //判断是否为更新紧急程度,如是,判断是否为全局报警,如是,则更新所有报警级别为此级别 if(orgInstAlertConfig != null && importantLevel != orgInstAlertConfig.getImportantLevel()){ if(InstanceAlertTypeEnum.ALL_ALERT.getValue() == orgInstAlertConfig.getType()){ instanceAlertConfigService.updateImportantLevel(orgInstAlertConfig.getAlertConfig(), compareType, importantLevel, orgInstAlertConfig.getAppType()); } } successEnum = SuccessEnum.SUCCESS; } catch (DuplicateKeyException e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.ALERT_CONFIG_CONSTRAINT_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); }catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} change instance alert id={}, alertValue={}, checkCycle={}, compareType={}, result is {}", appUser.getName(), id, alertValue, checkCycle, compareType, successEnum.info()); model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 删除配置 */ @RequestMapping(value = "/remove") public ModelAndView remove(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); int id = NumberUtils.toInt(request.getParameter("id")); InstanceAlertConfig instanceAlertConfig = instanceAlertConfigService.get(id); logger.warn("user {} want to delete config id {}, instanceAlertConfig {}", appUser.getName(), id, instanceAlertConfig); SuccessEnum successEnum; try { instanceAlertConfigService.remove(id); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} want to delete config id {}, instanceAlertConfig {}, result is {}", appUser.getName(), id, instanceAlertConfig, successEnum.info()); model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } private InstanceInfo getInstanceInfo(String hostPort) { String[] hostPortArr = hostPort.split(":"); String host = hostPortArr[0]; int port = NumberUtils.toInt(hostPortArr[1]); return instanceDao.getAllInstByIpAndPort(host, port); } private InstanceAlertConfig getInstanceAlertConfig(HttpServletRequest request) { // 相关参数 Date now = new Date(); String alertConfig = request.getParameter("alertConfig"); String alertValue = request.getParameter("alertValue"); String configInfo = request.getParameter("configInfo"); int compareType = NumberUtils.toInt(request.getParameter("compareType")); int checkCycle = NumberUtils.toInt(request.getParameter("checkCycle")); String importantLevelStr = request.getParameter("importantLevel"); Integer importantLevel = null; if(StringUtils.isNotEmpty(importantLevelStr)){ importantLevel = NumberUtils.toInt(importantLevelStr); } int instanceId = 0; int type = NumberUtils.toInt(request.getParameter("type")); int appType = NumberUtils.toInt(request.getParameter("appType")); if (InstanceAlertTypeEnum.INSTANCE_ALERT.getValue() == type) { String hostPort = request.getParameter("instanceHostPort"); InstanceInfo instanceInfo = getInstanceInfo(hostPort); instanceId = instanceInfo.getId(); } // 生成对象 InstanceAlertConfig instanceAlertConfig = new InstanceAlertConfig(); instanceAlertConfig.setAlertConfig(alertConfig); instanceAlertConfig.setAlertValue(alertValue); instanceAlertConfig.setConfigInfo(configInfo); instanceAlertConfig.setCompareType(compareType); instanceAlertConfig.setInstanceId(instanceId); instanceAlertConfig.setCheckCycle(checkCycle); instanceAlertConfig.setLastCheckTime(now); instanceAlertConfig.setType(type); instanceAlertConfig.setAppType(appType); instanceAlertConfig.setUpdateTime(now); instanceAlertConfig.setImportantLevel(importantLevel); instanceAlertConfig.setStatus(InstanceAlertStatusEnum.YES.getValue()); return instanceAlertConfig; } private List getInstanceAlertConfig(HttpServletRequest request, List instanceList) { List instanceAlertConfigList = new ArrayList(); if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { // sentinel节点忽略 if(TypeUtil.isRedisSentinel(instance.getType())){ logger.info("sentinel node ignore"); continue; } logger.info("ip:{},port:{} alert born ",instance.getHostId(),instance.getHostPort()); // 相关参数 Date now = new Date(); String alertConfig = request.getParameter("alertConfig"); String alertValue = request.getParameter("alertValue"); RedisAlertConfigEnum redisAlertConfigEnum = RedisAlertConfigEnum.getRedisAlertConfig(alertConfig); String configInfo = redisAlertConfigEnum == null ? "" : redisAlertConfigEnum.getInfo(); int compareType = NumberUtils.toInt(request.getParameter("compareType")); int checkCycle = NumberUtils.toInt(request.getParameter("checkCycle")); int instanceId = instance.getId(); // 生成对象 InstanceAlertConfig instanceAlertConfig = new InstanceAlertConfig(); instanceAlertConfig.setAlertConfig(alertConfig); instanceAlertConfig.setAlertValue(alertValue); instanceAlertConfig.setConfigInfo(configInfo); instanceAlertConfig.setCompareType(compareType); instanceAlertConfig.setInstanceId(instanceId); instanceAlertConfig.setCheckCycle(checkCycle); instanceAlertConfig.setLastCheckTime(now); instanceAlertConfig.setType(2); instanceAlertConfig.setUpdateTime(now); instanceAlertConfig.setStatus(InstanceAlertStatusEnum.YES.getValue()); //添加至监控列表 instanceAlertConfigList.add(instanceAlertConfig); } } return instanceAlertConfigList; } private InstanceAlertConfig getAppAlertConfig(HttpServletRequest request) { // 相关参数 Date now = new Date(); long appid = NumberUtils.toLong(request.getParameter("appid")); String alertConfig = request.getParameter("alertConfig"); String alertValue = request.getParameter("alertValue"); String configInfo = request.getParameter("configInfo"); int compareType = NumberUtils.toInt(request.getParameter("compareType")); int checkCycle = NumberUtils.toInt(request.getParameter("checkCycle")); Integer appType = NumberUtils.toInt(request.getParameter("appType")); String importantLevelStr = request.getParameter("importantLevel"); Integer importantLevel = null; if(StringUtils.isNotEmpty(importantLevelStr)){ importantLevel = NumberUtils.toInt(importantLevelStr); } // 生成对象 InstanceAlertConfig instanceAlertConfig = new InstanceAlertConfig(); instanceAlertConfig.setAlertConfig(alertConfig); instanceAlertConfig.setAlertValue(alertValue); instanceAlertConfig.setConfigInfo(configInfo); instanceAlertConfig.setCompareType(compareType); instanceAlertConfig.setInstanceId(appid); instanceAlertConfig.setCheckCycle(checkCycle); instanceAlertConfig.setLastCheckTime(now); instanceAlertConfig.setType(3); instanceAlertConfig.setAppType(appType); instanceAlertConfig.setUpdateTime(now); instanceAlertConfig.setStatus(InstanceAlertStatusEnum.YES.getValue()); instanceAlertConfig.setImportantLevel(importantLevel); return instanceAlertConfig; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/InstanceController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.alert.InstanceAlertService; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.*; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.web.chart.key.ChartKeysUtil; import com.sohu.cache.web.chart.model.SplineChartEntity; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.WebClientComponent; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.vo.RedisSlowLog; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.text.ParseException; import java.util.*; import java.util.stream.Collectors; /** * Created by hym on 14-7-27. */ @Controller @RequestMapping("/admin/instance") public class InstanceController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Resource(name = "instanceStatsCenter") private InstanceStatsCenter instanceStatsCenter; @Resource(name = "appStatsCenter") private AppStatsCenter appStatsCenter; @Resource(name = "redisCenter") private RedisCenter redisCenter; @Resource private InstanceAlertService instanceAlertService; @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId, String tabTag) { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); startDateParam = DateUtil.formatDate(startDate, "yyyyMMdd"); endDateParam = DateUtil.formatDate(endDate, "yyyyMMdd"); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); String condition = request.getParameter("condition"); int conditionInt = StringUtils.isEmpty(condition) ? 0 : Integer.parseInt(condition); model.addAttribute("condition", conditionInt); if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); if (instanceInfo == null) { model.addAttribute("type", -1); } else { if (appId != null && appId > 0) { model.addAttribute("appId", appId); } else { model.addAttribute("appId", instanceInfo.getAppId()); } model.addAttribute("type", instanceInfo.getType()); } } else { } if (tabTag != null) { model.addAttribute("tabTag", tabTag); } return new ModelAndView("instance/instanceIndex"); } @RequestMapping("/stat") public ModelAndView stat(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); startDateParam = DateUtil.formatDate(startDate, "yyyyMMdd"); endDateParam = DateUtil.formatDate(endDate, "yyyyMMdd"); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); model.addAttribute("instanceInfo", instanceInfo); model.addAttribute("appId", instanceInfo.getAppId()); model.addAttribute("appDetail", appStatsCenter.getAppDetail(instanceInfo.getAppId())); InstanceStats instanceStats = instanceStatsCenter.getInstanceStats(instanceId); model.addAttribute("instanceStats", instanceStats); List topLimitAppCommandStatsList = appStatsCenter.getTopLimitAppCommandStatsList(instanceInfo.getAppId(), Long.parseLong(startDateParam) * 10000, Long.parseLong(endDateParam) * 10000, 5); model.addAttribute("appCommandStats", topLimitAppCommandStatsList); } return new ModelAndView("instance/instanceStat"); } @RequestMapping("/advancedAnalysis") public ModelAndView advancedAnalysis(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); String formatStartDate = null; String formatEndDate = null; if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); startDateParam = DateUtil.formatDate(startDate, "yyyyMMdd"); endDateParam = DateUtil.formatDate(endDate, "yyyyMMdd"); formatStartDate = startDateParam; formatEndDate = endDateParam; }else{ if(startDateParam.contains("-") && endDateParam.contains("-")){ try{ formatStartDate = DateUtil.formatDate(DateUtil.parseYYYY_MM_dd(startDateParam), "yyyyMMdd"); formatEndDate = DateUtil.formatDate(DateUtil.parseYYYY_MM_dd(endDateParam), "yyyyMMdd"); }catch (Exception e){ logger.error("date format error", e); } }else{ formatStartDate = startDateParam; formatEndDate = endDateParam; } } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); model.addAttribute("instanceInfo", instanceInfo); model.addAttribute("appId", instanceInfo.getAppId()); List topLimitAppCommandStatsList = appStatsCenter.getTopLimitAppCommandStatsList(instanceInfo.getAppId(), Long.parseLong(formatStartDate) * 10000, Long.parseLong(formatEndDate) * 10000, 5); model.addAttribute("appCommandStats", topLimitAppCommandStatsList); } else { } return new ModelAndView("instance/instanceAdvancedAnalysis"); } /** * 获取某个命令时间分布图 * * @param instanceId 实例id * @param commandName 命令名称 * @throws java.text.ParseException */ @RequestMapping("/getCommandStats") public ModelAndView getCommandStats(HttpServletRequest request, HttpServletResponse response, Model model, Long instanceId, String commandName) throws ParseException { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); startDateParam = DateUtil.formatDate(startDate, "yyyyMMdd"); endDateParam = DateUtil.formatDate(endDate, "yyyyMMdd"); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); Date startDate = DateUtil.parseYYYYMMdd(startDateParam); Date endDate = DateUtil.parseYYYYMMdd(endDateParam); if (instanceId != null) { long firstDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + "0000"); long firstDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + "2359"); long secondDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + "0000"); long secondDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + "2359"); List instanceCommandStatsListFirst = instanceStatsCenter .getCommandStatsList(instanceId, firstDayBegin, firstDayEnd, commandName); List instanceCommandStatsListSecond = instanceStatsCenter .getCommandStatsList(instanceId, secondDayBegin, secondDayEnd, commandName); Map cmdStatsFirst = new HashMap(); Map cmdStatsSecond = new HashMap(); for (InstanceCommandStats first : instanceCommandStatsListFirst) { cmdStatsFirst.put(first.getCollectTime() + "", first); } for (InstanceCommandStats second : instanceCommandStatsListSecond) { cmdStatsSecond.put(second.getCollectTime() + "", second); } SplineChartEntity splineChartEntity = new SplineChartEntity(); String container = request.getParameter("container"); if (container != null) { splineChartEntity.renderTo(container); } model.addAttribute("chart", splineChartEntity); splineChartEntity.putTitle(ChartKeysUtil.TitleKey.TEXT.getKey(), "命令:" + commandName + " 的比较曲线【" + startDateParam + "】-【" + endDateParam + "】"); splineChartEntity.setYAxisTitle("y"); List data1 = new ArrayList(); List data2 = new ArrayList(); Map serie1 = new HashMap(); serie1.put("name", startDateParam); serie1.put("data", data1); // serie1.put("type", "area"); Map serie2 = new HashMap(); serie2.put("name", endDateParam); serie2.put("data", data2); // serie2.put("type", "area"); splineChartEntity.putSeries(serie1); splineChartEntity.putSeries(serie2); List x = new LinkedList(); for (int i = 0; i < 1440; i += 1) { Date date = DateUtils.addMinutes(startDate, i); String s = DateUtil.formatHHMM(date); if (cmdStatsFirst.containsKey(startDateParam + s)) { data1.add(cmdStatsFirst.get(startDateParam + s).getCommandCount()); } else { data1.add(0l); } if (cmdStatsSecond.containsKey(endDateParam + s)) { data2.add(cmdStatsSecond.get(endDateParam + s).getCommandCount()); } else { data2.add(0l); } x.add(s); } splineChartEntity.setXAxisCategories(x); } return new ModelAndView(""); } /** * 获取某个命令时间分布图 * * @param instanceId 实例id * @param commandName 命令名称 * @throws java.text.ParseException */ @RequestMapping("/getCommandStatsV2") public ModelAndView getCommandStatsV2(HttpServletRequest request, HttpServletResponse response, Model model, Long instanceId, String commandName) throws ParseException { String startDateParam = request.getParameter("startDate"); String endDateParam = request.getParameter("endDate"); if (StringUtils.isBlank(startDateParam) || StringUtils.isBlank(endDateParam)) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -1); startDateParam = DateUtil.formatDate(startDate, "yyyyMMdd"); endDateParam = DateUtil.formatDate(endDate, "yyyyMMdd"); } model.addAttribute("startDate", startDateParam); model.addAttribute("endDate", endDateParam); Date startDate = DateUtil.parseYYYYMMdd(startDateParam); Date endDate = DateUtil.parseYYYYMMdd(endDateParam); if (instanceId != null) { long firstDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + "0000"); long firstDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(startDate) + "2359"); long secondDayBegin = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + "0000"); long secondDayEnd = NumberUtils.toLong(DateUtil.formatYYYYMMdd(endDate) + "2359"); List instanceCommandStatsListFirst = instanceStatsCenter .getCommandStatsList(instanceId, firstDayBegin, firstDayEnd, commandName); List instanceCommandStatsListSecond = instanceStatsCenter .getCommandStatsList(instanceId, secondDayBegin, secondDayEnd, commandName); Map cmdStatsFirst = new HashMap(); Map cmdStatsSecond = new HashMap(); for (InstanceCommandStats first : instanceCommandStatsListFirst) { cmdStatsFirst.put(first.getCollectTime() + "", first); } for (InstanceCommandStats second : instanceCommandStatsListSecond) { cmdStatsSecond.put(second.getCollectTime() + "", second); } SplineChartEntity splineChartEntity = new SplineChartEntity(); String container = request.getParameter("container"); if (container != null) { splineChartEntity.renderTo(container); } model.addAttribute("chart", splineChartEntity); splineChartEntity.putTitle(ChartKeysUtil.TitleKey.TEXT.getKey(), "命令:" + commandName + " 的比较曲线【" + startDateParam + "】-【" + endDateParam + "】"); splineChartEntity.setYAxisTitle("y"); List data1 = new ArrayList(); List data2 = new ArrayList(); Map marker = new HashMap(); marker.put("radius", 1); Map serie1 = new HashMap(); serie1.put("name", startDateParam); serie1.put("data", data1); serie1.put("marker", marker); Map serie2 = new HashMap(); serie2.put("name", endDateParam); serie2.put("data", data2); serie2.put("marker", marker); splineChartEntity.putSeries(serie1); splineChartEntity.putSeries(serie2); List x = new LinkedList(); for (int i = 0; i < 1440; i += 1) { Date date = DateUtils.addMinutes(startDate, i); String s = DateUtil.formatHHMM(date); if (cmdStatsFirst.containsKey(startDateParam + s)) { data1.add(cmdStatsFirst.get(startDateParam + s).getCommandCount()); } else { data1.add(0l); } if (cmdStatsSecond.containsKey(endDateParam + s)) { data2.add(cmdStatsSecond.get(endDateParam + s).getCommandCount()); } else { data2.add(0l); } x.add(s); } splineChartEntity.setXAxisCategories(x); } return new ModelAndView(""); } @RequestMapping("/fault") public ModelAndView fault( Model model, Integer instanceId) { List list = null; try { list = instanceAlertService.getListByInstId(instanceId); } catch (Exception e) { logger.error(e.getMessage(), e); } if (list == null) { list = new ArrayList(); } model.addAttribute("list", list); return new ModelAndView("instance/instanceFault"); } @RequestMapping("/configSelect") public ModelAndView configSelect(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) { if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); Map redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue()); model.addAttribute("redisConfigList", redisConfigList); } if (appId != null && appId > 0) { model.addAttribute("appId", appId); } return new ModelAndView("instance/instanceConfigSelect"); } @RequestMapping("/slowSelect") public ModelAndView slowSelect(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId) { if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); List redisSlowLogs = redisCenter.getRedisSlowLogs(instanceId.intValue(), -1); model.addAttribute("redisSlowLogs", redisSlowLogs); } return new ModelAndView("instance/instanceSlowSelect"); } @Autowired private WebClientComponent webClientComponent; @Autowired private InstanceDao instanceDao; @Autowired private AppService appService; @RequestMapping("/clientList") public ModelAndView clientList(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, int condition) { if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); model.addAttribute("condition", condition); long appId = instanceDao.getInstanceInfoById(instanceId).getAppId(); List redisClientList = appService.getAppOnlineInstanceInfo(appId).stream().map(instanceInfo -> instanceInfo.getIp()).collect(Collectors.toList()); List ccWebClientList = webClientComponent.getWebClientIps(); List clientList = redisCenter.getClientList(instanceId.intValue()); model.addAttribute("clientList", clientList); List> clientMapList = redisCenter.formatClientList(clientList); List> clientMapList_final = new ArrayList<>(); switch (condition) { case 0: clientMapList_final = clientMapList.stream().filter(clientMap -> (!ccWebClientList.contains(clientMap.get("addr")) && !redisClientList.contains(clientMap.get("addr")))).collect(Collectors.toList()); break; case 1: clientMapList_final = clientMapList.stream().filter(clientMap -> ccWebClientList.contains(clientMap.get("addr"))).collect(Collectors.toList()); break; case 2: clientMapList_final = clientMapList.stream().filter(clientMap -> redisClientList.contains(clientMap.get("addr"))).collect(Collectors.toList()); break; case 3: clientMapList_final = clientMapList; break; } model.addAttribute("clientMapList", clientMapList_final); } return new ModelAndView("instance/instanceClientList"); } @RequestMapping("/command") public ModelAndView command(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) { if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); } return new ModelAndView("instance/instanceCommand"); } @RequestMapping("/commandExecute") public ModelAndView commandExecute(HttpServletRequest request, HttpServletResponse response, Model model, Integer admin, Long instanceId, Long appId) { if (instanceId != null && instanceId > 0) { model.addAttribute("instanceId", instanceId); String command = request.getParameter("command"); String result = instanceStatsCenter.executeCommand(instanceId, command); model.addAttribute("result", result); } else { model.addAttribute("result", "error"); } return new ModelAndView("instance/commandExecute"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/InstanceManageController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.stats.instance.InstanceStatsCenter; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.MigrateService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.map.HashedMap; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import redis.clients.jedis.HostAndPort; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; import java.util.concurrent.TimeUnit; /** * 应用后台管理 * * @author leifu * @Time 2014年7月3日 */ @Controller @RequestMapping("manage/instance") public class InstanceManageController extends BaseController { private Logger logger = LoggerFactory.getLogger(InstanceManageController.class); @Resource(name = "instanceDeployCenter") private InstanceDeployCenter instanceDeployCenter; @Resource(name = "redisCenter") private RedisCenter redisCenter; @Resource(name = "instanceStatsCenter") private InstanceStatsCenter instanceStatsCenter; @Resource SSHService sshService; @Autowired private MigrateService migrateService; /** * 上线(和下线分开) * * @param instanceId */ @RequestMapping(value = "/startInstance") public ModelAndView doStartInstance(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int instanceId) { AppUser appUser = getUserInfo(request); logger.warn("user {} startInstance {} ", appUser.getName(), instanceId); boolean result = false; if (instanceId > 0) { try { result = instanceDeployCenter.startExistInstance(appId, instanceId); } catch (Exception e) { logger.error(e.getMessage(), e); model.addAttribute("message", e.getMessage()); } } else { logger.error("doStartInstance instanceId:{}", instanceId); model.addAttribute("message", "wrong param"); } logger.warn("user {} startInstance {} result is {}", appUser.getName(), instanceId, result); if (result) { model.addAttribute("success", SuccessEnum.SUCCESS.value()); } else { model.addAttribute("success", SuccessEnum.FAIL.value()); } return new ModelAndView(); } @RequestMapping(value = "/scrollStartInstance") public ModelAndView scrollStartInstance(HttpServletRequest request, Model model, String machineIp) { AppUser appUser = getUserInfo(request); logger.warn("user {} scroll startInstance ip :{} ", appUser.getName(), machineIp); try { List instanceAlertValueResults = instanceDeployCenter.checkAndStartExceptionInstance(machineIp, false); if (!CollectionUtils.isEmpty(instanceAlertValueResults)) { model.addAttribute("message", "滚动重启:恢复实例数量:" + instanceAlertValueResults.size()); } else { model.addAttribute("message", "滚动重启:无实例需要启动!"); } model.addAttribute("success", SuccessEnum.SUCCESS.value()); } catch (Exception e) { logger.error("scrollStartInstance error message :{}", e.getMessage(), e); model.addAttribute("success", SuccessEnum.FAIL.value()); model.addAttribute("message", "滚动重启异常:" + e.getMessage()); } return new ModelAndView(); } /** * 下线实例 * * @param instanceId */ @RequestMapping(value = "/shutdownInstance") public ModelAndView doShutdownInstance(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int instanceId) { AppUser appUser = getUserInfo(request); logger.warn("user {} shutdownInstance {} ", appUser.getName(), instanceId); boolean result = false; if (instanceId > 0) { try { result = instanceDeployCenter.shutdownExistInstance(appId, instanceId); } catch (Exception e) { logger.error(e.getMessage(), e); model.addAttribute("message", e.getMessage()); } } else { logger.error("doShutdownInstance instanceId:{}", instanceId); model.addAttribute("message", "wrong param"); } logger.warn("user {} shutdownInstance {}, result is {}", appUser.getName(), instanceId, result); if (result) { model.addAttribute("success", SuccessEnum.SUCCESS.value()); } else { model.addAttribute("success", SuccessEnum.FAIL.value()); } return new ModelAndView(); } /** * cluster forget instance * * @param instanceId */ @RequestMapping(value = "/forgetInstance") public ModelAndView forgetInstance(HttpServletRequest request, HttpServletResponse response, Model model, long appId, int instanceId) { AppUser appUser = getUserInfo(request); logger.warn("user {} forgetInstance {} ", appUser.getName(), instanceId); boolean result = false; if (instanceId > 0) { try { result = instanceDeployCenter.forgetInstance(appId, instanceId); } catch (Exception e) { logger.error(e.getMessage(), e); model.addAttribute("message", e.getMessage()); } } else { logger.error("doForgetInstance instanceId:{}", instanceId); model.addAttribute("message", "wrong param"); } logger.warn("user {} forgetInstance {}, result is {}", appUser.getName(), instanceId, result); if (result) { model.addAttribute("success", SuccessEnum.SUCCESS.value()); } else { model.addAttribute("success", SuccessEnum.FAIL.value()); model.addAttribute("message", "请查看日志"); } return new ModelAndView(); } @Resource AsyncService asyncService; @PostConstruct public void init() { asyncService.assemblePool(AsyncThreadPoolFactory.TASK_EXECUTE_POOL, AsyncThreadPoolFactory.TASK_EXECUTE_THREAD_POOL); } @RequestMapping("/migrate") public ModelAndView doMigrateInstance(HttpServletResponse response, String sourceIp, String targetIp, String instanceIds, @RequestParam(value = "forceFlag", required = false, defaultValue = "false") boolean forceFlag) { Map resultMap = new HashedMap(); String key = "migrate-instance-" + sourceIp + "-" + targetIp; asyncService.submitFuture(AsyncThreadPoolFactory.MACHINE_POOL, new KeyCallable(key) { public Boolean execute() { try { if (!forceFlag) { //一键迁移 migrate(sourceIp, targetIp, instanceIds); } else { //一键强制迁移 migrateService.forceMigrate(sourceIp, targetIp); } return true; } catch (Exception e) { logger.error("doMigrateInstance ", e.getMessage(), e); return false; } } }); resultMap.put("status", 1); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } public boolean migrate(String sourceIp, String targetIp, String instanceIds) throws SSHException { /** * 1. 检查目标容器的连通性 * 2. 获取需要迁移的实例信息 * 3. 遍历实例:(只对cluster实例迁移) * 3.1 standalone/sentinel节点跳过 * 3.2 如果实例是master:添加新的从节点;获取master节点slave0;执行failover ;下线老节点 * 3.3 如果是slave节点:添加新从节点;下线老的从节点 * 4. 输出报告:下线节点数 ,迁移节点数 */ //1.检查目标容器的连通性 String execute = sshService.execute(targetIp, "echo ok"); //2.获取机器所有实例 List instanceList = machineCenter.getMachineInstanceInfo(sourceIp); //3.如果是部分实例迁移,剔除不需要迁移的实例 if (!StringUtil.isBlank(instanceIds) && !instanceIds.equals("-1")) { List partInstanceIds = Arrays.asList(instanceIds.split(",")); List partInstanceList = new ArrayList<>(); // 找出需要迁移的实例 for (InstanceInfo instanceInfo : instanceList) { if (instanceInfo != null && partInstanceIds.contains(String.valueOf(instanceInfo.getId()))) { partInstanceList.add(instanceInfo); } } instanceList = partInstanceList; } logger.info("container instance migrate instanceIds:{} list size:{}", instanceIds, instanceList.size()); // 4.开始迁移 if (!CollectionUtils.isEmpty(instanceList)) { for (InstanceInfo instanceInfo : instanceList) { if (instanceInfo.isOnline() && (instanceInfo.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER)) { //每次重新获取实例 slave/master角色,可能会发生变化 String role = redisCenter.getInstanceRole(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); logger.info("instanceInfo:{} {} role:{} start migrate", instanceInfo.getIp(), instanceInfo.getPort(),role); // a)当前为master节点 if (InstanceRoleEnum.MASTER.getInfo().equals(role)) { try { //a.1)获取master节点slave0 AppDesc appdesc = appService.getByAppId(instanceInfo.getAppId()); HostAndPort slave0 = redisCenter.getSlave0(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); // a.2)执行failover if (slave0 == null) { continue; } boolean isFailover = redisDeployCenter.clusterFailover(instanceInfo.getAppId(), slave0, "force"); if (!isFailover) { continue; } int times = 0; boolean checkFailover = false; while (!checkFailover && times++ <= 10) { Boolean status = redisCenter.getRedisReplicationStatus(instanceInfo.getAppId(), slave0.getHost(), slave0.getPort()); if (status) { checkFailover = status; } else { TimeUnit.MILLISECONDS.sleep(6000); logger.info(" check slave replication status ,waiting 5s ...."); } } if (!checkFailover) { // 如果failover失败 ,则不下线源节点,继续轮训下个节点 continue; } TimeUnit.SECONDS.sleep(5); //a.3) 添加新的从节点 Boolean isSuccess = null; HostAndPort masterInfo = redisCenter.getMaster(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); if (!StringUtils.isEmpty(masterInfo.getHost()) && masterInfo.getPort() > 0) { InstanceInfo masterInst = instanceDao.getInstByIpAndPort(masterInfo.getHost(), masterInfo.getPort()); if (masterInst == null) { continue; } isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); if (!isSuccess) { // 添加从节点 失败,则退出 检查原因 logger.error("migrate add slave {}:{} fail", instanceInfo.getAppId(), masterInst.getId()); break; } } //a.4) 下线节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(instanceInfo.getAppId(), instanceInfo.getId()); logger.info("MigrateInstance appid:{} offline node master:{} {}, add new slave :{} {}", instanceInfo.getAppId(), instanceInfo.getHostPort(), isOffline, targetIp, isSuccess); } catch (Exception e) { e.printStackTrace(); } } // b).当前为slave节点 if (InstanceRoleEnum.SLAVE.getInfo().equals(role)) { AppDesc appdesc = appService.getByAppId(instanceInfo.getAppId()); HostAndPort masterInfo = redisCenter.getMaster(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); if (masterInfo == null) { logger.error("migrate get master info fail,slave instanceInfo:{} {}", instanceInfo.getIp(), instanceInfo.getPort()); continue; } if (!StringUtils.isEmpty(masterInfo.getHost()) && masterInfo.getPort() > 0) { try { InstanceInfo masterInst = instanceDao.getInstByIpAndPort(masterInfo.getHost(), masterInfo.getPort()); if (masterInst == null) { continue; } //添加新的slave节点 boolean isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); //下线当前slave节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(instanceInfo.getAppId(), instanceInfo.getId()); // sleep 5s TimeUnit.SECONDS.sleep(5); logger.info("MigrateInstance appid:{} offline slave:{} {},add slave :{} {}", instanceInfo.getAppId(), instanceInfo.getHostPort(), isOffline, targetIp, isSuccess); } catch (Exception e) { e.printStackTrace(); } } } } } } return true; } /** * 查看redis节点日志 */ @RequestMapping("/log") public ModelAndView doShowLog(HttpServletRequest request, HttpServletResponse response, Model model, int instanceId) { int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 0); if (pageSize == 0) { pageSize = 100; } String instanceLogStr = instanceDeployCenter.showInstanceRecentLog(instanceId, pageSize); model.addAttribute("instanceLogList", StringUtils.isBlank(instanceLogStr) ? Collections.emptyList() : Arrays.asList(instanceLogStr.split("\n"))); return new ModelAndView("manage/instance/log"); } /** * 处理实例配置修改 * * @param appAuditId 审批id */ @RequestMapping(value = "/initInstanceConfigChange") public ModelAndView doInitInstanceConfigChange(HttpServletRequest request, HttpServletResponse response, Model model, Long appAuditId) { // 申请原因 AppAudit appAudit = appService.getAppAuditById(appAuditId); model.addAttribute("appAudit", appAudit); // 用第一个参数存实例id Long instanceId = NumberUtils.toLong(appAudit.getParam1()); Map redisConfigList = redisCenter.getRedisConfigList(instanceId.intValue()); model.addAttribute("redisConfigList", redisConfigList); // 实例 InstanceInfo instanceInfo = instanceStatsCenter.getInstanceInfo(instanceId); model.addAttribute("instanceInfo", instanceInfo); model.addAttribute("appId", appAudit.getAppId()); model.addAttribute("appAuditId", appAuditId); // 修改配置的键值对 model.addAttribute("instanceConfigKey", appAudit.getParam2()); model.addAttribute("instanceConfigValue", appAudit.getParam3()); return new ModelAndView("manage/appAudit/initInstanceConfigChange"); } /** * @param appId 应用id * @param host 实例ip * @param port 实例端口 * @param instanceConfigKey 实例配置key * @param instanceConfigValue 实例配置value * @param appAuditId 审批id * @return */ @RequestMapping(value = "/addInstanceConfigChange") public ModelAndView doAddAppConfigChange(HttpServletRequest request, HttpServletResponse response, Model model, Long appId, String host, int port, String instanceConfigKey, String instanceConfigValue, Long appAuditId) { AppUser appUser = getUserInfo(request); logger.warn("user {} change instanceConfig:appId={},{}:{};key={};value={},appAuditId:{}", appUser.getName(), appId, host, port, instanceConfigKey, instanceConfigValue, appAuditId); boolean isModify = false; if (StringUtils.isNotBlank(host) && port > 0 && StringUtils.isNotBlank(instanceConfigKey)) { try { if (appAuditId != null) { appAuditDao.updateAppAuditOperateUser(appAuditId, appUser.getId()); } isModify = instanceDeployCenter.modifyInstanceConfig(appId, appAuditId, host, port, instanceConfigKey, instanceConfigValue); } catch (Exception e) { logger.error(e.getMessage(), e); } } logger.warn("user {} change instanceConfig:appId={},{}:{};key={};value={},appAuditId:{},result is:{}", appUser.getName(), appId, host, port, instanceConfigKey, instanceConfigValue, appAuditId, isModify); if (appAuditId != null) { return new ModelAndView("redirect:/manage/app/auditList"); } else { JSONObject json = new JSONObject(); json.put("result", isModify ? 1 : 0); sendMessage(response, json.toString()); return null; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/InstanceOperationController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.constant.ErrorMessageEnum; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.*; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.enums.CompareTypeEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppRedisCommandCheckService; import com.sohu.cache.web.service.AppRedisConfigCheckService; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.vo.*; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * @Author: zengyizhao * @DateTime: 2021/9/27 17:34 * @Description: 实例运维检测 */ @Controller @RequestMapping("manage/instance") public class InstanceOperationController extends BaseController { @Autowired private AppRedisConfigCheckService appRedisConfigCheckService; @Autowired private AppRedisCommandCheckService appRedisCommandCheckService; @Autowired private AppScrollRestartService appScrollRestartService; @Autowired private MachineDao machineDao; /** * 实例运维页面 * @param request * @param model * @return */ @RequestMapping(value = "/opsList") public ModelAndView opsList(HttpServletRequest request, Model model) { AppUser currentUser = getUserInfo(request); //获取tab int tabId = NumberUtils.toInt(request.getParameter("tabId"), 1); model.addAttribute("tabId", tabId); model.addAttribute("insOperateActive", SuccessEnum.SUCCESS.value()); if(tabId == 1){ List versionList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); List redisConfigCheckResult = appRedisConfigCheckService.getRedisConfigCheckResult(); CompareTypeEnum[] values = CompareTypeEnum.values(); List compareTypeEnums = Arrays.asList(values); compareTypeEnums.sort((o1, o2) -> o1.getType()); List allAppDesc = appService.getAllAppDesc(); allAppDesc = allAppDesc.stream().filter(appDesc -> appDesc.getStatus() == AppStatusEnum.STATUS_PUBLISHED.getStatus()).collect(Collectors.toList()); model.addAttribute("appList", allAppDesc); model.addAttribute("redisVersionList", versionList); model.addAttribute("compareTypeList", compareTypeEnums); model.addAttribute("checkResultList", redisConfigCheckResult); } if(tabId == 2){ List redisCommandCheckResult = appRedisCommandCheckService.getRedisCommandCheckResult(); model.addAttribute("commandCheckResult", redisCommandCheckResult); } if(tabId == 3){ String appIdStr = request.getParameter("appId"); String pageNoStr = request.getParameter("pageNo"); Integer pageNo = 1; Long appId = null; if(!StringUtil.isBlank(appIdStr)) { appId = Long.valueOf(appIdStr); } ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setAppId(appId); if(!StringUtil.isBlank(pageNoStr)){ pageNo = Integer.valueOf(pageNoStr); } int pageSize = 10; List configRestartRecordByCondition = appScrollRestartService.getConfigRestartRecordByCondition(model, configRestartRecord, pageNo, pageSize); List instanceInfoList = new ArrayList<>(); if(appId != null){ instanceInfoList = appService.getAppBasicInstanceInfo(appId); }else{ Set appIdSet = new HashSet<>(); for (ConfigRestartRecord record : configRestartRecordByCondition) { if(appIdSet.contains(record.getAppId())){ continue; } appIdSet.add(record.getAppId()); instanceInfoList.addAll(appService.getAppBasicInstanceInfo(record.getAppId())); } } Map instanceInfoMap = instanceInfoList.stream().collect(Collectors.toMap(InstanceInfo::getId, Function.identity(), (v1, v2) -> v1)); model.addAttribute("restartRecordList", configRestartRecordByCondition); model.addAttribute("appId", appId); model.addAttribute("instanceInfoMap", instanceInfoMap); } return new ModelAndView("manage/instanceOps/instanceOpsIndex"); } /** * 配置检测 * @param request * @param model * @return */ @RequestMapping(value = "/configCheck") @ResponseBody public ModelAndView configCheck(HttpServletRequest request, Model model) { AppUser appUser = getUserInfo(request); AppRedisConfigCheckVo checkVo = getRedisConfigCheck(request); RedisConfigCheckResult configCheckResults = appRedisConfigCheckService.checkRedisConfig(appUser, checkVo); if(configCheckResults != null){ model.addAttribute("status", SuccessEnum.SUCCESS.value()); }else{ model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); } return new ModelAndView(""); } /** * 配置检测 * @param request * @param model * @return */ @RequestMapping(value = "/getMachineList") @ResponseBody public ModelAndView getMachineList(HttpServletRequest request, Model model, String ip, String realIp, Integer searchType) { List machineList = machineDao.getMachineListByCondition(ip, realIp); Set ipSet = new HashSet<>(); if(searchType == 1){ ipSet = machineList.stream().map(machineInfo -> machineInfo.getRealIp()).collect(Collectors.toSet()); }else if(searchType == 2){ ipSet = machineList.stream().map(machineInfo -> machineInfo.getIp()).collect(Collectors.toSet()); } model.addAttribute("ipSet", ipSet); model.addAttribute("status", SuccessEnum.SUCCESS.value()); return new ModelAndView(""); } /** * 获取某次配置检测结果 * @param request * @param model * @param uuid * @return */ @RequestMapping(value = "/getConfigCheck") public ModelAndView getConfigCheck(HttpServletRequest request, Model model, String uuid) { AppUser appUser = getUserInfo(request); List redisConfigCheckResult = appRedisConfigCheckService.getRedisConfigCheckDetailResult(uuid); List versionList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); model.addAttribute("redisVersionList", versionList); CompareTypeEnum[] values = CompareTypeEnum.values(); List compareTypeEnums = Arrays.asList(values); compareTypeEnums.sort((o1, o2) -> o1.getType()); model.addAttribute("compareTypeList", compareTypeEnums); model.addAttribute("checkResultList", redisConfigCheckResult); return new ModelAndView("manage/instanceOps/instanceConfigCheckList"); } private AppRedisConfigCheckVo getRedisConfigCheck(HttpServletRequest request) { String appIdStr = request.getParameter("appId"); Long appId = null; if(StringUtils.isNotEmpty(appIdStr)){ appId = Long.parseLong(appIdStr); } String configName = request.getParameter("configName"); String versionIdStr = request.getParameter("versionId"); Integer versionId = null; if(StringUtils.isNotEmpty(versionIdStr)){ versionId = Integer.parseInt(versionIdStr); } String expectValue = request.getParameter("expectValue"); int compareType = NumberUtils.toInt(request.getParameter("compareType")); // 生成对象 AppRedisConfigCheckVo appRedisConfigCheckVo = new AppRedisConfigCheckVo(); appRedisConfigCheckVo.setAppId(appId); appRedisConfigCheckVo.setConfigName(configName); appRedisConfigCheckVo.setVersionId(versionId); appRedisConfigCheckVo.setCompareType(compareType); appRedisConfigCheckVo.setExpectValue(expectValue); return appRedisConfigCheckVo; } /** * 命令检测 * @param request * @param model * @return */ @RequestMapping(value = "/commandCheck") @ResponseBody public ModelAndView doStatList(HttpServletRequest request, Model model) { AppUser appUser = getUserInfo(request); AppRedisCommandCheckVo checkVo = getRedisCommandCheck(request); appRedisCommandCheckService.checkRedisCommand(appUser, checkVo); model.addAttribute("status", SuccessEnum.SUCCESS.value()); return new ModelAndView(""); } private AppRedisCommandCheckVo getRedisCommandCheck(HttpServletRequest request) { String machineIps = request.getParameter("machineIps"); String podIp = request.getParameter("podIp"); String command = request.getParameter("command"); String checkTypeStr = request.getParameter("checkType"); Integer checkType = null; if(StringUtils.isNotEmpty(checkTypeStr)){ checkType = Integer.valueOf(checkTypeStr); } String infoIndicate = request.getParameter("infoIndicate"); String indicateName = request.getParameter("indicateName"); String maxTryStr = request.getParameter("maxTry"); Integer maxTry = null; if(StringUtils.isNotEmpty(maxTryStr)){ maxTry = Integer.valueOf(maxTryStr); } String expectValue = request.getParameter("expectValue"); String minuteInternalStr = request.getParameter("minuteInternal"); Integer minuteInternal = null; if(StringUtils.isNotEmpty(minuteInternalStr)){ minuteInternal = Integer.valueOf(minuteInternalStr); } AppRedisCommandCheckVo checkVo = new AppRedisCommandCheckVo(); checkVo.setMachineIps(machineIps); checkVo.setPodIp(podIp); checkVo.setCommand(command); checkVo.setCheckType(checkType); checkVo.setInfoIndicate(infoIndicate); checkVo.setIndicateName(indicateName); checkVo.setExpectValue(expectValue); checkVo.setMaxTry(maxTry); checkVo.setMinuteInternal(minuteInternal); return checkVo; } /** * 查询命令检测 * @param request * @param model * @param uuid * @return */ @RequestMapping(value = "/getCommandCheck") public ModelAndView getCommandCheck(HttpServletRequest request, Model model, String uuid) { AppUser appUser = getUserInfo(request); AppRedisCommandCheckResult appRedisCommandCheckResult = appRedisCommandCheckService.getRedisCommandCheckDetailResult(uuid); model.addAttribute("checkResult", appRedisCommandCheckResult); return new ModelAndView("manage/instanceOps/instanceCommandCheckList"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/LoginController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.LoginResult; import com.sohu.cache.login.LoginComponent; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.MD5Util; import com.sohu.cache.utils.EnvCustomUtil; import com.sohu.cache.web.enums.AdminEnum; import com.sohu.cache.web.enums.LoginEnum; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.vo.GeneralResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 登录逻辑 * * @author leifu * @Time 2014年6月12日 */ @Controller @RequestMapping("manage") public class LoginController extends BaseController { @Resource(name = "userLoginStatusService") private UserLoginStatusService userLoginStatusService; @Autowired(required = false) private LoginComponent loginComponent; /** * 用户登录界面 * * @param request * @return */ @RequestMapping(value = "/login", method = RequestMethod.GET) public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) { model.addAttribute(ConstUtils.RREDIRECT_URL_PARAM, request.getParameter(ConstUtils.RREDIRECT_URL_PARAM)); model.addAttribute("pwdswitch", EnvCustomUtil.pwdswitch); return new ModelAndView("manage/login"); } /** * 用户登录 * * @param userName 用户名 * @param password 密码 * @param isAdmin 是否勾选超级管理员选项,1是0否 * @return */ @RequestMapping(value = "/loginIn", method = RequestMethod.POST) public ModelAndView loginIn(HttpServletRequest request, HttpServletResponse response, Model model, String userName, String password, boolean isAdmin) { // 登录结果 LoginResult loginResult = new LoginResult(); loginResult.setAdminEnum((isAdmin == true ? AdminEnum.IS_ADMIN : AdminEnum.NOT_ADMIN)); loginResult.setLoginEnum(LoginEnum.LOGIN_WRONG_USER_OR_PASSWORD); AppUser userModel = null; if (ConstUtils.SUPER_ADMIN_NAME.equals(userName)) { userModel = userService.getByName(userName); String checkPwd = ConstUtils.SUPER_ADMIN_PASS; if(EnvCustomUtil.pwdswitch){ checkPwd = MD5Util.string2MD5(ConstUtils.SUPER_ADMIN_PASS); } if (userModel != null && checkPwd.equals(password)) { loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS); } else { loginResult.setLoginEnum(LoginEnum.LOGIN_WRONG_USER_OR_PASSWORD); } } else { if (loginComponent != null && loginComponent.passportCheck(userName, password)) { // 同时要验证是否有cachecloud权限 userModel = userService.getByName(userName); if (userModel != null && userModel.getType() != AppUserTypeEnum.NO_USER.value()) { if (isAdmin) { if (AppUserTypeEnum.ADMIN_USER.value().equals(userModel.getType())) { loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS); } else { loginResult.setLoginEnum(LoginEnum.LOGIN_NOT_ADMIN); } } else { loginResult.setLoginEnum(LoginEnum.LOGIN_SUCCESS); } } else { // 用户不存在 loginResult.setLoginEnum(LoginEnum.LOGIN_USER_NOT_EXIST); } } } // 登录成功写入登录状态 if (loginResult.getLoginEnum().equals(LoginEnum.LOGIN_SUCCESS)) { userLoginStatusService.addLoginStatus(request, response, userModel.getName()); } model.addAttribute("success", loginResult.getLoginEnum().value()); model.addAttribute("admin", loginResult.getAdminEnum().value()); return new ModelAndView(); } /** * 用户注销 * * @return */ @RequestMapping("/logout") public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) { userLoginStatusService.removeLoginStatus(request, response); //String redirectUrl = userLoginStatusService.getLogoutUrl(); return new ModelAndView("redirect:" + "/manage/login"); } /** * 用户登录 * * @param appUser 用户 * @return */ @RequestMapping(value = "/loginCheck", method = RequestMethod.POST) @ResponseBody public GeneralResponse loginCheck(HttpServletRequest request, @RequestBody AppUser appUser) { AppUser user = userService.getByName(appUser.getName()); if(user != null && user.getPassword() != null && user.getPassword().equals(appUser.getPassword())){ return GeneralResponse.ok(); } return GeneralResponse.error(1001, "用户名或密码错误"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/MachineManageController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineDeployCenter; import com.sohu.cache.task.TaskService; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.MachineTaskEnum; import com.sohu.cache.web.enums.SuccessEnum; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; /** * 机器管理 * * @author leifu * @Time 2014年10月14日 */ @Controller @RequestMapping("manage/machine") public class MachineManageController extends BaseController { private final static String COMMA = ","; @Resource private TaskService taskService; @Resource private MachineDeployCenter machineDeployCenter; @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag, String ipLike, Integer versionId, Integer isInstall, Integer useType, Integer type, Integer k8sType, String realip) { model.addAttribute("tabTag", tabTag); model.addAttribute("isInstall", isInstall); model.addAttribute("versionId",versionId); model.addAttribute("useType", useType); model.addAttribute("ipLike", ipLike); model.addAttribute("k8sType", k8sType); model.addAttribute("type", type); model.addAttribute("realip", realip); model.addAttribute("machineActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/machine/list"); } @RequestMapping(value = "/pod/changelist") public ModelAndView doPodList(Model model, String ip) { List machineRelationList = machineDeployCenter.getMachineRelationList(ip); MachineInfo machineinfo = machineCenter.getMachineInfoByIp(ip); String realIp = machineinfo != null ? machineinfo.getRealIp() : ""; logger.info("ip:{} ,realIp:{} ,pod change size:{}", ip, realIp, machineRelationList.size()); model.addAttribute("ip", ip); model.addAttribute("realIp", realIp); model.addAttribute("relationList", machineRelationList); return new ModelAndView("manage/pod/list"); } @RequestMapping(value = "/pod/add/syncTask", method = RequestMethod.POST) public ModelAndView doAddMachineSyncTask(Model model, HttpServletResponse response, String containerIp, String sourceIp, String targetIp, Integer relationId) { Map taskMap = new HashMap(); try { if (!StringUtils.isEmpty(containerIp) && !StringUtils.isEmpty(sourceIp) && !StringUtils.isEmpty(targetIp)) { // 检查是否已经有同步任务 SuccessEnum successEnum = machineDeployCenter.checkMachineSyncStatus(containerIp, sourceIp, MachineTaskEnum.SYNCING.getValue()); if (successEnum.value() == SuccessEnum.NO_REPEAT.value()) { long taskId = taskService.addMachineSyncTask(sourceIp, targetIp, containerIp, String.format("sourceMachine:%s tagetMachine:%s ", sourceIp, targetIp), 0); if (taskId > 0) { logger.info("add machine sync task:{} ", taskId); taskMap.put("status", SuccessEnum.SUCCESS.value()); taskMap.put("taskId", taskId); machineDeployCenter.updateMachineRelation(relationId, taskId, MachineTaskEnum.SYNCING.getValue()); } } else { taskMap.put("status", SuccessEnum.FAIL.value()); taskMap.put("message", "containerIp:" + containerIp + ",sourceIp:" + sourceIp + " ,任务:" + successEnum.info()); machineDeployCenter.updateMachineRelation(relationId, null, MachineTaskEnum.SYNC_FAILED.getValue()); } } else { taskMap.put("status", SuccessEnum.FAIL.value()); taskMap.put("message", "参数验证失败 containerIp:" + containerIp + ",sourceIp:" + sourceIp + ",targetIp:" + targetIp); } } catch (Exception e) { taskMap.put("status", SuccessEnum.FAIL.value()); taskMap.put("message", "add task exception:" + e.getMessage()); logger.error(e.getMessage(), e); } sendMessage(response, JSONObject.toJSONString(taskMap)); return null; } @RequestMapping(value = "/list") public ModelAndView doMachineList(HttpServletRequest request, HttpServletResponse response, Model model, String tabTag, String ipLike, Integer versionId, Integer isInstall, Integer useType, Integer type, Integer k8sType, String realip) { if (tabTag.equals("machine")) { List machineList = machineCenter.getMachineStats(ipLike, useType, type, versionId, isInstall, k8sType, realip); Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); List roomList = machineCenter.getEffectiveRoom(); model.addAttribute("roomList", roomList); model.addAttribute("list", machineList); model.addAttribute("isInstall", isInstall); model.addAttribute("versionId",versionId); model.addAttribute("useType", useType); model.addAttribute("ipLike", ipLike); model.addAttribute("k8sType", k8sType); model.addAttribute("type", type); model.addAttribute("realip", realip); model.addAttribute("machineActive", SuccessEnum.SUCCESS.value()); model.addAttribute("collectAlert", "(请等待" + ConstUtils.MACHINE_STATS_CRON_MINUTE + "分钟)"); model.addAttribute("machineInstanceCountMap", machineInstanceCountMap); return new ModelAndView("manage/machine/machineList"); } else if (tabTag.equals("room")) { List roomList = machineCenter.getAllRoom(); model.addAttribute("roomList", roomList); return new ModelAndView("manage/machine/roomList"); } return new ModelAndView(""); } /** * 机器实例展示 * * @param ip * @return */ @RequestMapping(value = "/machineInstances") public ModelAndView doMachineInstances(HttpServletRequest request, HttpServletResponse response, Model model, String ip) { //机器以及机器下面的实例信息 MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip); List instanceList = machineCenter.getMachineInstanceInfo(ip); List instanceStatList = machineCenter.getMachineInstanceStatsByIp(ip); //统计信息 fillInstanceModel(instanceList, instanceStatList, model); // 机器列表 List machineList = machineCenter.getMachineStats(null, null, null, null, null, null, null); // 获取机器信息 Map machineInstanceCountMap = machineCenter.getMachineInstanceCountMap(); model.addAttribute("machineInstanceCountMap", machineInstanceCountMap); model.addAttribute("machineList", machineList); model.addAttribute("machineInfo", machineInfo); model.addAttribute("machineActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/machine/machineInstances"); } /** * 检查机器下是否有存活的实例 * * @param ip * @return */ @RequestMapping(value = "/checkMachineInstances") public ModelAndView doCheckMachineInstances(HttpServletRequest request, HttpServletResponse response, Model model, String ip) { List instanceList = machineCenter.getMachineInstanceInfo(ip); model.addAttribute("machineHasInstance", CollectionUtils.isNotEmpty(instanceList)); return new ModelAndView(""); } @RequestMapping(value = "/add", method = {RequestMethod.POST}) public ModelAndView doAdd(HttpServletRequest request, HttpServletResponse response, Model model) { MachineInfo machineInfo = new MachineInfo(); machineInfo.setIp(request.getParameter("ip")); machineInfo.setRoom(request.getParameter("room")); machineInfo.setMem(NumberUtils.toInt(request.getParameter("mem"), 0)); machineInfo.setCpu(NumberUtils.toInt(request.getParameter("cpu"), 0)); machineInfo.setDisk(NumberUtils.toInt(request.getParameter("disk"), 0)); machineInfo.setVirtual(NumberUtils.toInt(request.getParameter("virtual"), 0)); machineInfo.setRealIp(request.getParameter("realIp")); machineInfo.setType(NumberUtils.toInt(request.getParameter("machineType"), 0)); machineInfo.setExtraDesc(request.getParameter("extraDesc")); machineInfo.setCollect(NumberUtils.toInt(request.getParameter("collect"), 1)); machineInfo.setVersionInstall(request.getParameter("versionInfo")); Date date = new Date(); machineInfo.setSshUser(ConstUtils.USERNAME); machineInfo.setSshPasswd(ConstUtils.PASSWORD); machineInfo.setServiceTime(date); machineInfo.setModifyTime(date); machineInfo.setAvailable(MachineInfoEnum.AvailableEnum.YES.getValue()); boolean isSuccess = machineDeployCenter.addMachine(machineInfo); model.addAttribute("result", isSuccess); return new ModelAndView(""); } @RequestMapping(value = "/addMultiple", method = {RequestMethod.POST}) public ModelAndView doAddMultiple(HttpServletRequest request, HttpServletResponse response, Model model) { boolean isSuccess = true; List ipList = Arrays.asList(request.getParameter("ip").split(COMMA)); List realIpList = Arrays.asList(request.getParameter("realIp").split(COMMA));//ip与realIp一一对应 for (int i = 0; i < ipList.size(); i++) { MachineInfo machineInfo = new MachineInfo(); machineInfo.setIp(ipList.get(i)); machineInfo.setRoom(request.getParameter("room")); machineInfo.setMem(NumberUtils.toInt(request.getParameter("mem"), 0)); machineInfo.setCpu(NumberUtils.toInt(request.getParameter("cpu"), 0)); machineInfo.setDisk(NumberUtils.toInt(request.getParameter("disk"), 0)); machineInfo.setVirtual(NumberUtils.toInt(request.getParameter("virtual"), 0)); machineInfo.setDisType(NumberUtils.toInt(request.getParameter("disType"), 0)); machineInfo.setRealIp(i < realIpList.size() ? realIpList.get(i) : ""); machineInfo.setType(NumberUtils.toInt(request.getParameter("machineType"), 0)); machineInfo.setUseType(NumberUtils.toInt(request.getParameter("useType"), 0)); machineInfo.setK8sType(NumberUtils.toInt(request.getParameter("k8sType"), 0)); machineInfo.setExtraDesc(request.getParameter("extraDesc")); machineInfo.setCollect(NumberUtils.toInt(request.getParameter("collect"), 1)); machineInfo.setVersionInstall(request.getParameter("versionInfo")); machineInfo.setRack(request.getParameter("rack")); Date date = new Date(); machineInfo.setSshUser(ConstUtils.USERNAME); machineInfo.setSshPasswd(ConstUtils.PASSWORD); machineInfo.setServiceTime(date); machineInfo.setModifyTime(date); machineInfo.setAvailable(MachineInfoEnum.AvailableEnum.YES.getValue()); if (!machineDeployCenter.addMachine(machineInfo)) { isSuccess = false; break; } } model.addAttribute("result", isSuccess); return new ModelAndView(""); } @RequestMapping(value = "/delete") public ModelAndView doDelete(HttpServletRequest request, HttpServletResponse response, Model model) { String machineIp = request.getParameter("machineIp"); if (StringUtils.isNotBlank(machineIp)) { MachineInfo machineInfo = machineCenter.getMachineInfoByIp(machineIp); boolean success = machineDeployCenter.removeMachine(machineInfo); logger.warn("delete machine {}, result is {}", machineIp, success); } else { logger.warn("machineIp is empty!"); } return new ModelAndView("redirect:/manage/machine/index?tabTag=machine"); } /** * 实例统计信息 * * @param * @param model */ protected void fillInstanceModel(List instanceList, List appInstanceStats, Model model) { Map machineStatsMap = new HashMap(); Map machineCanUseMem = new HashMap(); Map instanceStatsMap = new HashMap(); Map appInfoMap = new HashMap(); for (InstanceStats instanceStats : appInstanceStats) { instanceStatsMap.put(instanceStats.getIp() + ":" + instanceStats.getPort(), instanceStats); AppDesc appDesc = appService.getByAppId(instanceStats.getAppId()); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); appInfoMap.put(instanceStats.getAppId(), appDesc); } for (InstanceInfo instanceInfo : instanceList) { if (TypeUtil.isRedisSentinel(instanceInfo.getType())) { continue; } String ip = instanceInfo.getIp(); if (machineStatsMap.containsKey(ip)) { continue; } List machineStatsList = machineCenter.getMachineStats(ip); MachineStats machineStats = null; for (MachineStats stats : machineStatsList) { if (stats.getIp().equals(ip)) { machineStats = stats; machineStatsMap.put(ip, machineStats); break; } } MachineStats ms = machineCenter.getMachineMemoryDetail(ip); machineCanUseMem.put(ip, ms.getMachineMemInfo().getLockedMem()); machineStatsMap.get(ip).setMachineMemInfo(ms.getMachineMemInfo()); } model.addAttribute("appInfoMap", appInfoMap); model.addAttribute("machineCanUseMem", machineCanUseMem); model.addAttribute("machineStatsMap", machineStatsMap); model.addAttribute("instanceList", instanceList); model.addAttribute("instanceStatsMap", instanceStatsMap); } @RequestMapping(value = "room/add", method = {RequestMethod.POST}) public ModelAndView doRoomAdd(HttpServletRequest request, HttpServletResponse response, Model model) { MachineRoom room = new MachineRoom(); room.setId(NumberUtils.toInt(request.getParameter("id"))); room.setName(request.getParameter("name")); room.setStatus(NumberUtils.toInt(request.getParameter("status"), 1)); room.setDesc(request.getParameter("desc")); room.setIpNetwork(request.getParameter("ipNetwork")); room.setOperator(request.getParameter("operator")); boolean isSuccess = machineDeployCenter.addMachineRoom(room); model.addAttribute("result", isSuccess); return new ModelAndView(""); } @RequestMapping(value = "room/delete") public ModelAndView doRoomDelete(HttpServletRequest request, HttpServletResponse response, Model model) { int roomId = NumberUtils.toInt(request.getParameter("id"), -1); if (roomId > -1) { boolean success = machineDeployCenter.removeMachineRoom(roomId); logger.warn("delete machine {}, result is {}", roomId, success); } else { logger.warn("machineIp is empty!"); } return new ModelAndView("redirect:/manage/machine/index?tabTag=room"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/NoticeManageController.java ================================================ package com.sohu.cache.web.controller; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.AppEmailUtil; @Controller @RequestMapping("manage/notice") public class NoticeManageController extends BaseController { @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; /** * 初始化系统通知 * * @return */ @RequestMapping(value = "/initNotice") public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) { String notice = ""; model.addAttribute("notice", notice); model.addAttribute("success", request.getParameter("success")); model.addAttribute("noticeActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/notice/initNotice"); } /** * 发送邮件通知 */ @RequestMapping(value = "/add") public ModelAndView addNotice(HttpServletRequest request, HttpServletResponse response, Model model) { String notice = request.getParameter("notice"); boolean result = appEmailUtil.noticeAllUser(notice); model.addAttribute("success", result ? SuccessEnum.SUCCESS.value() : SuccessEnum.FAIL.value()); return new ModelAndView(""); } /** * 获取系统通知 * * @return */ @RequestMapping(value = "/get") public ModelAndView getNotice(HttpServletRequest request, HttpServletResponse response, Model model) { String notice = ""; List list = null; if (StringUtils.isNotBlank(notice)) { list = Arrays.asList(notice.split(ConstUtils.NEXT_LINE)); model.addAttribute("status", SuccessEnum.SUCCESS.value()); } else { list = new ArrayList(); model.addAttribute("status", SuccessEnum.FAIL.value()); } model.addAttribute("data", list); return new ModelAndView(""); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/OperationController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.constant.AppUserAlertEnum; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineDeployCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.task.constant.MachineSyncEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.enums.PodStatusEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppAlertRecordService; import com.sohu.cache.web.util.FreemakerUtils; import freemarker.template.Configuration; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.text.MessageFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 运维工具 * Created by rucao on 2018/7/30 */ @RestController @RequestMapping("operation") public class OperationController extends BaseController { private final static String DOT = "."; private final static String IPREG = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; private final static String format = "{0}:{1}"; @Resource private MachineDeployCenter machineDeployCenter; @Resource private MachineDao machineDao; @Resource private InstanceDao instanceDao; @Resource private AppDao appDao; @Resource private MachineRoomDao machineRoomDao; @Resource private EmailComponent emailComponent; @Resource private RedisConfigTemplateService redisConfigTemplateService; @Resource private MachineRelationDao machineRelationDao; @Autowired private Configuration configuration; @Autowired private AppAlertRecordService appAlertRecordService; @RequestMapping(value = "/machines", method = {RequestMethod.POST}) public ResponseEntity addMachines(@RequestHeader(value = "token", defaultValue = "addMachine") String token, @RequestBody List machineInfoList) { long startTime = System.currentTimeMillis(); HttpStatus status = HttpStatus.CREATED; String message = ""; List resultList = new ArrayList(); if (token.isEmpty() || !token.equals("addMachine")) { status = HttpStatus.UNAUTHORIZED; message = "TOKEN 验证失败"; OperationAlertValueResult operationResult = new OperationAlertValueResult("", null, "CREATE", status.toString() + status.getReasonPhrase(), message); resultList.add(operationResult); operationNotice(resultList, "CREATE"); return ResponseEntity.status(status).body(message); } for (int i = 0; i < machineInfoList.size(); i++) { MachineInfo machineInfo = machineInfoList.get(i); logger.info("machineInfo :{}", machineInfo); String ip = machineInfo.getIp(); if (!isIp(ip)) { status = HttpStatus.BAD_REQUEST; message += "ip为空或格式错误,无法插入\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "CREATE", status.toString() + status.getReasonPhrase(), "ip为空或格式错误,无法插入\n"); resultList.add(operationResult); continue; } if (isIpRepeat(ip)) { message += ip + "已经存在且有效,无法重新插入\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "CREATE", status.toString() + status.getReasonPhrase(), ip + "已经存在且有效,无法重新插入\n"); resultList.add(operationResult); continue; } message += ip; if (machineInfo.getMem() == 0) { message += "内存为空,"; } if (machineInfo.getCpu() == 0) { message += "cpu为空,"; } if (machineInfo.getVirtual() == 1 && !isIp(machineInfo.getRealIp())) { message += "宿主机ip为空或格式错误,"; } if (machineInfo.getUseType() == 0) { if (StringUtils.isEmpty(machineInfo.getProjectName())) { message += "Redis专用机器未填写项目名称,"; } else { machineInfo.setExtraDesc(MessageFormat.format(format, machineInfo.getExtraDesc(), machineInfo.getProjectName())); } } autoInsertRoom(machineInfo); Date date = new Date(); machineInfo.setType(MachineInfoEnum.TypeEnum.REDIS_NODE.getType()); machineInfo.setCollect(1); machineInfo.setSshUser(ConstUtils.USERNAME); machineInfo.setSshPasswd(ConstUtils.PASSWORD); machineInfo.setServiceTime(date); machineInfo.setModifyTime(date); machineInfo.setAvailable(MachineInfoEnum.AvailableEnum.YES.getValue()); try { if (!machineDeployCenter.addMachine(machineInfo)) { message += "插入失败\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "CREATE", "save or deploy machineInfo error", "插入失败\n"); resultList.add(operationResult); } else { message += "插入成功\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "CREATE", HttpStatus.CREATED.toString() + HttpStatus.CREATED.getReasonPhrase(), "插入成功\n"); resultList.add(operationResult); } logger.info(message); // 更新机器安装redis版本 if (machineInfo.getAvailable() == MachineInfoEnum.AvailableEnum.YES.getValue()) { // 3.更新线上机器version_install版本状态 redisConfigTemplateService.updateMachineInstallRedis(machineInfo.getIp()); } } catch (Exception ex) { logger.info("addMultiMachines: {}", ex.getMessage()); } } operationNotice(resultList, "CREATE"); logger.info("add {} machine costtime ={} ms", machineInfoList.size(), (System.currentTimeMillis() - startTime)); return ResponseEntity.status(status).body(message); } /** * k8s pod容器变更:上线 (k8s自身调度/升级) * * @param token * @param machineInfoList * @return */ @RequestMapping(value = "/pod/online", method = {RequestMethod.POST}) public ResponseEntity onlinePod(@RequestHeader(value = "token", defaultValue = "onlinePod") String token, @RequestBody List machineInfoList) { long startTime = System.currentTimeMillis(); HttpStatus status = HttpStatus.CREATED; String message = ""; String type = "POD-ONLINE"; List resultList = new ArrayList(); if (token.isEmpty() || !token.equals("onlinePod")) { status = HttpStatus.UNAUTHORIZED; message = "TOKEN 验证失败"; OperationAlertValueResult operationResult = new OperationAlertValueResult("", null, type, status.toString() + status.getReasonPhrase(), message); resultList.add(operationResult); operationNotice(resultList, type); return ResponseEntity.status(status).body(message); } if (machineInfoList != null && machineInfoList.size() > 0) { for (MachineInfo machineInfo : machineInfoList) { logger.info("machineInfo :{}", machineInfo); String ip = machineInfo.getIp(); String realIp = machineInfo.getRealIp(); // save machine relation try { long podUpdateTime = machineInfo.getPodUpdateTime() == 0 ? System.currentTimeMillis() : machineInfo.getPodUpdateTime(); MachineRelation machineRelation = new MachineRelation(ip, realIp, new Date(podUpdateTime), machineInfo.getProjectName(), PodStatusEnum.ONLINE.getValue()); machineRelationDao.saveOrUpdateMachineRelation(machineRelation); } catch (Exception e) { logger.info("save pod online relation: {}", e.getMessage()); } if (!isIp(ip)) { status = HttpStatus.BAD_REQUEST; message += "ip为空或格式错误,无法插入\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, type, status.toString() + status.getReasonPhrase(), "ip为空或格式错误,无法插入\n"); resultList.add(operationResult); continue; } message += ip; if (machineInfo.getMem() == 0) { message += "内存为空,"; } if (machineInfo.getCpu() == 0) { message += "cpu为空,"; } if (machineInfo.getVirtual() == 1 && !isIp(machineInfo.getRealIp())) { message += "宿主机ip为空或格式错误,"; } // 专用机器 if (machineInfo.getUseType() == 0) { if (StringUtils.isEmpty(machineInfo.getProjectName())) { message += "Redis专用机器未填写项目名称,"; } else { machineInfo.setExtraDesc(MessageFormat.format(format, machineInfo.getExtraDesc(), machineInfo.getProjectName())); } } // 插入机房信息 autoInsertRoom(machineInfo); Date date = new Date(); // 机器类型: redis/迁移工具 机器部署类型: 专用/混合/测试/sentinel MachineInfo machineOldInfo = getMachineInfo(ip); if (machineOldInfo != null) { machineInfo.setType(machineOldInfo.getType()); machineInfo.setUseType(machineOldInfo.getUseType()); } else { machineInfo.setType(MachineInfoEnum.TypeEnum.REDIS_NODE.getType()); } machineInfo.setCollect(1); machineInfo.setSshUser(ConstUtils.USERNAME); machineInfo.setSshPasswd(ConstUtils.PASSWORD); machineInfo.setServiceTime(date); machineInfo.setModifyTime(date); machineInfo.setAvailable(MachineInfoEnum.AvailableEnum.YES.getValue()); try { boolean saveOrUpdate = isK8sIpRepeat(ip); if (!machineDeployCenter.addMachine(machineInfo)) { message += "插入失败\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, type, "save or deploy machineInfo error", "插入失败\n"); resultList.add(operationResult); } else { // 判断机器是新增还是修改 if (saveOrUpdate) { message += ip + "修改机器成功\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, type, status.toString() + status.getReasonPhrase(), ip + "机器信息修改成功\n"); resultList.add(operationResult); // 提交异步任务检测实例 asyncExecuteDetectTask(ip); } else { message += "新增机器成功\n"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, type, HttpStatus.CREATED.toString() + HttpStatus.CREATED.getReasonPhrase(), "新增机器成功\n"); resultList.add(operationResult); } } logger.info(message); } catch (Exception ex) { logger.info("add Machine:{} error: {}", machineInfo, ex.getMessage()); } } logger.info("add pod {} machine costtime ={} ms", machineInfoList.size(), (System.currentTimeMillis() - startTime)); } operationNotice(resultList, type); return ResponseEntity.status(status).body(message); } /** *

* Description: 异步任务: 检测实例状态 & 滚动重启 *

*/ public void asyncExecuteDetectTask(final String ip) { String key = "detect-instance-" + ip; asyncService.submitFuture(AsyncThreadPoolFactory.DEFAULT_ASYNC_POOL, new KeyCallable(key) { public Boolean execute() { try { // 1.检测pod是否被调度到其他宿主机 MachineSyncEnum syncStatus = instanceDeployCenter.podChangeStatus(ip); // 2. pod状态为MachineSyncEnum.NO_CHANGE 或 MachineSyncEnum.SYNC_SUCCESS 自动检测实例 List instanceAlertValueResults = new ArrayList<>(); if (syncStatus.getValue() == MachineSyncEnum.NO_CHANGE.getValue() || syncStatus.getValue() == MachineSyncEnum.SYNC_SUCCESS.getValue()) { instanceAlertValueResults = instanceDeployCenter.checkAndStartExceptionInstance(ip, true); } logger.info("pod ip:{} sync status:{}, scroll redis number:{} ", ip, syncStatus.getDesc(), instanceAlertValueResults.size()); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } }); } /** * k8s pod容器变更:下线 (k8s自身调度/停止/滚动升级) * * @param token * @param machineInfoList * @return */ @RequestMapping(value = "/pod/offline", method = {RequestMethod.POST}) public ResponseEntity offlinePod(@RequestHeader(value = "token", defaultValue = "offlinePod") String token, @RequestBody List machineInfoList) { HttpStatus status = HttpStatus.NO_CONTENT; String message = ""; String type = "POD-OFFLINE"; logger.info("machineinfo list: {}", machineInfoList); List resultList = new ArrayList(); if (token.isEmpty() || !token.equals("offlinePod")) { status = HttpStatus.UNAUTHORIZED; message = "TOKEN 验证失败"; } // 遍历变更下线的pod if (machineInfoList != null && machineInfoList.size() > 0) { for (MachineInfo machineInfo : machineInfoList) { String ip = machineInfo.getIp(); String realIp = machineInfo.getRealIp(); // save machine relation try { long podUpdateTime = machineInfo.getPodUpdateTime() == 0 ? System.currentTimeMillis() : machineInfo.getPodUpdateTime(); MachineRelation machineRelation = new MachineRelation(ip, realIp, new Date(podUpdateTime), machineInfo.getProjectName(), PodStatusEnum.OFFLINE.getValue()); machineRelationDao.saveOrUpdateMachineRelation(machineRelation); //修改机器状态 为下线 machineDao.removeMachineInfoByIp(ip); } catch (Exception e) { logger.info("save pod offline relation: {}", e.getMessage()); } if (!isIp(ip)) { status = HttpStatus.BAD_REQUEST; message += "ip为空或格式错误\n"; } OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, type, status.toString() + status.getReasonPhrase(), message); resultList.add(operationResult); } } operationNotice(resultList, type); return ResponseEntity.status(status).body(message); } @RequestMapping(value = "/machine", method = {RequestMethod.DELETE}) public ResponseEntity deleteMachine(@RequestHeader(value = "token", defaultValue = "deleteMachine") String token, @RequestParam(value = "ip") String ip) { HttpStatus status = HttpStatus.NO_CONTENT; String message = ""; MachineInfo machineInfo = null; List resultList = new ArrayList(); if (token.isEmpty() || !token.equals("deleteMachine")) { status = HttpStatus.UNAUTHORIZED; message = "TOKEN 验证失败"; OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "DELETE", status.toString() + status.getReasonPhrase(), message); resultList.add(operationResult); operationNotice(resultList, "DELETE"); return ResponseEntity.status(status).body(message); } if (!isIp(ip)) { status = HttpStatus.BAD_REQUEST; message += "ip为空或格式错误\n"; } else if (checkMachineActive(ip)) { machineInfo = machineDao.getMachineInfoByIp(ip); status = HttpStatus.INTERNAL_SERVER_ERROR; message += ip + "有redis节点存活,删除失败\n"; } else { machineInfo = machineDao.getMachineInfoByIp(ip); if (machineInfo == null) { status = HttpStatus.NOT_FOUND; message += ip + "机器资源不存在\n"; } else if (!machineDeployCenter.removeMachine(machineInfo)) { message += ip + "删除失败\n"; } } OperationAlertValueResult operationResult = new OperationAlertValueResult(ip, machineInfo, "DELETE", status.toString() + status.getReasonPhrase(), message); resultList.add(operationResult); operationNotice(resultList, "DELETE"); return ResponseEntity.status(status).body(message); } @RequestMapping(value = "/users", method = RequestMethod.POST) @ApiResponses({ @ApiResponse(code = 201, message = "Created"), @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 401, message = "Unauthorized"), @ApiResponse(code = 500, message = "Internal Server Error") }) public ResponseEntity addUsers(@RequestHeader(value = "token", defaultValue = "addUsers") String token, @RequestParam(value = "appId") Long appId, @RequestBody List userList) { HttpStatus status = HttpStatus.CREATED; String message = ""; if (token.isEmpty() || !token.equals("addUsers")) { status = HttpStatus.UNAUTHORIZED; message = "TOKEN 验证失败"; return ResponseEntity.status(status).body(message); } try { if (appDao.getOnlineAppDescById(appId) == null) { status = HttpStatus.BAD_REQUEST; message = "appId应用状态无效"; return ResponseEntity.status(status).body(message); } if (userList.size() == 0) { status = HttpStatus.BAD_REQUEST; message = "userList为空"; return ResponseEntity.status(status).body(message); } for (AppUser appUser : userList) { String userName = appUser.getName(); if (StringUtils.isNotBlank(userName)) { try { AppUser needAddAppUser = userService.getByName(userName); if (needAddAppUser == null) { if (StringUtils.isBlank(appUser.getChName())) { appUser.setChName(""); } if (StringUtils.isBlank(appUser.getEmail())) { appUser.setEmail(""); } if (StringUtils.isBlank(appUser.getMobile())) { appUser.setMobile(""); } if (StringUtils.isBlank(appUser.getWeChat())) { appUser.setWeChat(""); } appUser.setType(AppUserTypeEnum.REGULAR_USER.value()); appUser.setIsAlert(AppUserAlertEnum.YES.value()); if (userService.save(appUser) == SuccessEnum.SUCCESS) { needAddAppUser = userService.getByName(userName); } else { status = HttpStatus.INTERNAL_SERVER_ERROR; message += "用户:" + userName + "不存在,且用户创建失败\n"; } } if (needAddAppUser != null) { if (appService.saveAppToUser(appId, needAddAppUser.getId())) { message += "用户:" + userName + "添加成功\n"; } else { status = HttpStatus.INTERNAL_SERVER_ERROR; message += "用户:" + userName + "添加失败\n"; } } } catch (Exception ex) { logger.info("addUsers: {}", ex.getMessage()); } } else { status = HttpStatus.BAD_REQUEST; message += "用户名(英文,域账户)为空\n"; } } } catch (Exception ex) { logger.info("addUsers: {}", ex.getMessage()); } return ResponseEntity.status(status).body(message); } /** * 根据网段自动识别机房并填入 * * @param machineInfo */ private void autoInsertRoom(MachineInfo machineInfo) { String ip = machineInfo.getIp(); List roomList = machineRoomDao.getEffectiveRoom(); for (MachineRoom room : roomList) { String ipNetwork = room.getIpNetwork(); String ipSub1 = ipNetwork.substring(0, ipNetwork.indexOf(DOT, 3)); String ipSub2 = ip.substring(0, ip.indexOf(DOT, 3)); if (ipSub1.equals(ipSub2)) { machineInfo.setRoom(room.getName()); } } } /** * 正则验证ip格式 * * @param ipAddress * @return */ private boolean isIp(String ipAddress) { if (ipAddress == null || ipAddress.isEmpty()) return false; Pattern pattern = Pattern.compile(IPREG); Matcher matcher = pattern.matcher(ipAddress); return matcher.matches(); } /** * ip是否重复 available==1 * * @param ip * @return */ private boolean isIpRepeat(String ip) { List machineInfos = machineDao.getMachineInfoByLikeIp(ip); if (machineInfos == null || machineInfos.size() == 0) { return false; } return true; } /** * ip,realIp 是否存在 * * @param ip * @return */ private boolean isK8sIpRepeat(String ip) { MachineInfo machineInfo = machineDao.existk8sMachine(ip); if (machineInfo == null) { return false; } return true; } /** * 机器类型(type/useType) 不覆盖 * * @param ip * @return */ private MachineInfo getMachineInfo(String ip) { return machineDao.getMachineInfoByIp(ip); } /** * machine的可删除状态,false表示不存活,可删;true表示有存活节点,不可删 * * @param ip * @return */ private boolean checkMachineActive(String ip) { List instancelist = instanceDao.getInstListByIp(ip); if (instancelist == null || instancelist.size() == 0) return false; return true; } /** * 操作给管理员发邮件通知 * * @param operationAlertValueResultList * @param type */ private void operationNotice(List operationAlertValueResultList, String type) { String title = "【CacheCloud】"; if (type.equalsIgnoreCase("DELETE")) { title += "销毁机器"; } else if (type.equalsIgnoreCase("CREATE")) { title += "添加机器"; } else if (type.equalsIgnoreCase("POD-ONLINE")) { title += "POD状态变更:上线"; } else if (type.equalsIgnoreCase("POD-OFFLINE")) { title += "POD状态变更:下线"; } Map context = new HashMap<>(); context.put("operationAlertValueResultList", operationAlertValueResultList); String mailContent = FreemakerUtils.createText("OperationAlert.ftl", configuration, context); logger.info("send mail content: {}" + operationAlertValueResultList); appAlertRecordService.saveAlertInfoByType(AlertTypeEnum.MACHINE_MANAGE, title, null, operationAlertValueResultList); emailComponent.sendMailToAdmin(title, mailContent); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/QuartzManageController.java ================================================ package com.sohu.cache.web.controller; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sohu.cache.entity.TriggerInfo; import com.sohu.cache.schedule.SchedulerCenter; import org.apache.commons.lang.StringUtils; import org.quartz.TriggerKey; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.sohu.cache.web.enums.SuccessEnum; /** * quartz管理test * * @author leifu * @Time 2014年7月4日 */ @Controller @RequestMapping("manage/quartz") public class QuartzManageController extends BaseController { @Resource private SchedulerCenter schedulerCenter; @RequestMapping(value = "/list") public ModelAndView doQuartzList(HttpServletRequest request, HttpServletResponse response, Model model) { String query = request.getParameter("query"); List triggerList; if (StringUtils.isBlank(query)) { triggerList = schedulerCenter.getAllTriggers(); query = ""; } else { triggerList = schedulerCenter.getTriggersByNameOrGroup(query); } model.addAttribute("triggerList", triggerList); model.addAttribute("quartzActive", SuccessEnum.SUCCESS.value()); model.addAttribute("query", query); return new ModelAndView("manage/quartz/list"); } @RequestMapping(value = "/pause") public String pause(HttpServletRequest request, HttpServletResponse response, Model model) { String name = request.getParameter("name"); String group = request.getParameter("group"); if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) { schedulerCenter.pauseTrigger(new TriggerKey(name, group)); } return "redirect:/manage/quartz/list"; } @RequestMapping(value = "/resume") public String resume(HttpServletRequest request, HttpServletResponse response, Model model) { String name = request.getParameter("name"); String group = request.getParameter("group"); if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) { schedulerCenter.resumeTrigger(new TriggerKey(name, group)); } return "redirect:/manage/quartz/list"; } @RequestMapping(value = "/remove") public String remove(HttpServletRequest request, HttpServletResponse response, Model model) { String name = request.getParameter("name"); String group = request.getParameter("group"); if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(group)) { schedulerCenter.unscheduleJob(new TriggerKey(name, group)); } return "redirect:/manage/quartz/list"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/RedisConfigTemplateController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.ErrorMessageEnum; import com.sohu.cache.constant.RedisConfigTemplateChangeEnum; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceConfig; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.AppEmailUtil; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Redis配置模板管理 * * @author leifu * @Date 2016-6-25 * @Time 下午2:48:25 */ @Controller @RequestMapping("manage/redisConfig") public class RedisConfigTemplateController extends BaseController { @Resource(name = "redisConfigTemplateService") private RedisConfigTemplateService redisConfigTemplateService; @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; @Autowired private ResourceService resourceService; /** * 初始化配置 */ @RequestMapping(value = "/init") public ModelAndView init(HttpServletRequest request, HttpServletResponse response, Model model) { // 默认是Redis普通节点配置 int type = NumberUtils.toInt(request.getParameter("type"), ConstUtils.CACHE_REDIS_STANDALONE); int resourceId = NumberUtils.toInt(request.getParameter("versionid"),0); // 获取redis资源包 List resourceList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); model.addAttribute("resourceList", resourceList); if(resourceId == 0){ model.addAttribute("currentVersion", resourceList.get(0)); }else{ model.addAttribute("currentVersion", resourceService.getResourceById(resourceId)); } model.addAttribute("redisConfigList", redisConfigTemplateService.getByVesionAndType(type, resourceId)); model.addAttribute("success", request.getParameter("success")); model.addAttribute("redisConfigActive", SuccessEnum.SUCCESS.value()); model.addAttribute("versionid", resourceId); model.addAttribute("type", type); return new ModelAndView("manage/redisConfig/init"); } /** * 修改配置 */ @RequestMapping(value = "/update") public ModelAndView update(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); String versionName = StringUtils.isEmpty(request.getParameter("versionName")) ? "" : String.valueOf(request.getParameter("versionName")); String id = request.getParameter("id"); String configKey = request.getParameter("configKey"); String configValue = request.getParameter("configValue"); String info = request.getParameter("info"); int status = NumberUtils.toInt(request.getParameter("status"), -1); int valueType = NumberUtils.toInt(request.getParameter("valueType"), 0); if (StringUtils.isBlank(id) || !NumberUtils.isDigits(id) || StringUtils.isBlank(configKey) || status > 1 || status < 0) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + "id=" + id + ",configKey=" + configKey + ",configValue=" + configValue + ",status=" + status); return new ModelAndView(""); } //开始修改 logger.warn("user {} want to change id={}'s configKey={}, configValue={}, info={}, status={}", appUser.getName(), id, configKey, configValue, info, status); SuccessEnum successEnum; InstanceConfig instanceConfig = redisConfigTemplateService.getById(NumberUtils.toLong(id)); try { instanceConfig.setConfigValue(configValue); instanceConfig.setInfo(info); instanceConfig.setStatus(status); instanceConfig.setValueType(valueType); redisConfigTemplateService.saveOrUpdate(instanceConfig); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} want to change {} id={}'s configKey={}, configValue={}, info={}, status={}, result is {}", appUser.getName(), versionName, id, configKey, configValue, info, status, successEnum.value()); //发送邮件通知 appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, versionName, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.UPDATE); model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 删除配置 */ @RequestMapping(value = "/remove") public ModelAndView remove(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); String idParam = request.getParameter("id"); String versionName = StringUtils.isEmpty(request.getParameter("versionName")) ? "" : String.valueOf(request.getParameter("versionName")); long id = NumberUtils.toLong(idParam); if (id <= 0) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + "id=" + idParam); return new ModelAndView(""); } logger.warn("user {} want to delete id={}'s config", appUser.getName(), id); SuccessEnum successEnum; InstanceConfig instanceConfig = redisConfigTemplateService.getById(id); try { redisConfigTemplateService.remove(id); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} want to delete {} id={}'s config, result is {}", appUser.getName(), versionName, id, successEnum.value()); //发送邮件通知 appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, versionName, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.DELETE); model.addAttribute("status", successEnum.value()); return new ModelAndView(""); } /** * 添加配置 */ @RequestMapping(value = "/add") public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Model model) { AppUser appUser = getUserInfo(request); String versionName = StringUtils.isEmpty(request.getParameter("versionName")) ? "" : String.valueOf(request.getParameter("versionName")); InstanceConfig instanceConfig = getInstanceConfig(request); if (StringUtils.isBlank(instanceConfig.getConfigKey())) { model.addAttribute("status", SuccessEnum.FAIL.value()); model.addAttribute("message", ErrorMessageEnum.PARAM_ERROR_MSG.getMessage() + "configKey=" + instanceConfig.getConfigKey()); return new ModelAndView(""); } logger.warn("user {} want to add config, configKey is {}, configValue is {}, type is {}", appUser.getName(), instanceConfig.getConfigKey(), instanceConfig.getConfigValue(), instanceConfig.getType()); SuccessEnum successEnum; try { redisConfigTemplateService.saveOrUpdate(instanceConfig); successEnum = SuccessEnum.SUCCESS; } catch (Exception e) { successEnum = SuccessEnum.FAIL; model.addAttribute("message", ErrorMessageEnum.INNER_ERROR_MSG.getMessage()); logger.error(e.getMessage(), e); } logger.warn("user {} want to add {} config, configKey is {}, configValue is {}, type is {}, result is {}", appUser.getName(), versionName, instanceConfig.getConfigKey(), instanceConfig.getConfigValue(), instanceConfig.getType(), successEnum.value()); model.addAttribute("status", successEnum.value()); //发送邮件通知 appEmailUtil.sendRedisConfigTemplateChangeEmail(appUser, versionName, instanceConfig, successEnum, RedisConfigTemplateChangeEnum.ADD); return new ModelAndView(""); } /** * Redis配置对比 */ @RequestMapping(value = "/contrast") public ModelAndView contrast(HttpServletRequest request, Model model, Integer upgradeVersionId, Integer currentVersionId) { //对比配置 List configList_current = redisConfigTemplateService.getByVesion(currentVersionId); List configList_upgrade = redisConfigTemplateService.getByVesion(upgradeVersionId); // current Map Map currentConfigMap = new HashMap(); for (InstanceConfig instanceConfig : configList_current) { if (instanceConfig.getStatus() == 1) { currentConfigMap.put(instanceConfig.getConfigKey(), instanceConfig.getConfigValue()); } } // upgrade Map Map upgradeConfigMap = new HashMap(); for (InstanceConfig instanceConfig : configList_upgrade) { if (instanceConfig.getStatus() == 1) { upgradeConfigMap.put(instanceConfig.getConfigKey(), instanceConfig.getConfigValue()); } } // same Map Map sameConfigMap = new HashMap(); logger.info("current config item size ={}", configList_current.size()); logger.info("upgarde config item size ={}", configList_upgrade.size()); // 临时变量 List localConfig = configList_upgrade; // 配置变更 for (InstanceConfig instanceConfig : localConfig) { String key = instanceConfig.getConfigKey(); String value = instanceConfig.getConfigValue(); if (currentConfigMap.containsKey(key) && currentConfigMap.get(key).equals(value)) { currentConfigMap.remove(key); upgradeConfigMap.remove(key); sameConfigMap.put(key, value); } } logger.info("diff current : {},size ={}", currentConfigMap, currentConfigMap.size()); logger.info("diff upgrade : {},size ={}", upgradeConfigMap, upgradeConfigMap.size()); logger.info("same configuration: {},size ={}", sameConfigMap, sameConfigMap.size()); // 获取当前redis的所有版本 model.addAttribute("sameConfigMap", sameConfigMap); model.addAttribute("currentConfigMap", currentConfigMap); model.addAttribute("currentVersion", resourceService.getResourceById(currentVersionId)); model.addAttribute("upgradeConfigMap", upgradeConfigMap); model.addAttribute("upgradeVersion", resourceService.getResourceById(upgradeVersionId)); model.addAttribute("success", request.getParameter("success")); model.addAttribute("redisConfigActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/redisConfig/contrast"); } /** * 预览配置 */ @RequestMapping(value = "/preview") public ModelAndView preview(HttpServletRequest request, HttpServletResponse response, Model model) { //默认配置 int type = NumberUtils.toInt(request.getParameter("type"), -1); String host = StringUtils.isBlank(request.getParameter("host")) ? "127.0.0.1" : request.getParameter("host"); int port = NumberUtils.toInt(request.getParameter("port"), 6379); int maxMemory = NumberUtils.toInt(request.getParameter("maxMemory"), 2048); int sentinelPort = NumberUtils.toInt(request.getParameter("sentinelPort"), 26379); String masterName = StringUtils.isBlank(request.getParameter("masterName")) ? "myMaster" : request .getParameter("masterName"); int versionId = NumberUtils.toInt(request.getParameter("versionId"), 1); // 根据类型生成配置模板 List configList = new ArrayList(); if (ConstUtils.CACHE_REDIS_STANDALONE == type) { configList = redisConfigTemplateService.handleCommonConfig(host, port, maxMemory, null, versionId); } else if (ConstUtils.CACHE_REDIS_SENTINEL == type) { configList = redisConfigTemplateService.handleSentinelConfig(masterName, host, port, host, sentinelPort, versionId, null); } else if (ConstUtils.CACHE_TYPE_REDIS_CLUSTER == type) { configList = redisConfigTemplateService.handleClusterConfig(port, versionId); } model.addAttribute("type", type); model.addAttribute("host", host); model.addAttribute("port", port); model.addAttribute("maxMemory", maxMemory); model.addAttribute("sentinelPort", sentinelPort); model.addAttribute("masterName", masterName); model.addAttribute("configList", configList); return new ModelAndView("manage/redisConfig/preview"); } /** * 使用最简单的request生成InstanceConfig对象 * * @return */ private InstanceConfig getInstanceConfig(HttpServletRequest request) { String configKey = request.getParameter("configKey"); String configValue = request.getParameter("configValue"); String info = request.getParameter("info"); String type = request.getParameter("type"); String versionid = request.getParameter("versionid"); int valueType = NumberUtils.toInt(request.getParameter("valueType"), 0); InstanceConfig instanceConfig = new InstanceConfig(); instanceConfig.setConfigKey(configKey); instanceConfig.setConfigValue(configValue); instanceConfig.setInfo(info); instanceConfig.setType(NumberUtils.toInt(type)); instanceConfig.setUpdateTime(new Date()); instanceConfig.setStatus(1); instanceConfig.setVersionId(NumberUtils.toInt(versionid)); instanceConfig.setValueType(valueType); return instanceConfig; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/RedisVersionUpgradeController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.RedisVersionStat; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisConfigTemplateService; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ResourceService; import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletResponse; import java.util.*; /** * Created by chenshi on 2018/9/4. */ @Controller @RequestMapping("manage/redis/upgrade") public class RedisVersionUpgradeController extends BaseController { private Logger logger = LoggerFactory.getLogger(RedisVersionUpgradeController.class); @Autowired private RedisConfigTemplateService redisConfigTemplateService; @Autowired private AppService appService; @Autowired private ResourceService resourceService; /** *

* Description: 实例和配置检查 *

* * @author chenshi * @version 1.0 * @date 2018/9/11 */ @RequestMapping(value = "check/instance", method = {RequestMethod.GET, RequestMethod.POST}) public ModelAndView checkInstance(HttpServletResponse response, Long appId, Integer upgradeVersionId, String upgradeVersionName) { logger.info("--------check instance , appId:{} , upgradeVersionId:{}", appId, upgradeVersionId); Map resultMap = new HashMap(); SuccessEnum successEnum; // 1.param check if (appId == null || upgradeVersionId == null) { // return error resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", String.format("appId:%s或版本号:%s参数不正确", appId, upgradeVersionName)); return null; } // 2.版本有效检查 SystemResource redisResource = resourceService.getResourceById(upgradeVersionId); if (redisResource == null || redisResource.getStatus() == 0) { // 无该版本配置 || 版本配置无效 resultMap.put("status", SuccessEnum.ERROR.value()); resultMap.put("message", String.format("升级版本号%s 无效或删除", upgradeVersionName)); return null; } // 4. 版本配置项变更预览 // 5. master是否都有slave节点,所有实例信息 List instanceList = appService.getAppInstanceInfo(appId); Set machineSet = new HashSet(); String instanceInfo; StringBuilder instanceInfoBuilder = new StringBuilder(); int masterNum = 0; int slaveNum = 0; if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append("\n"); // 主从节点判断 if (instance.getRoleDesc().equals("slave")) { slaveNum++; } else if (instance.getRoleDesc().equals("master")) { masterNum++; } machineSet.add(instance.getIp()); } } } instanceInfo = instanceInfoBuilder.toString(); // master节点数 <= slave节点数,才能迁移 if (masterNum > slaveNum || instanceList == null) { successEnum = SuccessEnum.ERROR; resultMap.put("message", String.format("主(%d)从(%d)实例节点不一致", masterNum, slaveNum)); } else { successEnum = SuccessEnum.SUCCESS; } // 5.1 实例机器redis资源包安装检查,如果没有redis资源包,自动拉取安装资源包 String machineInstallInfo = ""; if (!CollectionUtils.isEmpty(machineSet) && successEnum == SuccessEnum.SUCCESS) { for (String machineIp : machineSet) { // Redis资源校验&推包 Boolean installStatus = redisConfigTemplateService.checkAndInstallRedisResource(machineIp, redisResource); if (!installStatus) { successEnum = SuccessEnum.ERROR; resultMap.put("message", String.format("%s安装 %s版本失败,请检查日志!", machineIp, redisResource.getName())); break; } } } resultMap.put("status", successEnum.value()); resultMap.put("upgradeVersion", redisResource); resultMap.put("instanceInfo", instanceInfo); resultMap.put("machineInstallInfo", machineInstallInfo); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } /** *

* Description: slave更新配置并重启 *

* * @author chenshi * @version 1.0 * @date 2018/9/13 */ @RequestMapping(value = "slave/update/config", method = RequestMethod.POST) public ModelAndView slaveUpdateConfig(HttpServletResponse response, Long appId, Integer upgradeVersionId, String upgradeVersionName) { Map resultMap = redisConfigTemplateService.slaveUpdateConfig(appId, upgradeVersionId, upgradeVersionName); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } /** *

* Description: slave failover *

* * @author chenshi * @version 1.0 * @date 2018/9/13 */ @RequestMapping(value = "slave/failover", method = RequestMethod.POST) public ModelAndView masterSlavefailover(HttpServletResponse response, Long appId) { // 1.failover 状态 Map resultMap = redisConfigTemplateService.slaveFailover(appId); // 2. 输出节点信息及日志 List instanceList = appService.getAppInstanceInfo(appId); StringBuilder instanceInfoBuilder = new StringBuilder(); StringBuilder instanceLogBuilder = new StringBuilder(); if (instanceList != null && instanceList.size() > 0) { for (InstanceInfo instance : instanceList) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); //instanceInfo += instance.getIp() + ":" + instance.getPort() + " " + instance.getRoleDesc() + " version:" + redisVersion + " \n"; //instanceLog += "日志
"; instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(" ") .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append(" \n"); instanceLogBuilder.append("日志
"); } } } resultMap.put("instanceInfo", instanceInfoBuilder.toString()); resultMap.put("instanceLog", instanceLogBuilder.toString()); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } /** *

* Description: 更新应用信息,返回最终实例信息 *

* * @author chenshi * @version 1.0 * @date 2018/9/13 */ @RequestMapping(value = "complete/check", method = {RequestMethod.POST, RequestMethod.POST}) public ModelAndView completeCheck(HttpServletResponse response, Long appId, Integer upgradeVersionId) { Map resultMap = new HashMap(); // 1.更新应用为升级的版本 AppDesc appDesc = appService.getByAppId(appId); appDesc.setVersionId(upgradeVersionId); appService.update(appDesc); // 2.遍历当前节点状态 List instancelist = appService.getAppInstanceInfo(appId); StringBuilder instanceInfoBuilder = new StringBuilder(); if (instancelist != null && instancelist.size() > 0) { for (InstanceInfo instance : instancelist) { if (instance.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()) { String redisVersion = redisCenter.getRedisVersion(appId, instance.getIp(), instance.getPort()); //instanceInfo += instance.getIp() + ":" + instance.getPort() + " " + instance.getRoleDesc() + " version:" + redisVersion + " \n"; instanceInfoBuilder.append(instance.getIp()) .append(":") .append(instance.getPort()) .append(" ") .append(instance.getRoleDesc()) .append(" version:") .append(redisVersion) .append(" \n"); } } } resultMap.put("status", SuccessEnum.SUCCESS.value()); resultMap.put("instanceInfo", instanceInfoBuilder.toString()); resultMap.put("instanceLog", ""); sendMessage(response, JSONObject.toJSONString(resultMap)); return null; } public void setRedisConfigTemplateService(RedisConfigTemplateService redisConfigTemplateService) { this.redisConfigTemplateService = redisConfigTemplateService; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ResourceController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.entity.*; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.constant.PushEnum; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.service.ServerDataService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by chenshi on 2020/7/3. */ @Controller @RequestMapping("/manage/app/resource") public class ResourceController extends BaseController { @Autowired ResourceService resourceService; @Autowired SSHService sshService; @Autowired TaskService taskService; @Autowired ServerDataService serverDataService; @RequestMapping("/index") public ModelAndView index(Model model, String tabTag, String searchName) { model.addAttribute("tabTag", tabTag); model.addAttribute("searchName", searchName); model.addAttribute("reourcesActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/resource/list"); } @RequestMapping("/redis/{tab}") public ModelAndView tab(@PathVariable("tab") String tab, String searchName, Model model) { List resourceList = new ArrayList(); int resource_type = 0; List allServerInfo = new ArrayList<>(); switch (tab) { case "respo": resource_type = ResourceEnum.ALL.getValue(); break; case "script": resource_type = ResourceEnum.SCRIPT.getValue(); break; case "redis": resource_type = ResourceEnum.REDIS.getValue(); allServerInfo.addAll(serverDataService.getAllServerInfo()); break; case "tool": resource_type = ResourceEnum.TOOL.getValue(); break; case "sshkey": resource_type = ResourceEnum.SSHKEY.getValue(); break; case "dir": resource_type = ResourceEnum.DIR.getValue(); break; default: break; } if (StringUtils.isEmpty(searchName)) { resourceList = resourceService.getResourceList(resource_type); } else { resourceList = resourceService.getResourceList(resource_type, searchName); model.addAttribute("searchName", searchName); } //仓库资源 List reposlist = resourceService.getResourceList(ResourceEnum.Repository.getValue()); if (!CollectionUtils.isEmpty(reposlist)) { model.addAttribute("repository", reposlist.get(0)); } // 目录资源 List dirlist = resourceService.getResourceList(ResourceEnum.DIR.getValue()); model.addAttribute("tabTag", tab); model.addAttribute("resourceList", resourceList); model.addAttribute("allServerInfo", allServerInfo); model.addAttribute("dirList", dirlist); model.addAttribute("appUseMap", resourceService.getAppUseRedis()); model.addAttribute("reourcesActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/resource/" + tab); } @RequestMapping("/add") public ModelAndView resourceAdd(HttpServletRequest request, HttpServletResponse response, Integer resourceId, Model model) { JSONObject result = new JSONObject(); SystemResource resource = new SystemResource(); //修改 if (resourceId != null && resourceId > 0) { resource = resourceService.getResourceById(resourceId); } int versionCopyId = NumberUtils.toInt(request.getParameter("copyVersion"), -1); int resourceType = NumberUtils.toInt(request.getParameter("resourceType")); resource.setName(request.getParameter("resourceName")); resource.setIntro(request.getParameter("resourceDesc")); resource.setDir(request.getParameter("resourceDir")); resource.setStatus(NumberUtils.toInt(request.getParameter("resourceStatus"))); resource.setType(resourceType); resource.setUrl(request.getParameter("resourceUrl")); resource.setOrderNum(NumberUtils.toInt(request.getParameter("orderNum"))); resource.setLastmodify(new Date()); resource.setUsername(getUserInfo(request).getName()); SuccessEnum successEnum = null; if (resourceId != null && resourceId > 0) { resource.setId(resourceId); successEnum = resourceService.updateResource(resource); } else { // 验重 SystemResource existResource = resourceService.getResourceByName(resource.getName()); if (existResource != null && existResource.getId() > 0) { result.put("status", SuccessEnum.FAIL.value()); result.put("message", "资源名已存在"); sendMessage(response, result.toString()); return null; } resource.setIspush(PushEnum.NO.getValue()); successEnum = resourceService.saveResource(resource); if (versionCopyId > -1 && resourceType == ResourceEnum.REDIS.getValue()) { redisConfigTemplateService.copyRedisConfig(versionCopyId, resource); } } result.put("status", successEnum.value()); sendMessage(response, result.toString()); return null; } @RequestMapping("/get") public ModelAndView resourceGet(HttpServletResponse response, Integer resourceId) { JSONObject result = new JSONObject(); SuccessEnum successEnum = SuccessEnum.FAIL; if (resourceId != null && resourceId > 0) { SystemResource resource = resourceService.getResourceById(resourceId); if (resource != null) { successEnum = SuccessEnum.SUCCESS; result.put("resource", resource); } } result.put("status", successEnum.value()); sendMessage(response, result.toString()); return null; } @RequestMapping("/ssh") public ModelAndView generateSshkey(HttpServletResponse response, String command, String containerIp, Integer resourceId) { JSONObject result = new JSONObject(); if (StringUtils.isEmpty(containerIp)) { containerIp = machineCenter.getFirstMachineIp(); } SuccessEnum successEnum = SuccessEnum.FAIL; /*if (resourceId != null && resourceId > 0) { Boolean flag = resourceService.generateSshkey(containerIp, command); }*/ result.put("status", successEnum.value()); sendMessage(response, result.toString()); return null; } @RequestMapping("/push") public ModelAndView resourcePush(HttpServletRequest request, HttpServletResponse response, Integer repositoryId, Integer resourceId, String content) { // 1. push content SuccessEnum successEnum = null; JSONObject result = new JSONObject(); AppUser userInfo = getUserInfo(request); if (repositoryId != null && resourceId != null) { SystemResource resource = resourceService.getResourceById(resourceId); if (resource.getType() == ResourceEnum.SCRIPT.getValue()) { // 1.1推送脚本资源 successEnum = resourceService.pushScript(repositoryId, resourceId, content, userInfo); // 1.2.清理临时资源 clearTempResource(String.valueOf(resourceId)); } else if (resource.getType() == ResourceEnum.DIR.getValue()) { // 2.1.推送目录资源 successEnum = resourceService.pushDir(repositoryId, resourceId, userInfo); } result.put("status", successEnum == null ? successEnum : successEnum.value()); } else { result.put("status", SuccessEnum.ERROR.value()); result.put("message", "资源id异常"); } sendMessage(response, result.toString()); return null; } @RequestMapping("/compile") public ModelAndView compile(HttpServletRequest request, HttpServletResponse response, String containerIp, String compileInfo, Integer repositoryId, Integer resourceId, String content) { // 1. push content JSONObject result = new JSONObject(); if (StringUtils.isEmpty(containerIp)) { // 从机器列表获取一台可用机器 containerIp = machineCenter.getFirstMachineIp(); } AppUser userInfo = getUserInfo(request); if (repositoryId != null && resourceId != null) { // 推送资源 long taskid = taskService.addResourceCompileTask(resourceId, repositoryId, containerIp, userInfo); SystemResource resource = resourceService.getResourceById(resourceId); resource.setTaskId(taskid); resource.setCompileInfo(compileInfo); resourceService.updateResource(resource); result.put("status", SuccessEnum.SUCCESS.value()); } else { result.put("status", SuccessEnum.ERROR.value()); result.put("message", "资源id异常"); } sendMessage(response, result.toString()); return null; } @RequestMapping("/temporarySave") public ModelAndView temporarySave(HttpServletResponse response, Integer resourceId, String content) { // 1. push content JSONObject result = new JSONObject(); if (saveTempResource(String.valueOf(resourceId), content)) { result.put("status", SuccessEnum.SUCCESS.value()); SystemResource resource = resourceService.getResourceById(resourceId); if (resource.getIspush() == PushEnum.NO.getValue()) { resource.setIspush(PushEnum.NO_WITH_MODIFY.getValue()); } else if (resource.getIspush() == PushEnum.YES.getValue()) { resource.setIspush(PushEnum.YES_WITH_MODIFY.getValue()); } resourceService.updateResource(resource); } sendMessage(response, result.toString()); return null; } @RequestMapping("/script/load") public ModelAndView load(HttpServletResponse response, Integer resourceId, Integer respositoryId) { // 1. push content JSONObject result = new JSONObject(); if (resourceId != null && respositoryId != null) { String localContent = getTempResource(String.valueOf(resourceId)); if (StringUtils.isEmpty(localContent)) { String remoteContent = resourceService.getRemoteFileContent(resourceId, respositoryId); if (!StringUtils.isEmpty(remoteContent)) { result.put("content", remoteContent); // 来源:远程文件 result.put("source", "2"); } } else { // 来源:临时文件 result.put("content", localContent); result.put("source", "1"); } result.put("script", localContent); result.put("status", SuccessEnum.SUCCESS.value()); } sendMessage(response, result.toString()); return null; } @RequestMapping("/config") public ModelAndView config(HttpServletRequest request, HttpServletResponse response, Integer repositoryId, Integer resourceId) { // 1. push content JSONObject result = new JSONObject(); AppUser userInfo = getUserInfo(request); if (repositoryId != null && resourceId != null) { } return new ModelAndView("manage/resource/config"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/ServerController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSON; import com.sohu.cache.entity.ServerInfo; import com.sohu.cache.entity.ServerStatus; import com.sohu.cache.web.service.ServerDataService; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.*; /** * 获取服务器状态 */ @Controller @RequestMapping("/server") public class ServerController extends BaseController{ @Resource private ServerDataService serverDataService; private DecimalFormat df = new DecimalFormat("0.0"); /** * 跳转到主页 * @param request * @param response * @param model * @return */ @RequestMapping("/index") public ModelAndView index(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); model.addAttribute("ip", ip); String date = request.getParameter("date"); if(date == null) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); date = sdf.format(new Date()); } model.addAttribute("date", date); return new ModelAndView("server/index"); } /** * 服务器信息概览 * @param request * @param response * @param model * @return */ @RequestMapping("/overview") public ModelAndView overview(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); //获取服务器静态信息 ServerInfo info = serverDataService.queryServerInfo(ip); if(info != null) { model.addAttribute("info", info); //解析ulimit String ulimit = info.getUlimit(); if(!StringUtils.isEmpty(ulimit)) { String[] tmp = ulimit.split(";"); if(tmp.length ==2) { String[] a = tmp[0].split(","); if(a != null && a.length == 2) { if("f".equals(a[0])) { model.addAttribute("file", a[1]); } } a = tmp[1].split(","); if(a != null && a.length == 2) { if("p".equals(a[0])) { model.addAttribute("process", a[1]); } } } } } //获取服务器状态 List list = serverDataService.queryServerOverview(ip, date); //x轴坐标 List xAxis = new ArrayList(); //1分钟最大load float maxLoad1 = 0; //load1总量 double totalLoad1 = 0; //最大user float maxUser = 0; //最大sys float maxSys = 0; //最大wio float maxWa = 0; //当前可用内存 float curFree = 0; //最大内存使用量 float maxUse = 0; //最大内存cache量 float maxCache = 0; //最大内存buffer量 float maxBuffer = 0; //最大swap使用量 float maxSwapUse = 0; //最大网络流入速度 float maxNetIn = 0; //最大网络流出速度 float maxNetOut = 0; //最大连接ESTABLISHED数 int maxConn = 0; //最大连接TIME_WAIT数 int maxWait = 0; //最大连接ORPHAN数 int maxOrphan = 0; //最大读取速率 float maxRead = 0; //最大写入速率 float maxWrite = 0; //最繁忙程度 float maxBusy = 0; //最大iops量 float maxIops = 0; //load serie Series load1Serie = new Series("1-min"); Series load5Serie = new Series("5-min"); Series load15Serie = new Series("15-min"); //cpu serie Series userSerie = new Series("user"); Series sysSerie = new Series("sys"); Series waSerie = new Series("wa"); //memory serie Series totalSerie = new Series("total"); Series useSerie = new Series("use"); useSerie.setType("area"); Series cacheSerie = new Series("cache"); cacheSerie.setType("area"); Series bufferSerie = new Series("buffer"); bufferSerie.setType("area"); Series swapSerie = new Series("total"); Series swapUseSerie = new Series("use"); //net serie Series netInSerie = new Series("in"); Series netOutSerie = new Series("out"); //tcp serie Series establishedSerie = new Series("established"); Series twSerie = new Series("time wait"); Series orphanSerie = new Series("orphan"); //disk serie Series readSerie = new Series("read"); readSerie.setType("column"); Series writeSerie = new Series("write"); writeSerie.setType("column"); Series busySerie = new Series("busy"); busySerie.setYAxis(1); Series iopsSerie = new Series("iops"); iopsSerie.setYAxis(2); for(int i = 0; i < list.size(); ++i) { ServerStatus ss = list.get(i); //x axis xAxis.add(ss.getCtime().substring(0, 2) + ":" + ss.getCtime().substring(2)); //load相关 load1Serie.addData(ss.getCload1()); load5Serie.addData(ss.getCload5()); load15Serie.addData(ss.getCload15()); maxLoad1 = getBigger(maxLoad1, ss.getCload1()); totalLoad1 += ss.getCload1(); //cpu相关 userSerie.addData(ss.getCuser()); sysSerie.addData(ss.getCsys()); waSerie.addData(ss.getCwio()); maxUser = getBigger(maxUser, ss.getCuser()); maxSys = getBigger(maxSys, ss.getCsys()); maxWa = getBigger(maxWa, ss.getCwio()); //memory相关 totalSerie.addData(ss.getMtotal()); float use = ss.getMtotal()-ss.getMfree()-ss.getMcache()-ss.getMbuffer(); useSerie.addData(use); cacheSerie.addData(ss.getMcache()); bufferSerie.addData(ss.getMbuffer()); maxUse = getBigger(maxUse, use); maxCache = getBigger(maxCache, ss.getMcache()); maxBuffer = getBigger(maxBuffer, ss.getMbuffer()); if(i == list.size() - 1) { curFree = ss.getMtotal() - use; } //swap相关 swapSerie.addData(ss.getMswap()); float swapUse = ss.getMswap() - ss.getMswapFree(); swapUse = floor(swapUse); swapUseSerie.addData(swapUse); maxSwapUse = getBigger(maxSwapUse, swapUse); //net相关 netInSerie.addData(ss.getNin()); netOutSerie.addData(ss.getNout()); maxNetIn = getBigger(maxNetIn, ss.getNin()); maxNetOut = getBigger(maxNetOut, ss.getNout()); //tcp相关 establishedSerie.addData(ss.getTuse()); twSerie.addData(ss.getTwait()); orphanSerie.addData(ss.getTorphan()); maxConn = getBigger(maxConn, ss.getTuse()); maxWait = getBigger(maxWait, ss.getTwait()); maxOrphan = getBigger(maxOrphan, ss.getTorphan()); //disk相关 readSerie.addData(ss.getDread()); writeSerie.addData(ss.getDwrite()); busySerie.addData(ss.getDbusy()); iopsSerie.addData(ss.getDiops()); maxRead = getBigger(maxRead, ss.getDread()); maxWrite = getBigger(maxWrite, ss.getDwrite()); maxBusy = getBigger(maxBusy, ss.getDbusy()); maxIops = getBigger(maxIops, ss.getDiops()); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); //load model.addAttribute("load1", JSON.toJSONString(load1Serie)); model.addAttribute("load5", JSON.toJSONString(load5Serie)); model.addAttribute("load15", JSON.toJSONString(load15Serie)); model.addAttribute("maxLoad1", maxLoad1); model.addAttribute("avgLoad1", format(totalLoad1, list.size())); //cpu model.addAttribute("user", JSON.toJSONString(userSerie)); model.addAttribute("sys", JSON.toJSONString(sysSerie)); model.addAttribute("wa", JSON.toJSONString(waSerie)); model.addAttribute("maxUser", maxUser); model.addAttribute("maxSys", maxSys); model.addAttribute("maxWa", maxWa); //memory model.addAttribute("mtotal", JSON.toJSONString(totalSerie)); model.addAttribute("muse", JSON.toJSONString(useSerie)); model.addAttribute("mcache", JSON.toJSONString(cacheSerie)); model.addAttribute("mbuffer", JSON.toJSONString(bufferSerie)); model.addAttribute("curFree", format(curFree, 1024)); model.addAttribute("maxUse", format(maxUse, 1024)); model.addAttribute("maxCache", format(maxCache, 1024)); model.addAttribute("maxBuffer", format(maxBuffer, 1024)); //swap model.addAttribute("mswap", JSON.toJSONString(swapSerie)); model.addAttribute("mswapUse", JSON.toJSONString(swapUseSerie)); model.addAttribute("maxSwap", maxSwapUse); //net model.addAttribute("nin", JSON.toJSONString(netInSerie)); model.addAttribute("nout", JSON.toJSONString(netOutSerie)); model.addAttribute("maxNetIn", format(maxNetIn, 1024)); model.addAttribute("maxNetOut", format(maxNetOut, 1024)); //tcp model.addAttribute("testab", JSON.toJSONString(establishedSerie)); model.addAttribute("twait", JSON.toJSONString(twSerie)); model.addAttribute("torph", JSON.toJSONString(orphanSerie)); model.addAttribute("maxConn", maxConn); model.addAttribute("maxWait", maxWait); model.addAttribute("maxOrphan", maxOrphan); //disk model.addAttribute("dread", JSON.toJSONString(readSerie)); model.addAttribute("dwrite", JSON.toJSONString(writeSerie)); model.addAttribute("dbusy", JSON.toJSONString(busySerie)); model.addAttribute("diops", JSON.toJSONString(iopsSerie)); model.addAttribute("maxRead", format(maxRead, 1024)); model.addAttribute("maxWrite", format(maxWrite, 1024)); model.addAttribute("maxBusy", maxBusy); model.addAttribute("maxIops", maxIops); model.addAttribute("date", date); return new ModelAndView("server/overview"); } private String format(double a, int b) { if(b <= 0) { return "0"; } return df.format(a/b); } private float getBigger(float a, float b) { if(a > b) { return a; } return b; } private int getBigger(int a, int b) { if(a > b) { return a; } return b; } /** * 保留一位小数,四舍五入 * @param v * @return */ private float floor(float v) { return new BigDecimal(v).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue(); } /** * 获取服务器cpu各个核状态 * @param request * @param response * @param model * @return */ @RequestMapping("/cpu") public ModelAndView cpu(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List list = serverDataService.queryServerCpu(ip, date); Map subcpuMap = new TreeMap(); //x轴坐标 List xAxis = new ArrayList(); for(ServerStatus ss : list) { String subcpuString = ss.getCExt(); String[] subCpuArray = subcpuString.split(";"); xAxis.add(ss.getCtime()); for(String subcpu : subCpuArray) { if(StringUtils.isEmpty(subcpu)) { continue; } String[] cpu = subcpu.split(","); CpuChart cpuChart = subcpuMap.get(cpu[0]); if(cpuChart == null) { cpuChart = new CpuChart(cpu[0]); subcpuMap.put(cpu[0], cpuChart); } float user = NumberUtils.toFloat(cpu[1]); float sys = NumberUtils.toFloat(cpu[2]); float wa = NumberUtils.toFloat(cpu[3]); cpuChart.addUserSeries(user); cpuChart.addSysSeries(sys); cpuChart.addWaSeries(wa); cpuChart.setMaxUser(user); cpuChart.setMaxSys(sys); cpuChart.setMaxWa(wa); cpuChart.addUser(user); cpuChart.addSys(sys); cpuChart.addWa(wa); } } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("cpu", subcpuMap.values()); return new ModelAndView("server/cpu"); } /** * 获取服务器各网卡状态 * @param request * @param response * @param model * @return */ @RequestMapping("/net") public ModelAndView net(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List list = serverDataService.queryServerNet(ip, date); Map subnetMap = new TreeMap(); //x轴坐标 List xAxis = new ArrayList(); for(ServerStatus ss : list) { xAxis.add(ss.getCtime()); addNetMap(ss.getNinExt(), subnetMap, true); addNetMap(ss.getNoutExt(), subnetMap, false); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("net", subnetMap.values()); return new ModelAndView("server/net"); } /** * parse net to map * @param netString * @param subnetMap * @param isIn */ private void addNetMap(String netString, Map subnetMap, boolean isIn) { String[] subnetArray = netString.split(";"); for(String subnet : subnetArray) { if(StringUtils.isEmpty(subnet)) { continue; } String[] net = subnet.split(","); NetChart netChart = subnetMap.get(net[0]); if(netChart == null) { netChart = new NetChart(net[0]); subnetMap.put(net[0], netChart); } float v = NumberUtils.toFloat(net[1]); if(isIn) { netChart.addInSeries(v); netChart.addTotalIn(v); netChart.setMaxIn(v); }else { netChart.addOutSeries(v); netChart.addTotalOut(v); netChart.setMaxOut(v); } } } /** * 获取硬盘各分区状态 * @param request * @param response * @param model * @return */ @RequestMapping("/disk") public ModelAndView disk(HttpServletRequest request, HttpServletResponse response, Model model) { String ip = request.getParameter("ip"); String date = request.getParameter("date"); List list = serverDataService.queryServerDisk(ip, date); DiskChart readChart = new DiskChart(); DiskChart writeChart = new DiskChart(); DiskChart busyChart = new DiskChart(); DiskChart iopsChart = new DiskChart(); DiskChart spaceChart = new DiskChart(); //x轴坐标 List xAxis = new ArrayList(); for(ServerStatus ss : list) { xAxis.add(ss.getCtime()); //解析use String dext = ss.getDExt(); if(!StringUtils.isEmpty(dext)) { String[] items = dext.split(";"); if(items != null) { for(String item : items) { String[] sds = item.split("="); if(sds.length == 2) { if("DISKXFER".equals(sds[0])) { addToChart(sds[1], iopsChart); } else if("DISKREAD".equals(sds[0])) { addToChart(sds[1], readChart); } else if("DISKWRITE".equals(sds[0])) { addToChart(sds[1], writeChart); } else if("DISKBUSY".equals(sds[0])) { addToChart(sds[1], busyChart); } } } } } //解析space String space = ss.getDspace(); addToChart(space, spaceChart); } //x axis model.addAttribute("xAxis", JSON.toJSONString(xAxis)); model.addAttribute("read", readChart); model.addAttribute("write", writeChart); model.addAttribute("busy", busyChart); model.addAttribute("iops", iopsChart); model.addAttribute("space", spaceChart); return new ModelAndView("server/disk"); } private void addToChart(String line, DiskChart chart) { String[] parts = line.split(","); for(String part : parts) { if(StringUtils.isEmpty(part)) { continue; } String[] values = part.split(":"); float d = NumberUtils.toFloat(values[1]); chart.addSeries(values[0], d); chart.setMax(d); chart.addTotal(d); } } /** * net chart */ public class NetChart{ private String name; private Series inSeries = new Series("in"); private Series outSeries = new Series("out"); private float maxIn; private float maxOut; private float totalIn; private float totalOut; public NetChart(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Series getInSeries() { return inSeries; } public void addInSeries(float d) { this.inSeries.addData(d); } public Series getOutSeries() { return outSeries; } public void addOutSeries(float d) { this.outSeries.addData(d); } public float getMaxIn() { return maxIn; } public void setMaxIn(float in) { if(this.maxIn < in) { this.maxIn = in; } } public float getMaxOut() { return maxOut; } public void setMaxOut(float out) { if(this.maxOut < out) { this.maxOut = out; } } public void addTotalIn(float in) { this.totalIn += in; } public void addTotalOut(float out) { this.totalOut += out; } public String getAvgIn() { return format(totalIn, inSeries.getData().size()); } public String getAvgOut() { return format(totalOut, outSeries.getData().size()); } } /** * disk chart */ public class DiskChart{ private float max; private float total; private Map> seriesMap = new TreeMap>(); public void addSeries(String partition, float d) { Series series = seriesMap.get(partition); if(series == null) { series = new Series(partition); seriesMap.put(partition, series); } series.addData(d); } public Collection> getSeries() { return seriesMap.values(); } public float getMax() { return max; } public void setMax(float max) { if(this.max < max) { this.max = max; } } public String getAvg() { Collection> coll = seriesMap.values(); int size = 0; if(coll != null) { for(Series series : coll) { size += series.getData().size(); } } return format(total, size); } public void addTotal(float total) { this.total += total; } } /** * cpu chart */ public class CpuChart{ private String name; private Series userSeries = new Series("user"); private Series sysSeries = new Series("sys"); private Series waSeries = new Series("wa"); private float maxUser; private float maxSys; private float maxWa; private float totalUser; private float totalSys; private float totalWa; public CpuChart(String name) { this.name = name; } public String getName() { return name; } public float getMaxUser() { return maxUser; } public void setMaxUser(float user) { if(this.maxUser < user) { this.maxUser = user; } } public float getMaxSys() { return maxSys; } public void setMaxSys(float sys) { if(this.maxSys < sys) { this.maxSys = sys; } } public float getMaxWa() { return maxWa; } public void setMaxWa(float wa) { if(this.maxWa < wa) { this.maxWa = wa; } } public String getAvgUser() { return format(totalUser, userSeries.getData().size()); } public String getAvgSys() { return format(totalSys, sysSeries.getData().size()); } public String getAvgWa() { return format(totalWa, waSeries.getData().size()); } public void addUser(float user) { this.totalUser += user; } public void addSys(float sys) { this.totalSys += sys; } public void addWa(float wa) { this.totalWa += wa; } public Series getUserSeries() { return userSeries; } public void addUserSeries(Float v) { this.userSeries.addData(v); } public Series getSysSeries() { return sysSeries; } public void addSysSeries(Float v) { this.sysSeries.addData(v); } public Series getWaSeries() { return waSeries; } public void addWaSeries(Float v) { this.waSeries.addData(v); } } /** * Highchars Series * @param */ public static class Series{ private String name; private List data = new ArrayList(); private String type = "spline"; private int yAxis; public String toJson() { return JSON.toJSONString(this); } public Series(String name) { this.name = name; } public int getYAxis() { return yAxis; } public void setYAxis(int yAxis) { this.yAxis = yAxis; } public void setType(String type) { this.type = type; } public String getType() { return type; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void addData(T d) { data.add(d); } public List getData() { return data; } @Override public String toString() { return "Serie [name=" + name + ", data=" + data + ", type=" + type + ", yAxis=" + yAxis + "]"; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/TaskController.java ================================================ package com.sohu.cache.web.controller; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.OperateResult; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.task.TaskService; import com.sohu.cache.task.entity.TaskQueue; import com.sohu.cache.task.entity.TaskSearch; import com.sohu.cache.task.entity.TaskStepFlow; import com.sohu.cache.task.entity.TaskStepMeta; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.Page; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 任务管理 */ @Controller @RequestMapping("manage/task") public class TaskController extends BaseController { @Autowired private TaskService taskService; @Autowired private AssistRedisService assistRedisService; @RequestMapping(value = "/list") public ModelAndView taskQueueList(HttpServletRequest request, HttpServletResponse response, Model model, TaskSearch taskSearch) { List taskQueueList = null; Long searchTaskId = NumberUtils.toLong(request.getParameter("searchTaskId")); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 30); if (searchTaskId != null && searchTaskId > 0) { taskQueueList = taskService.getTaskQueueTreeByTaskId(searchTaskId); Page page = new Page(pageNo, pageSize, taskQueueList.size()); model.addAttribute("page", page); taskSearch.setPage(page); } else { // 分页相关:count int totalCount = taskService.getTaskQueueCount(taskSearch); Page page = new Page(pageNo, pageSize, totalCount); model.addAttribute("page", page); // 分页相关:list taskSearch.setPage(page); taskQueueList = taskService.getTaskQueueList(taskSearch); } //填充任务流 for (TaskQueue taskQueue : taskQueueList) { List taskStepFlowList = taskService.getTaskStepFlowList(taskQueue.getId()); taskQueue.setTaskStepFlowList(taskStepFlowList); } model.addAttribute("searchTaskId", searchTaskId); model.addAttribute("taskQueueList", taskQueueList); model.addAttribute("taskActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/task/queueList"); } @RequestMapping(value = "/execute") public ModelAndView execute(HttpServletRequest request, HttpServletResponse response, Model model) { final long taskId = NumberUtils.toLong(request.getParameter("taskId")); TaskQueue taskQueue = taskService.getTaskQueueById(taskId); //TODO if (taskQueue != null) { new Thread(new Runnable() { @Override public void run() { taskService.executeTask(taskId); } }).start(); } return new ModelAndView("redirect:/manage/task/flow?taskId=" + taskId); } @RequestMapping(value = "/changeParam") public ModelAndView changeParam(HttpServletRequest request, HttpServletResponse response, Model model) { long taskId = NumberUtils.toLong(request.getParameter("taskId")); String prettyParam = request.getParameter("prettyParamText"); JSONObject jsonObject = JSONObject.parseObject(prettyParam); String param = jsonObject.toJSONString(); OperateResult operateResult = taskService.updateParam(taskId, param); model.addAttribute("result", operateResult.isSuccess() ? 1 : 0); model.addAttribute("message", operateResult.getMessage()); return new ModelAndView(""); } @RequestMapping(value = "/changeTaskFlowStatus") public ModelAndView changeTaskFlowStatus(HttpServletRequest request, HttpServletResponse response, Model model) { long taskFlowId = NumberUtils.toLong(request.getParameter("taskFlowId")); int status = NumberUtils.toInt(request.getParameter("status")); OperateResult operateResult = taskService.updateTaskFlowStatus(taskFlowId, status); model.addAttribute("result", operateResult.isSuccess() ? 1 : 0); model.addAttribute("message", operateResult.getMessage()); return new ModelAndView(""); } @RequestMapping(value = "/flow") public ModelAndView taskFlowList(HttpServletRequest request, HttpServletResponse response, Model model) { long taskId = NumberUtils.toLong(request.getParameter("taskId")); //任务 TaskQueue taskQueue = taskService.getTaskQueueById(taskId); model.addAttribute("taskQueue", taskQueue); long appId = taskQueue.getAppId(); AppDesc appDesc = appService.getByAppId(appId); model.addAttribute("appDesc", appDesc); //任务流描述 String className = taskQueue.getClassName(); List taskStepMetaList = taskService.getTaskStepMetaList(className); //任务流列表 List taskStepFlowList = taskService.getTaskStepFlowList(taskId); model.addAttribute("taskStepFlowList", taskStepFlowList); List logList = new ArrayList(); for (TaskStepFlow taskStepFlow : taskStepFlowList) { String line = String .format("==========================%s %d======================", taskStepFlow.getStepName(), taskStepFlow.getOrderNo()); logList.add(line); String taskFlowIdKey = ConstUtils.getTaskFlowRedisKey(String.valueOf(taskStepFlow.getId())); List tempList = assistRedisService.lrange(taskFlowIdKey, 0, -1); logList.addAll(tempList); } model.addAttribute("logList", logList); Map> stepLogListMap = new HashMap>(); for (TaskStepFlow taskStepFlow : taskStepFlowList) { String stepName = taskStepFlow.getStepName(); String taskFlowIdKey = ConstUtils.getTaskFlowRedisKey(String.valueOf(taskStepFlow.getId())); List tempList = assistRedisService.lrange(taskFlowIdKey, 0, -1); stepLogListMap.put(stepName, tempList); } model.addAttribute("stepLogListMap", stepLogListMap); //task Progress taskQueue.setTaskStepFlowList(taskStepFlowList); //获取当前执行步骤 TaskStepFlow currentTaskStepFlow = taskService.getCurrentTaskStepFlow(taskId); model.addAttribute("currentTaskStepFlow", currentTaskStepFlow); //填充taskStepMeta fillTaskStepMeta(taskStepFlowList, taskStepMetaList, currentTaskStepFlow); model.addAttribute("taskActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/task/flowList"); } /** * 填充任务流描述 * * @param taskStepFlowList * @param taskStepMetaList */ private void fillTaskStepMeta(List taskStepFlowList, List taskStepMetaList, TaskStepFlow currentTaskStepFlow) { //生成Map Map classStepTaskStepMetaMap = new HashMap(); for (TaskStepMeta taskStepMeta : taskStepMetaList) { String key = generateClassStepKey(taskStepMeta.getClassName(), taskStepMeta.getStepName()); classStepTaskStepMetaMap.put(key, taskStepMeta); } //遍历TaskStepFlow for (TaskStepFlow taskStepFlow : taskStepFlowList) { String key = generateClassStepKey(taskStepFlow.getClassName(), taskStepFlow.getStepName()); TaskStepMeta taskStepMeta = (TaskStepMeta) MapUtils .getObject(classStepTaskStepMetaMap, key, new TaskStepMeta()); taskStepFlow.setTaskStepMeta(taskStepMeta); } //当前TaskStepFlow if (currentTaskStepFlow != null) { String currentKey = generateClassStepKey(currentTaskStepFlow.getClassName(), currentTaskStepFlow.getStepName()); TaskStepMeta currentTaskStepMeta = (TaskStepMeta) MapUtils .getObject(classStepTaskStepMetaMap, currentKey, new TaskStepMeta()); currentTaskStepFlow.setTaskStepMeta(currentTaskStepMeta); } } private String generateClassStepKey(String className, String stepName) { return className + "-" + stepName; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/TotalManageController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.MachineInfoEnum; import com.sohu.cache.dao.QuartzDao; import com.sohu.cache.dao.TaskQueueDao; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.task.constant.TaskQueueEnum.TaskStatusEnum; import com.sohu.cache.web.enums.StatEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.enums.TriggerStateEnum; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.Page; import com.sohu.cache.web.vo.AppDetailVO; import com.sohu.cache.web.vo.MachineStatsVo; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 全局统计 * * @author leifu * @Time 2014年10月14日 */ @Controller @RequestMapping("manage/total") public class TotalManageController extends BaseController { @Resource(name = "appStatsCenter") private AppStatsCenter appStatsCenter; @Resource private MachineCenter machineCenter; @Autowired private ResourceService resourceService; @Autowired private TaskQueueDao taskQueueDao; @Autowired private QuartzDao quartzDao; /** * 应用运维 */ @RequestMapping(value = "/list") public ModelAndView doTotalList(HttpServletRequest request, HttpServletResponse response, String appParam, Model model, AppSearch appSearch) { AppUser currentUser = getUserInfo(request); // 获取所有有效版本信息 List redisVersionList = resourceService.getResourceList(ResourceEnum.REDIS.getValue()); //appParam 判断是查询appid还是应用名称 if (!StringUtils.isEmpty(appParam)) { if (StringUtils.isNumeric(appParam)) { appSearch.setAppId(Long.parseLong(appParam)); } else { appSearch.setAppName(appParam); } } //分页 int totalCount = appService.getAppDescCount(currentUser, appSearch); int pageNo = NumberUtils.toInt(request.getParameter("pageNo"), 1); int pageSize = NumberUtils.toInt(request.getParameter("pageSize"), 20); Page page = new Page(pageNo, pageSize, totalCount); appSearch.setPage(page); List apps = appService.getAppDescList(currentUser, appSearch); List appDetailList = new ArrayList(); if (apps != null && apps.size() > 0) { for (AppDesc appDesc : apps) { AppDetailVO appDetail = appStatsCenter.getAppDetail(appDesc.getAppId()); appDetail.getAppDesc().setBackupType(appDesc.getBackupType()); appDetailList.add(appDetail); } } else { //如果没有查询结果 page.setTotalCount(0); } model.addAttribute("apps", apps); model.addAttribute("appDetailList", appDetailList); model.addAttribute("list", apps); model.addAttribute("appOperateActive", SuccessEnum.SUCCESS.value()); model.addAttribute("appParam", appParam); model.addAttribute("page", page); model.addAttribute("persistenceType", appSearch.getPersistenceType()); model.addAttribute("backupType", appSearch.getBackupType()); model.addAttribute("redisVersionList", redisVersionList); return new ModelAndView("manage/total/list"); } /** * 全局统计 */ @RequestMapping(value = "/statlist") public ModelAndView doStatList(HttpServletRequest request, HttpServletResponse response, Model model) { // 一.应用及内存统计 Map appTotalStat = appStatsCenter.getAppTotalStat(); model.addAttribute("totalRunningApps", MapUtils.getString(appTotalStat, StatEnum.TOTAL_EFFETIVE_APP.value(), "0")); model.addAttribute("totalMachineCount", MapUtils.getString(appTotalStat, StatEnum.TOTAL_MACHINE_NUM.value(), "0")); model.addAttribute("totalRunningInstance", MapUtils.getString(appTotalStat, StatEnum.TOTAL_INSTANCE_NUM.value(), "0")); model.addAttribute("redisTypeCount", MapUtils.getString(appTotalStat, StatEnum.REDIS_VERSION_COUNT.value())); model.addAttribute("redisDistributeList", MapUtils.getString(appTotalStat, StatEnum.REDIS_VERSION_DISTRIBUTE.value())); model.addAttribute("machineMemoryDistributeList", MapUtils.getString(appTotalStat, StatEnum.MACHINE_USEDMEMORY_DISTRIBUTE.value())); model.addAttribute("maxMemoryDistributeList", MapUtils.getString(appTotalStat, StatEnum.MACHINE_MAXMEMORY_DISTRIBUTE.value())); model.addAttribute("roomDistributeList", MapUtils.getString(appTotalStat, StatEnum.MACHIEN_ROOM_DISTRIBUTE.value())); List machineStatsVoList = machineCenter.getmachineStatsVoList(); int redisToolNum = machineCenter.getMachineNum(MachineInfoEnum.TypeEnum.REDIS_MIGRATE_TOOL.getType()); model.addAttribute("machineStatsVoList", machineStatsVoList); model.addAttribute("machineRedisCount", MapUtils.getInteger(appTotalStat, StatEnum.TOTAL_MACHINE_NUM.value(), 0)-redisToolNum); model.addAttribute("machineRedisToolCount", redisToolNum); //二、quartz相关 int triggerWaitingCount = quartzDao.getTriggerStateCount(TriggerStateEnum.WAITING.getState()); int triggerErrorCount = quartzDao.getTriggerStateCount(TriggerStateEnum.ERROR.getState()); int triggerPausedCount = quartzDao.getTriggerStateCount(TriggerStateEnum.PAUSED.getState()); int triggerAcquiredCount = quartzDao.getTriggerStateCount(TriggerStateEnum.ACQUIRED.getState()); int triggerBlockedCount = quartzDao.getTriggerStateCount(TriggerStateEnum.BLOCKED.getState()); int misfireCount = quartzDao.getMisFireTriggerCount(); int triggerTotalCount = triggerWaitingCount + triggerErrorCount + triggerPausedCount + triggerAcquiredCount + triggerBlockedCount; model.addAttribute("triggerWaitingCount", triggerWaitingCount); model.addAttribute("triggerErrorCount", triggerErrorCount); model.addAttribute("triggerPausedCount", triggerPausedCount); model.addAttribute("triggerAcquiredCount", triggerAcquiredCount); model.addAttribute("triggerBlockedCount", triggerBlockedCount); model.addAttribute("misfireCount", misfireCount); model.addAttribute("triggerTotalCount", triggerTotalCount); //三、任务相关 int newTaskCount = taskQueueDao.getStatusCount(TaskStatusEnum.NEW.getStatus()); int runningTaskCount = taskQueueDao.getStatusCount(TaskStatusEnum.RUNNING.getStatus()); int abortTaskCount = taskQueueDao.getStatusCount(TaskStatusEnum.ABORT.getStatus()); int successTaskCount = taskQueueDao.getStatusCount(TaskStatusEnum.SUCCESS.getStatus()); int totalTaskCount = newTaskCount + runningTaskCount + abortTaskCount + successTaskCount; model.addAttribute("newTaskCount", newTaskCount); model.addAttribute("runningTaskCount", runningTaskCount); model.addAttribute("abortTaskCount", abortTaskCount); model.addAttribute("successTaskCount", successTaskCount); model.addAttribute("totalTaskCount", totalTaskCount); model.addAttribute("totalActive", SuccessEnum.SUCCESS.value()); return new ModelAndView("manage/totalstat/list"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/TriggerController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.util.ObjectConvert; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Controller; import org.springframework.util.Assert; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; /** * trigger操作 * @author leifu * @Date 2014年05月19日 * @Time 下午5:15:36 */ @Controller @RequestMapping(value = "/cache/triggers") public class TriggerController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired(required = false) @Qualifier("clusterScheduler") private Scheduler scheduler; @RequestMapping(value = "/pause/{appId}/{type}/{host}/{port}") public void pauseTrigger(@PathVariable long appId, @PathVariable int type, @PathVariable String host, @PathVariable int port) { Assert.isTrue(appId > 0); Assert.isTrue(type > 0); Assert.hasText(host); Assert.isTrue(port > 0); String triggerName = ObjectConvert.linkIpAndPort(host, port); String triggerGroup = ""; TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup); try { scheduler.pauseTrigger(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } logger.info("trigger with name: {}, group: {} is paused", port, host); } @RequestMapping(value = "/resume/{appId}/{type}/{host}/{port}") public void resumeTrigger(@PathVariable long appId, @PathVariable int type, @PathVariable String host, @PathVariable int port) { Assert.isTrue(appId > 0); Assert.isTrue(type > 0); Assert.hasText(host); Assert.isTrue(port > 0); String triggerName = ObjectConvert.linkIpAndPort(host, port); String triggerGroup = ""; TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup); try { scheduler.resumeTrigger(triggerKey); } catch (SchedulerException e) { logger.error(e.getMessage(), e); } logger.info("trigger with name: {}, group: {} is resumed", port, host); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/UserController.java ================================================ package com.sohu.cache.web.controller; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sohu.cache.entity.AppBiz; import com.sohu.cache.utils.EnvCustomUtil; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.sohu.cache.constant.AppAuditType; import com.sohu.cache.entity.AppAudit; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.AppEmailUtil; import java.util.List; /** * 注册用户管理(页面没有权限限制) * * @author leifu * @Date 2014年10月28日 * @Time 上午10:49:32 */ @Controller @RequestMapping("/user") public class UserController extends BaseController{ @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; /** * 注册用户页面 */ @RequestMapping(value = "/register") public ModelAndView userRegister(HttpServletRequest request, HttpServletResponse response, Model model, Integer success) { List bizList = userService.getBizList(); model.addAttribute("success", success); model.addAttribute("bizList", bizList); model.addAttribute("pwdswitch", EnvCustomUtil.pwdswitch); return new ModelAndView("user/userRegister"); } /** * 注册用户申请 */ @RequestMapping(value = "/apply") public ModelAndView doAddUser(HttpServletRequest request, HttpServletResponse response, Model model, String name, String chName, String email, String mobile, String weChat, Integer type, Long userId, Integer isAlert, String password, String company, String purpose, Long bizId) { SuccessEnum success = SuccessEnum.SUCCESS; try { //保存用户(type=-1为无效用户,需要审批) AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, weChat, type, isAlert, password, company, purpose, bizId); userService.save(appUser); //提交审批 AppAudit appAudit = appService.saveRegisterUserApply(appUser,AppAuditType.REGISTER_USER_APPLY); appEmailUtil.noticeUserResult(appUser, appAudit); } catch (Exception e) { success = SuccessEnum.FAIL; logger.error(e.getMessage(), e); } return new ModelAndView("redirect:/user/register?success=" + success.value()); } @RequestMapping(value = "/checkUserNameExist") public ModelAndView doCheckUserNameExist(HttpServletRequest request, HttpServletResponse response, Model model, String userName) { AppUser appUser = userService.getByName(userName); if (appUser != null) { write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } else { write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/UserManageController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.AppUserTypeEnum; import com.sohu.cache.entity.AppAudit; import com.sohu.cache.entity.AppBiz; import com.sohu.cache.entity.AppUser; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.utils.EnvCustomUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.util.AppEmailUtil; import com.sohu.cache.web.vo.AppUserVo; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * 用户信息管理 * * @author leifu * @Time 2014年6月6日 */ @Controller @RequestMapping("manage/user") public class UserManageController extends BaseController { @Resource(name = "appEmailUtil") private AppEmailUtil appEmailUtil; /** * 用户初始化 * * @param id 用户id * @return */ @RequestMapping(value = "/init") public ModelAndView doUserInit(HttpServletRequest request, HttpServletResponse response, Model model, Long id) { if (id != null) { AppUser user = userService.get(id); model.addAttribute("user", user); model.addAttribute("modify", true); } return new ModelAndView("manage/user/initUser"); } /** * 更新用户 * * @param name * @param chName * @param email * @param mobile * @param weChat * @param type * @param userId * @return */ @RequestMapping(value = "/add") public ModelAndView doAddUser(HttpServletRequest request, HttpServletResponse response, Model model, String name, String chName, String email, String mobile, String weChat, Integer type, Long userId, Integer isAlert, String company, String purpose, Long bizId) { // 后台暂时不对参数进行验证 AppUser appUser = AppUser.buildFrom(userId, name, chName, email, mobile, weChat, type, isAlert, company, purpose, bizId); try { if (userId == null) { appUser.setPassword(ConstUtils.DEFAULT_USER_PASSWORD); userService.save(appUser); } else { userService.update(appUser); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { write(response, String.valueOf(SuccessEnum.FAIL.value())); logger.error(e.getMessage(), e); } return null; } /** * 删除用户 * * @param userId * @return */ @RequestMapping(value = "/delete") public ModelAndView doDeleteUser(HttpServletRequest request, HttpServletResponse response, Model model, Long userId) { userService.delete(userId); return new ModelAndView("redirect:/manage/user/list"); } /** * 重置密码 * * @param userId * @return */ @RequestMapping(value = "/resetPwd") public ModelAndView doResetUserPwd(HttpServletRequest request, HttpServletResponse response, Model model, Long userId) { userService.resetPwd(userId); return new ModelAndView("redirect:/manage/user/list"); } /** * 修改密码 * * @param userId * @return */ @RequestMapping(value = "/updatePwd") public ModelAndView doResetUserPwd(HttpServletRequest request, HttpServletResponse response, Model model, Long userId, String password) { SuccessEnum successEnum = userService.updatePwd(userId, password); if(successEnum.equals(SuccessEnum.SUCCESS)){ write(response, String.valueOf(SuccessEnum.SUCCESS.value())); }else{ write(response, String.valueOf(SuccessEnum.FAIL.value())); } return null; } /** * 用户列表 * * @param searchChName 中文名 * @return */ @RequestMapping(value = "/list") public ModelAndView doUserList(HttpServletRequest request, HttpServletResponse response, Model model, String searchChName, String searchBizName) { //获取tab int tabId = NumberUtils.toInt(request.getParameter("tabId"), 1); model.addAttribute("tabId", tabId); if(tabId == 1){ List users = userService.getUserWithBizList(searchChName, searchBizName); model.addAttribute("users", users); model.addAttribute("searchChName", searchChName); model.addAttribute("searchBizName", searchBizName); } List bizList = userService.getBizList(); model.addAttribute("bizList", bizList); if(tabId == 2){ } model.addAttribute("userActive", SuccessEnum.SUCCESS.value()); model.addAttribute("pwdswitch", EnvCustomUtil.pwdswitch); return new ModelAndView("manage/user/list"); } @RequestMapping(value = "/addAuditStatus") public ModelAndView doAddAuditStatus(HttpServletRequest request, HttpServletResponse response, Model model, Integer status, Integer type, Long appAuditId, String refuseReason, Long appId) { AppAudit appAudit = appService.getAppAuditById(appAuditId); AppUser appUser = userService.get(appAudit.getUserId()); // 通过或者驳回并记录日志 appService.updateUserAuditStatus(appAuditId, status, appUser.getId()); // 记录驳回原因 if (AppCheckEnum.APP_REJECT.value().equals(status)) { appAudit.setRefuseReason(refuseReason); appService.updateRefuseReason(appAudit, getUserInfo(request)); userService.delete(appUser.getId()); } // 发邮件统计 if (AppCheckEnum.APP_PASS.value().equals(status) || AppCheckEnum.APP_REJECT.value().equals(status)) { appUser.setType(AppUserTypeEnum.REGULAR_USER.value()); appAudit.setStatus(status); userService.update(appUser); appEmailUtil.noticeUserResult(appUser, appAudit); } // 批准成功直接跳转 if (AppCheckEnum.APP_PASS.value().equals(status)) { return new ModelAndView("redirect:/manage/app/auditList"); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return null; } /** * 更新业务组 * * @param toRemoverUserName * @param toChargeUserName * @return */ @RequestMapping(value = "/takeover") public void doTakeover(HttpServletRequest request, HttpServletResponse response, String toRemoverUserName, String toChargeUserName) { if(StringUtils.isNotBlank(toRemoverUserName) && StringUtils.isNotBlank(toChargeUserName) && !toRemoverUserName.equals(toChargeUserName)){ try { AppUser toRemoverUser = userService.getByName(toRemoverUserName); AppUser toChargeUser = userService.getByName(toChargeUserName); if(toRemoverUser != null && toChargeUser != null && toRemoverUser != toChargeUser){ SuccessEnum successEnum = userService.takeoverUser(toRemoverUser, toChargeUser); if(successEnum.equals(SuccessEnum.SUCCESS)){ write(response, String.valueOf(SuccessEnum.SUCCESS.value())); return; } } } catch (Exception e) { logger.error(e.getMessage(), e); } } write(response, String.valueOf(SuccessEnum.FAIL.value())); } /** * 根据id删除业务组 * * @return */ @RequestMapping(value = "/biz/delete") public ModelAndView doUserBizList(HttpServletRequest request, HttpServletResponse response, Model model, Long bizId, Integer tabId) { userService.deleteBiz(bizId); if(tabId == null){ tabId = 1; } return new ModelAndView("redirect:/manage/user/list?tabId=" + tabId); } /** * 更新业务组 * * @param name * @param bizDesc * @return */ @RequestMapping(value = "/biz/add") public ModelAndView doAddBiz(HttpServletRequest request, HttpServletResponse response, Model model, String name, String bizDesc, Long bizId) { // 后台暂时不对参数进行验证 AppBiz appBiz = AppBiz.of(name, bizDesc); try { if (bizId == null) { userService.saveBiz(appBiz); } else { appBiz.setId(bizId); userService.updateBiz(appBiz); } write(response, String.valueOf(SuccessEnum.SUCCESS.value())); } catch (Exception e) { write(response, String.valueOf(SuccessEnum.FAIL.value())); logger.error(e.getMessage(), e); } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/WebResourceController.java ================================================ package com.sohu.cache.web.controller; import com.sohu.cache.util.ConstUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 前端页面相关基础资源 * * @author zengyizhao * @Time 2023年7月3日 */ @Controller @RequestMapping("/web/resource") public class WebResourceController extends BaseController { private Logger logger = LoggerFactory.getLogger(WebResourceController.class); /** * 初始化贡献者页面 * * @return */ @RequestMapping("/{path}/{filename}") public ModelAndView doInitBecomeContributor(@PathVariable String path, @PathVariable String filename, HttpServletRequest request, HttpServletResponse response, Model model) { if(("inc".equals(path) && "daily".equals(filename)) || ("inc".equals(path) && "contact".equals(filename))){ model.addAttribute("contact", ConstUtils.CONTACT); } return new ModelAndView(path + "/" + filename); } /** * 初始化贡献者页面 * * @return */ @RequestMapping("/noPower") public ModelAndView redirectNoPower(@RequestParam("appId") String appId, Model model, HttpServletRequest request, HttpServletResponse response) { model.addAttribute("appId", appId); return new ModelAndView("noPower"); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/controller/WikiController.java ================================================ package com.sohu.cache.web.controller; import com.vladsch.flexmark.ext.tables.TablesExtension; import com.vladsch.flexmark.html.HtmlRenderer; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.parser.ParserEmulationProfile; import com.vladsch.flexmark.util.ast.Document; import com.vladsch.flexmark.util.builder.Extension; import com.vladsch.flexmark.util.options.MutableDataSet; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import java.io.InputStream; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Map; @Controller @RequestMapping("/wiki") public class WikiController extends BaseController { @RequestMapping("/{path}/{filename}") public String subPages(@PathVariable String path, @PathVariable String filename, @RequestParam(required = false) String entry, Map map) throws Exception { String html = markdown2html(path + "/" + filename, ".md"); //html = html.replace("${version}", "1.0.0"); // toc String toc = markdown2html(path + "/" + filename, ".toc.md"); if (toc != null) { map.put("toc", toc); } map.put("response", html); if (entry != null && entry.equals("client") && "client".equals(filename)) { return "wikiAccessClientTemplate"; } return "wikiTemplate"; } public String markdown2html(String filename, String suffix) throws Exception { String templatePath = "static/wiki/" + filename + suffix; InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templatePath); if (inputStream == null) { return null; } String markdown = new String(read(inputStream), Charset.forName("utf-8")); MutableDataSet options = new MutableDataSet(); options.setFrom(ParserEmulationProfile.MARKDOWN); options.set(Parser.EXTENSIONS, Arrays.asList(new Extension[]{TablesExtension.create()})); Document document = Parser.builder(options).build().parse(markdown); String html = HtmlRenderer.builder(options).build().render(document); return html; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/AdminEnum.java ================================================ package com.sohu.cache.web.enums; /** * 管理员 * * @author leifu * @Time 2014年10月16日 */ public enum AdminEnum { IS_ADMIN(1), // 是管理员 NOT_ADMIN(0); // 不是管理员 int value; private AdminEnum(int value) { this.value = value; } public int value() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/AlertTypeEnum.java ================================================ package com.sohu.cache.web.enums; import java.util.HashMap; import java.util.Map; /** * @Author: zengyizhao * @DateTime: 2021/9/3 14:40 * @Description: 邮件报警类型枚举 */ public enum AlertTypeEnum { INSTANCE_RUNNING_STATE_CHANGE(1, "实例运行状态变更", 1, 1), INATANCE_EXCEPTION_STATE_MONITOR(2, "实例状态异常监控", 1, 1), MACHINE_MEMORY_OVER_PRESET(3, "机器内存报警", 1, 2), INSTANCE_MINUTE_MONITOR(4, "实例分钟报警", 1, 0), POD_RESTART_SYNC_TASK(5, "Pod重启机器同步任务报警", 1, 1), POD_RESTART_INSTANCE_RECOVER(6, "Pod重启探测Redis实例报警", 1, 1), MACHINE_MANAGE(7, "机器管理", 1, 1), APP_MINUTE_MONITOR(8, "实例分钟报警", 1, 0), APP_CLIENT_CONNECTION(9, "应用客户端连接数报警", 0, 2), APP_SHARD_CLENT_CONNECTION(10, "应用实例-分片客户端连接数报警", 0, 2), APP_HIT_RATIO(11, "应用平均命中率报警", 0, 2), APP_MEM_USED_RATIO(12, "应用内存使用率报警", 0, 2), APP_SHARD_MEM_USED_RATIO(13, "分片内存使用率报警", 0, 2), MACHINE_DISK_OVER_PRESET(14, "机器磁盘报警", 1, 2), APP_DISK_USED_RATIO(15, "应用磁盘使用率报警", 0, 2), APP_SHARD_DISK_USED_RATIO(16, "分片磁盘使用率报警", 0, 2); private int type;//邮件类型 private String info;//邮件类型信息 private int visibleType;//可见类型(0:均可见;1:仅管理员可见;) private int importantLevel;//重要类型(0:一般;1:重要;2:紧急) private static Map MAP = new HashMap(); static { for (AppTypeEnum appTypeEnum : AppTypeEnum.values()) { MAP.put(appTypeEnum.getType(), appTypeEnum); } } AlertTypeEnum(int type, String info, int visibleType, int importantLevel) { this.type = type; this.info = info; this.visibleType = visibleType; this.importantLevel = importantLevel; } public static AppTypeEnum getByType(int type) { return MAP.get(type); } public int getType() { return type; } public String getInfo() { return info; } public int getVisibleType() { return visibleType; } public int getImportantLevel() { return importantLevel; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/AppImportStatusEnum.java ================================================ package com.sohu.cache.web.enums; /** * @Author: rucao * @Date: 2021/1/11 下午5:45 */ public enum AppImportStatusEnum { PREPARE(0, "准备", "应用导入-未开始"), START(1, "进行中...", "应用导入-开始"), ERROR(2, "error", "应用导入-出错"), VERSION_BUILD_START(11, "进行中...", "新建redis版本-进行中"), VERSION_BUILD_ERROR(12, "error", "新建redis版本-出错"), VERSION_BUILD_END(20, "成功", "新建redis版本-完成"), APP_BUILD_INIT(21, "准备就绪", "新建redis应用-准备就绪"), APP_BUILD_START(22, "进行中...", "新建redis应用-进行中"), APP_BUILD_ERROR(23, "error", "新建redis应用-出错"), APP_BUILD_END(30, "成功", "新建redis应用-完成"), MIGRATE_INIT(31, "准备就绪", "数据迁移-准备就绪"), MIGRATE_START(32, "进行中...", "数据迁移-进行中"), MIGRATE_ERROR(33, "error", "数据迁移-出错"), MIGRATE_END(3, "成功", "应用导入-成功"), ; private int status; private String desc; private String info; AppImportStatusEnum(int status, String desc, String info) { this.status = status; this.desc = desc; this.info = info; } public int getStatus() { return status; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/AppOrderByEnum.java ================================================ package com.sohu.cache.web.enums; /** * app列表排序 * @Date 2014年11月14日 * @Time 上午10:55:47 */ public enum AppOrderByEnum { HIT_PERCENTAGE_HIGH_TO_LOW("hit_percentage_high_to_low"), HIT_PERCENTAGE_LOW_TO_HIGH("hit_percentage_low_to_high"); private String value; private AppOrderByEnum(String value) { this.value = value; } public String getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/AppTypeEnum.java ================================================ package com.sohu.cache.web.enums; import java.util.HashMap; import java.util.Map; /** * 应用类型 */ public enum AppTypeEnum { TWEMPROXY(1, "twemproxy"), REDIS_CLUSTER(2, "Redis-Cluster"), CODIS(3, "codis"), PIKA(4, "pika"), REDIS_SENTINEL(5, "Redis-Sentinel"), REDIS_STANDALONE(6, "Redis-Standalone"), MEMCACHED(7, "memcached"), PIKA_SENTINEL(8, "pika-sentinel"); private int type; private String info; private static Map MAP = new HashMap(); static { for (AppTypeEnum appTypeEnum : AppTypeEnum.values()) { MAP.put(appTypeEnum.getType(), appTypeEnum); } } AppTypeEnum(int type, String info) { this.type = type; this.info = info; } public static AppTypeEnum getByType(int type) { return MAP.get(type); } public int getType() { return type; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/BooleanEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by rucao on 2020/1/17 */ public enum BooleanEnum { OTHER(-1), FALSE(0), TRUE(1); int value; BooleanEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/CheckEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by chenshi on 2021/1/12. */ public enum CheckEnum { //正常 CONSISTENCE(1), //异常 INCONSISTENCE(2), // EXCEPTION(3); private int value; CheckEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/ClientTypeEnum.java ================================================ package com.sohu.cache.web.enums; /** * @Author: rucao * @Date: 2020/5/13 5:35 下午 */ public enum ClientTypeEnum { A("A", " 尽可能快地关闭连接"), b("b", " 客户端正在等待阻塞事件"), c("c", " 在将回复完整地写出之后,关闭链接"), d("d", " 一个受监视(watched)的键已被修改,EXEC命令将失败"), i("i", " 客户端正在等待VM I/O操作(已废弃)"), M("M", " master客户端"), N("N", " 普通客户端"), O("O", " 客户端是MONITOR模式下的附属节点(slave)"), P("P", " Pub/Sub客户端"), r("r", " 客户端是只读模式的集群节点"), S("S", " slave客户端"), u("u", " 客户端未被阻塞(unblocked)"), U("U", " 通过Unix套接字连接的客户端"), x("x", " 客户端正在执行事务"), Method("method", "method"); private final String flags; private final String desc; ClientTypeEnum(String flags, String desc) { this.flags = flags; this.desc = desc; } public String getFlags() { return flags; } public String getDesc() { return desc; } public String getDesc(String flags) { for (ClientTypeEnum e : ClientTypeEnum.values()) { if (e.flags.equals(flags)) { return e.flags + ":" + e.desc; } } return flags; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/CompareTypeEnum.java ================================================ package com.sohu.cache.web.enums; import java.util.HashMap; import java.util.Map; /** * @Author: zengyizhao * @DateTime: 2021/9/27 14:40 * @Description: 比较类型-redis配置项检测 */ public enum CompareTypeEnum { EQUAL(1, "等于"), NOT_EQUAL(2, "不等于"), LESS_THAN(3, "小于"), MORE_THAN(4, "大于"); private int type;//比较类型 private String info;//比较类型说明 private static Map MAP = new HashMap(); static { for (CompareTypeEnum compareTypeEnum : CompareTypeEnum.values()) { MAP.put(compareTypeEnum.getType(), compareTypeEnum); } } CompareTypeEnum(int type, String info) { this.type = type; this.info = info; } public static CompareTypeEnum getByType(int type) { return MAP.get(type); } public int getType() { return type; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/ConfigRestartOperateEnum.java ================================================ package com.sohu.cache.web.enums; /** * @Author: zengyizhao * @DateTime: 2021/11/16 16:10 * @Description: 配置、重启操作类型 */ public enum ConfigRestartOperateEnum { /** * 操作类型(0:滚动重启,1:修改配置强制重启;2:修改配置) */ RESTART(0), CONFIG_RESTART(1), CONFIG(2); private int value; ConfigRestartOperateEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/DeployInfoEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by rucao on 2018/10/12 */ public enum DeployInfoEnum { SUCCESS("success"), EMPTY("empty:error"), EXCEPTION("exception:error"), PARAM_ERROR("param:error"), MACHINE_NUM_ERROR("machine_num:error"); private String value; DeployInfoEnum(String value) { this.value = value; } public String getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/ExamToolEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by rucao on 2019/1/29 */ public enum ExamToolEnum { EXAM_ALL(0,"exam_all"), EXAM_NON_TEST(1,"exam_non_test"), EXAM_LIST(2,"exam_appid_list"), EXAM_APPID(3,"exam_appid"); private final int value; private final String examTypeStr; ExamToolEnum (int value,String examTypeStr){ this.value=value; this.examTypeStr=examTypeStr; } public int getValue(){ return this.value; } public String getExamTypeStr(){ return this.examTypeStr; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/ImportantLevelTypeEnum.java ================================================ package com.sohu.cache.web.enums; import java.util.ArrayList; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/22 13:34 * @Description: 报警重要程度配置 */ public enum ImportantLevelTypeEnum { NORMAL(0, "一般"), IMPORTANT(1, "重要"), URGENT(2, "紧急"); private final static List instanceAlertTypeEnumList = new ArrayList(); static { for (ImportantLevelTypeEnum instanceAlertTypeEnum : ImportantLevelTypeEnum.values()) { instanceAlertTypeEnumList.add(instanceAlertTypeEnum); } } private int type; private String info; private ImportantLevelTypeEnum(int type, String info) { this.type = type; this.info = info; } public int getType() { return type; } public String getInfo() { return info; } public static String getInfoByType(int type){ for(ImportantLevelTypeEnum importantLevelTypeEnum: instanceAlertTypeEnumList){ if(importantLevelTypeEnum.getType() == type){ return importantLevelTypeEnum.getInfo(); } } return ImportantLevelTypeEnum.NORMAL.getInfo(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/LoginEnum.java ================================================ package com.sohu.cache.web.enums; /** * 登录状态 * * @author leifu * @Time 2014年10月16日 */ public enum LoginEnum { LOGIN_SUCCESS(1), // 成功 LOGIN_WRONG_USER_OR_PASSWORD(0), // 用户名或者密码错误 LOGIN_USER_NOT_EXIST(-1), // 不是cachecloud用户 LOGIN_NOT_ADMIN(-2);// 不是超级管理员 int value; private LoginEnum(int value) { this.value = value; } public int value() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/MachineMemoryDistriEnum.java ================================================ package com.sohu.cache.web.enums; import com.sohu.cache.util.NumberUtil; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 机器内存使用或分配区间 */ public enum MachineMemoryDistriEnum { BETWEEN_0_TO_1_PERCENT("0_1", "0-1%", 2), BETWEEN_1_TO_10_PERCENT("1_10", "1-10%", 3), BETWEEN_10_TO_25_PERCENT("10_25", "10-25%", 4), BETWEEN_25_TO_50_PERCENT("25_50", "25-50%", 5), BETWEEN_50_TO_75_PERCENT("50_75", "50-75%", 6), BETWEEN_75_TO_100_PERCENT("75_90", "75-90%", 7), BETWEEN_90_TO_100_PERCENT("90_100", "90-100%", 8), BETWEEN_100_TO_1000_PERCENT("100_1000", "100%以上", 9); public final static Map MAP; static { Map tmpMap = new HashMap<>(); for (MachineMemoryDistriEnum enumObject : MachineMemoryDistriEnum.values()) { tmpMap.put(enumObject.getValue(), enumObject); } MAP = Collections.unmodifiableMap(tmpMap); } private String value; private String info; private int type; private MachineMemoryDistriEnum(String value, String info, int type) { this.value = value; this.info = info; this.type = type; } public static MachineMemoryDistriEnum getByValue(String targetValue) { return MAP.get(targetValue); } /** * @param percent * @return */ public static MachineMemoryDistriEnum getRightPercentDistri(int percent) { MachineMemoryDistriEnum[] enumArr = MachineMemoryDistriEnum.values(); for (MachineMemoryDistriEnum enumObject : enumArr) { if (isInSize(enumObject, percent)) { return enumObject; } } return null; } /** * @param enumObject * @return */ private static boolean isInSize(MachineMemoryDistriEnum enumObject, long costTime) { String value = enumObject.getValue(); int index = value.indexOf("_"); int start = NumberUtil.toInt(value.substring(0, index)); int end = NumberUtil.toInt(value.substring(index + 1)); if (costTime >= start && costTime < end) { return true; } return false; } public String getValue() { return value; } public String getInfo() { return info; } public int getType() { return type; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/MachineTaskEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by chenshi on 2019/5/28. */ public enum MachineTaskEnum { //未同步 UNSYNC(0), //已同步 SYNCED(1), //同步中 SYNCING(-1), //同步失败 SYNC_FAILED(-2); private int value; MachineTaskEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/MasterSlaveExistEnum.java ================================================ package com.sohu.cache.web.enums; import java.util.HashMap; import java.util.Map; /** * 应用类型 */ public enum MasterSlaveExistEnum { NONE(0, "no master or slave"), MASTER(1, "only master"), SLAVE(2, "only slave"), MASTRE_SLAVE(3, "both master and slave"); private int type; private String info; private static Map MAP = new HashMap(); static { for (MasterSlaveExistEnum appTypeEnum : MasterSlaveExistEnum.values()) { MAP.put(appTypeEnum.getType(), appTypeEnum); } } MasterSlaveExistEnum(int type, String info) { this.type = type; this.info = info; } public static MasterSlaveExistEnum getByType(int type) { return MAP.get(type); } public int getType() { return type; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/NodeEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by chenshi on 2019/4/19. */ public enum NodeEnum { REDIS_NODE(1), SENTINEL_NODE(2), TWEMPROXY_NODE(3), PIKA_NODE(4); private int value; private NodeEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/PodStatusEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by chenshi on 2019/5/21. */ public enum PodStatusEnum { OFFLINE(0),ONLINE(1); private int value; PodStatusEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/RedisOperateEnum.java ================================================ package com.sohu.cache.web.enums; /** * * @author leifu * @Date 2016年1月12日 * @Time 下午2:28:25 */ public enum RedisOperateEnum { OP_SUCCESS(1), ALREADY_SUCCESS(2), FAIL(0); private int value; private RedisOperateEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/RedisVersionEnum.java ================================================ package com.sohu.cache.web.enums; /** * Created by chenshi on 2018/8/23. */ public enum RedisVersionEnum { Redis3_0_7(1), // Redis3_2(2), // Redis4_0(3); Not_bind(0), Is_bind(1), Redis_installed(1), Redis_uninstalled(0), Redis_installException(-1); private int value; private RedisVersionEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/RestartStatusEnum.java ================================================ package com.sohu.cache.web.enums; /** * @Author: zengyizhao * @DateTime: 2021/9/13 16:10 * @Description: */ public enum RestartStatusEnum { /** * 状态:0等待,1运行,2成功,3失败,4配置修改待重启 */ WAITING(0), RUNNING(1), SUCCESS(2), FAIL(3), NEED_RESTART(4), RESTART_AFTER_CONFIG(5), INTERUPT(6); private int value; RestartStatusEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/SshAuthTypeEnum.java ================================================ package com.sohu.cache.web.enums; /** * ssh授权方式 * @author leifu * @date 2018年6月15日 * @time 下午5:56:59 */ public enum SshAuthTypeEnum { PASSWORD(1, "用户密码"), PUBLIC_KEY(2, "公钥"); private int value; private String info; private SshAuthTypeEnum(int value, String info) { this.value = value; this.info = info; } public int getValue() { return value; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/StatEnum.java ================================================ package com.sohu.cache.web.enums; /** *

* Description:后台管理总览相关统计参数 *

* @author chenshi * @version 1.0 * @date 2017/8/14 * @param * @return */ public enum StatEnum { /** * 基础统计: * 1.在线应用数 * 2.在线实例数 * 3.在线机器数 * 4.Redis版本数量 */ TOTAL_EFFETIVE_APP("effetiveAppCount"), TOTAL_INSTANCE_NUM("totalInstanceCount"), TOTAL_MACHINE_NUM("totalMachineCount"), TOTAL_PHYSICAL_MACHINE_NUM("totalPhysicalMachineCount"), REDIS_VERSION_COUNT("redisTypeCount"), /** * 分布统计: * 1.Redis版本分布与统计 * 2.机器内存统计 * 3.实例内存统计 * 4.按机房内存统计 */ REDIS_VERSION_DISTRIBUTE("redisDistribute"), MACHINE_MAXMEMORY_DISTRIBUTE("maxMemoryDistrubute"), MACHINE_USEDMEMORY_DISTRIBUTE("usedMemoryDistribute"), MACHIEN_ROOMMEMORY_DISTRIBUTE("roomMemoryDistribute"), MACHIEN_ROOM_DISTRIBUTE("roomDistribute"); String value; private StatEnum(String value) { this.value = value; } public String value() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/SuccessEnum.java ================================================ package com.sohu.cache.web.enums; /** * 成功失败状态 * * @author leifu * @Time 2014年10月16日 */ public enum SuccessEnum { ERROR(-1), SUCCESS(1), FAIL(0), REPEAT(2), NO_REPEAT(4), INSTALLED(3); int value; private SuccessEnum(int value) { this.value = value; } public int value() { return value; } public String info() { if (value == 3) { return "已安装"; }else if (value == 2) { return "重复插入"; }else if (value == 4) { return "不重复"; } else if (value == 1) { return "成功"; } else if (value == -1) { return "错误"; } else { return "失败"; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/TriggerStateEnum.java ================================================ package com.sohu.cache.web.enums; /** * @author fulei * @date 2018年8月8日 * @time 下午3:29:48 */ public enum TriggerStateEnum { WAITING("WAITING", "等待"), ACQUIRED("ACQUIRED", "正常运行"), PAUSED("PAUSED", "暂停"), BLOCKED("BLOCKED", "阻塞"), ERROR("ERROR", "错误"); private String state; private String info; private TriggerStateEnum(String state, String info) { this.state = state; this.info = info; } public String getState() { return state; } public String getInfo() { return info; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/UseTypeEnum.java ================================================ package com.sohu.cache.web.enums; /** * @Description: 机器部署类型 * @Author: caoru * @CreateDate: 2018/10/8 18:32 */ public enum UseTypeEnum { Machine_special(0), Machine_test(1), Machine_mix(2); private int value; private UseTypeEnum(int value) { this.value = value; } public int getValue() { return value; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/enums/WebClients.java ================================================ package com.sohu.cache.web.enums; import java.util.ArrayList; import java.util.List; /** * @Author: rucao * @Date: 2020/5/19 3:59 下午 */ public class WebClients { public static List webClientIpList = new ArrayList<>(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppAlertRecordService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppAlertRecord; import com.sohu.cache.web.enums.AlertTypeEnum; import java.util.List; /** * 保存报警信息 * @author zengyizhao * @Date 2021年9月3日 */ public interface AppAlertRecordService { /** * 保存报警信息 * * @param appAlertRecord * @return */ int saveAlertInfo(AppAlertRecord appAlertRecord); /** * 批量保存报警信息 * @param appAlertRecordList * @return */ int saveBatchAlertInfo(List appAlertRecordList); /** * 异步保存报警信息 * * @param appAlertRecord * @return */ void asyncSaveAlertInfo(AppAlertRecord appAlertRecord); /** * 异步批量保存报警信息 * @param appAlertRecordList * @return */ void asyncSaveBatchAlertInfo(List appAlertRecordList); /** * 根据报警类型,保存报警信息 * @param type 类型 * @param title 邮件标题 * @param message 邮件内容 * @param object * @return */ int saveAlertInfoByType(AlertTypeEnum type, String title, String message, Object... object); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppAutoCapacityService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppCapacityMonitor; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import java.util.Map; /** * 容量监控 * @author zengyizhao * @Date 2022年10月9日 */ public interface AppAutoCapacityService { /** * 检查是否需自动扩容,并扩容处理 * * @param appDesc * @param appMemUsePercent * @param instanceStatsMap * @return */ void checkAndExpandCapacity(AppDesc appDesc, int appMemUsePercent, Map instanceStatsMap); void updateAppCapacityMonitor(AppCapacityMonitor appCapacityMonitor); void updateAppMemUsedHistory(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppImportService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppImport; import java.util.List; /** * @Author: rucao * @Date: 2021/1/8 上午10:48 */ public interface AppImportService { List getImportAppList(Integer status); int save(AppImport appImport); int update(AppImport appImport); AppImport appImport(Long id); AppImport get(Long id); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppRedisCommandCheckService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.vo.*; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/26 17:24 * @Description: redis命令检测 */ public interface AppRedisCommandCheckService { RedisCommandCheckResult checkRedisCommand(AppUser appUser, AppRedisCommandCheckVo appRedisCommandCheckVo); void saveRedisCommandCheckResult(RedisCommandCheckResult redisCommandCheckResult, AppRedisCommandCheckResult resultList); List getRedisCommandCheckResult(); AppRedisCommandCheckResult getRedisCommandCheckDetailResult(String uuid); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppRedisConfigCheckService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.vo.AppRedisConfigCheckResult; import com.sohu.cache.web.vo.AppRedisConfigCheckVo; import com.sohu.cache.web.vo.RedisConfigCheckResult; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/26 17:24 * @Description: redis配置检测 */ public interface AppRedisConfigCheckService { RedisConfigCheckResult checkRedisConfig(AppUser appUser, AppRedisConfigCheckVo configCheckVo); void saveRedisConfigCheckResult(RedisConfigCheckResult redisConfigCheckResult, List resultList); List getRedisConfigCheckResult(); List getRedisConfigCheckDetailResult(String uuid); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppScrollRestartService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.ConfigRestartRecord; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.web.enums.RestartStatusEnum; import com.sohu.cache.web.vo.AppRedisConfigVo; import com.sohu.cache.web.vo.ExecuteResult; import org.springframework.ui.Model; import java.util.List; import java.util.Map; import java.util.Optional; /** * @Author: zengyizhao * @DateTime: 2021/9/13 16:09 * @Description: 应用滚动重启修改配置 */ public interface AppScrollRestartService { /** * 处理应用实例信息(封装主从信息) * @param instanceInfoList * @param appDesc */ boolean handleAppInstanceInfo(List instanceInfoList, AppDesc appDesc); /** * 根据主节点分组 * @param instanceList * @return */ Map> instanceGroupByMaster(List instanceList); /** * 根据用户信息,应用信息,重启请求信息,操作类型生成重启记录并保存 * @param appUser * @param appDesc * @param paramObj * @param opertateType * @return */ long generateAndSaveConfigRestartRecord(AppUser appUser, AppDesc appDesc, Object paramObj, Integer opertateType, List pointedInstanceList); /** * 保存重启记录 * @param configRestartRecord */ void saveConfigRestartRecord(ConfigRestartRecord configRestartRecord); /** * 更新重启记录 * @param configRestartRecord */ void updateConfigRestartRecord(ConfigRestartRecord configRestartRecord); /** * 更新修改配置、重启记录 * @param recordId * @param restartStatusEnum * @param lastLog */ void updateConfigRestartRecord(long recordId, RestartStatusEnum restartStatusEnum, String... lastLog); /** * 查询重启记录 * @param id * @return */ ConfigRestartRecord getConfigRestartRecord(long id); /** * 查询重启记录及信息 * @param configRestartRecord * @return */ List getConfigRestartRecordByCondition(Model model, ConfigRestartRecord configRestartRecord, int pageNo, int pageSize); /** * 保存过程日志到redis * @param id * @param log */ void saveConfigRestartLog(long id, String log); /** * 获取过程日志,并删除 * @param id * @return */ List getAndDeleteConfigRestartLog(long id); /** * 删除redis过程日志 * @param id */ void deleteConfigRestartLog(long id); /** * 添加停止滚动重启标志 * @param appId * @return */ boolean addStopRestartFlag(Long appId); /** * 删除停止滚动重启标志 * @param appId * @return */ boolean deleteStopRestartFlag(Long appId); /** * 判断是否有停止滚动重启标志 * @param appId * @return */ boolean existsStopRestartFlag(Long appId); /** * 处理滚动重启 * @param appDesc * @param instanceInfoList * @param appRedisConfigVo * @return */ ExecuteResult handleRestart(AppUser appUser, AppDesc appDesc, List instanceInfoList, AppRedisConfigVo appRedisConfigVo); /** * 按分组处理滚动重启 * @param appUser * @param appDesc * @param appRedisConfigVo * @param instanceInfoList * @param pointedInstanceList * @param groupMap */ void handleRestartByGroup(AppUser appUser, AppDesc appDesc, AppRedisConfigVo appRedisConfigVo, List instanceInfoList, List pointedInstanceList, Map> groupMap); /** * 处理修改配置 * @param appUser * @param appDesc * @param instanceInfoList * @param appRedisConfigVo * @return */ Map handleConfig(AppUser appUser, AppDesc appDesc, List instanceInfoList, AppRedisConfigVo appRedisConfigVo); /** * 判断应用是否正在滚动重启 * @param appId * @return */ boolean isAppOnScrollRestart(long appId); /** * 执行failover 并check重试 * @param retryTime * @param slaveInstance * @param appDesc * @return */ boolean failoverAndCheckIdempotent(int retryTime, InstanceInfo slaveInstance, AppDesc appDesc); /** * 执行failover并检查 * @param slaveInstance 必须包括masterHost & masterPort * @param appDesc * @return */ Optional clusterFailoverAndCheck(InstanceInfo slaveInstance, AppDesc appDesc); /** * 判断实例是否完成加载dump文件 * @param instanceInfo */ boolean checkLoadFinish(InstanceInfo instanceInfo); /** * 判断实例是否准备完成 * @param instanceInfo */ boolean checkSlaveReadyFinish(InstanceInfo instanceInfo); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/AppService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.constant.AppAuditType; import com.sohu.cache.entity.*; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.web.enums.SuccessEnum; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; /** * 应用相关操作 * * @author leifu * @Time 2014年10月21日 */ public interface AppService { /** * 查询指定用户下的应用个数 * * @param appUser * @return */ int getAppDescCount(AppUser appUser, AppSearch appSearch); /** * 获取应用master节点 * * @param appId * @return */ List getAppMasterInstanceInfoList(long appId); /** * 查询指定用户下的所有的应用 * * @param appUser * @return */ List getAppDescList(AppUser appUser, AppSearch appSearch); /** * 按照Appid取应用信息 * * @param appId * @return */ AppDesc getByAppId(Long appId); /** * 保存应用 * * @param appDesc * @return */ int save(AppDesc appDesc); /** * 更新应用 * * @param appDesc * @return */ int update(AppDesc appDesc); /** * 更新应用 pwd * @param appId * @param appPwd * @return */ int updateAppPwd(long appId, String appPwd); /** * 获取应用下实例的基本信息 * @param appId * @return */ List getAppBasicInstanceInfo(Long appId); /** * 获取应用下实例基本信息,并按照主从分组 * @param appId * @return */ Map> getAppInstanceInfoGroup(Long appId); /** * 获取应用的实例 * * @param appId * @return */ List getAppInstanceInfo(Long appId); List getAppOnlineInstanceInfo(Long appId); List getAppInstanceStats(Long appId); int updateWithCustomPwd(AppDesc appDesc); /** * 保存用户与应用的关系 * * @param appId * @param userId * @return */ boolean saveAppToUser(Long appId, Long userId); /** * 更新审核状态 * * @param id 审批id * @param appId * @param status 审批状态 * @param appUser 更新人 */ void updateAppAuditStatus(Long id, Long appId, Integer status, AppUser appUser); /** * 更新用户审核状态 * * @param id 审批id * @param status 审批状态 */ void updateUserAuditStatus(Long id, Integer status, Long operateId); /** * 通过应用名获取应用 * * @param appName * @return */ AppDesc getAppByName(String appName); /** * 获取应用下的所有用户应用关系列表 * * @param appId * @return */ List getAppToUserList(Long appId); /** * 删除用户应用关系 * * @param appId * @param userId */ SuccessEnum deleteAppToUser(Long appId, Long userId); /** * 获取审批列表 * * @param status(参考AppAppCheckEnum) * @param type (参考AppAuditType) * @return */ List getAppAudits(Integer status, Integer type, Long auditId, Long userId, Long operateId); Map getStatisticGroupByStatus(Long userId, Long operateId, Date startTime, Date endTime); Map getStatisticGroupByType(Long userId, Long operateId, Date startTime, Date endTime); /** * 获取应用申请信息 * * @param appid 应用id * @param type (参考AppAuditType) */ List getAppAudits(Long appid, Integer type); /** * 保存扩容申请 * * @param appDesc * @param appUser * @param applyMemSize 扩容容量 * @param appScaleReason 扩容原因 * @param appScale 申请类型 */ AppAudit saveAppScaleApply(AppDesc appDesc, AppUser appUser, String applyMemSize, String appScaleReason, AppAuditType appScale); /** * 保存应用配置申请 * * @param appDesc * @param appUser * @param instanceId 实例id * @param appConfigKey 配置项 * @param appConfigValue 配置值 * @param modifyConfig 申请类型 */ AppAudit saveAppChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason, AppAuditType modifyConfig); /** * 保存实例配置申请 * * @param appDesc * @param appUser * @param instanceId * @param instanceConfigKey * @param instanceConfigValue * @param instanceConfigReason * @param instanceModifyConfig * @return */ AppAudit saveInstanceChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason, AppAuditType instanceModifyConfig); /** * 获取审批信息 * * @param appAuditId * @return */ AppAudit getAppAuditById(Long appAuditId); /** * 驳回理由 * * @param appAudit * @param userInfo */ SuccessEnum updateRefuseReason(AppAudit appAudit, AppUser userInfo); /** * 获取用户的应用数量 * * @param userId * @return */ int getUserAppCount(Long userId); /** * 获取应用的机器信息 * * @param appId * @return */ List getAppMachineDetail(Long appId); /** * 获取应用拥有实例的机器 * @param appId * @return */ public List getAppMachine(Long appId); /** * 根据应用id获取审批记录 * * @param appId * @return */ List getAppAuditListByAppId(Long appId); /** * 注册用户申请 * * @param appUser * @param registerUserApply * @return */ AppAudit saveRegisterUserApply(AppUser appUser, AppAuditType registerUserApply); /** * 获取所有应用 */ List getAllAppDesc(); /** * 修改报警配置 * * @param appId * @param memAlertValue * @param clientConnAlertValue * @param appUser * @return */ SuccessEnum changeAppAlertConfig(long appId, int memAlertValue, int clientConnAlertValue, int hitPrecentAlertValue, int isAccessMonitor, AppUser appUser); /** * 更新appKey * * @param appId */ void updateAppKey(long appId); /** * @param machinelist 机器信息 * @param type 参考NodeEum * @param appType 应用类型 * @param instanceNum 实例数量 * @param maxMemory 内存大小 * @param hasSalve 是否有从节点 * @return 添加部署Redis/Pika节点信息 */ public List generateInstanceInfo(List machinelist, int type, int appType, int instanceNum, int maxMemory, int hasSalve, List deployInfoList); /** * @param proxylist 机器信息 * @param type 参考NodeEum * @param appType 应用类型 * @param proxyNum 实例数量 * @return 添加sentinel/proxy节点 */ public List generateProxyinfo(List proxylist, int type, int appType, int proxyNum, List deployInfoList); String generateDeployInfo(Integer type, Integer isSalve, String room, Double size, Integer machineNum, Integer instanceNum, Integer useType, String machines, String excludeMachines, String sentinelMachines, List getDeployInfo, List resMachines); /** * @Description: 获取部署信息统计 * @Author: caoru * @CreateDate: 2018/10/10 16:34 */ Map getMachineDeployStat(Set ipList, List deployInfoList); /** * @Description: 计算内存和核数 * @Author: caoru * @CreateDate: 2018/10/14 21:06 */ void getMachineCandiList(MachineMemStatInfo memStatInfo, Double reqSize, Integer reqCpu, Integer isSalve, List machineCandi); /** * @Description: 从备选集中获取机器列表 * @Author: caoru * @CreateDate: 2018/10/9 10:34 */ void getResMachines(List machineCandi, Integer machineNum, List resMachines); /** *

* Description: *

* * @author chenshi * @version 1.0 * @date 2018/11/14 */ List checkAppStatus(List appids); /** * 键值分析 * * @param appDesc * @param appUser * @param appAnalysisReason * @return */ AppAudit saveAppKeyAnalysis(AppDesc appDesc, AppUser appUser, String appAnalysisReason, String nodeInfo); /** * 应用诊断 * * @param appDesc * @param appUser * @param reason * @return */ AppAudit saveAppDiagnostic(AppDesc appDesc, AppUser appUser, String reason); /** * 获取碎片率高的应用 */ List getTopMemFragRatioApps(TimeBetween timeBetween); public List getAppInstanceByType(long appId, InstanceTypeEnum instanceTypeEnum); /** * @param gatherTime * @return */ Map> getAppClientStatGather(long appId, String gatherTime); Map>> getFilterAppClientStatGather(long appId, String gatherTime); /** * 检查应用持久化配置并修复 * @param appId * @param masterConfigMap * @param slaveConfigMap * @return 执行失败信息 */ String checkAppPersistenceConfigAndFix(long appId, Map masterConfigMap, Map slaveConfigMap); /** * 更新持久化类型 * @param appId * @param persistenceType */ boolean updateAppPersistenceType(long appId, int persistenceType); /** * 更新内存策略 * @param appId * @param maxmemoryPolicy * @return */ boolean updateAppMaxmemoryPolicy(long appId, int maxmemoryPolicy); /** * 获取用户所属应用的内存统计信息(包含版本) * @param userId * @param isAdmin * @return */ List getAppCapacityStatistics(Long userId, Boolean isAdmin); Map getAppCapacityStats(Long userId, Boolean isAdmin); /** * 获取用户所属应用的监控统计信息 * @param userId * @param isAdmin * @param startTime * @param endTime * @return */ List getAppMonitorStatistics(Long userId, Boolean isAdmin, String startTime, String endTime); /** * 更新应用拓扑检测结果 * @param topologyExam * @return */ int saveAppTopologyExam(AppClientStatisticGather topologyExam); /** * 获取拓扑检测失败的应用 * @param gatherTime * @return */ List getTopologyExamFailedByGatherTime(String gatherTime); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/ConfigService.java ================================================ package com.sohu.cache.web.service; import java.util.List; import java.util.Map; import com.sohu.cache.entity.SystemConfig; import com.sohu.cache.web.enums.SuccessEnum; /** * cachecloud配置服务 * @author leifu * @Date 2016年5月23日 * @Time 上午10:35:04 */ public interface ConfigService { /** * 加载配置 */ public void reloadSystemConfig(); /** * 更新配置 * @param configMap * @return */ SuccessEnum updateConfig(Map configMap); /** * 获取配置列表 * @param status * @return */ List getConfigList(int status); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/DiagnosticToolService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.entity.InstanceInfo; import java.util.List; import java.util.Map; /** * @Author: rucao * @Date: 2020/6/5 5:33 下午 */ public interface DiagnosticToolService { Map> getAppInstancesMap(List appDescList); List getDiagnosticTaskRecords(Long appId, Long parentTaskId, Long auditId, Integer type, Integer status); List getScanDiagnosticData(String redisKey); List getScanCleanDiagnosticData(String redisKey); Map getDiagnosticDataMap(String redisKey,int type,boolean err); String getHotkeyDiagnosticData(String redisKey); List getSampleScanData(Long appId, String nodes, String pattern); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/InstancePortService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.task.entity.NutCrackerNode; import com.sohu.cache.task.entity.RedisSentinelNode; import com.sohu.cache.task.entity.RedisServerNode; import java.util.List; /** * @author fulei * @date 2018年7月4日 * @time 下午3:20:57 */ public interface InstancePortService { /** * 检查机器端口是否被占用 * @param ip * @param port * @return */ public boolean checkHostPortExist(String ip, int port); /** * 从当前机器生成一个可用实例 * @param appId * @param host * @param maxMemory * @return */ public RedisServerNode generateRedisServerNode(long appId, String host, int maxMemory, InstanceRoleEnum instanceRoleEnum); /** * 从当前机器生成一个可用实例 * @param appId * @param host * @param maxMemory * @return */ // public PikaNode generatePikaNode(long appId, String host, int maxMemory, InstanceRoleEnum instanceRoleEnum); /** * 生成redis server 实例列表 * @param appId * @param redisServerMachineList * @param masterPerMachine * @param maxMemory * @return */ public List generateRedisServerNodeList(long appId, List redisServerMachineList, int masterPerMachine, int maxMemory); /** * 生成redis server 实例列表 * @param appId * @param appDeployInfoList (masterIp:maxmemory:slaveIp) * @param masterPerMachine * @param maxMemory * @return */ public List generateRedisServerNodeListWithDeployInfo(long appId, List appDeployInfoList, int masterPerMachine, int maxMemory); /** * 生成redis sentinel 实例列表 * @param appId * @param redisSentinelMachineList * @param sentinelPerMachine * @return */ public List generateRedisSentinelNodeList(long appId, List redisSentinelMachineList, int sentinelPerMachine); /** * 生成nut cracker 实例列表 * @param appId * @param nutCrackerMachineList * @param nutCrackerPerMachine * @return */ public List generateNutCrackerNodeList(long appId, List nutCrackerMachineList,int nutCrackerPerMachine); /** * 获取redis-port 实例列表 * @param sourceAppId * @param targetAppId * @param slaveInstanceInfoList * @param proxyInstanceInfoList * @return */ // public List generateRedisPortNodeList(long sourceAppId, long targetAppId,List slaveInstanceInfoList, List proxyInstanceInfoList); /** * 获取redis-migrate-tool实例列表 * @return */ // public List generateRedisMigrateToolNodeList(int rmtCount, String logicName); /** * 获取proxy实例列表 * @param appId * @param codisProxyMachineList * @param codisProxyPerMachine * @return */ // public List generateCodisProxyList(long appId, List codisProxyMachineList,int codisProxyPerMachine); /** * 获取dashboard实例列表 * @param appId * @param codisDashboardMachineList * @return */ // public List generateCodisDashboardList(long appId, List codisDashboardMachineList); /** * @param appId * @param pikaMachineList * @param masterPerMachine * @return */ // public List generatePikaNodeList(long appId, List pikaMachineList, int masterPerMachine); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/MigrateService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.exception.SSHException; /** * @Author: zengyizhao * @CreateTime: 2023/2/28 15:33 * @Description: 迁移服务 * @Version: 1.0 */ public interface MigrateService { /** * 根据机器pod,强制迁移 * @param sourceIp * @param targetIp * @throws SSHException */ public void forceMigrate(String sourceIp, String targetIp) throws SSHException; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/ResourceService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.web.enums.SuccessEnum; import java.util.List; import java.util.Map; /** * Created by chenshi on 2020/7/6. */ public interface ResourceService { SuccessEnum saveResource(SystemResource systemResouce); SuccessEnum updateResource(SystemResource systemResouce); List getResourceList(int resourceType); List getResourceList(int resourceType, String searchName); SuccessEnum pushScript(Integer repositoryId, Integer resourceId, String content, AppUser userInfo); SuccessEnum pushDir(Integer repositoryId, Integer resourceId, AppUser userInfo); SystemResource getResourceById(int resourceId); SystemResource getResourceByName(String resourceName); String getRespositoryUrl(int resourceId, int respoitoryId); String getRemoteFileContent(int resourceId, int respoitoryId); //获取远程仓库信息 SystemResource getRepository(); Map getAppUseRedis(); SystemResource getRedisResourceByCache(Integer repositoryId); String getRedisVersion(Integer repositoryId); boolean checkRedisVersionGreater(Integer repositoryId, int[] versions); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/ServerDataService.java ================================================ package com.sohu.cache.web.service; import java.util.List; import com.sohu.cache.entity.ServerInfo; import com.sohu.cache.entity.ServerStatus; import com.sohu.cache.server.data.Server; public interface ServerDataService { /** * 查询服务器基本信息 * @param ip * @return @ServerInfo */ public ServerInfo queryServerInfo(String ip); /** * 获取所有机器的系统信息 * @return */ public List getAllServerInfo(); /** * 保存服务器发行版信息 * @param ip * @param dist from /etc/issue */ public void saveServerInfo(String ip, String dist); /** * 保存/更新服务器信息 * @param server * @return 影响的行数 */ public Integer saveAndUpdateServerInfo(Server server); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerStatus(String ip, String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerOverview(String ip, String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerCpu(String ip, String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerNet(String ip, String date); /** * 查询服务器状态 * @param ip * @param date * @return List */ public List queryServerDisk(String ip, String date); /** * 保存服务器状态 */ public void saveServerStat(Server server); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/ToolService.java ================================================ package com.sohu.cache.web.service; import java.util.List; import java.util.Map; /** * Created by rucao on 2018/12/11 */ public interface ToolService { /** *

* Description: 通过appid进行任务检查 *

* @param appId 应用id */ List topologyExamByAppid(long appId); /** *

* Description: 所有线上应用进行任务检查 *

* @param appidList 线上appid集合 */ void topologyExam(List appidList); void restAppDescOfficer(); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/UserLoginStatusService.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.entity.AppUser; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 用户登录状态信息服务 * * @author leifu * @Date 2016年6月15日 * @Time 下午1:24:09 */ public interface UserLoginStatusService { public final static String LOGIN_USER_STATUS_NAME = "CACHE_CLOUD_USER_STATUS"; /** * 获取用户登录状态信息 * * @param request * @return */ String getUserNameFromLoginStatus(HttpServletRequest request); /** * 解析ticket * * @param request * @return */ String getUserNameFromTicket(HttpServletRequest request); /** * 获取登录跳转地址 * * @param request * @return * @throws Exception */ String getRedirectUrl(HttpServletRequest request); /** * 获取注销登录地址 * * @return * @throws Exception */ String getLogoutUrl(); /** * 获取新用户注册地址 * * @return * @throws Exception */ String getRegisterUrl(AppUser user); /** * 添加用户登录状态信息 * * @param request * @param response * @param userName */ void addLoginStatus(HttpServletRequest request, HttpServletResponse response, String userName); /** * 移除用户登录状态信息 * * @param request * @param response */ void removeLoginStatus(HttpServletRequest request, HttpServletResponse response); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/UserService.java ================================================ package com.sohu.cache.web.service; import java.util.List; import com.sohu.cache.entity.AppBiz; import com.sohu.cache.entity.AppUser; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.vo.AppUserVo; /** * 用户管理service * @author leifu * @Date 2014年10月27日 * @Time 上午9:57:47 */ public interface UserService { /** * 通过id获取用户 * @param userId * @return */ AppUser get(Long userId); /** * 通过中文名获取用户 * @param chName * @return */ List getUserList(String chName); /** * 通过中文名和业务组名获取用户 * @param chName * @param bizName * @return */ List getUserWithBizList(String chName, String bizName); /** * 获取所有用户 */ List getAllUser(); /** * 获取某个应用下的所有用户 * @param appId * @return */ List getByAppId(Long appId); /** * 获取需要报警的用户列表 * @param appId * @return */ public List getAlertByAppId(Long appId); /** * 通过域账户前缀获取用户 * @param name * @return */ AppUser getByName(String name); /** * 保存用户 * @param appUser * @return */ SuccessEnum save(AppUser appUser); /** * 更新用户 * @param appUser * @return */ SuccessEnum update(AppUser appUser); /** * 删除用户 * @param userId * @return */ SuccessEnum delete(Long userId); /** * 重置密码 * @param userId * @return */ SuccessEnum resetPwd(Long userId); /** * 修改密码 * @param userId * @param password * @return */ SuccessEnum updatePwd(Long userId, String password); String getOfficerName(Long appId); String getOfficerName(String officer); /** * 获取某个应用下的所有负责人 * @param officer * @return */ List getOfficerUserByUserIds(String officer); /** * 接手用户 * @param toRemoveUser * @param toChargeUser * @return */ SuccessEnum takeoverUser(AppUser toRemoveUser, AppUser toChargeUser); /** * 通过id获取业务组 * @param bizId * @return */ AppBiz getBiz(Long bizId); /** * 获取所有业务组 * @return */ List getBizList(); /** * 保存业务组 * @param appBiz * @return */ SuccessEnum saveBiz(AppBiz appBiz); /** * 更新业务组 * @param appBiz * @return */ SuccessEnum updateBiz(AppBiz appBiz); /** * 删除业务组 * @param bizId * @return */ SuccessEnum deleteBiz(Long bizId); } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/WebClientComponent.java ================================================ package com.sohu.cache.web.service; import com.sohu.cache.web.enums.WebClients; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; /** * @Author: rucao * @Date: 2020/5/19 3:48 下午 */ @Component public class WebClientComponent { @Value("${cachecloud.web.clients:127.0.0.1}") private String[] clients; public List getWebClientIps() { if (CollectionUtils.isEmpty(WebClients.webClientIpList)) { WebClients.webClientIpList = Arrays.asList(clients); } return WebClients.webClientIpList; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppAlertRecordServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.entity.*; import com.sohu.cache.web.enums.AlertTypeEnum; import com.sohu.cache.web.service.AppAlertRecordService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.dao.AppAlertRecordDao; import com.sohu.cache.web.vo.AppDetailVO; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/3 13:34 * @Description: 报警记录服务实现类 */ @Slf4j @Service public class AppAlertRecordServiceImpl implements AppAlertRecordService { @Autowired private AppAlertRecordDao appAlertRecordDao; /** * 保存报警信息 * * @param appAlertRecord * @return */ @Override public int saveAlertInfo(AppAlertRecord appAlertRecord) { return appAlertRecordDao.save(appAlertRecord); } /** * 批量保存报警信息 * @param appAlertRecordList * @return */ @Override public int saveBatchAlertInfo(List appAlertRecordList) { return appAlertRecordDao.batchSave(appAlertRecordList); } /** * 异步保存报警信息 * @param appAlertRecord * @return */ @Override public void asyncSaveAlertInfo(AppAlertRecord appAlertRecord) { AsyncThreadPoolFactory.ALERT_RECORD_THREAD_POOL.execute(new Runnable() { @Override public void run() { appAlertRecordDao.save(appAlertRecord); } }); } /** * 异步批量保存报警信息 * @param appAlertRecordList * @return */ @Override public void asyncSaveBatchAlertInfo(List appAlertRecordList) { AsyncThreadPoolFactory.ALERT_RECORD_THREAD_POOL.execute(new Runnable() { @Override public void run() { appAlertRecordDao.batchSave(appAlertRecordList); } }); } /** * 根据报警类型,保存报警信息 * @param type 类型 * @param object * @return */ @Override public int saveAlertInfoByType(AlertTypeEnum type, String title, String content, Object... object) { try{ Date date = new Date(); List appAlertRecordList = this.getAlertRecordByType(type, date, title, content, object); if(CollectionUtils.isNotEmpty(appAlertRecordList)){ this.asyncSaveBatchAlertInfo(appAlertRecordList); } }catch (Exception e){ log.error("saveAlertInfoByType error : ", e); } return 1; } /** * 根据邮件类型及信息生成对应的报警信息记录 * @param type * @param title * @param content * @param objects * @return */ private List getAlertRecordByType(AlertTypeEnum type, Date date, String title, String content, Object... objects){ if(type == null){ return null; } if(objects == null || objects.length < 1){ return null; } List appAlertRecordList = new ArrayList<>(); if(type == AlertTypeEnum.INSTANCE_RUNNING_STATE_CHANGE){ InstanceInfo info = (InstanceInfo) (objects[0]); generateAlertRecordByInstanceInfo(type, date, appAlertRecordList, title, content, info); } else if(type == AlertTypeEnum.INATANCE_EXCEPTION_STATE_MONITOR || type == AlertTypeEnum.INSTANCE_MINUTE_MONITOR || type == AlertTypeEnum.POD_RESTART_INSTANCE_RECOVER){ //此类型,传入的content为空,content需自己组装 List alertInstInfoList = (List) (objects[0]); generateAlertRecordByInstanceAlertList(type, date, appAlertRecordList, title, alertInstInfoList); }else if(type == AlertTypeEnum.MACHINE_MEMORY_OVER_PRESET || type == AlertTypeEnum.POD_RESTART_SYNC_TASK){ String ip = (String) (objects[0]); generateAlertRecordByIp(type, date, appAlertRecordList, title, content, ip); }else if(type == AlertTypeEnum.MACHINE_MANAGE){ //此类型,传入的content为空,content需自己组装 List recoverInstInfo = (List) (objects[0]); generateAlertRecordByOPerationList(type, date, appAlertRecordList, title, recoverInstInfo); }else if(type == AlertTypeEnum.APP_SHARD_CLENT_CONNECTION || type == AlertTypeEnum.APP_SHARD_MEM_USED_RATIO){ AppDetailVO appDetailVO = (AppDetailVO) (objects[0]); InstanceStats instanceStats = (InstanceStats) (objects[1]); generateAlertRecordByAppAndInstance(type, date, appAlertRecordList, title, content, appDetailVO, instanceStats); }else if(type == AlertTypeEnum.APP_CLIENT_CONNECTION || type == AlertTypeEnum.APP_HIT_RATIO || type == AlertTypeEnum.APP_MEM_USED_RATIO){ AppDetailVO appDetailVO = (AppDetailVO) (objects[0]); generateAlertRecordByAppDetailVO(type, date, appAlertRecordList, title, content, appDetailVO); } //此种类型type == AlertTypeEnum.APP_MINUTE_MONITOR不做处理,与 AlertTypeEnum.INSTANCE_MINUTE_MONITOR重复 return appAlertRecordList; } /** * 根据实例信息生成报警信息 * @param type * @param appAlertRecordList * @param title * @param content * @param instanceInfo */ private void generateAlertRecordByInstanceInfo(AlertTypeEnum type, Date date, List appAlertRecordList, String title, String content, InstanceInfo instanceInfo){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); appAlertRecord.setContent(content); appAlertRecord.setAppId(instanceInfo.getAppId()); appAlertRecord.setInstanceId(Long.valueOf(instanceInfo.getId())); appAlertRecord.setIp(instanceInfo.getIp()); appAlertRecord.setPort(instanceInfo.getPort()); appAlertRecord.setCreateTime(date); appAlertRecordList.add(appAlertRecord); } /** * 根据机器ip生成报警信息 * @param type * @param appAlertRecordList * @param title * @param content * @param ip */ private void generateAlertRecordByIp(AlertTypeEnum type, Date date, List appAlertRecordList, String title, String content, String ip){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); appAlertRecord.setContent(content); appAlertRecord.setIp(ip); appAlertRecord.setCreateTime(date); appAlertRecordList.add(appAlertRecord); } /** * 根据应用详细信息生成报警信息 * @param type * @param appAlertRecordList * @param title * @param content * @param appDetailVO */ private void generateAlertRecordByAppDetailVO(AlertTypeEnum type, Date date, List appAlertRecordList, String title, String content, AppDetailVO appDetailVO){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); appAlertRecord.setContent(content); long appId = appDetailVO.getAppDesc().getAppId(); appAlertRecord.setAppId(appId); appAlertRecord.setCreateTime(date); appAlertRecordList.add(appAlertRecord); } /** * 根据应用和实例信息生成报警信息 * @param type * @param appAlertRecordList * @param title * @param content * @param appDetailVO * @param instanceStats */ private void generateAlertRecordByAppAndInstance(AlertTypeEnum type, Date date, List appAlertRecordList, String title, String content, AppDetailVO appDetailVO, InstanceStats instanceStats){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); appAlertRecord.setContent(content); long appId = appDetailVO.getAppDesc().getAppId(); appAlertRecord.setAppId(appId); appAlertRecord.setInstanceId(instanceStats.getInstId()); appAlertRecord.setIp(instanceStats.getIp()); appAlertRecord.setPort(instanceStats.getPort()); appAlertRecord.setCreateTime(date); appAlertRecordList.add(appAlertRecord); } /** * 根据实例报警结果列表生成报警信息 * @param type * @param appAlertRecordList * @param title * @param alertInstInfoList */ private void generateAlertRecordByInstanceAlertList(AlertTypeEnum type, Date date, List appAlertRecordList, String title, List alertInstInfoList){ for(InstanceAlertValueResult instanceAlert : alertInstInfoList){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); appAlertRecord.setAppId(instanceAlert.getAppId()); appAlertRecord.setIp(instanceAlert.getInstanceInfo().getIp()); appAlertRecord.setPort(instanceAlert.getInstanceInfo().getPort()); StringBuilder sb = new StringBuilder(); if(type == AlertTypeEnum.INATANCE_EXCEPTION_STATE_MONITOR) { sb.append("状态:"); sb.append(instanceAlert.getInstanceInfo().getStatusDesc()); sb.append(", 说明:"); sb.append(instanceAlert.getOtherInfo()); } if(type == AlertTypeEnum.INSTANCE_MINUTE_MONITOR) { if(instanceAlert.getInstanceAlertConfig() != null && instanceAlert.getInstanceAlertConfig().getImportantLevel() != null){ appAlertRecord.setImportantLevel(instanceAlert.getInstanceAlertConfig().getImportantLevel()); } sb.append("属性值:"); sb.append(instanceAlert.getInstanceAlertConfig().getAlertConfig()); sb.append(", 说明:"); sb.append(instanceAlert.getAlertMessage()); sb.append(", 其他信息:"); sb.append(instanceAlert.getOtherInfo()); } if(type == AlertTypeEnum.POD_RESTART_INSTANCE_RECOVER) { sb.append("实例恢复时间:"); sb.append(instanceAlert.getOtherInfo()); } appAlertRecord.setContent(sb.toString()); appAlertRecord.setCreateTime(date); appAlertRecordList.add(appAlertRecord); } } /** * 根据机器操作结果列表生成报警信息 * @param type * @param appAlertRecordList * @param title * @param recoverInstInfo */ private void generateAlertRecordByOPerationList(AlertTypeEnum type, Date date, List appAlertRecordList, String title, List recoverInstInfo){ for(OperationAlertValueResult operationAlertValueResult : recoverInstInfo){ AppAlertRecord appAlertRecord = new AppAlertRecord(); appAlertRecord.setVisibleType(type.getVisibleType()); appAlertRecord.setImportantLevel(type.getImportantLevel()); appAlertRecord.setTitle(title); MachineInfo machineInfo = operationAlertValueResult.getMachineInfo(); StringBuilder sb = new StringBuilder(); if(machineInfo != null){ appAlertRecord.setIp(machineInfo.getIp()); sb.append("ip:"); sb.append(machineInfo.getIp()); sb.append(", real_ip:"); sb.append(machineInfo.getRealIp()); sb.append(", machineInfo(内存:"); sb.append(machineInfo.getMem()); sb.append(", cpu:"); sb.append(machineInfo.getCpu()); sb.append(", 备注说明:"); sb.append(machineInfo.getExtraDesc()); sb.append("), "); } sb.append("操作:"); sb.append(operationAlertValueResult.getType()); sb.append(", staus:"); sb.append(operationAlertValueResult.getStatus()); sb.append(", message:"); sb.append(operationAlertValueResult.getMessage()); appAlertRecord.setCreateTime(date); appAlertRecord.setContent(sb.toString()); appAlertRecordList.add(appAlertRecord); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppAutoCapacityServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.dao.AppCapacityMonitorDao; import com.sohu.cache.dao.AppDao; import com.sohu.cache.entity.AppCapacityMonitor; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.InstanceStats; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.AppAutoCapacityService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.UserService; import freemarker.template.Configuration; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.OptionalLong; import java.util.stream.Collectors; /** * 容量监控 * @author zengyizhao * @Date 2022年10月9日 */ @Slf4j @Service("appAutoCapacityService") public class AppAutoCapacityServiceImpl implements AppAutoCapacityService { @Autowired private AppCapacityMonitorDao appCapacityMonitorDao; /** * 邮箱报警 */ @Autowired private EmailComponent emailComponent; @Autowired private AppDao appDao; @Autowired private AppService appService; @Autowired private UserService userService; @Autowired private AppStatsCenter appStatsCenter; @Autowired private Configuration configuration; @Async("asyncExecutor") @Override public void checkAndExpandCapacity(AppDesc appDesc, int appMemUsePercent, Map instanceStatsMap) { try{ if(appDesc != null){ return; } Collection stats = instanceStatsMap.values(); stats = stats.stream().filter(instanceStats -> instanceStats != null).collect(Collectors.toList()); Long shardingMasterCount = stats.stream().filter(instanceStats -> instanceStats.getRole() == 1).count(); int shardingMasterNum = Long.valueOf(shardingMasterCount == null ? 0L : shardingMasterCount).intValue(); //保存当前内存使用 List> collect = instanceStatsMap.entrySet().stream().filter(entry -> entry.getValue() != null && entry.getValue().getRole() == 1).collect(Collectors.toList()); long totalMem = collect.stream().mapToLong(entry -> entry.getValue().getMaxMemory()).sum(); long appUsedMem = collect.stream().mapToLong(entry -> entry.getValue().getUsedMemory()).sum(); long shardingUsedMem = 0; OptionalLong shardingUsedMaxMem = collect.stream().mapToLong(entry -> entry.getValue().getUsedMemory()).max(); if(shardingUsedMaxMem.isPresent()){ shardingUsedMem = shardingUsedMaxMem.getAsLong(); } OptionalLong shardingMaxMem = stats.stream().filter(instanceStats -> instanceStats.getRole() == 1).mapToLong(stat -> stat.getMaxMemory()).max(); long shardingMem = 0; if(shardingMaxMem.isPresent()){ shardingMem = shardingMaxMem.getAsLong(); } AppCapacityMonitor appCapacityMonitor = appCapacityMonitorDao.getAppCapacityMonitorByAppId(appDesc.getAppId()); //无历史信息 if(appCapacityMonitor == null){ //添加记录并不进行下方check this.saveAppCapacityMonitor(appDesc, shardingMasterNum, totalMem, appUsedMem, shardingMem, shardingUsedMem); return; } //更新记录 this.updateAppCapacityMonitor(appCapacityMonitor.getId(), appUsedMem, totalMem, shardingUsedMem, shardingMem); //判断是否减小过容量,更新缩容记录及时间 if(totalMem < appCapacityMonitor.getCurMem()){ this.cleanAppCapacityReduceSchedule(appCapacityMonitor.getId()); } } catch(Exception exp){ log.error("checkAndExpandCapacity app:{} error:{} ", appDesc, exp.getMessage()); } } private void saveAppCapacityMonitor(AppDesc appDesc, int shardingMasterNum, long mem, long appMemUsed, long shardingMem, long shardingUsedMem) { ExpandConfig expandConfig = this.getExpandConfig(mem); AppCapacityMonitor appCapacityMonitor = new AppCapacityMonitor(); appCapacityMonitor.setAppId(appDesc.getAppId()); appCapacityMonitor.setShardingMasterNum(shardingMasterNum); appCapacityMonitor.setMem(mem); appCapacityMonitor.setCurMem(mem); appCapacityMonitor.setMemUsed(appMemUsed); appCapacityMonitor.setShardingMem(shardingMem); appCapacityMonitor.setCurShardingMem(shardingMem); appCapacityMonitor.setShardingMemUsed(shardingUsedMem); appCapacityMonitor.setExpandMemPercent(expandConfig.getExpandMemPercent()); appCapacityMonitor.setExpandRatio(expandConfig.getExpandRatio()); appCapacityMonitor.setExpandRatioTotal(expandConfig.getExpandRatioTotal()); appCapacityMonitor.setExpandCount(expandConfig.getExpandCount()); appCapacityMonitor.setIsExpand(1); appCapacityMonitor.setIsReduce(1); appCapacityMonitor.setUpdateTime(new Date()); appCapacityMonitorDao.save(appCapacityMonitor); } private void updateAppCapacityMonitor(long id, long appMemUsed, long curMem, long shardingUsedMem, long curShardingMem) { ExpandConfig expandConfig = this.getExpandConfig(curMem); AppCapacityMonitor appCapacityMonitor = new AppCapacityMonitor(); appCapacityMonitor.setId(id); appCapacityMonitor.setMemUsed(appMemUsed); appCapacityMonitor.setCurMem(curMem); appCapacityMonitor.setShardingMemUsed(shardingUsedMem); appCapacityMonitor.setCurShardingMem(curShardingMem); appCapacityMonitor.setExpandMemPercent(expandConfig.getExpandMemPercent()); appCapacityMonitor.setExpandRatio(expandConfig.getExpandRatio()); appCapacityMonitor.setExpandRatioTotal(expandConfig.getExpandRatioTotal()); appCapacityMonitor.setExpandCount(expandConfig.getExpandCount()); appCapacityMonitorDao.update(appCapacityMonitor); } private void cleanAppCapacityReduceSchedule(long id) { AppCapacityMonitor appCapacityMonitor = new AppCapacityMonitor(); appCapacityMonitor.setId(id); appCapacityMonitor.setScheduleStatus(0); appCapacityMonitorDao.updateAppCapacityReduceSchedule(appCapacityMonitor); } @Override public void updateAppCapacityMonitor(AppCapacityMonitor appCapacityMonitor) { appCapacityMonitorDao.update(appCapacityMonitor); } @Data @NoArgsConstructor @AllArgsConstructor private static class ExpandConfig{ //初始内存下限G private long memSmall; //初始内存上限G private long memGreat; //当日扩容次数限制 private int expandCount; //扩容内存使用率百分比 private int expandMemPercent; //扩容比率 private int expandRatio; //总扩容比率 private int expandRatioTotal; public ExpandConfig(String[] params){ if(params != null && params.length == 6){ this.memSmall = Long.valueOf(params[0]); this.memGreat = Long.valueOf(params[1]); this.expandCount = Integer.valueOf(params[2]); this.expandMemPercent = Integer.valueOf(params[3]); this.expandRatio = Integer.valueOf(params[4]); this.expandRatioTotal = Integer.valueOf(params[5]); } } } private ExpandConfig getExpandConfig(long mem){ String redisExpandConfig = ConstUtils.REDIS_EXPAND_CAPACITY_CONFIG; List defaultExpandConfigList = new ArrayList<>(); if(StringUtils.isNotBlank(redisExpandConfig)){ String[] expandConfigs = redisExpandConfig.split(";"); List list = Arrays.asList(expandConfigs); list.stream().forEach(expandConfig -> defaultExpandConfigList.add(new ExpandConfig(expandConfig.split(",")))); } ExpandConfig meetExpandConfig = null; Optional expandConfigOptional = defaultExpandConfigList.stream().filter(expandConfig -> (expandConfig.getMemSmall() * 1024 * 1024 * 1024 < mem && expandConfig.getMemGreat() * 1024 * 1024 * 1024 >= mem)).findFirst(); if(expandConfigOptional.isPresent()){ meetExpandConfig = expandConfigOptional.get(); } return meetExpandConfig; } @Override public void updateAppMemUsedHistory() { List appDescList = appDao.getOnlineApps(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd0000"); Date date = new Date(); Date beginDate = DateUtils.addDays(date, 0 - ConstUtils.REDIS_MEM_USED_MAX_DAYS); String beginTime = sdf.format(beginDate); String endTime = sdf.format(date); appDescList.stream().forEach(appDesc -> { Long usedMemoryMax = appStatsCenter.getUsedMemoryMaxByTimeBetween(appDesc.getAppId(), Long.valueOf(beginTime), Long.valueOf(endTime)); if(usedMemoryMax != null && usedMemoryMax > 0){ appCapacityMonitorDao.updateAppUsedMemHistory(appDesc.getAppId(), usedMemoryMax); } }); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppImportServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.dao.AppImportDao; import com.sohu.cache.entity.AppImport; import com.sohu.cache.web.service.AppImportService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * @Author: rucao * @Date: 2021/1/8 上午11:43 */ @Slf4j @Service public class AppImportServiceImpl implements AppImportService { @Autowired private AppImportDao appImportDao; @Override public List getImportAppList(Integer status) { List appImportList = new ArrayList<>(); try { appImportList = appImportDao.getAppImports(status); } catch (Exception e) { log.error(e.getMessage(), e); } return appImportList; } @Override public int save(AppImport appImport) { try { return appImportDao.save(appImport); } catch (Exception e) { log.error(e.getMessage(), e); } return -1; } @Override public int update(AppImport appImport) { try { return appImportDao.update(appImport); } catch (Exception e) { log.error(e.getMessage(), e); } return -1; } @Override public AppImport appImport(Long id) { AppImport appImport = get(id); if (appImport == null) { } return null; } @Override public AppImport get(Long id) { try { return appImportDao.get(id); } catch (Exception e) { log.error(e.getMessage(), e); } return null; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppRedisCommandCheckServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.constant.RedisConstant; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.entity.MachineInfo; import com.sohu.cache.exception.SSHException; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.util.StringUtil; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.service.AppRedisCommandCheckService; import com.sohu.cache.web.vo.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import javax.annotation.Resource; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * @Author: zengyizhao * @DateTime: 2021/9/29 11:34 * @Description: redis命令检测 */ @Slf4j @Service public class AppRedisCommandCheckServiceImpl implements AppRedisCommandCheckService { @Autowired private InstanceDao instanceDao; @Autowired private RedisCenter redisCenter; @Autowired private AssistRedisService assistRedisService; private static final String REDIS_COMMAND_CHECK_RESULT_SAVE_KEY = "redis:command:check:result"; private static final String REDIS_COMMAND_CHECK_RESULT_KEY = "redis:command:check:result:"; @Resource private MachineDao machineDao; @Resource private EmailComponent emailComponent; /** * * @param checkVo */ @Override public RedisCommandCheckResult checkRedisCommand(AppUser appUser, AppRedisCommandCheckVo checkVo){ RedisCommandCheckResult redisCommandCheckResult = new RedisCommandCheckResult(); BeanUtils.copyProperties(checkVo, redisCommandCheckResult); redisCommandCheckResult.setCreateTime(new Date()); redisCommandCheckResult.setSuccess(true); redisCommandCheckResult.setUserName(appUser.getChName() == null ? appUser.getName() : appUser.getChName()); long beginTime = System.currentTimeMillis(); StringBuilder stringBuilder = new StringBuilder(); List allInstanceList = getInstanceListToCheck(checkVo.getMachineIps(), checkVo.getPodIp()); AppRedisCommandCheckResult checkResult = new AppRedisCommandCheckResult(); List instanceCheckResultList = new ArrayList<>(); checkResult.setMachineIps(checkVo.getMachineIps()); checkResult.setCreateTime(new Date()); checkResult.setPodIp(checkVo.getPodIp()); checkResult.setCommand(checkVo.getCommand()); checkResult.setSuccess(false); //遍历实例并分别处理 for (InstanceInfo instanceInfo : allInstanceList){ BooleanEnum master = redisCenter.isMaster(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); if(master.equals(BooleanEnum.OTHER)){ continue; } InstanceRedisCommandCheckResult instanceCheckResult = new InstanceRedisCommandCheckResult(); instanceCheckResultList.add(instanceCheckResult); instanceCheckResult.setInstanceInfo(instanceInfo); String s = handleByInstance(instanceInfo, checkVo); if(StringUtil.isBlank(s)){ instanceCheckResult.setSuccess(true); continue; } redisCommandCheckResult.setSuccess(false); instanceCheckResult.setSuccess(false); instanceCheckResult.setMessage(s); stringBuilder.append(s); stringBuilder.append("\r\n"); } checkResult.setInstanceCheckList(instanceCheckResultList); log.info("耗时:{}ms,结果信息:{}", System.currentTimeMillis() - beginTime, checkResult); UUID uuid = UUID.randomUUID(); redisCommandCheckResult.setKey(uuid.toString()); this.saveRedisCommandCheckResult(redisCommandCheckResult, checkResult); return redisCommandCheckResult; } //machineIps //podIp //命令 private List getInstanceListToCheck(String machineIps, String podIp){ List allInstanceList = new ArrayList<>(); if(StringUtils.isNotEmpty(podIp)){ allInstanceList = getInstanceInfoList(podIp); }else if(machineIps != null){ List machineList = getMachineIpist(machineIps); //遍历machine list,分别获取machine下 pod list List allMachineList = new ArrayList<>(); for (String machineIp: machineList) { List vmPodList = getVmPodList(machineIp); if(!org.springframework.util.CollectionUtils.isEmpty(vmPodList)){ allMachineList.addAll(vmPodList); } } //分别获取 pod下 redis intance list for (MachineInfo machineInfo : allMachineList) { List instanceInfoList = getInstanceInfoList(machineInfo.getIp()); if(!CollectionUtils.isEmpty(instanceInfoList)){ allInstanceList.addAll(instanceInfoList); } } } return allInstanceList; } /** * 获取机器ip列表 * @return */ private List getMachineIpist(String machineIps){ String[] split = machineIps.split(";"); List ipList = Arrays.asList(split); return ipList; } /** * 获取机器pod列表 * @return */ private List getVmPodList(String realIp){ List machineInfoList = machineDao.getMachineInfoByCondition(null, -1, -1, null , -1, realIp); return machineInfoList; } /** * 根据机器ip获取instance列表 * @param ip * @return */ private List getInstanceInfoList(String ip){ //获取一台机器的所有实例 List instListByIp = instanceDao.getInstListByIp(ip); return instListByIp; } /** * 根据实例进行处理 * @param instanceInfo * @return */ private String handleByInstance(InstanceInfo instanceInfo, AppRedisCommandCheckVo checkVo){ long startTime = 0L; //执行命令 if("bgsave".equals(checkVo.getCommand())){ startTime = sendBgsaveCommand(instanceInfo); }else if("bgrewriteaof".equals(checkVo.getCommand())) { startTime = sendBgrewriteaofCommand(instanceInfo); } if(startTime == 0L){ return String.format("实例appId:%s, ip:%s, port:%s,处理失败:发送命令失败", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); } //等待命令执行结束或定时等待 String checkInfo = null; if("bgsave".equals(checkVo.getCommand())){ checkInfo = checkByInfo(instanceInfo, startTime, checkVo.getMaxTry(), RedisConstant.Persistence, "rdb_bgsave_in_progress", "0"); }else if("bgrewriteaof".equals(checkVo.getCommand())) { checkInfo = checkByInfo(instanceInfo, startTime, checkVo.getMaxTry(), RedisConstant.Persistence, "aof_rewrite_in_progress", "0"); } log.info("实例appId:{}, ip:{}, port:{},执行checkByInfo用时:{}ms,结果:{}", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), System.currentTimeMillis() - startTime, checkInfo); if(checkInfo != null){ return checkInfo; } //检测校验 checkInfo = checkByLog(instanceInfo, "crashed by signal", 10); if(checkInfo == null){ log.info("实例appId:{}, ip:{}, port:{},未出现指定信息", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); }else{ log.info("实例appId:{}, ip:{}, port:{},出现错误信息:{}", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), checkInfo); } return checkInfo; } /** * 发送bgrewriteaof命令并获取返回信息 * @param instanceInfo * @return */ private long sendBgrewriteaofCommand(InstanceInfo instanceInfo){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); long appId = instanceInfo.getAppId(); StringBuilder infoBuilder = new StringBuilder(); Jedis jedis = null; long start = 0L; try { jedis = redisCenter.getAdminJedis(appId, host, port); start = System.currentTimeMillis(); String info = jedis.bgrewriteaof(); log.info("实例appId:{}, ip:{}, port:{},bgrewriteaof结果:{}", appId, host, port, info); } catch (Exception e) { start = 0L; log.error("实例appId:{}, host:{}, port:{}, redis-bgrewriteaof errorMsg:{}", appId, host, port, e.getMessage()); } finally { if (jedis != null){ jedis.close(); } } return start; } /** * 发送命令并获取返回信息 * @param instanceInfo * @return */ private long sendBgsaveCommand(InstanceInfo instanceInfo){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); long appId = instanceInfo.getAppId(); StringBuilder infoBuilder = new StringBuilder(); Jedis jedis = null; long start = 0L; try { jedis = redisCenter.getAdminJedis(appId, host, port); start = System.currentTimeMillis(); String info = jedis.bgsave(); log.info("实例appId:{}, ip:{}, port:{},bgrewriteaof结果:{}", appId, host, port, info); } catch (Exception e) { start = 0L; log.error("实例appId:{}, host:{}, port:{}, redis-bgrewriteaof errorMsg:{}", appId, host, port, e.getMessage()); } finally { if (jedis != null){ jedis.close(); } } return start; } private String getMethod(String command) { return null; } /** * 发送info命令查看相关指标信息,进行监测 * @param instanceInfo 实例信息 * @param startTime 开始时间戳 * @param maxTry 最大重试次数 * @param redisConstant redis info中一级指标常量 * @param indicateName 配置项 * @param expectValue 期望值 * @return */ private String checkByInfo(InstanceInfo instanceInfo, long startTime, Integer maxTry, RedisConstant redisConstant, String indicateName, String expectValue){ String result = null; String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); long appId = instanceInfo.getAppId(); Jedis jedis = null; boolean reConfirmFlag = true; long costTime = 0L; try { jedis = redisCenter.getAdminJedis(appId, host, port); int retryTimes = 1; long sleepTime = 500L; boolean printMemory = true; String configValue = null; while(reConfirmFlag && retryTimes < maxTry){ try { Thread.sleep(retryTimes * sleepTime > 3000L ? 3000L : retryTimes * sleepTime ); } catch (InterruptedException e) { } String info = jedis.info("all"); Map> infoStats = processRedisStats(info); Map persistenceMap = infoStats.get(redisConstant); if(printMemory){ log.info("实例appId:{}, ip:{}, port:{},retryTimes:{}, info : {}", appId, host, port, retryTimes, info); printMemory = false; } configValue = MapUtils.getString(persistenceMap, indicateName); if(expectValue.equals(configValue)){ reConfirmFlag = false; costTime = System.currentTimeMillis() - startTime; } retryTimes++; } if(reConfirmFlag){ result = String.format("实例appId:%s, ip:%s, port:%s, redis-checkByInfo, configName:%s, expectValue:%s, configValue:%s", appId, host, port, indicateName, expectValue, configValue); } log.info("实例appId:{}, ip:{}, port:{},重试次数:{},配置项:{},期望值:{},实际值:{} 最终结果(结束false/未结束true):{},耗时:{}ms", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), retryTimes - 1, indicateName, expectValue, configValue, reConfirmFlag, costTime); } catch (Exception e) { e.printStackTrace(); log.error(String.format("实例appId:%s, ip:%s, port:%s, redis-checkByInfo errorMsg:", appId, host, port), e); result = String.format("实例appId:%s, ip:%s, port:%s, redis-checkByInfo errorMsg:%s", appId, host, port, e.getMessage()); } finally { if (jedis != null) jedis.close(); } return result; } /** * 查看实例日志中,aof rewrite是否被terminated 或 redis是否crashed by signal: 11 * @param instanceInfo * @return */ private String checkByLog(InstanceInfo instanceInfo, String expectValue, int minuteInternalAllow){ String recentLog = getRecentLog(instanceInfo); if(StringUtil.isBlank(recentLog)){ return "实例appId:" + instanceInfo.getAppId() + "-ip:" + instanceInfo.getIp() + "-port:" + instanceInfo.getPort() + "-结果:无日志,请确认实例是否正常并人工判定"; } String[] logArray = recentLog.split(System.getProperty("line.separator")); if(logArray != null && logArray.length > 1){ for(int i = logArray.length - 1; i >= 0; i--){ String log = logArray[i]; if(log != null && log.contains(expectValue)){ if(!checkLogTimeMeet(log, minuteInternalAllow)){ continue; } return "实例appId:" + instanceInfo.getAppId() + "-ip:" + instanceInfo.getIp() + "-port:" + instanceInfo.getPort() + "-结果log: " + log; } } } return null; } private boolean checkLogTimeMeet(String log, int minuteInternalAllow) { boolean flag = false; Calendar calendar = Calendar.getInstance(Locale.US); int year = 0; try{ calendar.add(Calendar.MINUTE, -minuteInternalAllow); year = calendar.get(Calendar.YEAR); }catch (Exception e){ return flag; } SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy hh:mm:ss.SSS", Locale.US); String[] strArray = log.split(" "); if (strArray != null && strArray.length > 5) { StringBuilder sb = new StringBuilder(); int strSize = 5; for (int i = 1; i < strSize; i++) { String str = strArray[i]; if(i == 3 && !str.equals(String.valueOf(year))){ sb.append(year); sb.append(" "); strSize = 4; } sb.append(str); sb.append(" "); } sb.deleteCharAt(sb.length() - 1); try { Date parse = sdf.parse(sb.toString()); flag = !parse.before(calendar.getTime()); } catch (ParseException e) { } } return flag; } /** * 发送info命令查看aof rewrite是否结束 * @param instanceInfo * @return */ private boolean checkInProgress(InstanceInfo instanceInfo, long startTime){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); long appId = instanceInfo.getAppId(); Jedis jedis = null; boolean reConfirmFlag = true; long costTime = 0L; try { jedis = redisCenter.getAdminJedis(appId, host, port); int retryTimes = 1; long sleepTime = 500L; boolean printMemory = true; while(reConfirmFlag && retryTimes < 40){ try { Thread.sleep(retryTimes * sleepTime > 3000L ? 3000L : retryTimes * sleepTime ); } catch (InterruptedException e) { } String info = jedis.info("all"); Map> infoStats = processRedisStats(info); Map persistenceMap = infoStats.get(RedisConstant.Persistence); if(printMemory){ Map memoryMap = infoStats.get(RedisConstant.Memory); String used_memory_human = MapUtils.getString(memoryMap, "used_memory_human"); log.info("实例appId:{}, ip:{}, port:{},retryTimes:{}, info used_memory_human: {}", appId, host, port, retryTimes, used_memory_human); printMemory = false; } String aof_rewrite_in_progress = MapUtils.getString(persistenceMap, "aof_rewrite_in_progress"); if("0".equals(aof_rewrite_in_progress)){ reConfirmFlag = false; long lastCostTime = MapUtils.getLong(persistenceMap, "aof_last_rewrite_time_sec"); if(lastCostTime != 0L && lastCostTime != -1L){ costTime = lastCostTime * 1000; }else{ costTime = System.currentTimeMillis() - startTime; } } retryTimes++; } log.info("实例appId:{}, ip:{}, port:{},重试次数:{}, 最终结果(结束false/未结束true):{},耗时:{}ms", instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), retryTimes - 1, reConfirmFlag, costTime); } catch (Exception e) { log.error("实例appId:{}, host:{}, port:{}, redis-checkInProgress errorMsg:{}", appId, host, port, e.getMessage()); } finally { if (jedis != null) jedis.close(); } return reConfirmFlag; } /** * 处理redis统计信息 * * @param statResult 统计结果串 */ private Map> processRedisStats(String statResult) { Map> redisStatMap = new HashMap>(); String[] data = statResult.split("\r\n"); String key; int i = 0; int length = data.length; while (i < length) { if (data[i].contains("#")) { int index = data[i].indexOf('#'); key = data[i].substring(index + 1); ++i; RedisConstant redisConstant = RedisConstant.value(key.trim()); if (redisConstant == null) { continue; } Map sectionMap = new LinkedHashMap(); while (i < length && data[i].contains(":")) { String[] pair = StringUtils.splitByWholeSeparator(data[i], ":"); sectionMap.put(pair[0], pair[1]); i++; } redisStatMap.put(redisConstant, sectionMap); } else { i++; } } return redisStatMap; } /** * 查看实例日志中,aof rewrite是否被terminated 或 redis是否crashed by signal: 11 * @param instanceInfo * @return */ private String getRecentLog(InstanceInfo instanceInfo){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); String logType = ""; if (TypeUtil.isRedisDataType(type)) { logType = "redis-"; } else if (TypeUtil.isRedisSentinel(type)) { logType = "redis-sentinel-"; } String remoteFilePath = getMachineRelativeDir(host, DirEnum.LOG_DIR.getValue()) + logType + port + "-*.log"; StringBuilder command = new StringBuilder(); command.append("/usr/bin/tail -n").append(1000).append(" ").append(remoteFilePath); try { return SSHUtil.execute(host, command.toString()); } catch (SSHException e) { log.error("实例appId:{}, host:{}, port:{}, redis-checkInProgress errorMsg:{}", instanceInfo.getAppId(), host, port, e.getMessage()); return null; } } /** * 获取日志相对路径 * @param host * @param dirType * @return */ public String getMachineRelativeDir(String host, int dirType) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo != null && machineInfo.isK8sMachine(machineInfo.getK8sType())) { return MachineProtocol.getK8sDir(host, dirType); } return MachineProtocol.getDir(dirType); } @Override public void saveRedisCommandCheckResult(RedisCommandCheckResult redisCommandCheckResult, AppRedisCommandCheckResult checkResult) { if(redisCommandCheckResult != null){ Long llen = assistRedisService.llen(REDIS_COMMAND_CHECK_RESULT_SAVE_KEY); if(llen >= 20){ String configResult = assistRedisService.lpop(REDIS_COMMAND_CHECK_RESULT_SAVE_KEY); RedisCommandCheckResult toRemoveResult = JSONObject.parseObject(configResult, RedisCommandCheckResult.class); assistRedisService.remove(REDIS_COMMAND_CHECK_RESULT_KEY + toRemoveResult.getKey()); } assistRedisService.rpush(REDIS_COMMAND_CHECK_RESULT_SAVE_KEY, JSONObject.toJSONString(redisCommandCheckResult)); if(checkResult != null && CollectionUtils.isNotEmpty(checkResult.getInstanceCheckList())){ assistRedisService.set(REDIS_COMMAND_CHECK_RESULT_KEY + redisCommandCheckResult.getKey(), JSONObject.toJSONString(checkResult)); } } } @Override public List getRedisCommandCheckResult() { List lists = new ArrayList<>(); List lrange = assistRedisService.lrange(REDIS_COMMAND_CHECK_RESULT_SAVE_KEY, 0, 20); if(CollectionUtils.isNotEmpty(lrange)){ for (String str : lrange) { lists.add(JSONObject.parseObject(str, RedisCommandCheckResult.class)); } } lists = lists.stream().sorted(Comparator.comparing(RedisCommandCheckResult::getCreateTime).reversed()).collect(Collectors.toList()); return lists; } @Override public AppRedisCommandCheckResult getRedisCommandCheckDetailResult(String uuid) { AppRedisCommandCheckResult checkResult = null; String resultStr = assistRedisService.get(REDIS_COMMAND_CHECK_RESULT_KEY + uuid); if(StringUtils.isNotEmpty(resultStr)){ checkResult = JSONObject.parseObject(resultStr, AppRedisCommandCheckResult.class); } return checkResult; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppRedisConfigCheckServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppStatusEnum; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppSearch; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.CompareTypeEnum; import com.sohu.cache.web.service.AppRedisConfigCheckService; import com.sohu.cache.web.vo.AppRedisConfigCheckResult; import com.sohu.cache.web.vo.AppRedisConfigCheckVo; import com.sohu.cache.web.vo.InstanceRedisConfigCheckResult; import com.sohu.cache.web.vo.RedisConfigCheckResult; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import java.util.*; import java.util.stream.Collectors; /** * @Author: zengyizhao * @DateTime: 2021/9/26 17:34 * @Description: redis配置检测 */ @Slf4j @Service public class AppRedisConfigCheckServiceImpl implements AppRedisConfigCheckService { @Autowired private AppDao appDao; @Autowired private InstanceDao instanceDao; @Autowired private RedisCenter redisCenter; @Autowired private AssistRedisService assistRedisService; private static final String REDIS_CHECK_RESULT_SAVE_KEY = "redis:check:result"; private static final String REDIS_CHECK_RESULT_KEY = "redis:check:result:"; @Override public RedisConfigCheckResult checkRedisConfig(AppUser appUser, AppRedisConfigCheckVo configCheckVo) { RedisConfigCheckResult redisConfigCheckResult = new RedisConfigCheckResult(); redisConfigCheckResult.setUserName(appUser.getChName() == null ? appUser.getName() : appUser.getChName()); redisConfigCheckResult.setCreateTime(new Date()); redisConfigCheckResult.setSuccess(true); BeanUtils.copyProperties(configCheckVo, redisConfigCheckResult); List configCheckResults = new ArrayList<>(); //获取待检测配置项 String configName = configCheckVo.getConfigName(); //trim一下首尾 String expectValue = configCheckVo.getExpectValue(); //获取应用(根据redis版本,用户指定应用id,全部) List appDescList = getAppByCondition(configCheckVo.getAppId(), configCheckVo.getVersionId()); //获取检测规则, 并校验 int compareType = configCheckVo.getCompareType(); CompareTypeEnum compareTypeEnum = getCompareType(compareType); if(compareTypeEnum == null){ return null; } //递归对每个应用进行处理(1.获取应用下实例; 2.根据检测项获取配置值,与检测规则对比,得出结果; 3.每个应用的配置值进行对比,并返回校验失败的信息) for(AppDesc appDesc : appDescList){ AppRedisConfigCheckResult appCheckResult = new AppRedisConfigCheckResult(); appCheckResult.setAppDesc(appDesc); appCheckResult.setCompareType(compareType); appCheckResult.setConfigName(configName); appCheckResult.setExpectValue(expectValue); appCheckResult.setVersionId(configCheckVo.getVersionId()); appCheckResult.setSuccess(true); appCheckResult.setCreateTime(new Date()); List instanceCheckResultList = new ArrayList<>(); List instanceInfoList = getInstanceInfoListByApp(appDesc.getAppId()); for (InstanceInfo instanceInfo : instanceInfoList) { BooleanEnum master = redisCenter.isMaster(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); if(master.equals(BooleanEnum.OTHER)){ continue; } InstanceRedisConfigCheckResult instanceCheckResult = new InstanceRedisConfigCheckResult(); instanceCheckResult.setInstanceInfo(instanceInfo); String realValue = getConfigByCommand(appDesc, instanceInfo, configName); boolean checkResult = checkConfigSatisfy(expectValue, realValue, compareTypeEnum); if(!checkResult){ redisConfigCheckResult.setSuccess(false); appCheckResult.setSuccess(false); instanceCheckResult.setSuccess(false); instanceCheckResult.setConfigName(configName); instanceCheckResult.setExpectValue(expectValue); instanceCheckResult.setRealValue(realValue); }else{ instanceCheckResult.setSuccess(true); } instanceCheckResultList.add(instanceCheckResult); } appCheckResult.setInstanceCheckList(instanceCheckResultList); configCheckResults.add(appCheckResult); } UUID uuid = UUID.randomUUID(); redisConfigCheckResult.setKey(uuid.toString()); this.saveRedisConfigCheckResult(redisConfigCheckResult, configCheckResults); return redisConfigCheckResult; } /** * 获取比较类型 * @param compareType * @return */ private CompareTypeEnum getCompareType(int compareType) { return CompareTypeEnum.getByType(compareType); } /** * 根据(appId, versionId)查询应用 * @param appId * @param versionId * @return */ private List getAppByCondition(Long appId, Integer versionId){ AppSearch appSearch = new AppSearch(); appSearch.setAppId(appId); appSearch.setVersionId(versionId); appSearch.setAppStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus()); List allAppDescList = appDao.getAllAppDescList(appSearch); return allAppDescList; } /** * 查询应用下有效的实例信息 * @param appId * @return */ private List getInstanceInfoListByApp(Long appId){ // 2.获取当前应用下redis实例信息 List instanceList = instanceDao.getInstListByAppId(appId);; //过滤出运行中的实例 instanceList = instanceList.stream().filter(instanceInfo -> instanceInfo.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus()).collect(Collectors.toList()); return instanceList; } /** * 通过config get获取配置项的值 * @param appDesc * @param instanceInfo * @param configName * @return */ private String getConfigByCommand(AppDesc appDesc, InstanceInfo instanceInfo, String configName){ String configValue = null; // 1.获取连接 final Jedis jedis = redisCenter.getAdminJedis(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000); try { List strings = jedis.configGet(configName); if(strings != null && strings.size() > 1){ configValue = strings.get(1); } } catch (Exception e) { if(e instanceof JedisConnectionException){ configValue = "连接失败,未取到值"; }else if(e instanceof JedisDataException){ if(e.getMessage().contains("ERR unknown command `CONFIG`, with args beginning with: `get`, ")){ configValue = "无此配置,未取到值"; } } if(configValue == null){ configValue = "异常,未取到值"; } log.error("getConfigByCommand", e); } finally { if (jedis != null) jedis.close(); } return configValue; } private boolean checkConfigSatisfy(String expectValue, String realValue, CompareTypeEnum compareTypeEnum){ boolean resultFlag = false; if(StringUtil.isBlank(expectValue)){ expectValue = ""; } if(CompareTypeEnum.EQUAL.equals(compareTypeEnum)){ if(StringUtil.isBlank(realValue) && StringUtil.isBlank(expectValue)){ resultFlag = true; }else { resultFlag = expectValue.equals(realValue); } return resultFlag; }else if(CompareTypeEnum.NOT_EQUAL.equals(compareTypeEnum)){ if(StringUtil.isBlank(realValue) && StringUtil.isBlank(expectValue)){ resultFlag = false; }else { resultFlag = !expectValue.equals(realValue); } return resultFlag; }else { if(StringUtil.isBlank(realValue) || StringUtil.isBlank(expectValue)){ return resultFlag; } Integer compare = null; try{ long l = Long.parseLong(realValue); long l1 = Long.parseLong(expectValue); compare = Long.compare(l, l1); }catch (Exception e){ } if(compare == null){ try{ double v = Double.parseDouble(realValue); double v1 = Double.parseDouble(expectValue); compare = Double.compare(v, v1); }catch (Exception e){ } } if(compare == null){ return resultFlag; } if(CompareTypeEnum.LESS_THAN.equals(compareTypeEnum)){ return compare < 0; } if(CompareTypeEnum.MORE_THAN.equals(compareTypeEnum)){ return compare > 0; } return resultFlag; } } @Override public void saveRedisConfigCheckResult(RedisConfigCheckResult redisConfigCheckResult, List resultList) { if(redisConfigCheckResult != null){ Long llen = assistRedisService.llen(REDIS_CHECK_RESULT_SAVE_KEY); if(llen >= 20){ String configResult = assistRedisService.lpop(REDIS_CHECK_RESULT_SAVE_KEY); RedisConfigCheckResult toRemoveResult = JSONObject.parseObject(configResult, RedisConfigCheckResult.class); assistRedisService.remove(REDIS_CHECK_RESULT_KEY + toRemoveResult.getKey()); } assistRedisService.rpush(REDIS_CHECK_RESULT_SAVE_KEY, JSONObject.toJSONString(redisConfigCheckResult)); if(CollectionUtils.isNotEmpty(resultList)){ assistRedisService.set(REDIS_CHECK_RESULT_KEY + redisConfigCheckResult.getKey(), JSONObject.toJSONString(resultList)); } } } @Override public List getRedisConfigCheckResult() { List lists = new ArrayList<>(); List lrange = assistRedisService.lrange(REDIS_CHECK_RESULT_SAVE_KEY, 0, 20); if(CollectionUtils.isNotEmpty(lrange)){ for (String str : lrange) { lists.add(JSONObject.parseObject(str, RedisConfigCheckResult.class)); } } lists = lists.stream().sorted(Comparator.comparing(RedisConfigCheckResult::getCreateTime).reversed()).collect(Collectors.toList()); return lists; } @Override public List getRedisConfigCheckDetailResult(String uuid) { List configCheckResults = new ArrayList<>(); String resultStr = assistRedisService.get(REDIS_CHECK_RESULT_KEY + uuid); if(!StringUtil.isBlank(resultStr)){ configCheckResults = JSONObject.parseArray(resultStr, AppRedisConfigCheckResult.class); } return configCheckResults; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppScrollRestartServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.alibaba.fastjson.JSONObject; import com.sohu.cache.constant.AppDescEnum; import com.sohu.cache.constant.InstanceStatusEnum; import com.sohu.cache.dao.ConfigRestartRecordDao; import com.sohu.cache.dao.InstanceConfigDao; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.*; import com.sohu.cache.exception.SSHException; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.redis.enums.DirEnum; import com.sohu.cache.redis.enums.RedisConfigEnum; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.IdempotentConfirmer; import com.sohu.cache.util.StringUtil; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.AppTypeEnum; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.MasterSlaveExistEnum; import com.sohu.cache.web.enums.RestartStatusEnum; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.util.DateUtil; import com.sohu.cache.web.util.Page; import com.sohu.cache.web.vo.AppRedisConfigVo; import com.sohu.cache.web.vo.ExecuteResult; import com.sohu.cache.web.vo.MasterSlaveGroupBo; import com.sohu.cache.web.vo.RedisConfigVo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.ui.Model; import org.springframework.util.CollectionUtils; import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisDataException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * @Author: zengyizhao * @DateTime: 2021/9/13 16:10 * @Description: */ @Slf4j @Service public class AppScrollRestartServiceImpl implements AppScrollRestartService { @Autowired private MachineDao machineDao; @Autowired private InstanceConfigDao instanceConfigDao; @Autowired private RedisCenter redisCenter; @Autowired private RedisDeployCenter redisDeployCenter; @Autowired protected InstanceDeployCenter instanceDeployCenter; @Autowired private ConfigRestartRecordDao configRestartRecordDao; @Autowired protected AppService appService; @Autowired private AssistRedisService assistRedisService; @Value("${cachecloud.redis.config-test.appid:#{null}}") private Long TEST_APP_ID; private static final String RESTART_LOG_KEY = "restart:log:"; private final static String RESTART_CONFIG_KEY = "restart:config:"; private final static String RESTART_STOP_KEY = "restart:stop:"; private final static String INTERRUPT_STOP = ">>>>> 被中断 >>>>>"; /** * * @param instanceInfoList * @param appDesc * @return */ @Override public boolean handleAppInstanceInfo(List instanceInfoList, AppDesc appDesc) { boolean resultFlag = true; if (instanceInfoList != null && instanceInfoList.size() > 0) { for (InstanceInfo instanceInfo : instanceInfoList) { int type = instanceInfo.getType(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 幂等操作 BooleanEnum isMaster = BooleanEnum.OTHER; int retryTime = 3; while (BooleanEnum.OTHER.equals(isMaster) && retryTime-- > 0){ isMaster = redisCenter.isMaster(instanceInfo.getAppId(), host, port); } if(BooleanEnum.OTHER.equals(isMaster)){ return false; } instanceInfo.setRoleDesc(isMaster); if (BooleanEnum.FALSE == isMaster) { retryTime = 3; HostAndPort hap = null; while (hap == null && retryTime-- > 0){ hap = redisCenter.getMaster(host, port, appDesc.getAppPassword()); } if(hap == null){ return false; } if (hap != null) { instanceInfo.setMasterHost(hap.getHost()); instanceInfo.setMasterPort(hap.getPort()); for (InstanceInfo innerInfo : instanceInfoList) { if (innerInfo.getIp().equals(hap.getHost()) && innerInfo.getPort() == hap.getPort()) { instanceInfo.setMasterInstanceId(innerInfo.getId()); break; } } } } } } } return resultFlag; } @Override public Map> instanceGroupByMaster(List instanceList) { Map> resultMap = new HashMap>(); for (InstanceInfo info : instanceList) { String roleDesc = info.getRoleDesc(); if (roleDesc != null && roleDesc.equals("master")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getId(), new ArrayList()); list.add(info); resultMap.put(info.getId(), list); } else if (roleDesc != null && roleDesc.equals("slave")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getMasterInstanceId(), new ArrayList()); list.add(info); resultMap.put(info.getMasterInstanceId(), list); } } return resultMap; } @Override public long generateAndSaveConfigRestartRecord(AppUser appUser, AppDesc appDesc, Object paramObject, Integer opertateType, List instanceInfoList){ ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setAppId(appDesc.getAppId()); configRestartRecord.setAppName(appDesc.getName()); configRestartRecord.setParam(JSONObject.toJSONString(paramObject)); if(opertateType == null){ if(paramObject instanceof AppRedisConfigVo){ configRestartRecord.setOperateType(((AppRedisConfigVo)paramObject).isConfigFlag() == true ? 1 : 0); } }else{ configRestartRecord.setOperateType(opertateType); } List instanceIdList = new ArrayList<>(); if(instanceInfoList != null && instanceInfoList.size() > 0){ instanceInfoList.forEach(instanceInfo -> instanceIdList.add(instanceInfo.getId())); } configRestartRecord.setInstances(JSONObject.toJSONString(instanceIdList)); Date date = new Date(); configRestartRecord.setCreateTime(date); configRestartRecord.setEndTime(date); configRestartRecord.setStartTime(date); configRestartRecord.setUpdateTime(date); configRestartRecord.setStatus(RestartStatusEnum.RUNNING.getValue()); configRestartRecord.setUserId(appUser.getId()); configRestartRecord.setUserName(appUser.getChName()); this.saveConfigRestartRecord(configRestartRecord); return configRestartRecord.getId(); } @Override public void saveConfigRestartRecord(ConfigRestartRecord configRestartRecord) { configRestartRecordDao.save(configRestartRecord); } @Override public void updateConfigRestartRecord(ConfigRestartRecord configRestartRecord) { configRestartRecordDao.updateByCondition(configRestartRecord); } @Override public ConfigRestartRecord getConfigRestartRecord(long id) { ConfigRestartRecord configRestartRecord = configRestartRecordDao.getById(id); if(RestartStatusEnum.WAITING.getValue() == configRestartRecord.getStatus() || RestartStatusEnum.RUNNING.getValue() == configRestartRecord.getStatus()){ List logList = assistRedisService.lrange(RESTART_LOG_KEY + id, 0, -1); configRestartRecord.setLog(JSONObject.toJSONString(logList)); } return configRestartRecord; } @Override public List getConfigRestartRecordByCondition(Model model, ConfigRestartRecord configRestartRecordParam, int pageNo, int pageSize) { int totalCount = configRestartRecordDao.getCountByCondition(configRestartRecordParam); Page page = new Page(pageNo, pageSize, totalCount); model.addAttribute("page", page); // 分页相关:list configRestartRecordParam.setPage(page); List listByCondition = configRestartRecordDao.getListByCondition(configRestartRecordParam); listByCondition.stream().forEach(configRestartRecord -> { if(RestartStatusEnum.WAITING.getValue() == configRestartRecord.getStatus() || RestartStatusEnum.RUNNING.getValue() == configRestartRecord.getStatus() || RestartStatusEnum.NEED_RESTART.getValue() == configRestartRecord.getStatus() || RestartStatusEnum.RESTART_AFTER_CONFIG.getValue() == configRestartRecord.getStatus() ){ List logList = assistRedisService.lrange(RESTART_LOG_KEY + configRestartRecord.getId(), 0, -1); configRestartRecord.setLog(JSONObject.toJSONString(logList)); } }); return listByCondition; } @Override public void saveConfigRestartLog(long id, String log) { assistRedisService.rpush(RESTART_LOG_KEY + id, log); } @Override public List getAndDeleteConfigRestartLog(long id){ List logList = assistRedisService.lrange(RESTART_LOG_KEY + id, 0, -1); assistRedisService.remove(RESTART_LOG_KEY + id); return logList; } @Override public void deleteConfigRestartLog(long id){ assistRedisService.remove(RESTART_LOG_KEY + id); } /** * 更新修改配置、重启记录 * @param recordId * @param restartStatusEnum * @param lastLog */ @Override public void updateConfigRestartRecord(long recordId, RestartStatusEnum restartStatusEnum, String... lastLog) { ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setId(recordId); configRestartRecord.setStatus(restartStatusEnum.getValue()); List logList = new ArrayList<>(); if(!RestartStatusEnum.NEED_RESTART.equals(restartStatusEnum) && !RestartStatusEnum.RESTART_AFTER_CONFIG.equals(restartStatusEnum)){ logList = this.getAndDeleteConfigRestartLog(recordId); } if(lastLog != null && lastLog.length > 0){ logList.addAll(Arrays.asList(lastLog)); } if(!CollectionUtils.isEmpty(logList)){ configRestartRecord.setLog(JSONObject.toJSONString(logList)); } configRestartRecord.setEndTime(new Date()); this.updateConfigRestartRecord(configRestartRecord); } /** * 添加停止滚动重启标志 * @param appId * @return */ @Override public boolean addStopRestartFlag(Long appId) { boolean result = false; result = assistRedisService.set(RESTART_STOP_KEY + appId, 1); return result; } /** * 删除停止滚动重启标志 * @param appId * @return */ @Override public boolean deleteStopRestartFlag(Long appId) { boolean result = false; result = assistRedisService.del(RESTART_STOP_KEY + appId); return result; } /** * 判断是否有停止滚动重启标志 * @param appId * @return */ @Override public boolean existsStopRestartFlag(Long appId){ boolean result = false; result = assistRedisService.exists(RESTART_STOP_KEY + appId); return result; } /** * 滚动重启处理 * @param appDesc * @param instanceInfoList * @param appRedisConfigVo * @return */ @Override public ExecuteResult handleRestart(AppUser appUser, AppDesc appDesc, List instanceInfoList, AppRedisConfigVo appRedisConfigVo){ if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ return ExecuteResult.error("滚动重启/修改配置正在执行中,不允许重复操作。"); } log.info(String.format("restart info, appId: %s, instanceInfoList: %s, paramInfo: %s", appDesc.getAppId(), instanceInfoList, appRedisConfigVo)); //拆分实例为,主从分组 Map> groupMap = this.instanceGroupByMaster(instanceInfoList); //筛选出需要处理的实例 List instanceIdList = appRedisConfigVo.getInstanceList(); List pointedInstanceList = this.filterPointedInstance(instanceInfoList, instanceIdList); //走重启逻辑, 校验相关的实例是否为主从备份 boolean check = this.checkIsMasterSlavePair(pointedInstanceList, groupMap); if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ return ExecuteResult.error("滚动重启/修改配置正在执行中,不允许重复操作。"); } if(!check){ String tipInfo = "集群主从实例不满足操作"; return ExecuteResult.error(tipInfo); } if(assistRedisService.get(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()) != null){ return ExecuteResult.error("滚动重启/修改配置正在执行中,不允许重复操作。"); } //按实例主从分组处理——重启实例, 异步 AsyncRestartService asyncRestartService = new AsyncRestartService(appUser, appDesc, appRedisConfigVo, instanceInfoList, pointedInstanceList, groupMap); asyncRestartService.start(); return ExecuteResult.ok("重启进行中,请前往查看进程记录。"); } /** * 处理修改配置 * @param appUser * @param appDesc * @param instanceInfoList * @param appRedisConfigVo * @return */ @Override public Map handleConfig(AppUser appUser, AppDesc appDesc, List instanceInfoList, AppRedisConfigVo appRedisConfigVo){ Map map = new HashMap<>(); map.put("commandSet", false); //拆分实例为,主从分组 Map> groupMap = this.instanceGroupByMaster(instanceInfoList); //处理配置项,将相同配置名的归为一组进行处理 Map> redisConfigMap = this.groupRedisConfigByName(appRedisConfigVo.getConfigList()); //校验配置项合法性 boolean isSupport = this.checkConfigIsSupport(appDesc, redisConfigMap); if(!isSupport){ // map.put("errorInfo", String.format("配置模板中无此配置项:%s", redisConfigMap)); // return map; log.error(String.format("配置模板中无此配置项:%s", redisConfigMap)); } //筛选出需要处理的实例 List instanceIdList = appRedisConfigVo.getInstanceList(); List pointedInstanceList = this.filterPointedInstance(instanceInfoList, instanceIdList); //获取一个实例用于check config set是否可用 InstanceInfo toCheckInstance = this.getInstanceToCheckConfigSet(instanceInfoList, instanceIdList); //通过一个实例运行config set 判断是否成功,成功则全部通过进行处理。 Map toCheckInstanceConfig = this.getConfigByCommand(appDesc, toCheckInstance, redisConfigMap); int checkResult = this.checkConfigSetAvailable(appDesc, toCheckInstance, redisConfigMap); //保存重启记录 Integer operateType = 1; if(checkResult == 1 || checkResult == 2){ operateType = 2; } long recordId = this.generateAndSaveConfigRestartRecord(appUser, appDesc, appRedisConfigVo, operateType, instanceInfoList); appRedisConfigVo.setRecordId(recordId); map.put("recordId", recordId); // 仅修改相关实例的配置,无需重启 String errorInfo = null; if(checkResult == 1){ this.saveConfigRestartLog(recordId, this.generateLog("修改配置 >>>> 开始,共%s个实例, 配置信息为:%s", pointedInstanceList.size(), redisConfigMap)); //获取原有配置 List> pointedInstanceConfigList = new ArrayList<>(); for(int i = 0; i < pointedInstanceList.size(); i++){ InstanceInfo instanceInfo = pointedInstanceList.get(i); if(!InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc()) && !InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())){ continue; } } for(int i = 0; i < pointedInstanceList.size(); i++){ InstanceInfo instanceInfo = pointedInstanceList.get(i); if(!InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc()) && !InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())){ continue; } //获取原配置信息 Map configByCommand = null; if(instanceInfo.equals(toCheckInstance)){ configByCommand = toCheckInstanceConfig; }else{ configByCommand = this.getConfigByCommand(appDesc, instanceInfo, redisConfigMap); } long startTime = System.currentTimeMillis(); boolean configResult = this.configSetAndRewrite(appDesc, instanceInfo, redisConfigMap); long endTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("第%s个实例, 实例信息:%s, 原配置信息:%s,结果:%s,耗时:%s", (i + 1), instanceInfo.getHostPort(), configByCommand, (configResult ? "成功" : "失败"), this.getTimeBetween(endTime, startTime))); if(!configResult){ errorInfo = String.format("修改配置config set/rewrite失败, 请人工确认。节点信息如下:appId:%s,instanceId:%s,hostPort:%s", instanceInfo.getAppId(), instanceInfo.getId(), instanceInfo.getHostPort()); break; } } map.put("commandSet", true); map.put("errorInfo", errorInfo); if(StringUtil.isBlank(errorInfo)){ this.updateConfigRestartRecord(recordId, RestartStatusEnum.SUCCESS, this.generateLog("修改配置 >>>> 结束")); // 增加特殊逻辑,判断是否为修改maxMemory-policy,对应修改appDesc表设置 if (redisConfigMap.containsKey(RedisConfigEnum.MAXMEMORY_POLICY.getKey())) { Set maxMemoryPolicys = redisConfigMap.get(RedisConfigEnum.MAXMEMORY_POLICY.getKey()); if (org.apache.commons.collections.CollectionUtils.isNotEmpty(maxMemoryPolicys)) { String maxMemoryPolicy = maxMemoryPolicys.iterator().next(); AppDescEnum.MaxmemoryPolicyType maxmemoryPolicyType = AppDescEnum.MaxmemoryPolicyType.getByName(maxMemoryPolicy); if(maxmemoryPolicyType != null){ appService.updateAppMaxmemoryPolicy(appDesc.getAppId(), maxmemoryPolicyType.getType()); } } } }else{ this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog(errorInfo)); } return map; } if(checkResult == 2){ errorInfo = String.format("配置值不合法,配置:%s", redisConfigMap); map.put("commandSet", false); map.put("errorInfo", errorInfo); this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog(errorInfo)); return map; } //走重启逻辑, 校验相关的实例是否为主从备份 boolean check = this.checkIsMasterSlavePair(pointedInstanceList, groupMap); if(!check){ errorInfo = "集群主从实例不满足操作"; map.put("errorInfo", errorInfo); this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog(errorInfo)); return map; } //在测试机上进行测试 boolean testFlag = this.testUpdateConfigFileAndRestart(appDesc.getAppId(), redisConfigMap); if(!testFlag){ errorInfo = String.format("配置有严重错误或不支持,配置: %s", redisConfigMap); map.put("commandSet", false); map.put("errorInfo", errorInfo); this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog(errorInfo)); return map; } //按实例主从分组处理——修改配置实例 errorInfo = this.handleConfigByGroup(appDesc, appRedisConfigVo, pointedInstanceList, groupMap, redisConfigMap); map.put("errorInfo", errorInfo); return map; } @Override public boolean isAppOnScrollRestart(long appId) { ConfigRestartRecord configRestartRecord = new ConfigRestartRecord(); configRestartRecord.setAppId(appId); List restartList = configRestartRecordDao.getListByCondition(configRestartRecord); Optional restartRecordOptional = restartList.stream().filter(restartRecord -> restartRecord.getStatus() == RestartStatusEnum.RUNNING.getValue() || restartRecord.getStatus() == RestartStatusEnum.RESTART_AFTER_CONFIG.getValue()).findFirst(); return restartRecordOptional.isPresent(); } /** * 校验相关的实例是否为主从备份 * @param pointedInstanceList 指定的某些节点, 可为空 * @param groupMap 已根据主从进行分组,参见#AppScrollRestartService.instanceGroupByMaster * @return false:不满足主从,true满足 */ private boolean checkIsMasterSlavePair(List pointedInstanceList, Map> groupMap){ if(CollectionUtils.isEmpty(pointedInstanceList)){ //校验是否均为主从备份 Set>> entries = groupMap.entrySet(); for (Map.Entry> entry : entries){ List instanceInfos = entry.getValue(); if(instanceInfos.size() < 2){ return false; } } }else{ for(InstanceInfo instanceInfo : pointedInstanceList){ if(InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())){ List instanceInfos = groupMap.get(instanceInfo.getId()); if(instanceInfos.size() < 2){ return false; } } if(InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())){ List instanceInfos = groupMap.get(instanceInfo.getMasterInstanceId()); if(instanceInfos.size() < 2){ return false; } } } } return true; } /** * 从实例中获取一个实例去进行config set 校验 * @param instanceInfoList * @param instanceIdList * @return */ private InstanceInfo getInstanceToCheckConfigSet(List instanceInfoList, List instanceIdList){ InstanceInfo toCheckInstance = null; if(CollectionUtils.isEmpty(instanceIdList)){ for(InstanceInfo instanceInfo : instanceInfoList){ if(InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())){ toCheckInstance = instanceInfo; break; } } if(toCheckInstance == null){ toCheckInstance = instanceInfoList.get(0); } }else{ for(InstanceInfo instanceInfo : instanceInfoList){ if(instanceInfo.getId() == instanceIdList.get(0)){ toCheckInstance = instanceInfo; break; } } } return toCheckInstance; } /** * 筛选出指定实例 * @param instanceInfoList * @param instanceIdList * @return */ private List filterPointedInstance(List instanceInfoList, List instanceIdList){ if(CollectionUtils.isEmpty(instanceIdList)){ return instanceInfoList; } List filterInstanceList = new ArrayList<>(); for(Integer instanceId : instanceIdList){ for(InstanceInfo instanceInfo : instanceInfoList){ if(instanceId == instanceInfo.getId()){ filterInstanceList.add(instanceInfo); break; } } } return filterInstanceList; } class AsyncRestartService extends Thread{ private AppUser appUser; private AppDesc appDesc; private AppRedisConfigVo appRedisConfigVo; private List instanceInfoList; private List pointedInstanceList; private Map> groupMap; public AsyncRestartService(){ } public AsyncRestartService(AppUser appUser, AppDesc appDesc, AppRedisConfigVo appRedisConfigVo, List instanceInfoList, List pointedInstanceList, Map> groupMap){ this.appUser = appUser; this.appDesc = appDesc; this.appRedisConfigVo = appRedisConfigVo; this.instanceInfoList = instanceInfoList; this.pointedInstanceList = pointedInstanceList; this.groupMap = groupMap; } @Override public void run() { handleRestartByGroup(appUser, appDesc, appRedisConfigVo, instanceInfoList, pointedInstanceList, groupMap); } } /** * 按实例主从分组重启, 异步 * @param appDesc * @param groupMap * @return */ @Override public void handleRestartByGroup(AppUser appUser, AppDesc appDesc, AppRedisConfigVo appRedisConfigVo, List instanceInfoList, List pointedInstanceList, Map> groupMap){ Long recordId = null; boolean restartAfterConfig = false; //保存重启记录 if(appRedisConfigVo.getRecordId() == null){ recordId = this.generateAndSaveConfigRestartRecord(appUser, appDesc, appRedisConfigVo, null, instanceInfoList); appRedisConfigVo.setRecordId(recordId); }else{ recordId = appRedisConfigVo.getRecordId(); restartAfterConfig = true; } if (!assistRedisService.setNx(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId(), "1")) { this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog("滚动重启/修改配置正在执行中,不允许重复操作。")); return; } if(assistRedisService.exists(RESTART_STOP_KEY + appRedisConfigVo.getAppId())){ assistRedisService.del(RESTART_STOP_KEY + appRedisConfigVo.getAppId()); } try{ if(restartAfterConfig){ this.updateConfigRestartRecord(recordId, RestartStatusEnum.RESTART_AFTER_CONFIG); } log.info(String.format("restart by group, start, appId: %s, paramInfo: %s", appDesc.getAppId(), appRedisConfigVo)); ExecuteResult executeResult = new ExecuteResult(); executeResult.setSuccess(false); boolean transferFlag = appRedisConfigVo.isTransferFlag(); boolean quickFinishFlag = appRedisConfigVo.isQuickFinishFlag(); Set>> entries = groupMap.entrySet(); //------------------------ int groupCount = 0; for(Map.Entry> map : entries) { MasterSlaveGroupBo masterSlaveGroupBo = this.getOneMasterSlaveGroup(pointedInstanceList, map); MasterSlaveExistEnum masterSlaveExistEnum = masterSlaveGroupBo.getMasterSlaveExistEnum();//1:only master;2:only slave;3:master and slave if (MasterSlaveExistEnum.NONE.equals(masterSlaveExistEnum)) { continue; } groupCount++; } this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 开始,主从分组共%s个", groupCount)); long initialStartTime = System.currentTimeMillis(); //------------------- int runGroup = 0; for(Map.Entry> map : entries){ MasterSlaveGroupBo masterSlaveGroupBo = this.getOneMasterSlaveGroup(pointedInstanceList, map); MasterSlaveExistEnum masterSlaveExistEnum = masterSlaveGroupBo.getMasterSlaveExistEnum();//1:only master;2:only slave;3:master and slave InstanceInfo oneGroupMaster = masterSlaveGroupBo.getMaster(); List oneGroupSlave = masterSlaveGroupBo.getSlaveList(); if(MasterSlaveExistEnum.NONE.equals(masterSlaveExistEnum)){ continue; } runGroup++; //处理当前某一分组 List slaveStrList = new ArrayList<>(); oneGroupSlave.forEach(slaveInfo -> slaveStrList.add(slaveInfo.getHostPort())); if(this.existsStopRestartFlag(appRedisConfigVo.getAppId())){ if(restartAfterConfig){ this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 被中断,请注意配置文件已修改,需人工判定生效范围及影响")); }else{ this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 被中断,请确认影响")); } this.updateConfigRestartRecord(recordId, RestartStatusEnum.INTERUPT); return; } this.saveConfigRestartLog(recordId, this.generateLog("处理第%s个主从分组开始,主节点信息:%s,从节点信息:%s,主从存在标志:%s", runGroup, oneGroupMaster.getHostPort(), slaveStrList, masterSlaveExistEnum.getInfo())); long startTime = System.currentTimeMillis(); executeResult = this.restartOneGroup(recordId, runGroup, appDesc, oneGroupMaster, oneGroupSlave, masterSlaveExistEnum, transferFlag, quickFinishFlag); long endTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("处理第%s个主从分组结束。结果为:%s,耗时:%s", runGroup, (executeResult.isSuccess() ? "成功" : executeResult.getMessage()), this.getTimeBetween(endTime, startTime))); if(!executeResult.isSuccess()){ //中断 if(executeResult.getMessage() != null && executeResult.getMessage().contains(INTERRUPT_STOP)){ long finalEndTime = System.currentTimeMillis(); if(restartAfterConfig){ this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 结束,被中断,请注意配置文件已修改,需人工判定生效范围及影响,主从分组共%s个,耗时:%s", groupCount, this.getTimeBetween(finalEndTime, initialStartTime))); }else{ this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 结束,被中断,主从分组共%s个,耗时:%s", groupCount, this.getTimeBetween(finalEndTime, initialStartTime))); } this.updateConfigRestartRecord(recordId, RestartStatusEnum.INTERUPT); return; }else{ //异常结束 long finalEndTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 结束,失败,耗时:%s", groupCount, this.getTimeBetween(finalEndTime, initialStartTime))); this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL); return; } } } long finalEndTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("滚动重启 >>>>>> 结束,主从分组共%s个,耗时:%s", groupCount, this.getTimeBetween(finalEndTime, initialStartTime))); //正常结束 this.updateConfigRestartRecord(recordId, RestartStatusEnum.SUCCESS); return; }catch (Exception e){ log.error("handleRestartByGroup error: ", e); }finally { assistRedisService.remove(RESTART_CONFIG_KEY + appRedisConfigVo.getAppId()); this.deleteStopRestartFlag(appRedisConfigVo.getAppId()); } } /** * 按实例主从分组配置 * @param appDesc * @param groupMap * @return */ private String handleConfigByGroup(AppDesc appDesc, AppRedisConfigVo appRedisConfigVo, List pointedInstanceList, Map> groupMap, Map> redisConfigMap){ Long recordId = appRedisConfigVo.getRecordId(); boolean transferFlag = appRedisConfigVo.isTransferFlag(); StringBuilder sb = new StringBuilder(); if(CollectionUtils.isEmpty(groupMap)){ return null; } Set>> entries = groupMap.entrySet(); //------------------------ int groupCount = 0; for(Map.Entry> map : entries) { MasterSlaveGroupBo masterSlaveGroupBo = this.getOneMasterSlaveGroup(pointedInstanceList, map); MasterSlaveExistEnum masterSlaveExistEnum = masterSlaveGroupBo.getMasterSlaveExistEnum();//1:only master;2:only slave;3:master and slave if (MasterSlaveExistEnum.NONE.equals(masterSlaveExistEnum)) { continue; } groupCount++; } this.saveConfigRestartLog(recordId, this.generateLog("强制修改配置 >>>> 开始,待处理主从分组共%s个,配置信息为:%s", groupCount, redisConfigMap)); long initialStartTime = System.currentTimeMillis(); //------------------- int runGroup = 0; for(Map.Entry> map : entries){ MasterSlaveGroupBo masterSlaveGroupBo = this.getOneMasterSlaveGroup(pointedInstanceList, map); MasterSlaveExistEnum masterSlaveExistEnum = masterSlaveGroupBo.getMasterSlaveExistEnum();//1:only master;2:only slave;3:master and slave InstanceInfo oneGroupMaster = masterSlaveGroupBo.getMaster(); List oneGroupSlave = masterSlaveGroupBo.getSlaveList(); if(MasterSlaveExistEnum.NONE.equals(masterSlaveExistEnum)){ continue; } runGroup++; //处理当前某一分组 long startTime = System.currentTimeMillis(); // this.saveConfigRestartLog(recordId, this.generateLog("强制修改配置,处理第%s个主从分组开始", runGroup)); String oneGroupError = this.configOneGroup(recordId, runGroup, appDesc, oneGroupMaster, oneGroupSlave, redisConfigMap, masterSlaveExistEnum, transferFlag); long endTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("第%s个主从分组结束。结果为:%s,耗时:%s" , runGroup, (StringUtil.isBlank(oneGroupError) ? "成功" : oneGroupError), this.getTimeBetween(endTime, startTime))); if(StringUtils.isNotEmpty(oneGroupError)){ sb.append(oneGroupError); sb.append(";\n"); this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL); return sb.toString(); } } long finalEndTime = System.currentTimeMillis(); if(StringUtil.isBlank(sb.toString())){ this.saveConfigRestartLog(recordId, this.generateLog("强制修改配置 >>>> 结束,结果为:%s,耗时:%s", (StringUtil.isBlank(sb.toString()) ? "成功" : sb.toString()), this.getTimeBetween(finalEndTime, initialStartTime))); this.saveConfigRestartLog(recordId, this.generateLog(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")); this.updateConfigRestartRecord(recordId, RestartStatusEnum.NEED_RESTART); }else{ this.updateConfigRestartRecord(recordId, RestartStatusEnum.FAIL, this.generateLog("强制修改配置 >>>> 结束,结果为:失败,失败信息:%s,耗时:%s", (StringUtil.isBlank(sb.toString()) ? "成功" : sb.toString()), this.getTimeBetween(finalEndTime, initialStartTime))); this.saveConfigRestartLog(recordId, this.generateLog(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")); } return sb.toString(); } /** * (根据指定实例),拆分出主节点,从节点(多个),及主从节点是否均包含 * @param pointedInstanceList * @param map * @return */ private MasterSlaveGroupBo getOneMasterSlaveGroup(List pointedInstanceList, Map.Entry> map){ MasterSlaveGroupBo masterSlaveGroupBo = new MasterSlaveGroupBo(); int masterSlaveFlag = 0;//1:only master;2:only slave;3:master and slave InstanceInfo oneGroupMaster = null; List oneGroupSlave = new ArrayList<>(); if(CollectionUtils.isEmpty(pointedInstanceList)){ List oneGroupList = map.getValue(); //获取当前分组主节点、从节点列表 for (InstanceInfo instanceInfo : oneGroupList) { if(InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc())){ oneGroupMaster = instanceInfo; } if(InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc())){ oneGroupSlave.add(instanceInfo); } } masterSlaveFlag = 3; }else{ List oneGroupList = map.getValue(); //从指定的实例中,获取当前分组待处理的主节点,从节点列表 for(int i = 0; i < pointedInstanceList.size(); i++){ InstanceInfo instanceInfo = pointedInstanceList.get(i); if(InstanceRoleEnum.MASTER.getInfo().equals(instanceInfo.getRoleDesc()) && instanceInfo.getId() == map.getKey()){ oneGroupMaster = instanceInfo; masterSlaveFlag = masterSlaveFlag > 0 ? 3 : 1; }else{ if(InstanceRoleEnum.SLAVE.getInfo().equals(instanceInfo.getRoleDesc()) && instanceInfo.getMasterInstanceId() == map.getKey()){ oneGroupSlave.add(instanceInfo); masterSlaveFlag = masterSlaveFlag > 0 ? (masterSlaveFlag == 2 ? 2: 3) : 2; } } if(i == pointedInstanceList.size() - 1 && masterSlaveFlag == 1){ for (InstanceInfo oneGroupInstance : oneGroupList) { if(InstanceRoleEnum.SLAVE.getInfo().equals(oneGroupInstance.getRoleDesc())){ oneGroupSlave.add(oneGroupInstance); break; } } } if(i == pointedInstanceList.size() - 1 && masterSlaveFlag == 2){ for (InstanceInfo oneGroupInstance : oneGroupList) { if(InstanceRoleEnum.MASTER.getInfo().equals(oneGroupInstance.getRoleDesc())){ oneGroupMaster = oneGroupInstance; break; } } } } } masterSlaveGroupBo.setMaster(oneGroupMaster); masterSlaveGroupBo.setMasterSlaveExistEnum(MasterSlaveExistEnum.getByType(masterSlaveFlag)); masterSlaveGroupBo.setSlaveList(oneGroupSlave); return masterSlaveGroupBo; } /** * 滚动重启:重启从节点,选某个从节点failover,重启原主节点,根据条件(在原主节点failover) * @param appDesc * @param master * @param slaveList * @param masterSlaveFlag * @param transferFlag * @return */ private ExecuteResult restartOneGroup(long recordId, int runGroup, AppDesc appDesc, InstanceInfo master, List slaveList, MasterSlaveExistEnum masterSlaveFlag , boolean transferFlag, boolean quickFinishFlag){ ExecuteResult executeResult = ExecuteResult.error(); log.info(String.format("restart by group one group, recordId: %s, master: %s, slaveList: %s, masterSlaveFlag: %s", recordId, master.getHostPort(), slaveList.stream().map(slaveInfo -> slaveInfo.getHostPort()).collect(Collectors.joining(",")), masterSlaveFlag)); if(this.existsStopRestartFlag(appDesc.getAppId())){ return ExecuteResult.error(String.format("本分组未开始时%s", INTERRUPT_STOP)); } if(MasterSlaveExistEnum.MASTRE_SLAVE.equals(masterSlaveFlag) || MasterSlaveExistEnum.SLAVE.equals(masterSlaveFlag)){ //重启并修改从节点 executeResult = this.restartSlaveNodes(recordId, appDesc, slaveList, master); if (!executeResult.isSuccess()) { return executeResult; } //判断是否与主节点完成同步 boolean slaveReady = this.checkSlaveReadyFinish(slaveList.get(0)); if(!slaveReady){ return ExecuteResult.error(String.format("判定从节点是否完成与主节点同步失败,slave :%s", slaveList.get(0))); } if(quickFinishFlag){ //重启节点后,休息3s try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { } }else { //重启节点后,休息30s try { TimeUnit.SECONDS.sleep(30); } catch (InterruptedException e) { } } } if(this.existsStopRestartFlag(appDesc.getAppId())){ return ExecuteResult.error(String.format("从节点重启后,从节点failover未开始,主节点重启未开始时%s", INTERRUPT_STOP)); } if(!MasterSlaveExistEnum.SLAVE.equals(masterSlaveFlag)){ //failover到从节点 Optional failOverResult = this.clusterFailoverSlaveInstanceAndCheck(recordId, slaveList.get(0), master, appDesc); if (failOverResult.isPresent()) { return ExecuteResult.error(String.format("对从节点执行failover失败,信息如下:%s", failOverResult.get())); } //failover后,休息120s if(quickFinishFlag){ try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { } }else{ try { TimeUnit.SECONDS.sleep(120); } catch (InterruptedException e) { } } if(this.existsStopRestartFlag(appDesc.getAppId())){ return ExecuteResult.error(String.format("从节点重启后,从节点failover后,主节点重启未开始时%s,请注意是否允许主从切换,并人工处理。", INTERRUPT_STOP)); } //重启原主节点 Optional restartResult = this.restartSlaveNode(recordId, appDesc, master, slaveList.get(0)); if (restartResult.isPresent()) { return ExecuteResult.error(restartResult.get()); } if (!transferFlag) { if(this.existsStopRestartFlag(appDesc.getAppId())){ return ExecuteResult.error(String.format("从节点重启后,从节点failover后,主节点重启后,主节点failover未开始时%s,请注意是否允许主从切换,并人工处理。", INTERRUPT_STOP)); } //判断是否与主节点完成同步 boolean slaveReady = this.checkSlaveReadyFinish(master); if(!slaveReady){ return ExecuteResult.error(String.format("判定从节点是否完成与主节点同步失败,slave :%s", slaveList.get(0))); } //对原主节点进行failover failOverResult = this.clusterFailoverSlaveInstanceAndCheck(recordId, master, slaveList.get(0), appDesc); if (failOverResult.isPresent()) { return ExecuteResult.error(String.format("对原主节点执行failover失败,信息如下:%s", failOverResult.get())); } //failover后,休息120s if(!quickFinishFlag){ try { TimeUnit.SECONDS.sleep(120); } catch (InterruptedException e) { } } } } return ExecuteResult.ok(); } /** * 修改配置 * 修改配置://只修改从节点(关闭从节点,修改配置文件,重启从节点) * 修改配置://只修改主节点(选某个从节点failover, 关闭原主节点,修改配置文件,重启原主节点,在原主节点failover) * 修改配置://修改主和从节点(关闭从节点,修改从节点配置,重启从节点,选某个从节点failover, 关闭原主节点,修改原主节点配置,重启原主节点,根据条件(在原主节点failover)) * @param appDesc * @param master * @param slaveList * @param masterSlaveExistEnum * @param transferFlag * @return */ private String configOneGroup(long recordId, int runGroup, AppDesc appDesc, InstanceInfo master, List slaveList, Map> redisConfigMap, MasterSlaveExistEnum masterSlaveExistEnum , boolean transferFlag){ if(MasterSlaveExistEnum.MASTRE_SLAVE.equals(masterSlaveExistEnum) || CollectionUtils.isEmpty(redisConfigMap) || MasterSlaveExistEnum.SLAVE.equals(masterSlaveExistEnum)){ //重启并修改从节点 String res = this.configNodes(appDesc, recordId, runGroup, slaveList, redisConfigMap); if (StringUtils.isNotEmpty(res)) { return res; } } if(!MasterSlaveExistEnum.SLAVE.equals(masterSlaveExistEnum)){ //重启并修改原主节点 long statTime = System.currentTimeMillis(); Map configByCommand = this.getConfigByCommand(appDesc, master, redisConfigMap); String res = this.configNode(appDesc, master, redisConfigMap); long endTime = System.currentTimeMillis(); this.saveConfigRestartLog(recordId, this.generateLog("第%s分组,主节点信息:%s,原配置信息:%s,结果:%s,耗时:%s", runGroup, master.getHostPort(), configByCommand, (StringUtil.isBlank(res) ? "成功" : "失败"), this.getTimeBetween(endTime, statTime))); if (StringUtils.isNotEmpty(res)) { return res; } } return null; } /** * 修改配置从节点 * @param instanceInfoList * @param redisConfigMap * @return */ private String configNodes(AppDesc appDesc, long recordId, int runGroup, List instanceInfoList, Map> redisConfigMap) { StringBuilder sb = new StringBuilder(); for(InstanceInfo instanceInfo : instanceInfoList){ long statTime = System.currentTimeMillis(); Map configByCommand = this.getConfigByCommand(appDesc, instanceInfo, redisConfigMap); String res = this.configNode(appDesc, instanceInfo, redisConfigMap); long endTime = System.currentTimeMillis(); //获取原配置信息 this.saveConfigRestartLog(recordId, this.generateLog("第%s分组,从节点信息:%s,原配置信息:%s,结果:%s,耗时:%s", runGroup, instanceInfo.getHostPort(), configByCommand, (StringUtil.isBlank(res) ? "成功" : "失败"), this.getTimeBetween(endTime, statTime))); if(StringUtils.isNotEmpty(res)){ sb.append(res); break; } } return sb.toString(); } /** * 修改配置从节点 * @param instanceInfo * @param redisConfigMap * @return */ private String configNode(AppDesc appDesc, InstanceInfo instanceInfo, Map> redisConfigMap) { boolean executeFlag = false; if(CollectionUtils.isEmpty(redisConfigMap)) { return null; } //修改配置 executeFlag = this.updateConfigFile(instanceInfo, redisConfigMap); if(!executeFlag){ return String.format("关闭节点后,修改配置文件失败,需进行手动重启,节点信息如下:appId:%s,instanceId:%s,hostPort:%s", instanceInfo.getAppId(), instanceInfo.getId(), instanceInfo.getHostPort()); } return null; } /** * 依次重启从节点,一旦有一个失败,则返回 * @param appDesc * @param slaveList * @param currentMaster * @return */ private ExecuteResult restartSlaveNodes(long recordId, AppDesc appDesc, List slaveList, InstanceInfo currentMaster) { ExecuteResult executeResult = ExecuteResult.error(); StringBuilder sb = new StringBuilder(); for(int i = 0; i < slaveList.size(); i++){ InstanceInfo instanceInfo = slaveList.get(i); Optional restartResult = this.restartSlaveNode(recordId, appDesc, instanceInfo, currentMaster); log.info(String.format("重启第%s个从节点,从节点信息:%s,结果为:%s", (i + 1), instanceInfo.getHostPort(), (restartResult.isPresent() ? restartResult.get() : "成功"))); // appScrollRestartService.saveConfigRestartLog(recordId, this.generateLog("重启第%s个从节点,从节点信息:%s,结果为:%s", (i + 1), instanceInfo.getHostPort(), (restartResult.isPresent() ? restartResult.get() : "成功"))); if(restartResult.isPresent()){ sb.append(String.format("重启从节点失败,instance:%s,失败信息:%s", instanceInfo.getHostPort(), restartResult.get())); sb.append("\n"); return executeResult.error(sb.toString()); }else{ sb.append(String.format("重启从节点成功,instance:%s", instanceInfo.getAppId(), instanceInfo.getHostPort())); sb.append("\n"); } } return ExecuteResult.ok(sb.toString()); } /** * 重启节点 * @param appDesc * @param instanceInfo * @return */ private Optional restartNode(Long recordId, AppDesc appDesc, InstanceInfo instanceInfo) { log.info(String.format("restart slave node, shutdown instance, start, recordId: %s, slaveInstance: %s", recordId, instanceInfo.getHostPort())); boolean executeFlag = this.shutdownInstanceIdempotent(3, recordId, appDesc, instanceInfo); log.info(String.format("restart slave node, shutdown instance, end, recordId: %s, slaveInstance: %s, result: %s", recordId, instanceInfo.getHostPort(), executeFlag)); if(!executeFlag){ return Optional.of(String.format("重启从节点,关闭从节点失败,节点信息:%s", instanceInfo.getHostPort())); } log.info(String.format("restart slave node, start instance, start, recordId: %s, slaveInstance: %s", recordId, instanceInfo.getHostPort())); executeFlag = startInstance(instanceInfo); log.info(String.format("restart slave node, start instance, end, recordId: %s, slaveInstance: %s, result: %s", recordId, instanceInfo.getHostPort(), executeFlag)); if(!executeFlag){ return Optional.of(String.format("重启从节点,关闭从节点后,重启从节点失败,节点信息:%s", instanceInfo.getHostPort())); } executeFlag = this.checkLoadFinish(instanceInfo); if(!executeFlag){ log.error(String.format("重启从节点,关闭从节点后,重启从节点,加载dump文件失败,任务继续。如有需要,请管理员确认,节点信息:%s", instanceInfo.getHostPort())); } return Optional.empty(); } /** * 关闭实例,幂等操作,目前最大支持3次 * @return */ private boolean shutdownInstanceIdempotent(int retryTime, Long recordId, AppDesc appDesc, InstanceInfo instanceInfo){ boolean executeFlag = false; long beginShutdown = System.currentTimeMillis(); executeFlag = shutdownInstance(instanceInfo); log.info(String.format("restart slave node, shutdown instance, recordId: %s, slaveInstance: %s, result: %s", recordId, instanceInfo.getHostPort(), executeFlag)); if(!executeFlag){ return false; } //2. check the slave node original process has release config file int tryTimes = 200; long sleepTime = 2L; while(tryTimes-- > 0){ try{ executeFlag = this.checkFileReleaseAfterShutdown(appDesc, instanceInfo); if(executeFlag){ break; } TimeUnit.SECONDS.sleep(sleepTime); if(tryTimes == 195){ // this.saveConfigRestartLog(recordId, this.generateLog("重启从节点, shutdown and check,持续10s仍未完成,请等待留意,节点信息:%s。", instanceInfo.getHostPort())); } if(tryTimes % 5 == 0){ boolean shutdownFailFlag = this.checkByLog(instanceInfo, "can't exit", beginShutdown); log.info(String.format("restart slave node, shutdown instance fail and retry check, recordId: %s, slaveInstance: %s, result: %s", recordId, instanceInfo.getHostPort(), shutdownFailFlag)); if(shutdownFailFlag && retryTime-- > 0){ log.info(String.format("restart slave node, shutdown instance fail and retry, recordId: %s, slaveInstance: %s, retryTime left : %s", recordId, instanceInfo.getHostPort(), retryTime)); TimeUnit.SECONDS.sleep(20 * (3 - retryTime) > 40 ? 40 : 20 * (3 - retryTime)); return this.shutdownInstanceIdempotent(retryTime, recordId, appDesc, instanceInfo); } } }catch (Exception e){ log.error("shutdown Instance error: ", e); continue; } } return executeFlag; } /** * 重启从节点 * @param appDesc * @param slaveInstance * @param currentMaster * @return */ private Optional restartSlaveNode(long recordId, AppDesc appDesc, InstanceInfo slaveInstance, InstanceInfo currentMaster) { //判断当前实例是否为从节点,且存在主节点,且master_link_status up BooleanEnum slaveAndMasterUp = BooleanEnum.FALSE; int tryTimes = 3; while (tryTimes-- > 0) { try { slaveAndMasterUp = redisCenter.isSlaveAndPointedMasterUp(appDesc, slaveInstance, currentMaster); if (BooleanEnum.TRUE.equals(slaveAndMasterUp)){ break; } TimeUnit.SECONDS.sleep(2L); } catch (Exception e) { log.error("restartSlaveNode check is Slave and master is up, error: ", e); continue; } } log.info(String.format("restart slave node, isSlaveAndPointedMasterUp check, recordId: %s, slaveInstance: %s, currentMaster: %s, slaveAndMasterUp: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort(), slaveAndMasterUp)); if(BooleanEnum.FALSE.equals(slaveAndMasterUp)){ return Optional.of("重启从节点,主从状态校验失败"); } return this.restartNode(recordId, appDesc, slaveInstance); } /** * 执行failover并检查是否成功 * @param slaveInstance * @param currentMaster * @param appDesc * @return */ private Optional clusterFailoverSlaveInstanceAndCheck(long recordId, InstanceInfo slaveInstance, InstanceInfo currentMaster, AppDesc appDesc){ try{ //判断当前实例是否为从节点,且存在主节点,且master_link_status up BooleanEnum slaveAndMasterUp = BooleanEnum.FALSE; int tryTimes = 300; while (tryTimes-- > 0) { try { BooleanEnum result = redisCenter.isSlaveAndPointedMasterUp(appDesc, slaveInstance, currentMaster); if (BooleanEnum.TRUE.equals(result)){ slaveAndMasterUp = result; break; } TimeUnit.SECONDS.sleep(2L); } catch (Exception e) { log.error("clusterFailoverSlaveInstanceAndCheck is Slave and master is pointed master error: ", e); continue; } } log.info(String.format("restart slave node, failover pre check, isSlaveAndPointedMasterUp, recordId: %s, slaveInstance: %s, currentMaster: %s, result: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort(), slaveAndMasterUp)); if(BooleanEnum.FALSE.equals(slaveAndMasterUp)){ return Optional.of(String.format("执行failover and check, 检验为从节点及与主节点连接正常,失败,从节点信息:%s,主节点信息:%s", slaveInstance.getHostPort(), currentMaster.getHostPort())); } log.info(String.format("restart slave node, failoverAndCheckIdempotent, start, recordId: %s, slaveInstance: %s, currentMaster: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort())); boolean isFailover = this.failoverAndCheckIdempotent(3, recordId, slaveInstance, currentMaster, appDesc); //failover后,检测是否完成主从同步 if(isFailover){ this.checkSlaveReadyFinish(currentMaster); log.info(String.format("restart slave node, failoverAndCheckIdempotent success and check new slave ready, recordId: %s, new slaveInstance: %s, currentMaster: %s, result: %s", recordId, currentMaster.getHostPort(), slaveInstance.getHostPort(), isFailover)); } log.info(String.format("restart slave node, failoverAndCheckIdempotent, end, recordId: %s, slaveInstance: %s, currentMaster: %s, result: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort(), isFailover)); if(!isFailover){ return Optional.of(String.format("执行failover and check失败,从节点信息:%s,主节点信息:%s", slaveInstance.getHostPort(), currentMaster.getHostPort())); } return Optional.empty(); }catch (Exception e){ log.error("clusterFailoverSlaveInstanceAndCheck is Slave and master is pointed master error: ", e); return Optional.of(String.format("执行failover and check,出现异常,异常信息:%s,从节点信息:%s,主节点信息:%s", e.getMessage(), slaveInstance.getHostPort(), currentMaster.getHostPort())); } } /** * 关闭实例,幂等操作,目前最大支持3次 * @return */ private boolean failoverAndCheckIdempotent(int retryTime, long recordId, InstanceInfo slaveInstance, InstanceInfo currentMaster, AppDesc appDesc){ long beginShutdown = System.currentTimeMillis(); boolean executeFlag = false; try{ if(AppTypeEnum.REDIS_CLUSTER.getType() == appDesc.getType()){ executeFlag = redisDeployCenter.clusterFailover(slaveInstance.getAppId(), slaveInstance.getId(), null); } }catch (Exception e){ log.error("cluster failover异常,异常信息:", e); } log.info(String.format("restart slave node, clusterFailover, recordId: %s, slaveInstance: %s, currentMaster: %s, result: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort(), executeFlag)); if (!executeFlag) { return executeFlag; } int tryTimes = 200; long sleepTime = 2L; while(tryTimes-- > 0){ try{ executeFlag = redisCenter.getRedisReplicationStatus(slaveInstance.getAppId(), slaveInstance.getIp(), slaveInstance.getPort()); if (executeFlag) { break; } TimeUnit.SECONDS.sleep(sleepTime); if(tryTimes == 195){ // this.saveConfigRestartLog(recordId, this.generateLog("failover and check, 持续10s仍未完成,请等待留意,节点信息:%s。", slaveInstance.getHostPort())); } if(tryTimes % 5 == 0){ boolean shutdownFailFlag = this.checkByLog(slaveInstance, "Manual failover timed out", beginShutdown); log.info(String.format("restart slave node, clusterFailover fail and retry check, recordId: %s, slaveInstance: %s, currentMaster: %s, result: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort(), shutdownFailFlag)); if(shutdownFailFlag && retryTime-- > 0){ log.info(String.format("restart slave node, clusterFailover fail and retry, recordId: %s, slaveInstance: %s, currentMaster: %s", recordId, slaveInstance.getHostPort(), currentMaster.getHostPort())); TimeUnit.SECONDS.sleep(20 * (3 - retryTime) > 40 ? 40 : 20 * (3 - retryTime)); return this.failoverAndCheckIdempotent(retryTime, recordId, slaveInstance, currentMaster, appDesc); } } }catch (Exception e){ log.error("failover and check error: ", e); continue; } } return executeFlag; } /** * 执行failover并检查 * @param slaveInstance 必须包括masterHost & masterPort * @param appDesc * @return */ public Optional clusterFailoverAndCheck(InstanceInfo slaveInstance, AppDesc appDesc){ InstanceInfo currentMaster = new InstanceInfo(); currentMaster.setAppId(slaveInstance.getAppId()); currentMaster.setType(slaveInstance.getType()); currentMaster.setIp(slaveInstance.getMasterHost()); currentMaster.setPort(slaveInstance.getMasterPort()); try{ // 先判断slave是否已load完成并ready, this.checkLoadFinish(slaveInstance); this.checkSlaveReadyFinish(slaveInstance); //判断当前实例是否为从节点,且存在主节点,且master_link_status up BooleanEnum slaveAndMasterUp = BooleanEnum.FALSE; int tryTimes = 300; while (tryTimes-- > 0) { try { BooleanEnum result = redisCenter.isSlaveAndPointedMasterUp(appDesc, slaveInstance, currentMaster); if (BooleanEnum.TRUE.equals(result)){ slaveAndMasterUp = result; break; } TimeUnit.SECONDS.sleep(2L); } catch (Exception e) { log.error("clusterFailoverAndCheck is Slave and master is pointed master error: ", e); continue; } } log.info(String.format("failover pre check, isSlaveAndPointedMasterUp, slaveInstance: %s, currentMaster: %s, result: %s", slaveInstance.getHostPort(), currentMaster.getHostPort(), slaveAndMasterUp)); if(BooleanEnum.FALSE.equals(slaveAndMasterUp)){ return Optional.of(String.format("执行failover and check, 检验为从节点及与主节点连接正常,失败,从节点信息:%s,主节点信息:%s", slaveInstance.getHostPort(), currentMaster.getHostPort())); } log.info(String.format("failoverAndCheckIdempotent, start, slaveInstance: %s, currentMaster: %s", slaveInstance.getHostPort(), currentMaster.getHostPort())); boolean isFailover = this.failoverAndCheckIdempotent(3, slaveInstance, appDesc); //failover后,检测是否完成主从同步 if(isFailover){ this.checkSlaveReadyFinish(currentMaster); log.info(String.format("failoverAndCheckIdempotent success and check slave ready, new slaveInstance: %s, currentMaster: %s, result: %s", currentMaster.getHostPort(), slaveInstance.getHostPort(), isFailover)); } log.info(String.format("failoverAndCheckIdempotent, end, slaveInstance: %s, currentMaster: %s, result: %s", slaveInstance.getHostPort(), currentMaster.getHostPort(), isFailover)); if(!isFailover){ return Optional.of(String.format("执行failover and check失败,从节点信息:%s,主节点信息:%s", slaveInstance.getHostPort(), currentMaster.getHostPort())); } return Optional.empty(); }catch (Exception e){ log.error("clusterFailoverSlaveInstanceAndCheck is Slave and master is pointed master error: ", e); return Optional.of(String.format("执行failover and check,出现异常,异常信息:%s,从节点信息:%s,主节点信息:%s", e.getMessage(), slaveInstance.getHostPort(), currentMaster.getHostPort())); } } /** * 关闭实例,幂等操作,目前最大支持3次 * @return */ @Override public boolean failoverAndCheckIdempotent(int retryTime, InstanceInfo slaveInstance, AppDesc appDesc){ long beginShutdown = System.currentTimeMillis(); boolean executeFlag = false; try{ if(AppTypeEnum.REDIS_CLUSTER.getType() == appDesc.getType()){ executeFlag = redisDeployCenter.clusterFailover(slaveInstance.getAppId(), slaveInstance.getId(), null); } }catch (Exception e){ log.error("cluster failover异常,异常信息:", e); } log.info(String.format("clusterFailover, slaveInstance: %s, currentMaster: %s, result: %s", slaveInstance.getHostPort(), (slaveInstance.getMasterHost() + ":" + slaveInstance.getMasterPort()), executeFlag)); if (!executeFlag) { return executeFlag; } int tryTimes = 200; long sleepTime = 2L; while(tryTimes-- > 0){ try{ if(TypeUtil.isRedisType(appDesc.getType())){ executeFlag = redisCenter.getRedisReplicationStatus(slaveInstance.getAppId(), slaveInstance.getIp(), slaveInstance.getPort()); } if (executeFlag) { break; } TimeUnit.SECONDS.sleep(sleepTime); if(TypeUtil.isRedisType(appDesc.getType())){ if(tryTimes % 5 == 0){ boolean shutdownFailFlag = this.checkByLog(slaveInstance, "Manual failover timed out", beginShutdown); log.info(String.format("clusterFailover fail and retry check, slaveInstance: %s, currentMaster: %s, result: %s", slaveInstance.getHostPort(), (slaveInstance.getMasterHost() + ":" + slaveInstance.getMasterPort()), shutdownFailFlag)); if(shutdownFailFlag && retryTime-- > 0){ log.info(String.format("clusterFailover fail and retry, slaveInstance: %s, currentMaster: %s", slaveInstance.getHostPort(), (slaveInstance.getMasterHost() + ":" + slaveInstance.getMasterPort()))); TimeUnit.SECONDS.sleep(20 * (3 - retryTime) > 40 ? 40 : 20 * (3 - retryTime)); return this.failoverAndCheckIdempotent(retryTime, slaveInstance, appDesc); } } } }catch (Exception e){ log.error("failover and check error: ", e); continue; } } return executeFlag; } /** * 下线实例 * @param instanceInfo * @return */ public boolean shutdownInstance(InstanceInfo instanceInfo) { if (instanceInfo != null) { try { boolean operationFlag = instanceDeployCenter.shutdownExistInstance(instanceInfo.getAppId(), instanceInfo.getId()); log.info("shutdown slave, appId:${}, instance:${}, result:${}", instanceInfo.getAppId(), instanceInfo.getHostPort(), operationFlag); return operationFlag; } catch (Exception e) { log.error("shutdown slave, appId: " + instanceInfo.getAppId() +", instance:" + instanceInfo.getHostPort() + ",异常:", e); return false; } } return true; } /** * 启动实例 * @param instanceInfo */ public boolean startInstance(InstanceInfo instanceInfo) { if (instanceInfo != null) { try { boolean operationFlag = instanceDeployCenter.startExistInstanceWithoutResourceCheck(instanceInfo.getAppId(), instanceInfo.getId()); log.info("restart slave node, start instance, appId:${}, instance:${}, result:${}", instanceInfo.getAppId(), instanceInfo.getHostPort(), operationFlag); return operationFlag; } catch (Exception e) { log.error("restart slave node, start instance, error, appId: " + instanceInfo.getAppId() +", instance:" + instanceInfo.getHostPort() + ",异常:", e); return false; } } return false; } /** * 判断实例是否完成加载dump文件 * @param instanceInfo */ public boolean checkLoadFinish(InstanceInfo instanceInfo) { boolean loadFinish = false; if (instanceInfo != null) { int retry = 3; while (retry-- > 0) { // 1.获取连接 try (Jedis jedis = redisCenter.getAdminJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000);) { if(TypeUtil.isRedisType(instanceInfo.getType())){ loadFinish = redisCenter.checkLoadFinish(jedis, 5); } log.info("checkLoadFinish instance, appId:${}, instance:${}, result:${}", instanceInfo.getAppId(), instanceInfo.getHostPort(), loadFinish); if(loadFinish){ break; } } catch (Exception e) { log.error("restart slave node, start instance, error, appId: " + instanceInfo.getAppId() + ", instance:" + instanceInfo.getHostPort() + ",异常:", e); } } } return loadFinish; } /** * 判断实例是否准备完成 * @param instanceInfo */ public boolean checkSlaveReadyFinish(InstanceInfo instanceInfo) { boolean slaveReady = false; if (instanceInfo != null) { try { int checkTimes = 100; while (checkTimes-- > 0){ // 1.获取连接 try (Jedis jedis = redisCenter.getAdminJedis(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000);){ if(TypeUtil.isRedisType(instanceInfo.getType())){ slaveReady = redisCenter.checkSlaveReady(jedis, null); } log.info("checkSlaveReadyFinish instance, appId:${}, instance:${}, result:${}", instanceInfo.getAppId(), instanceInfo.getHostPort(), slaveReady); if(slaveReady){ break; } TimeUnit.SECONDS.sleep(5); } catch (Exception e) { log.error("checkSlaveReadyFinish, instance, error, appId: " + instanceInfo.getAppId() +", instance:" + instanceInfo.getHostPort() + ",异常:", e); } } } catch (Exception e) { log.error("{}:{} checkSlaveReadyFinish failed {}", instanceInfo.getIp(), instanceInfo.getPort(), e.getMessage(), e); } } return slaveReady; } /** * check whether config set is ok with this to updated config name * just support check one config name, if more than one, update this logic code * @param instanceInfo * @return 0:失败;1:成功;2:配置值错误 */ private int checkConfigSetAvailable(AppDesc appDesc, InstanceInfo instanceInfo, Map> redisConfigMap) { int checkResult = 0; // 1.获取连接 final Jedis jedis = redisCenter.getAdminJedis(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000); try { int retry = 3; while (retry-- > 0) { Set>> entrySet = redisConfigMap.entrySet(); for (Map.Entry> entry : entrySet) { String configName = entry.getKey(); Set configValueSet = entry.getValue(); StringBuilder sb = new StringBuilder(); for (String configValue : configValueSet) { sb.append(configValue); sb.append(" "); } sb.deleteCharAt(sb.length() - 1); try { String result = jedis.configSet(configName, sb.toString()); if (result != null) { log.info(String.format("check config set available, config set, appId:%s, instance:%s, configName:%s, configValue:%s, result=%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), configName, sb, result)); if (result.equalsIgnoreCase("OK")) { checkResult = 1; continue; } else if (result.equalsIgnoreCase("Invalid argument")) { checkResult = 2; continue; } } } catch (Exception e) { log.error(e.getMessage(), e); if (e instanceof JedisDataException && e.getMessage() != null && e.getMessage().contains("Invalid argument")) { checkResult = 2; continue; } } } if(checkResult != 0){ break; } } return checkResult; } catch (Exception e) { log.error(String.format("check config set available, appId:%s, instance:%s, 异常:", instanceInfo.getAppId(), instanceInfo.getHostPort()), e); } finally { if (jedis != null) jedis.close(); } return checkResult; } /** * config set and rewrite * @param instanceInfo * @return */ private boolean configSetAndRewrite(AppDesc appDesc, InstanceInfo instanceInfo, Map> redisConfigMap) { // 1.获取连接 final Jedis jedis = redisCenter.getAdminJedis(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000); try { boolean isConfig = new IdempotentConfirmer() { @Override public boolean execute() { boolean isRun = redisCenter.isRun(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); if (!isRun) { log.warn("config set and rewrite, check is run fail, instance is not run, appId:${}, instance:${}", instanceInfo.getAppId(), instanceInfo.getHostPort()); return false; } Set>> entrySet = redisConfigMap.entrySet(); boolean isConfig =false; for (Map.Entry> entry : entrySet){ String configName = entry.getKey(); Set configValueSet = entry.getValue(); StringBuilder sb = new StringBuilder(); for (String configValue : configValueSet) { sb.append(configValue); sb.append(" "); } sb.deleteCharAt(sb.length() - 1); String result = jedis.configSet(configName, sb.toString()); isConfig = result != null && result.equalsIgnoreCase("OK"); if (!isConfig) { log.error(String.format("config set and rewrite, config set fail, appId:%s, instance:%s, configName:%s, configValue:%s, result=%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), configName, sb.toString(), result)); return false; } } return isConfig; } }.run(); String response = jedis.configRewrite(); boolean isRewrite = response != null && response.equalsIgnoreCase("OK"); if (!isRewrite) { log.error(String.format("config set and rewrite, config rewrite fail, appId:%s, instance:%s", instanceInfo.getAppId(), instanceInfo.getHostPort())); } return isConfig; } catch (Exception e) { log.error(String.format("config set and rewrite, occur error, appId:%s, instance:%s, error:", instanceInfo.getAppId(), instanceInfo.getHostPort()), e); } finally { if (jedis != null) jedis.close(); } return false; } /** * 通过config get获取配置项的值 * @param appDesc * @param instanceInfo * @param redisConfigMap * @return */ private Map getConfigByCommand(AppDesc appDesc, InstanceInfo instanceInfo, Map> redisConfigMap){ Map configNameValueMap = new HashMap<>(); Set configNameSet = redisConfigMap.keySet(); if(configNameSet.size() > 0) { String configValue = null; // 1.获取连接 final Jedis jedis = redisCenter.getAdminJedis(appDesc.getAppId(), instanceInfo.getIp(), instanceInfo.getPort(), 5000, 5000); try { for (String configName : configNameSet) { try { List strings = jedis.configGet(configName); if (strings != null && strings.size() > 1) { configValue = strings.get(1); } } catch (Exception e) { if (e instanceof JedisConnectionException) { configValue = "连接失败,未取到值"; } else if (e instanceof JedisDataException) { if (e.getMessage().contains("ERR unknown command `CONFIG`, with args beginning with: `get`, ")) { configValue = "无此配置,未取到值"; } } if (configValue == null) { configValue = "异常,未取到值"; } log.error("getConfigByCommand", e); } configNameValueMap.put(configName, configValue); } } finally { if (jedis != null) jedis.close(); } } return configNameValueMap; } /** * 將redis config 进行合并 * @param redisConfigList * @return */ private Map> groupRedisConfigByName(List redisConfigList){ Map> map = new HashMap<>(); for (RedisConfigVo redisConfigVo : redisConfigList) { if(map.containsKey(redisConfigVo.getConfigName())){ map.get(redisConfigVo.getConfigName()).add(redisConfigVo.getConfigValue()); }else{ HashSet valueSet = new HashSet<>(); valueSet.add(redisConfigVo.getConfigValue()); map.put(redisConfigVo.getConfigName(), valueSet); } } return map; } /** * config redis.conf file directly * @param instanceInfo * @return */ private boolean updateConfigFile(InstanceInfo instanceInfo, Map> redisConfigMap){ if(CollectionUtils.isEmpty(redisConfigMap)){ return true; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); String confType = ""; if (TypeUtil.isRedisCluster(type)) { confType = "redis-cluster-"; } else if (TypeUtil.isRedisSentinel(type)) { confType = "redis-sentinel-"; } else if (TypeUtil.isRedisStandalone(type)){ confType = "redis-sentinel-"; } String remoteFilePath = getMachineRelativeDir(host, DirEnum.CONF_DIR.getValue()) + confType + port + ".conf"; String backFilePath = remoteFilePath + ".program.bak"; //拷贝副本,命名统一 program.bak StringBuilder command = new StringBuilder(); command.append("cp ").append(remoteFilePath).append(" ").append(backFilePath); log.info(String.format("update config file, copy file, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command)); boolean executeFlag = true; try { SSHUtil.execute(host, command.toString()); } catch (SSHException e) { executeFlag = false; log.error(String.format("update config file, copy file, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), command), e); } Set>> configSet = redisConfigMap.entrySet(); for (Map.Entry> entry : configSet) { String configName = entry.getKey(); Set configValues = entry.getValue(); if(executeFlag){ //删除原有配置项 StringBuilder removeConfigCommand = new StringBuilder(); removeConfigCommand.append("sed -i '/^").append(configName).append(" /d' ").append(remoteFilePath); log.info(String.format("update config file, delete config name, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), removeConfigCommand)); //sed -i '/save /d' redis-test-111.conf try { SSHUtil.execute(host, removeConfigCommand.toString()); } catch (SSHException e) { executeFlag = false; log.error(String.format("update config file, delete config name, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), removeConfigCommand), e); } } if(executeFlag){ //新增新的配置项 StringBuilder addConfigCommand = new StringBuilder(); addConfigCommand.append("echo -e '").append("\n"); for(String configValue : configValues){ addConfigCommand.append(configName).append(" ").append(configValue).append("\n"); } addConfigCommand.append("' >> ").append(remoteFilePath); log.info(String.format("update config file, add config name value, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), addConfigCommand)); try { SSHUtil.execute(host, addConfigCommand.toString()); } catch (SSHException e) { executeFlag = false; log.error(String.format("update config file, add config name value, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), addConfigCommand), e); } } } return executeFlag; } /** * rollback redis.conf file to last version * @param instanceInfo * @return */ private boolean rollbackUpdateConfigFile(InstanceInfo instanceInfo){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); String confType = ""; if (TypeUtil.isRedisCluster(type)) { confType = "redis-cluster-"; } else if (TypeUtil.isRedisSentinel(type)) { confType = "redis-sentinel-"; } else if (TypeUtil.isRedisStandalone(type)) { confType = "redis-sentinel-"; } String remoteFilePath = getMachineRelativeDir(host, DirEnum.CONF_DIR.getValue()) + confType + port + ".conf"; String backFilePath = remoteFilePath + ".program.bak"; //拷贝副本,命名统一 program.bak StringBuilder command = new StringBuilder(); command.append("mv ").append(backFilePath).append(" ").append(remoteFilePath); log.info(String.format("rollback config file to last version, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command)); boolean executeFlag = true; try { String execute = SSHUtil.execute(host, command.toString()); if(StringUtil.isBlank(execute) || (execute != null && execute.contains("No such file"))){ executeFlag = true; }else{ executeFlag = false; } log.info(String.format("rollback config file to last version, appId:%s, instance:%s, command:%s, resultStr:%s, result:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command, execute, executeFlag)); } catch (SSHException e) { executeFlag = false; log.error(String.format("rollback config file to last version, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), command), e); } return executeFlag; } /** * 关闭节点后,判断配置文件句柄是否释放 * @param appDesc * @param instanceInfo * @return */ private boolean checkFileReleaseAfterShutdown(AppDesc appDesc, InstanceInfo instanceInfo) { String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); StringBuilder command = new StringBuilder(); command.append("ps -ef | grep redis | grep redis-server | grep :").append(port).append(" | grep -v \"grep\""); log.info(String.format("check config file release, appId:%s, instance:%s, command:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command)); boolean executeFlag = false; try { String execute = SSHUtil.execute(host, command.toString()); log.info(String.format("check config file release, appId:%s, instance:%s, command:%s, result:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), command, execute)); if(StringUtils.isEmpty(execute)){ executeFlag = true; } } catch (SSHException e) { executeFlag = false; log.error(String.format("check config file release, appId:%s, instance:%s, command:%s, error: ", instanceInfo.getAppId(), instanceInfo.getHostPort(), command), e); } return executeFlag; } /** * 获取相对路径 * @param host * @param dirType * @return */ public String getMachineRelativeDir(String host, int dirType) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(host); if (machineInfo != null && machineInfo.isK8sMachine(machineInfo.getK8sType())) { return MachineProtocol.getK8sDir(host, dirType); } return MachineProtocol.getDir(dirType); } /** * 校验当前版本的配置模板中的配置项,是否支持这些配置 * @param appDesc 应用信息 * @param redisConfigMap 根据配置名分组的配置信息,value为配置值的set * @return */ public boolean checkConfigIsSupport(AppDesc appDesc, Map> redisConfigMap){ int type = appDesc.getType(); int versionId = appDesc.getVersionId(); //根据redis version获取配置模板列表 List instanceConfigList = instanceConfigDao.getByVersion(versionId); //过滤配置,有效配置,仅根据应用类型保留:2.cluster节点特殊配置(cluster类型是保留), 5:sentinel节点配置(删除), 6:redis普通节点(保留) instanceConfigList = instanceConfigList.stream().filter(instanceConfig -> instanceConfig.getType() != 5 && instanceConfig.getStatus() == 1).collect(Collectors.toList()); if(!AppTypeEnum.REDIS_CLUSTER.equals(AppTypeEnum.getByType(type))){ instanceConfigList = instanceConfigList.stream().filter(instanceConfig -> instanceConfig.getType() != 2).collect(Collectors.toList()); } Set configNames = redisConfigMap.keySet(); for(String configName : configNames){ for (int i = 0; i < instanceConfigList.size(); i++){ InstanceConfig instanceConfig = instanceConfigList.get(i); String configKey = instanceConfig.getConfigKey(); if(configName.equals(configKey)){ break; }else{ if(configKey.contains(" ")){ String[] s = configKey.split(" "); if(s != null && s.length > 1 && configName.equals(s[0])){ break; } } if(i == instanceConfigList.size() - 1){ return false; } } } } return true; } /** * 校验当前版本的配置模板中的配置项,是否支持这些配置 * @param redisConfigMap 根据配置名分组的配置信息,value为配置值的set * @return */ public boolean testUpdateConfigFileAndRestart(Long appId, Map> redisConfigMap){ //专用于测试的应用信息 AppDesc appDesc = null; List instanceInfoList = null; if(TEST_APP_ID != null){ appDesc = appService.getByAppId(TEST_APP_ID); instanceInfoList = appService.getAppInstanceInfo(TEST_APP_ID); }else{ appDesc = appService.getByAppId(appId); instanceInfoList = appService.getAppInstanceInfo(appId); } if(CollectionUtils.isEmpty(instanceInfoList)){ return false; } //获取一个实例用于check config set是否可用 InstanceInfo instanceInfo = this.getInstanceToCheckConfigSet(instanceInfoList, null); //更新配置文件 this.updateConfigFile(instanceInfo, redisConfigMap); //重启节点 Optional s1 = this.restartNode(null, appDesc, instanceInfo); log.info(String.format("test update config file and restart, appId:%s, instance:%s, resultMsg:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), s1)); if(s1.isPresent()){ log.error(String.format("test update config file and restart, error, rollback config and restart begin, appId:%s, instance:%s", instanceInfo.getAppId(), instanceInfo.getHostPort())); //失败时,还原配置并重启 boolean executeFlag = this.rollbackUpdateConfigFile(instanceInfo); log.error(String.format("test update config file and restart error, rollback config and restart, rollback config fail, appId:%s, instance:%s", instanceInfo.getAppId(), instanceInfo.getHostPort())); if(executeFlag == true){ //重启节点 Optional s2 = this.restartNode(null, appDesc, instanceInfo); if(s2.isPresent()){ log.error(String.format("test update config file and restart, error, rollback config and restart, rollback config success, restart fail, appId:%s, instance:%s, restartResult:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), s2)); } } return false; }else{ boolean executeFlag = this.rollbackUpdateConfigFile(instanceInfo); log.info(String.format("test update config file and restart success, this time just rollback config file, appId:%s, instance:%s, rollback result:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), executeFlag)); if(executeFlag == true) { //重启节点 Optional s2 = this.restartNode(null, appDesc, instanceInfo); log.info(String.format("test update config file and restart success, this time just restart node, appId:%s, instance:%s, restartResult:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), s2)); if(s2.isPresent()){ log.error(String.format("test update config file and restart success, just rollback this config test, appId:%s, instance:%s, restartResult:%s", instanceInfo.getAppId(), instanceInfo.getHostPort(), s2)); return false; } } } return true; } private String generateLog(String format, Object... objects){ List objectsList = new ArrayList<>(); if(objects != null){ for(int i = 0; i < objects.length; i++){ objectsList.add(objects[i]); } } objectsList.add(0, DateUtil.formatYYYYMMddHHMMSS(new Date())); return String.format("%s " + format, objectsList.toArray()); } private String getTimeBetween(long endTime, long startTime){ long l = (endTime - startTime); return l + "ms"; } /** * 查看实例日志中,aof rewrite是否被terminated 或 redis是否crashed by signal: 11 * @param instanceInfo * @return */ private boolean checkByLog(InstanceInfo instanceInfo, String expectValue, long startTime){ String recentLog = getRecentLog(instanceInfo); if(StringUtil.isBlank(recentLog)){ return false; } String[] logArray = recentLog.split(System.getProperty("line.separator")); if(logArray != null && logArray.length > 1){ for(int i = logArray.length - 1; i >= 0; i--){ String logInfo = logArray[i]; if(logInfo != null && logInfo.contains(expectValue)){ log.info(String.format("check by log, log info : %s, time: %s", logInfo, startTime)); if(!checkLogTimeMeet(logInfo, startTime)){ continue; }else{ return true; } } } } return false; } /** * 查看实例日志中,aof rewrite是否被terminated 或 redis是否crashed by signal: 11 * @param instanceInfo * @return */ private String getRecentLog(InstanceInfo instanceInfo){ String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); int type = instanceInfo.getType(); String logType = ""; if (TypeUtil.isRedisDataType(type)) { logType = "redis-"; } else if (TypeUtil.isRedisSentinel(type)) { logType = "redis-sentinel-"; } String remoteFilePath = getMachineRelativeDir(host, DirEnum.LOG_DIR.getValue()) + logType + port + "-*.log"; StringBuilder command = new StringBuilder(); command.append("/usr/bin/tail -n").append(500).append(" ").append(remoteFilePath); try { return SSHUtil.execute(host, command.toString()); } catch (SSHException e) { log.error("实例appId:{}, host:{}, port:{}, getRecentLog errorMsg:{}", instanceInfo.getAppId(), host, port, e.getMessage()); return null; } } private boolean checkLogTimeMeet(String logInfo, long beginTime) { //allow machine clock 1s difference beginTime = beginTime - 1 * 1000; boolean flag = false; Calendar calendar = Calendar.getInstance(Locale.US); int year = 0; try{ calendar.setTimeInMillis(beginTime); year = calendar.get(Calendar.YEAR); }catch (Exception e){ return flag; } SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy hh:mm:ss.SSS", Locale.US); String[] strArray = logInfo.split(" "); if (strArray != null && strArray.length > 5) { StringBuilder sb = new StringBuilder(); int strSize = 5; for (int i = 1; i < strSize; i++) { String str = strArray[i]; if(i == 3 && !str.equals(String.valueOf(year))){ sb.append(year); sb.append(" "); strSize = 4; } sb.append(str); sb.append(" "); } sb.deleteCharAt(sb.length() - 1); try { Date parse = sdf.parse(sb.toString()); flag = !parse.before(calendar.getTime()); } catch (ParseException e) { log.error("log time parse error : ", e); } } return flag; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/AppServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.AsyncThreadPoolFactory; import com.sohu.cache.constant.*; import com.sohu.cache.dao.*; import com.sohu.cache.entity.*; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.task.constant.InstanceInfoEnum.InstanceTypeEnum; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.util.AppKeyUtil; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.Pair; import com.sohu.cache.util.TypeUtil; import com.sohu.cache.web.enums.BooleanEnum; import com.sohu.cache.web.enums.DeployInfoEnum; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.enums.UseTypeEnum; import com.sohu.cache.web.service.AppScrollRestartService; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.vo.AppDetailVO; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.assertj.core.util.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import redis.clients.jedis.HostAndPort; import javax.annotation.PostConstruct; import java.util.*; import java.util.stream.Collectors; /** * 应用操作实现类 * * @author leifu * @Time 2014年10月21日 */ @Service("appService") public class AppServiceImpl implements AppService { private Logger logger = LoggerFactory.getLogger(AppServiceImpl.class); /** * 应用相关dao */ @Autowired private AppDao appDao; /** * 应用日志相关dao */ @Autowired private AppAuditLogDao appAuditLogDao; /** * 实例相关dao */ @Autowired private InstanceDao instanceDao; /** * 应用用户关系相关dao */ @Autowired private AppToUserDao appToUserDao; /** * 应用申请相关dao */ @Autowired private AppAuditDao appAuditDao; /** * 用户信息dao */ @Autowired private AppUserDao appUserDao; /** * 业务组信息dao */ @Autowired private AppBizDao appBizDao; /** * 应用统计dao */ @Autowired private AppStatsDao appStatsDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired @Lazy private RedisCenter redisCenter; @Autowired @Lazy private MachineCenter machineCenter; @Autowired private MachineDao machineDao; @Autowired private MachineStatsDao machineStatsDao; @Autowired private AsyncService asyncService; @Autowired private AppService appService; @Autowired private AppClientStatisticGatherDao appClientStatisticGatherDao; @Autowired private AppStatsCenter appStatsCenter; @Autowired private AppScrollRestartService appScrollRestartService; @PostConstruct public void init() { asyncService.assemblePool(AsyncThreadPoolFactory.APP_POOL, AsyncThreadPoolFactory.APP_THREAD_POOL); } @Override public int getAppDescCount(AppUser appUser, AppSearch appSearch) { int count = 0; // 管理员获取全部应用 if (AppUserTypeEnum.ADMIN_USER.value().equals(appUser.getType())) { count = appDao.getAllAppCount(appSearch); } else { count = appDao.getUserAppCount(appUser.getId()); } return count; } @Override public List getAppMasterInstanceInfoList(long appId) { List resultList = new ArrayList(); List appInstanceInfoList = getAppInstanceInfo(appId); for (InstanceInfo instanceInfo : appInstanceInfoList) { if ((instanceInfo.isRedisData() || instanceInfo.isPika()) && "master".equals(instanceInfo.getRoleDesc()) && instanceInfo.getMasterInstanceId() == 0) { resultList.add(instanceInfo); } } return resultList; } @Override public List getAppDescList(AppUser appUser, AppSearch appSearch) { List list; // 管理员获取全部应用 if (AppUserTypeEnum.ADMIN_USER.value().equals(appUser.getType())) { list = appDao.getAllAppDescList(appSearch); } else { list = appDao.getAppDescList(appUser.getId()); } return list; } @Override public AppDesc getByAppId(Long appId) { AppDesc appDesc = null; try { appDesc = appDao.getAppDescById(appId); } catch (Exception e) { logger.error(e.getMessage(), e); } return appDesc; } @Override public int save(AppDesc appDesc) { return appDao.save(appDesc); } @Override public int update(AppDesc appDesc) { return appDao.update(appDesc); } /** * 更新应用 pwd * @param appId * @param appPwd * @return */ @Override public int updateAppPwd(long appId, String appPwd){ return appDao.updateAppPwd(appId, appPwd); } @Override public int updateWithCustomPwd(AppDesc appDesc) { return appDao.updateWithCustomPwd(appDesc); } @Override public boolean saveAppToUser(Long appId, Long userId) { try { // 用户id下应用 List list = appToUserDao.getByUserId(userId); if (CollectionUtils.isNotEmpty(list)) { for (AppToUser appToUser : list) { if (appToUser.getAppId().equals(appId)) { return true; } } } appToUserDao.save(new AppToUser(userId, appId)); return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } @Override public void updateAppAuditStatus(Long id, Long appId, Integer status, AppUser appUser) { appAuditDao.updateAppAuditUser(id, status, appUser.getId()); AppDesc appDesc = appDao.getAppDescById(appId); AppAudit appAudit = appAuditDao.getAppAudit(id); // 只有应用创建才会设置状态 if (AppAuditType.APP_AUDIT.getValue() == appAudit.getType()) { if (AppCheckEnum.APP_PASS.value().equals(status)) { appDesc.setStatus(AppStatusEnum.STATUS_PUBLISHED.getStatus()); appDesc.setPassedTime(new Date()); appDao.update(appDesc); } else if (AppCheckEnum.APP_REJECT.value().equals(status)) { appDesc.setStatus(AppStatusEnum.STATUS_DENY.getStatus()); appDao.update(appDesc); } } // 保存审批日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_CHECK); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } } @Override public void updateUserAuditStatus(Long id, Integer status, Long operateId) { appAuditDao.updateAppAuditUser(id, status, operateId); } @Override public List getAppToUserList(Long appId) { return appToUserDao.getByAppId(appId); } @Override public AppDesc getAppByName(String appName) { return appDao.getByAppName(appName); } /** * 获取app 基本实例信息 * @param appId * @return */ @Override public List getAppBasicInstanceInfo(Long appId) { AppDesc appDesc = appDao.getAppDescById(appId); if(appDesc == null){ return new ArrayList<>(); } return instanceDao.getInstListByAppId(appId); } /** * 获取应用下实例基本信息,并按照主从分组 * @param appId * @return */ @Override public Map> getAppInstanceInfoGroup(Long appId){ AppDesc appDesc = appDao.getAppDescById(appId); if(appDesc == null){ return Collections.EMPTY_MAP; } List instanceInfoList = instanceDao.getInstListByAppId(appId); instanceInfoList = instanceInfoList.stream() .filter(instanceInfo -> instanceInfo.getStatus() == InstanceStatusEnum.GOOD_STATUS.getStatus() && TypeUtil.isRedisDataType(instanceInfo.getType())) .collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(instanceInfoList)) { for (InstanceInfo instanceInfo : instanceInfoList) { int type = instanceInfo.getType(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 幂等操作 BooleanEnum isMaster = redisCenter.isMaster(appId, host, port); instanceInfo.setRoleDesc(isMaster); if (BooleanEnum.FALSE == isMaster) { HostAndPort hap = redisCenter.getMaster(host, port, appDesc.getAppPassword()); if (hap != null) { instanceInfo.setMasterHost(hap.getHost()); instanceInfo.setMasterPort(hap.getPort()); for (InstanceInfo innerInfo : instanceInfoList) { if (innerInfo.getIp().equals(hap.getHost()) && innerInfo.getPort() == hap.getPort()) { instanceInfo.setMasterInstanceId(innerInfo.getId()); break; } } } } } } } Map> resultMap = new HashMap>(); for (InstanceInfo info : instanceInfoList) { String roleDesc = info.getRoleDesc(); if (roleDesc != null && roleDesc.equals("master")) { List list = (ArrayList) MapUtils.getObject(resultMap, info, new ArrayList()); resultMap.put(info, list); } else if (roleDesc != null && roleDesc.equals("slave")) { int masterInstanceId = info.getMasterInstanceId(); Optional masterInstanceOptional = instanceInfoList.stream().filter(instance -> instance.getId() == masterInstanceId).findFirst(); if(masterInstanceOptional.isPresent()){ InstanceInfo masterInstance = masterInstanceOptional.get(); List list = (ArrayList) MapUtils.getObject(resultMap, masterInstance, new ArrayList()); list.add(info); resultMap.put(masterInstance, list); } } } return resultMap; } @Override public List getAppInstanceInfo(Long appId) { AppDesc appDesc = appDao.getAppDescById(appId); String password = appDesc.getAppPassword(); List resultList = instanceDao.getInstListByAppId(appId); return getInstancelistInfo(appId, password, resultList); } @Override public List getAppOnlineInstanceInfo(Long appId) { AppDesc appDesc = appDao.getAppDescById(appId); if(appDesc == null){ return Collections.EMPTY_LIST; } String password = appDesc.getAppPassword(); List resultList = instanceDao.getEffectiveInstListByAppId(appId); return getInstancelistInfo(appId, password, resultList); } public List getInstancelistInfo(Long appId, String password, List resultList) { if (resultList != null && resultList.size() > 0) { for (InstanceInfo instanceInfo : resultList) { int type = instanceInfo.getType(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { continue; } if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { continue; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 幂等操作 BooleanEnum isMaster = redisCenter.isMaster(appId, host, port); instanceInfo.setRoleDesc(isMaster); if (BooleanEnum.FALSE == isMaster) { HostAndPort hap = redisCenter.getMaster(host, port, password); if (hap != null) { instanceInfo.setMasterHost(hap.getHost()); instanceInfo.setMasterPort(hap.getPort()); for (InstanceInfo innerInfo : resultList) { if (innerInfo.getIp().equals(hap.getHost()) && innerInfo.getPort() == hap.getPort()) { instanceInfo.setMasterInstanceId(innerInfo.getId()); break; } } } } } } } return resultList; } @Override public List getAppInstanceStats(Long appId) { List instanceStats = instanceStatsDao.getInstanceStatsByAppId(appId); return instanceStats; } @Override public SuccessEnum deleteAppToUser(Long appId, Long userId) { try { appToUserDao.deleteAppToUser(appId, userId); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public List getAppAudits(Integer status, Integer type, Long auditId, Long userId, Long operateId) { List list = appAuditDao.selectWaitAppAudits(status, type, auditId, userId, operateId); for (Iterator i = list.iterator(); i.hasNext(); ) { AppAudit appAudit = i.next(); AppDesc appDesc = appDao.getAppDescById(appAudit.getAppId()); appAudit.setAppDesc(appDesc); } return list; } @Override public Map getStatisticGroupByStatus(Long userId, Long operateId, Date startTime, Date endTime) { List> statis = appAuditDao.getStatisticGroupByStatus(userId, operateId, startTime, endTime); return statis.stream().collect(Collectors.toMap(stat -> MapUtils.getString(stat, "status"), stat -> MapUtils.getInteger(stat, "count"))); } @Override public Map getStatisticGroupByType(Long userId, Long operateId, Date startTime, Date endTime) { List> statis = appAuditDao.getStatisticGroupByType(userId, operateId, startTime, endTime); return statis.stream().collect(Collectors.toMap(stat -> MapUtils.getString(stat, "type"), stat -> MapUtils.getInteger(stat, "count"))); } public List getAppAudits(Long appid, Integer type) { return appAuditDao.getAppAuditByCondition(appid, type); } @Override public AppAudit saveAppScaleApply(AppDesc appDesc, AppUser appUser, String applyMemSize, String appScaleReason, AppAuditType appScale) { AppAudit appAudit = new AppAudit(); appAudit.setAppId(appDesc.getAppId()); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); appAudit.setParam1(applyMemSize); appAudit.setParam2(appScaleReason); appAudit.setInfo("扩容申请---申请容量:" + applyMemSize + ", 申请原因: " + appScaleReason); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(appScale.getValue()); appAuditDao.insertAppAudit(appAudit); //保存扩容申请 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_SCALE_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } @Override public AppAudit saveAppChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String appConfigKey, String appConfigValue, String appConfigReason, AppAuditType modifyConfig) { AppAudit appAudit = new AppAudit(); appAudit.setAppId(appDesc.getAppId()); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); appAudit.setParam1(String.valueOf(instanceId)); appAudit.setParam2(appConfigKey); appAudit.setParam3(appConfigValue); appAudit.setInfo("修改配置项:" + appConfigKey + ", 配置值: " + appConfigValue + ", 修改原因: " + appConfigReason); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(modifyConfig.getValue()); appAuditDao.insertAppAudit(appAudit); //保存日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_CONFIG_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } @Override public AppAudit saveInstanceChangeConfig(AppDesc appDesc, AppUser appUser, Long instanceId, String instanceConfigKey, String instanceConfigValue, String instanceConfigReason, AppAuditType instanceModifyConfig) { AppAudit appAudit = new AppAudit(); long appId = appDesc.getAppId(); appAudit.setAppId(appId); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); appAudit.setParam1(String.valueOf(instanceId)); appAudit.setParam2(instanceConfigKey); appAudit.setParam3(instanceConfigValue); InstanceInfo instanceInfo = instanceDao.getInstanceInfoById(instanceId); String hostPort = instanceInfo == null ? "" : (instanceInfo.getIp() + ":" + instanceInfo.getPort()); appAudit.setInfo( "appId=" + appId + "下的" + hostPort + "实例申请修改配置项:" + instanceConfigKey + ", 配置值: " + instanceConfigValue + ", 修改原因: " + instanceConfigReason); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(instanceModifyConfig.getValue()); appAuditDao.insertAppAudit(appAudit); //保存日志 AppAuditLog appAuditLog = AppAuditLog .generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.INSTANCE_CONFIG_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } @Override public SuccessEnum updateRefuseReason(AppAudit appAudit, AppUser userInfo) { try { appAuditDao.updateRefuseReason(appAudit.getId(), appAudit.getRefuseReason()); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public int getUserAppCount(Long userId) { int count = 0; try { // 表比较小 List list = appToUserDao.getByUserId(userId); if (CollectionUtils.isNotEmpty(list)) { count = list.size(); } } catch (Exception e) { logger.error(e.getMessage(), e); } return count; } @Override public List getAppMachineDetail(Long appId) { //应用信息 Assert.isTrue(appId != null && appId > 0L); AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error("appDesc:id={} is not exist", appId); return Collections.emptyList(); } //应用实例列表 List appInstanceList = getAppInstanceInfo(appId); if (CollectionUtils.isEmpty(appInstanceList)) { return Collections.emptyList(); } //防止重复 Set instanceMachineHosts = new HashSet(); //结果列表 List machineDetailVOList = new ArrayList(); //应用的机器信息 for (InstanceInfo instanceInfo : appInstanceList) { String ip = instanceInfo.getIp(); if (instanceMachineHosts.contains(ip)) { continue; } else { instanceMachineHosts.add(ip); } MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); if (machineStats == null) { continue; } //已经分配的内存 int memoryHost = instanceDao.getMemoryByHost(ip); machineStats.setMemoryAllocated(memoryHost); //机器信息 MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip); if (machineInfo == null) { continue; } //下线机器不展示 if (machineInfo.isOffline()) { continue; } machineStats.setInfo(machineInfo); machineDetailVOList.add(machineStats); } return machineDetailVOList; } @Override public List getAppMachine(Long appId) { //应用信息 Assert.isTrue(appId != null && appId > 0L); AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { logger.error("appDesc:id={} is not exist", appId); return Collections.emptyList(); } //应用实例列表 List appInstanceList = getAppInstanceInfo(appId); if (CollectionUtils.isEmpty(appInstanceList)) { return Collections.emptyList(); } //防止重复 Set instanceMachineHosts = new HashSet(); //结果列表 List machineDetailVOList = new ArrayList(); //应用的机器信息 for (InstanceInfo instanceInfo : appInstanceList) { if(!instanceInfo.isOffline()){ String ip = instanceInfo.getIp(); if (instanceMachineHosts.contains(ip)) { continue; } else { instanceMachineHosts.add(ip); } MachineStats machineStats = machineStatsDao.getMachineStatsByIp(ip); if (machineStats == null) { continue; } //已经分配的内存 int memoryHost = instanceDao.getMemoryByHost(ip); machineStats.setMemoryAllocated(memoryHost); //机器信息 MachineInfo machineInfo = machineCenter.getMachineInfoByIp(ip); if (machineInfo == null) { continue; } //下线机器不展示 if (machineInfo.isOffline()) { continue; } machineStats.setInfo(machineInfo); machineDetailVOList.add(machineStats); } } return machineDetailVOList; } @Override public AppAudit getAppAuditById(Long appAuditId) { return appAuditDao.getAppAudit(appAuditId); } @Override public List getAppAuditListByAppId(Long appId) { Assert.isTrue(appId != null && appId > 0L); List appAudits = appAuditDao.getAppAuditByAppId(appId); if (CollectionUtils.isNotEmpty(appAudits)) { for (AppAudit appAudit : appAudits) { Long appAuditId = appAudit.getId(); List logList = appAuditLogDao.getAuditByType(appAuditId, AppAuditLogTypeEnum.APP_CHECK.value()); AppAuditLog log = null; if (CollectionUtils.isNotEmpty(logList)) { log = logList.get(0); log.setAppUser(appUserDao.get(log.getUserId())); } appAudit.setAppAuditLog(log); } } return appAudits; } @Override public AppAudit saveRegisterUserApply(AppUser appUser, AppAuditType registerUserApply) { AppAudit appAudit = new AppAudit(); appAudit.setAppId(0); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); StringBuilder info = new StringBuilder(); info.append(appUser.getChName() + "申请成为Cachecloud用户, 手机:" + appUser.getMobile() + ",邮箱:" + appUser.getEmail() + ",微信:" + appUser.getWeChat()); if(!StringUtils.isEmpty(appUser.getCompany())){ info.append(",公司:" + appUser.getCompany()); } if(!StringUtils.isEmpty(appUser.getPurpose())){ info.append(",使用目的:" + appUser.getPurpose()); } if(!StringUtils.isEmpty(appUser.getBizId())){ AppBiz appBiz = appBizDao.get(appUser.getBizId()); if(appBiz != null && !StringUtils.isEmpty(appBiz.getName())){ info.append(",归属业务组:" + appBiz.getName()); } } appAudit.setInfo(info.toString()); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(registerUserApply.getValue()); appAuditDao.insertAppAudit(appAudit); return appAudit; } @Override public List getAllAppDesc() { return appDao.getAllAppDescList(null); } @Override public SuccessEnum changeAppAlertConfig(long appId, int memAlertValue, int clientConnAlertValue, int hitPrecentAlertConfig, int isAccessMonitor, AppUser appUser) { if (appId <= 0 || memAlertValue <= 0 || clientConnAlertValue <= 0) { return SuccessEnum.FAIL; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return SuccessEnum.FAIL; } try { // 修改报警阀值 appDesc.setMemAlertValue(memAlertValue); appDesc.setClientConnAlertValue(clientConnAlertValue); appDesc.setHitPrecentAlertValue(hitPrecentAlertConfig); appDesc.setIsAccessMonitor(isAccessMonitor); appDao.update(appDesc); // 添加日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, 0L, AppAuditLogTypeEnum.APP_CHANGE_ALERT); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public void updateAppKey(long appId) { appDao.updateAppKey(appId, AppKeyUtil.genSecretKey(appId)); } @Override public String generateDeployInfo(Integer type, Integer isSalve, String room, Double size, Integer machineNum, Integer instanceNum, Integer useType, String machines, String excludeMachines, String sentinelMachines, List deployInfoList, List resMachines) { String result = DeployInfoEnum.SUCCESS.getValue(); // 获取有效可用机器列表 List excludeMachineList = Arrays.asList(excludeMachines.split(",")); List sentinelMachineLIst = Arrays.asList(sentinelMachines.split(",")); //存储满足条件的机器ip List machineCandi = new ArrayList(); //存储real machines ip //Set realMachines = new HashSet(); //每个机器的需求size,向上取整 Double reqSize = Math.ceil(size / instanceNum) * Math.ceil(instanceNum * 1.0D / machineNum); Integer reqCpu = instanceNum % machineNum == 0 ? instanceNum / machineNum : instanceNum / machineNum + 1; if (useType == UseTypeEnum.Machine_special.getValue()) { if (machines != null && !machines.isEmpty()) { List ipList = Arrays.asList(machines.split(",")); if (ipList.size() < machineNum) { logger.info("指定机器数小于分配机器数"); result = "指定机器数小于分配机器数"; return result; } List tmp = machineCenter.getValidMachineMemByIpList(ipList); for (MachineMemStatInfo memStatInfo : tmp) { resMachines.add(memStatInfo); } } else { logger.info("部署类型为专用,指定机器为空"); result = "machine list is null"; return result; } } else { List machineMemStatInfoList = machineCenter .getAllValidMachineMem(excludeMachineList, room, useType); for (MachineMemStatInfo memStatInfo : machineMemStatInfoList) { getMachineCandiList(memStatInfo, reqSize, reqCpu, isSalve, machineCandi); } getResMachines(machineCandi, machineNum, resMachines); if ((resMachines == null || resMachines.size() == 0) && useType == UseTypeEnum.Machine_test.getValue()) { getResMachines(machineMemStatInfoList, machineNum, resMachines); } } if (resMachines == null || resMachines.size() == 0) { logger.info("无可用机器"); result = "可用机器数小于指定机器数"; return result; } getDeployInfo(type, isSalve, resMachines, size, instanceNum, sentinelMachineLIst, deployInfoList); logger.info("deployInfoList: {}", deployInfoList); return result; } /** * @Description: 通过机器列表生成部署详情 * @Author: caoru * @CreateDate: 2018/9/25 22:03 */ private void getDeployInfo(Integer type, Integer isSalve, List machineList, Double size, Integer instanceNum, List sentinelMachineLIst, List deployInfoList) { if (machineList == null) return; try { /** * redis cluster */ if (TypeUtil.isRedisCluster(type)) { Double instanceSize = Math.ceil(size / instanceNum); //masterIp-memSize for (int i = 0; i < instanceNum; i++) { DeployInfo deployInfo = new DeployInfo(type, machineList.get(i % machineList.size()).getIp(), instanceSize.intValue()); deployInfoList.add(deployInfo); } //+slaveIp if (isSalve == 1) { int i = 0; for (int j = 0; j < deployInfoList.size(); j++) { DeployInfo deployInfo = deployInfoList.get(j); while (isSameRealMachine(deployInfo.getMasterIp(), machineList.get(i % machineList.size()).getIp())) { i++; } deployInfo.setSlaveIp(machineList.get(i % machineList.size()).getIp()); i++; } } } /** * redis Sentinel */ else if (TypeUtil.isRedisSentinel(type)) { if (isSalve == 1) {//master:size:slave DeployInfo deployInfo = new DeployInfo(type, machineList.get(0).getIp(), size.intValue()); int i = 0; while (isSameRealMachine(deployInfo.getMasterIp(), machineList.get(i % machineList.size()).getIp())) { i++; } deployInfo.setSlaveIp(machineList.get(i % machineList.size()).getIp()); deployInfoList.add(deployInfo); } else {//master:size DeployInfo deployInfo = new DeployInfo(type, machineList.get(0).getIp(), size.intValue()); deployInfoList.add(deployInfo); } //sentinel list for (int i = 0; i < sentinelMachineLIst.size(); i++) { DeployInfo sentinel = new DeployInfo(type, sentinelMachineLIst.get(i)); deployInfoList.add(sentinel); } machineList.addAll(machineCenter.getValidMachineMemByIpList(sentinelMachineLIst)); } /** * redis standalone */ else if (TypeUtil.isRedisStandalone(type)) { //master:size DeployInfo deployInfo = new DeployInfo(type, machineList.get(0).getIp(), size.intValue()); deployInfoList.add(deployInfo); } } catch (Exception ex) { logger.warn(ex.getMessage()); logger.warn("getDeployInfo error"); } } /** * @Description: 获取候选机器列表 * @Author: caoru * @CreateDate: 2018/10/8 20:43 */ public void getMachineCandiList(MachineMemStatInfo memStatInfo, Double reqSize, Integer reqCpu, Integer isSalve, List machineCandi) { Integer mem = memStatInfo.getMem();//单位G Long applyMen = memStatInfo.getApplyMem();//单位bit Long availMen = mem * 1024 - applyMen / 1024 / 1024;////单位M Integer availCpu = memStatInfo.getCpu() - memStatInfo.getInstanceNum(); if (availMen >= Math.ceil(reqSize) * (isSalve + 1) && availCpu >= reqCpu * (isSalve + 1)) { machineCandi.add(memStatInfo); } } @Override public Map getMachineDeployStat(Set ipList, List deployInfoList) { Map machineDeployStatMap = new HashMap(); if (!CollectionUtils.isEmpty(deployInfoList)) { for (String ip : ipList) { Integer masterNum = 0; Integer slaveNum = 0; Integer sentinelNum = 0; Integer twemproxylNum = 0; for (DeployInfo deployInfo : deployInfoList) { masterNum += (deployInfo.getMasterIp() != null && deployInfo.getMasterIp().equals(ip)) || (deployInfo.getMasterPikaIp() != null && deployInfo.getMasterPikaIp().equals(ip)) ? 1 : 0; slaveNum += (deployInfo.getSlaveIp() != null && deployInfo.getSlaveIp().equals(ip)) || (deployInfo.getSlavePikaIp() != null && deployInfo.getSlavePikaIp().equals(ip)) ? 1 : 0; sentinelNum += deployInfo.getSentinelIp() != null && deployInfo.getSentinelIp().equals(ip) ? 1 : 0; twemproxylNum += deployInfo.getTwemproxyIp() != null && deployInfo.getTwemproxyIp().equals(ip) ? 1 : 0; } DeployInfoStat deployInfoStat = new DeployInfoStat(masterNum, slaveNum, sentinelNum, twemproxylNum); machineDeployStatMap.put(ip, deployInfoStat); } } return machineDeployStatMap; } @Override public void getResMachines(List machineCandi, Integer machineNum, List resMachines) { if (machineCandi == null) { return; } Map map = new HashMap(); if (machineCandi.size() < machineNum) { return; } else { while (map.size() < machineNum) { int random = (int) (Math.random() * machineCandi.size()); if (!map.containsKey(random)) { map.put(random, ""); resMachines.add(machineCandi.get(random)); } } } } /** * @param machinelist 机器信息 * @param type 应用类型 * @param instanceNum 实例数量 实例数据为0时,则每个机器部署一个实例 * @param maxMemory 内存大小 * @param hasSalve 是否有从节点 * @return 添加部署Redis/Pika节点信息 */ public List generateInstanceInfo(List machinelist, int type, int appType, int instanceNum, int maxMemory, int hasSalve, List deployInfoList) { if (!CollectionUtils.isEmpty(machinelist)) { for (int index = 0; index < instanceNum; index++) { DeployInfo deployInfo = null; if (DeployInfo.isRedisNode(type)) { deployInfo = hasSalve == 1 ? DeployInfo.getRedisInfo(appType, machinelist.get(index % machinelist.size()), maxMemory, machinelist.get((index + 1) % machinelist.size())) : DeployInfo.getRedisInfo(appType, machinelist.get(index % machinelist.size()), maxMemory, null); } else { deployInfo = hasSalve == 1 ? DeployInfo.getPikaInfo(appType, machinelist.get(index % machinelist.size()), maxMemory, machinelist.get((index + 1) % machinelist.size())) : DeployInfo.getPikaInfo(appType, machinelist.get(index % machinelist.size()), maxMemory, null); } if (deployInfo != null) { deployInfoList.add(deployInfo); } } //每台机器仅部署一个实例处理逻辑 if (instanceNum == 0) { for (int index = 0; index < machinelist.size() - 1; ) { DeployInfo deployInfo = null; if (DeployInfo.isRedisNode(type)) { deployInfo = hasSalve == 1 ? DeployInfo.getRedisInfo(appType, machinelist.get(index), maxMemory, machinelist.get(index + 1)) : DeployInfo.getRedisInfo(appType, machinelist.get(index), maxMemory, null); } else { deployInfo = hasSalve == 1 ? DeployInfo.getPikaInfo(appType, machinelist.get(index), maxMemory, machinelist.get(index + 1)) : DeployInfo.getPikaInfo(appType, machinelist.get(index), maxMemory, null); } if (deployInfo != null) { deployInfoList.add(deployInfo); } if(hasSalve == 1) { index += 2; } else { index += 1; } } } } return deployInfoList; } public List generateProxyinfo(List proxylist, int type, int appType, int proxyNum, List deployInfoList) { if (!CollectionUtils.isEmpty(proxylist)) { for (int index = 0; index < proxyNum; index++) { DeployInfo deployInfo = null; if (DeployInfo.isSentinelNode(type)) { deployInfo = DeployInfo.getSentinelInfo(appType, proxylist.get(index % proxylist.size())); } else { deployInfo = DeployInfo.getTwemproxyInfo(appType, proxylist.get(index % proxylist.size())); } if (deployInfo != null) { deployInfoList.add(deployInfo); } } } return deployInfoList; } @Override public List checkAppStatus(List appIds) { return appDao.getAppDescByIds(appIds); } @Override public List getTopMemFragRatioApps(TimeBetween timeBetween) { long startTime = timeBetween.getStartTime(); long endTime = timeBetween.getEndTime(); return appStatsDao.getTopMemFragRatioApps(startTime, endTime); } @Override public Map> getAppClientStatGather(long appId, String gatherTime) { List> appClientGatherStatList = appClientStatisticGatherDao.getAppClientStatisticByGatherTime(appId, gatherTime); return appClientGatherStatList.stream().collect(Collectors.toMap(appClientGatherStat -> MapUtils.getLong(appClientGatherStat, "app_id"), appClientGatherStat -> appClientGatherStat)); } @Override public Map>> getFilterAppClientStatGather(long appId, String gatherTime) { List> appClientGatherStatList = appClientStatisticGatherDao.getExpAppStatisticByGatherTime(gatherTime); return groupAppClientStatGather(appClientGatherStatList); } private boolean appClientStatGatherFilter(Map appClientGatherStat) { if (MapUtils.isEmpty(appClientGatherStat)) { return false; } try { long appId = MapUtils.getLongValue(appClientGatherStat, "app_id", 0l); if (appService.getByAppId(appId).isTestOk()) { return false; } return true; } catch (Exception e) { logger.error(e.getMessage(), e); return false; } } private Map>> groupAppClientStatGather(List> appClientGatherStatList) { Map>> result = new HashMap<>(); if (CollectionUtils.isEmpty(appClientGatherStatList)) { return result; } List> expAppStats = new ArrayList<>(); List> latencyAppStats = new ArrayList<>(); List> memAlterAppStats = new ArrayList<>(); List> fragRatioAppStats = new ArrayList<>(); List> topologyAppStats = new ArrayList<>(); try { appClientGatherStatList.forEach(appClientGatherMap -> { long appId = MapUtils.getLongValue(appClientGatherMap, "app_id", 0l); AppDesc appDesc = appService.getByAppId(appId); if (appDesc != null && !appDesc.isTestOk()) { //增加应用是否下线判断,如应用下线,此条客户端统计信息不做处理 if(AppStatusEnum.STATUS_PUBLISHED.getStatus() != appDesc.getStatus()){ return; } AppDetailVO appDetail = appStatsCenter.getAppDetail(appId); long mem = appDetail.getMem(); long exp_count = MapUtils.getLongValue(appClientGatherMap, "exp_count", 0l); long slow_log_count = MapUtils.getLongValue(appClientGatherMap, "slow_log_count", 0l); //double mem_used_ratio = MapUtils.getDoubleValue(appClientGatherMap, "mem_used_ratio", 0.00); double avg_mem_frag_ratio = MapUtils.getDoubleValue(appClientGatherMap, "avg_mem_frag_ratio", 0.00); double format_mem = mem / 1024.0; double format_used_memory = MapUtils.getLongValue(appClientGatherMap, "used_memory", 0l) / 1024 / 1024 / 1024.0; double format_used_memory_rss = MapUtils.getLongValue(appClientGatherMap, "used_memory_rss", 0l) / 1024 / 1024 / 1024.0; double mem_used_ratio = format_mem == 0 ? 0.0 : (format_used_memory / format_mem) * 100; int topology_exam_result = MapUtils.getIntValue(appClientGatherMap, "topology_exam_result", -1); if (exp_count > 0) { expAppStats.add(appClientGatherMap); } if (slow_log_count > 100) { latencyAppStats.add(appClientGatherMap); } if (mem > 1024 * 10 && mem_used_ratio <= 40.0) { appClientGatherMap.put("format_mem", String.format("%.2f", format_mem)); appClientGatherMap.put("format_used_memory", String.format("%.2f", format_used_memory)); appClientGatherMap.put("mem_used_ratio", Double.valueOf(String.format("%.2f", mem_used_ratio))); memAlterAppStats.add(appClientGatherMap); } if (format_used_memory * 1024 > 500 && avg_mem_frag_ratio > 1.2) { appClientGatherMap.put("format_used_memory", String.format("%.2f", format_used_memory)); appClientGatherMap.put("format_used_memory_rss", String.format("%.2f", format_used_memory_rss)); fragRatioAppStats.add(appClientGatherMap); } if (topology_exam_result == 1) { topologyAppStats.add(appClientGatherMap); } } }); } catch (Exception e) { logger.error(e.getMessage(), e); } try { Collections.sort(latencyAppStats, (o1, o2) -> { long val1 = (long) o1.get("slow_log_count"); long val2 = (long) o2.get("slow_log_count"); return val1 > val2 ? -1 : 1; // 从大到小 }); } catch (Exception e) { logger.error(e.getMessage(), e); } try { Collections.sort(memAlterAppStats, (o1, o2) -> { double val1 = (double) o1.get("mem_used_ratio"); double val2 = (double) o2.get("mem_used_ratio"); return val1 > val2 ? 1 : -1; // 从小到大 }); } catch (Exception e) { logger.error(e.getMessage(), e); } try { Collections.sort(fragRatioAppStats, (o1, o2) -> { double val1 = (double) o1.get("avg_mem_frag_ratio"); double val2 = (double) o2.get("avg_mem_frag_ratio"); return val1 > val2 ? -1 : 1; // 从大到小 }); } catch (Exception e) { logger.error(e.getMessage(), e); } result.put("expAppStats", expAppStats); result.put("latencyAppStats", latencyAppStats.subList(0, latencyAppStats.size() < 10 ? latencyAppStats.size() : 10)); result.put("memAlterAppStats", memAlterAppStats.subList(0, memAlterAppStats.size() < 10 ? memAlterAppStats.size() : 10)); result.put("fragRatioAppStats", fragRatioAppStats.subList(0, fragRatioAppStats.size() < 10 ? fragRatioAppStats.size() : 10)); result.put("topologyAppStats", topologyAppStats); return result; } @Override public AppAudit saveAppKeyAnalysis(AppDesc appDesc, AppUser appUser, String appAnalysisReason, String nodeInfo) { AppAudit appAudit = new AppAudit(); appAudit.setAppId(appDesc.getAppId()); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); // nodeInfo 待分析节点地址 if (StringUtils.hasText(nodeInfo)) { appAudit.setParam1(nodeInfo); } appAudit.setModifyTime(new Date()); appAudit.setInfo("申请原因: " + appAnalysisReason); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(AppAuditType.KEY_ANALYSIS.getValue()); Date now = new Date(); appAudit.setCreateTime(now); appAudit.setModifyTime(now); appAuditDao.insertAppAudit(appAudit); // 保存日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.KEY_VALUE_ANALYSIS); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } @Override public AppAudit saveAppDiagnostic(AppDesc appDesc, AppUser appUser, String reason) { AppAudit appAudit = new AppAudit(); appAudit.setAppId(appDesc.getAppId()); appAudit.setUserId(appUser.getId()); appAudit.setUserName(appUser.getName()); appAudit.setModifyTime(new Date()); appAudit.setInfo("申请原因: " + reason); appAudit.setStatus(AppCheckEnum.APP_WATING_CHECK.value()); appAudit.setType(AppAuditType.APP_DIAGNOSTIC.getValue()); Date now = new Date(); appAudit.setCreateTime(now); appAudit.setModifyTime(now); appAuditDao.insertAppAudit(appAudit); // 保存日志 AppAuditLog appAuditLog = AppAuditLog.generate(appDesc, appUser, appAudit.getId(), AppAuditLogTypeEnum.APP_DIAGNOSTIC_APPLY); if (appAuditLog != null) { appAuditLogDao.save(appAuditLog); } return appAudit; } private void addRealMeachine(MachineInfo machineInfo, Set realMachines) { if (machineInfo.getVirtual() == 0) { realMachines.add(machineInfo.getIp()); } else { realMachines.add(machineInfo.getRealIp()); } } private boolean isSameRealMachine(String ip1, String ip2) { if (ip1.equals(ip2)) return true; MachineInfo machine1 = machineDao.getMachineInfoByIp(ip1); MachineInfo machine2 = machineDao.getMachineInfoByIp(ip2); if (machine1.getVirtual() == 1 && machine2.getVirtual() == 1) { return machine1.getExtraDesc().equals(machine2.getRealIp()); } else { return machine1.getIp().equals(machine2.getIp()); } } @Override public List getAppInstanceByType(long appId, InstanceTypeEnum instanceTypeEnum) { List resultList = new ArrayList(); List appInstanceInfoList = getAppInstanceInfo(appId); for (InstanceInfo instanceInfo : appInstanceInfoList) { if (instanceTypeEnum.getType() == instanceInfo.getType()) { resultList.add(instanceInfo); } } return resultList; } @Override public String checkAppPersistenceConfigAndFix(long appId, Map masterConfigMap, Map slaveConfigMap) { AppDesc appDesc = appDao.getAppDescById(appId); List instanceInfoList = this.getInstanceInfoListWithRole(appId); Map> groupMap = this.groupInstanceByMaster(instanceInfoList); boolean masterSlavePair = this.checkIsMasterSlavePair(groupMap); if(!masterSlavePair){ if(appScrollRestartService.isAppOnScrollRestart(appId)){ logger.error("checkAppPersistenceConfigAndFix, the app is on scroll restart, checkIsMasterSlavePair failed and will ignore this time, appId:{}", appId); return null; } logger.error("checkAppPersistenceConfigAndFix checkIsMasterSlavePair failed, appId:{}", appId); return "checkIsMasterSlavePair failed"; } StringBuilder sb = new StringBuilder(); groupMap.forEach((masterId, instanceInfoS) -> { List oneGroupList = new ArrayList<>(); //check instanceInfoS.forEach(instanceInfo -> { if(instanceInfo.getRoleDesc().equals(InstanceRoleEnum.MASTER.getInfo())){ masterConfigMap.forEach((configKey, expectConfigValue) -> { String configValue = redisCenter.configGet(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey); if(StringUtils.isEmpty(expectConfigValue) && StringUtils.isEmpty(configValue) || expectConfigValue.equals(configValue)){ return; }else{ oneGroupList.add(instanceInfo); } }); }else if(instanceInfo.getRoleDesc().equals(InstanceRoleEnum.SLAVE.getInfo())){ slaveConfigMap.forEach((configKey, expectConfigValue) -> { String configValue = redisCenter.configGet(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey); if (StringUtils.isEmpty(expectConfigValue) && StringUtils.isEmpty(configValue) || expectConfigValue.equals(configValue)) { return; } else { oneGroupList.add(0, instanceInfo); } }); } }); oneGroupList.forEach(instanceInfo -> { if(instanceInfo.getRoleDesc().equals(InstanceRoleEnum.MASTER.getInfo())){ masterConfigMap.forEach((configKey, expectConfigValue) -> { String configValue = redisCenter.configGet(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey); if(StringUtils.isEmpty(expectConfigValue) && StringUtils.isEmpty(configValue) || expectConfigValue.equals(configValue)){ return; }else{ logger.info("checkAppPersistenceConfigAndFix configSetAndRewrite success, appId:{} host:{} port:{} key:{} value:{}", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); boolean configSetAndRewrite = redisCenter.configSetAndRewrite(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); if(!configSetAndRewrite){ logger.error("checkAppPersistenceConfigAndFix configSetAndRewrite failed, appId:{} host:{} port:{} key:{} value:{}", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); sb.append(String.format("configSetAndRewrite master failed, appId:%s host:%s port:%s key:%s value:%s", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue)); } } }); }else if(instanceInfo.getRoleDesc().equals(InstanceRoleEnum.SLAVE.getInfo())){ slaveConfigMap.forEach((configKey, expectConfigValue) -> { String configValue = redisCenter.configGet(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey); if (StringUtils.isEmpty(expectConfigValue) && StringUtils.isEmpty(configValue) || expectConfigValue.equals(configValue)) { return; } else { logger.info("checkAppPersistenceConfigAndFix configSetAndRewrite success, appId:{} host:{} port:{} key:{} value:{}", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); boolean configSetAndRewrite = redisCenter.configSetAndRewrite(appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); if(!configSetAndRewrite){ logger.error("checkAppPersistenceConfigAndFix configSetAndRewrite failed, appId:{} host:{} port:{} key:{} value:{}", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue); sb.append(String.format("configSetAndRewrite slave failed, appId:%s host:%s port:%s key:%s value:%s", appId, instanceInfo.getIp(), instanceInfo.getPort(), configKey, expectConfigValue)); } } }); } }); }); if(sb.length() > 0){ return sb.toString(); } return null; } public List getInstanceInfoListWithRole(Long appId) { AppDesc appDesc = appDao.getAppDescById(appId); return this.getInstanceInfoListWithRole(appId, appDesc); } public List getInstanceInfoListWithRole(Long appId, AppDesc appDesc) { List resultList = instanceDao.getInstListByAppId(appId); String password = appDesc.getAppPassword(); resultList.forEach(instanceInfo -> { int type = instanceInfo.getType(); if (instanceInfo.getStatus() != InstanceStatusEnum.GOOD_STATUS.getStatus()) { return; } if (TypeUtil.isRedisType(type)) { if (TypeUtil.isRedisSentinel(type)) { return; } String host = instanceInfo.getIp(); int port = instanceInfo.getPort(); // 幂等操作 BooleanEnum isMaster = redisCenter.isMaster(appId, host, port); instanceInfo.setRoleDesc(isMaster); if (BooleanEnum.FALSE == isMaster) { HostAndPort hap = redisCenter.getMaster(host, port, password); if (hap != null) { instanceInfo.setMasterHost(hap.getHost()); instanceInfo.setMasterPort(hap.getPort()); for (InstanceInfo innerInfo : resultList) { if (innerInfo.getIp().equals(hap.getHost()) && innerInfo.getPort() == hap.getPort()) { instanceInfo.setMasterInstanceId(innerInfo.getId()); break; } } } } } }); return resultList; } public Map> groupInstanceByMaster(List instanceInfoWithRoleList) { Map> resultMap = new HashMap>(); instanceInfoWithRoleList.forEach(info -> { String roleDesc = info.getRoleDesc(); if (roleDesc != null && roleDesc.equals("master")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getId(), new ArrayList()); list.add(info); resultMap.put(info.getId(), list); } else if (roleDesc != null && roleDesc.equals("slave")) { List list = (ArrayList) MapUtils.getObject(resultMap, info.getMasterInstanceId(), new ArrayList()); list.add(info); resultMap.put(info.getMasterInstanceId(), list); } }); return resultMap; } /** * 校验相关的实例是否为主从备份 * @param groupMap 已根据主从进行分组 * @return false:不满足主从,true满足 */ private boolean checkIsMasterSlavePair(Map> groupMap){ //校验是否均为主从备份 Set>> entries = groupMap.entrySet(); for (Map.Entry> entry : entries){ List instanceInfos = entry.getValue(); if(instanceInfos.size() < 2){ return false; } } return true; } @Override public boolean updateAppPersistenceType(long appId, int persistenceType) { int execNum = appDao.updateAppPersistenceType(appId, persistenceType); if(execNum > 0){ return true; } return false; } @Override public boolean updateAppMaxmemoryPolicy(long appId, int maxmemoryPolicy) { int execNum = appDao.updateAppMaxmemoryPolicy(appId, maxmemoryPolicy); if(execNum > 0){ return true; } return false; } /** * 获取用户所属应用的内存统计信息(包含版本) * @param userId * @param isAdmin * @return */ @Override public List getAppCapacityStatistics(Long userId, Boolean isAdmin){ AppStatisticsSearch search = AppStatisticsSearch.builder().userId(userId).isAdmin(isAdmin).build(); return appDao.getCapacityStatistics(search); } @Override public Map getAppCapacityStats(Long userId, Boolean isAdmin){ Map resultMap = new HashMap<>(); List capacityStatistics = this.getAppCapacityStatistics(userId, isAdmin); Map versionMap = new HashMap<>(); long totalApplyMem = 0L; long totalUsedMem = 0L; long totalMasterCount = 0L; for (AppCapacityStatisticsResult result : capacityStatistics) { totalUsedMem += result.getMemUsed() == null ? 0 :result.getMemUsed(); totalApplyMem += result.getCurMem() == null ? 0 :result.getCurMem(); totalMasterCount += result.getShardingMasterNum() == null ? 0 :result.getShardingMasterNum(); Integer versionId = result.getVersionId(); if(versionMap.containsKey(versionId)){ versionMap.put(versionId, (versionMap.get(versionId) + 1)); }else{ versionMap.put(versionId, 1); } } Map resourceMap = ConstUtils.REDIS_RESOURCE; List> versionList = new ArrayList<>(); versionMap.keySet().forEach(versionId -> { SystemResource systemResource = resourceMap.get(versionId); if(systemResource != null){ versionList.add(new Pair<>(systemResource.getName(), versionMap.get(versionId))); } }); resultMap.put("appCount", capacityStatistics.size()); resultMap.put("applyMem", totalApplyMem); resultMap.put("usedMem", totalUsedMem); resultMap.put("notUsedMem", totalApplyMem - totalUsedMem); resultMap.put("masterCount", totalMasterCount); resultMap.put("versionList", versionList); List> capacityAuditList = new ArrayList<>(); capacityStatistics.sort(Comparator.comparingDouble(AppCapacityStatisticsResult :: getMemUsedRatio)); if(capacityStatistics != null){ int limit = capacityStatistics.size() > 5 ? 5 : capacityStatistics.size(); for(int i = 0; i < limit; i++){ AppCapacityStatisticsResult statisticsResult = capacityStatistics.get(i); capacityAuditList.add(new Pair<>(statisticsResult.getAppId(), statisticsResult.getMemUsedRatio())); } } resultMap.put("auditList", capacityAuditList); return resultMap; } /** * 获取用户所属应用的监控统计信息 * @param userId * @param isAdmin * @param startTime * @param endTime * @return */ @Override public List getAppMonitorStatistics(Long userId, Boolean isAdmin, String startTime, String endTime){ AppStatisticsSearch search = AppStatisticsSearch.builder().userId(userId).isAdmin(isAdmin).startTime(startTime).endTime(endTime).build(); return appDao.getMonitorStatistics(search); } /** * 更新应用拓扑检测结果 * @param topologyExam * @return */ @Override public int saveAppTopologyExam(AppClientStatisticGather topologyExam){ return appClientStatisticGatherDao.batchSaveTopologyExam(Lists.newArrayList(topologyExam)); } /** * 获取拓扑检测失败的应用 * @param gatherTime * @return */ @Override public List getTopologyExamFailedByGatherTime(String gatherTime){ return appClientStatisticGatherDao.getTopologyExamFailedByGatherTime(gatherTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/ConfigServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import com.sohu.cache.alert.utils.AlertUtils; import com.sohu.cache.util.StringUtil; import org.apache.commons.collections.MapUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.dao.ConfigDao; import com.sohu.cache.entity.SystemConfig; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; /** * @author leifu * @Date 2016年5月23日 * @Time 上午10:35:26 */ @Service("configService") public class ConfigServiceImpl implements ConfigService { private Logger logger = LoggerFactory.getLogger(ConfigServiceImpl.class); @Autowired private ConfigDao configDao; @PostConstruct public void init() { reloadSystemConfig(); } /** * 加载配置 */ public void reloadSystemConfig() { logger.info("ConfigServiceImpl reload config start"); // 加载配置 Map configMap = getConfigMap(); // 文案相关 ConstUtils.CONTACT = MapUtils.getString(configMap, "cachecloud.contact"); logger.debug("{}: {}", "ConstUtils.CONTACT", ConstUtils.CONTACT); // 报警相关配置 AlertUtils.EMAILS = MapUtils.getString(configMap, "cachecloud.owner.email"); logger.debug("{}: {}", "ConstUtils.EMAILS", AlertUtils.EMAILS); AlertUtils.PHONES = MapUtils.getString(configMap, "cachecloud.owner.phone"); logger.debug("{}: {}", "ConstUtils.PHONES", AlertUtils.PHONES); AlertUtils.WECHAT = MapUtils.getString(configMap, "cachecloud.owner.weChat"); logger.debug("{}: {}", "ConstUtils.WECHAT", AlertUtils.WECHAT); // ssh相关配置 ConstUtils.USERNAME = MapUtils.getString(configMap, "cachecloud.machine.ssh.name", ConstUtils.DEFAULT_USERNAME); logger.debug("{}: {}", "ConstUtils.USERNAME", ConstUtils.USERNAME); ConstUtils.PASSWORD = MapUtils.getString(configMap, "cachecloud.machine.ssh.password", ConstUtils.DEFAULT_PASSWORD); logger.debug("{}: {}", "ConstUtils.PASSWORD", ConstUtils.PASSWORD); ConstUtils.SSH_PORT_DEFAULT = Integer.parseInt(MapUtils.getString(configMap, "cachecloud.machine.ssh.port", String.valueOf(ConstUtils.DEFAULT_SSH_PORT_DEFAULT))); logger.debug("{}: {}", "ConstUtils.SSH_PORT_DEFAULT", ConstUtils.SSH_PORT_DEFAULT); //ssh授权方式 ConstUtils.SSH_AUTH_TYPE = MapUtils.getIntValue(configMap, "cachecloud.ssh.auth.type", ConstUtils.DEFAULT_SSH_AUTH_TYPE); logger.debug("{}: {}", "ConstUtils.SSH_AUTH", ConstUtils.SSH_AUTH_TYPE); //public key pem ConstUtils.PUBLIC_KEY_PEM = MapUtils.getString(configMap, "cachecloud.public.key.pem", ConstUtils.DEFAULT_PUBLIC_KEY_PEM); logger.debug("{}: {}", "ConstUtils.PUBLIC_KEY_PEM", ConstUtils.PUBLIC_KEY_PEM); ConstUtils.PUBLIC_KEY_PEM = MapUtils.getString(configMap, "cachecloud.public.key.pem", ConstUtils.DEFAULT_PUBLIC_KEY_PEM); logger.debug("{}: {}", "ConstUtils.PUBLIC_KEY_PEM", ConstUtils.PUBLIC_KEY_PEM); ConstUtils.PUBLIC_USERNAME = MapUtils.getString(configMap, "cachecloud.public.user.name", ConstUtils.DEFAULT_PUBLIC_USERNAME); logger.debug("{}: {}", "ConstUtils.PUBLIC_USERNAME", ConstUtils.PUBLIC_USERNAME); // 管理员相关配置 ConstUtils.SUPER_ADMIN_NAME = MapUtils.getString(configMap, "cachecloud.admin.user.name", ConstUtils.DEFAULT_SUPER_ADMIN_NAME); logger.debug("{}: {}", "ConstUtils.SUPER_ADMIN_NAME", ConstUtils.SUPER_ADMIN_NAME); ConstUtils.SUPER_ADMIN_PASS = MapUtils.getString(configMap, "cachecloud.admin.user.password", ConstUtils.DEFAULT_SUPER_ADMIN_PASS); logger.debug("{}: {}", "ConstUtils.SUPER_ADMIN_PASS", ConstUtils.SUPER_ADMIN_PASS); ConstUtils.SUPER_ADMINS = MapUtils.getString(configMap, "cachecloud.superAdmin", ConstUtils.DEFAULT_SUPER_ADMINS); logger.debug("{}: {}", "ConstUtils.SUPER_ADMINS", ConstUtils.SUPER_ADMINS); ConstUtils.SUPER_MANAGER = Arrays.asList(ConstUtils.SUPER_ADMINS.split(",")); logger.debug("{}: {}", "ConstUtils.SUPER_MANAGER", ConstUtils.SUPER_MANAGER); String leaderEmailListStr = MapUtils.getString(configMap, "cachecloud.leader.email"); if (!StringUtil.isBlank(leaderEmailListStr)) { ConstUtils.LEADER_EMAIL_LIST = Arrays.asList(leaderEmailListStr.split(",")); } // 机器报警阀值 ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD = MapUtils.getDoubleValue(configMap, "machine.mem.alert.ratio", ConstUtils.DEFAULT_MEMORY_USAGE_RATIO_THRESHOLD); logger.debug("{}: {}", "ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD", ConstUtils.MEMORY_USAGE_RATIO_THRESHOLD); //cachecloud根目录 ConstUtils.CACHECLOUD_BASE_DIR = MapUtils.getString(configMap, "cachecloud.base.dir", ConstUtils.DEFAULT_CACHECLOUD_BASE_DIR); logger.debug("{}: {}", "ConstUtils.CACHECLOUD_BASE_DIR", ConstUtils.CACHECLOUD_BASE_DIR); //应用客户端连接报警阀值 ConstUtils.APP_CLIENT_CONN_THRESHOLD = MapUtils.getIntValue(configMap, "cachecloud.app.client.conn.threshold", ConstUtils.DEFAULT_APP_CLIENT_CONN_THRESHOLD); logger.debug("{}: {}", "ConstUtils.APP_CLIENT_CONN_THRESHOLD", ConstUtils.APP_CLIENT_CONN_THRESHOLD); //邮件报警接口 AlertUtils.EMAIL_ALERT_INTERFACE = MapUtils.getString(configMap, "cachecloud.email.alert.interface"); logger.debug("{}: {}", "ConstUtils.EMAIL_ALERT_INTERFACE", AlertUtils.EMAIL_ALERT_INTERFACE); //短信报警接口 AlertUtils.MOBILE_ALERT_INTERFACE = MapUtils.getString(configMap, "cachecloud.mobile.alert.interface"); logger.debug("{}: {}", "ConstUtils.MOBILE_ALERT_INTERFACE", AlertUtils.MOBILE_ALERT_INTERFACE); //微信报警接口 AlertUtils.WECHAT_ALERT_INTERFACE = MapUtils.getString(configMap, "cachecloud.weChat.alert.interface"); logger.debug("{}: {}", "ConstUtils.MOBILE_ALERT_INTERFACE", AlertUtils.MOBILE_ALERT_INTERFACE); //是否定期清理各种统计数据(详见CleanUpStatisticsJob) ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA = MapUtils.getBooleanValue(configMap, "cachecloud.whether.schedule.clean.data", ConstUtils.DEFAULT_WHETHER_SCHEDULE_CLEAN_DATA); logger.debug("{}: {}", "ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA", ConstUtils.WHETHER_SCHEDULE_CLEAN_DATA); // 机器性能统计周期(分钟) ConstUtils.MACHINE_STATS_CRON_MINUTE = MapUtils.getIntValue(configMap, "cachecloud.machine.stats.cron.minute", ConstUtils.DEFAULT_MACHINE_STATS_CRON_MINUTE); logger.debug("{}: {}", "ConstUtils.MACHINE_STATS_CRON_MINUTE", ConstUtils.MACHINE_STATS_CRON_MINUTE); logger.info("ConfigServiceImpl reload config end"); } @Override public SuccessEnum updateConfig(Map configMap) { for (Entry entry : configMap.entrySet()) { String configKey = entry.getKey(); String configValue = entry.getValue(); try { configDao.update(configKey, configValue); } catch (Exception e) { logger.error("key {} value {} update faily" + e.getMessage(), configKey, configValue, e); return SuccessEnum.FAIL; } } return SuccessEnum.SUCCESS; } @Override public List getConfigList(int status) { try { return configDao.getConfigList(status); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } /** * 获取所有配置的key-value * * @return */ private Map getConfigMap() { Map configMap = new LinkedHashMap(); List systemConfigList = getConfigList(1); for (SystemConfig systemConfig : systemConfigList) { configMap.put(systemConfig.getConfigKey(), systemConfig.getConfigValue()); } return configMap; } public void setConfigDao(ConfigDao configDao) { this.configDao = configDao; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/DiagnosticToolServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.constant.DiagnosticTypeEnum; import com.sohu.cache.dao.DiagnosticTaskRecordDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.DiagnosticTaskRecord; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.AssistRedisService; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.DiagnosticToolService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.Jedis; import redis.clients.jedis.ScanParams; import redis.clients.jedis.ScanResult; import java.nio.charset.Charset; import java.util.*; import java.util.stream.Collectors; /** * @Author: rucao * @Date: 2020/6/5 5:33 下午 */ @Service @Slf4j public class DiagnosticToolServiceImpl implements DiagnosticToolService { @Autowired private AssistRedisService assistRedisService; @Autowired private DiagnosticTaskRecordDao diagnosticTaskRecordDao; @Autowired private AppService appService; @Autowired private RedisCenter redisCenter; @Override public Map> getAppInstancesMap(List appDescList) { Map> appInstancesMap = appDescList.parallelStream().collect(Collectors.toMap( appDesc -> appDesc.getAppId(), appDesc -> appService.getAppOnlineInstanceInfo(appDesc.getAppId()))); return appInstancesMap; } @Override public List getDiagnosticTaskRecords(Long appId, Long parentTaskId, Long auditId, Integer type, Integer status) { List diagnosticTaskRecords = new ArrayList<>(); try { diagnosticTaskRecords = diagnosticTaskRecordDao.getDiagnosticTaskRecords(appId, parentTaskId, auditId, type, status); } catch (Exception e) { log.error(e.getMessage(), e); } return diagnosticTaskRecords; } @Override public Map getDiagnosticDataMap(String redisKey, int type, boolean err) { if (type == DiagnosticTypeEnum.SLOT_ANALYSIS.getType() && err == true) { Map tmp = assistRedisService.hgetAll(redisKey); return tmp.keySet().stream() .filter(key -> tmp.get(key).contains("error")) .collect(Collectors.toMap(key -> key, key -> tmp.get(key))); } return assistRedisService.hgetAll(redisKey); } @Override public String getHotkeyDiagnosticData(String redisKey) { return assistRedisService.get(redisKey); } @Override public List getScanDiagnosticData(String redisKey) { return assistRedisService.lrange(redisKey, 0, -1); } @Override public List getScanCleanDiagnosticData(String redisKey) { return assistRedisService.lrange(redisKey, 0, -1); } @Override public List getSampleScanData(Long appId, String nodes, String pattern) { List sampleScanData = new ArrayList<>(); String host = ""; int port = 0; if (StringUtil.isBlank(nodes)) { List instanceInfoList = appService.getAppOnlineInstanceInfo(appId); for (InstanceInfo instanceInfo : instanceInfoList) { if ("master".equals(instanceInfo.getRoleDesc())) { host = instanceInfo.getIp(); port = instanceInfo.getPort(); break; } } } else { String[] nodeArray = nodes.split(","); String hostPort = nodeArray.length > 0 ? nodeArray[0] : ""; if (!StringUtil.isBlank(hostPort)) { host = hostPort.split(":").length > 0 ? hostPort.split(":")[0] : ""; port = hostPort.split(":").length > 1 ? Integer.parseInt(hostPort.split(":")[1]) : 0; } } long startTime = System.currentTimeMillis(); Jedis jedis = null; try { jedis = redisCenter.getAdminJedis(appId, host, port); long dbSize = jedis.dbSize(); if (dbSize == 0) { log.info("{} {}:{} dbsize is {}", appId, host, port, dbSize); return sampleScanData; } log.info("{} {}:{} total key is {} ", appId, host, port, dbSize); // scan参数 byte[] cursor = "0".getBytes(Charset.forName("UTF-8")); ScanParams scanParams = StringUtil.isBlank(pattern) ? new ScanParams().count(50) : new ScanParams().match(pattern).count(50); while (true) { try { ScanResult scanResult = jedis.scan(cursor, scanParams); cursor = scanResult.getCursorAsBytes(); List keyList = scanResult.getResult(); if (CollectionUtils.isNotEmpty(keyList)) { sampleScanData.addAll(keyList.stream().map(byteKey -> new String(byteKey)).collect(Collectors.toList())); } } catch (Exception e) { log.error(e.getMessage(), e); } finally { //防止无限循环 if (sampleScanData.size() >= 50 || Arrays.equals("0".getBytes(Charset.forName("UTF-8")), cursor)) { break; } } } //结果存redis long cost = System.currentTimeMillis() - startTime; log.info("{} {}:{} scan key successfully, cost time is {} ms, total key is {}", appId, host, port, cost, sampleScanData.size()); return sampleScanData; } catch (RuntimeException e) { throw e; } catch (Exception e) { log.error("redis-cli -h {} -p {} admin auth error", host, port); log.error("scan key appId {} {}:{} error:" + e.getMessage(), appId, host, port, e); return sampleScanData; } finally { if (jedis != null) { jedis.close(); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/InstancePortServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.MachineRoomDao; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.task.BaseTask; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.task.entity.NutCrackerNode; import com.sohu.cache.task.entity.RedisSentinelNode; import com.sohu.cache.task.entity.RedisServerNode; import com.sohu.cache.task.util.AppWechatUtil; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.InstancePortService; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import java.util.*; import java.util.concurrent.TimeUnit; /** * @author fulei * @date 2018年7月4日 * @time 下午3:29:10 */ @Service public class InstancePortServiceImpl implements InstancePortService { private Logger logger = LoggerFactory.getLogger(InstancePortServiceImpl.class); /*@Value("${appEnvName}") private String appEnvName;*/ @Autowired private AppWechatUtil appWechatUtil; /** * 机房dao */ @Autowired private MachineRoomDao machineRoomDao; /** * 实例dao */ @Autowired private InstanceDao instanceDao; /** * redis-port实例dao */ // private RedisPortInstanceDao redisPortInstanceDao; /** * redis-migrate-tool实例dao */ // private RedisMigrateToolInstanceDao redisMigrateToolInstanceDao; /** * redis相关 */ @Autowired @Lazy private RedisCenter redisCenter; /** * 1. 主从不同机器 * 2. 端口从起始端口开始自增1 */ @Override public List generateRedisServerNodeList(long appId, List redisServerMachineList, int masterPerMachine, int maxMemory) { // 最终结果 List redisServerNodeList = new ArrayList(); // 起始节点 int masterPort = (int) (ConstUtils.REDIS_SERVER_BASE_PORT + (appId % 10) * 10); // 记录本次每个机器分配的port Map> ipPortSetMap = new HashMap>(); for (int i = 0; i < redisServerMachineList.size(); i++) { String masterHost = redisServerMachineList.get(i); String slaveHost = redisServerMachineList.get((i + 1) % redisServerMachineList.size()); for (int j = 0; j < masterPerMachine; j++) { // master node //如果端口存在就自增 while (checkHostPortExist(ipPortSetMap, masterHost, masterPort)) { masterPort++; } redisServerNodeList.add(new RedisServerNode(masterHost, masterPort, InstanceRoleEnum.MASTER.getRole(), maxMemory, "", 0)); // slave node int slavePort = masterPort + ConstUtils.SLAVE_PORT_INCREASE; //如果端口存在就自增 while (checkHostPortExist(ipPortSetMap, slaveHost, slavePort)) { slavePort++; } redisServerNodeList.add(new RedisServerNode(slaveHost, slavePort, InstanceRoleEnum.SLAVE.getRole(), maxMemory, masterHost, masterPort)); masterPort += 1; } } return redisServerNodeList; } /** * 1. 主从不同机器 * 2. 端口从起始端口开始自增1 */ @Override public List generateRedisServerNodeListWithDeployInfo(long appId, List appDeployInfoList, int masterPerMachine, int maxMemory) { // 最终结果 List redisServerNodeList = new ArrayList(); // 起始节点 int masterPort = (int) (ConstUtils.REDIS_SERVER_BASE_PORT + (appId % 10) * 10); // 记录本次每个机器分配的port Map> ipPortSetMap = new HashMap>(); for (int i=0; i < appDeployInfoList.size(); i++) { String masterAndSlaveHost = appDeployInfoList.get(i); String[] hostInfoArray = masterAndSlaveHost.split(":"); String masterHost = hostInfoArray[0]; maxMemory = Integer.parseInt(hostInfoArray[1]); while (checkHostPortExist(ipPortSetMap, masterHost, masterPort)) { masterPort++; } redisServerNodeList.add(new RedisServerNode(masterHost, masterPort, InstanceRoleEnum.MASTER.getRole(), maxMemory, "", 0)); if (hostInfoArray.length >= 3) { String slaveHost = hostInfoArray[2]; int slavePort = masterPort + ConstUtils.SLAVE_PORT_INCREASE; while (checkHostPortExist(ipPortSetMap, slaveHost, slavePort)) { slavePort++; } redisServerNodeList.add(new RedisServerNode(slaveHost, slavePort, InstanceRoleEnum.SLAVE.getRole(), maxMemory, masterHost, masterPort)); } masterPort += 1; } return redisServerNodeList; } @Override public List generateRedisSentinelNodeList(long appId, List redisSentinelMachineList, int sentinelPerMachine) { // 最终结果 List redisSentinelNodeList = new ArrayList(); // 起始节点,appid 10000起步 @TODO int port = (int) (ConstUtils.REDIS_SENTINEL_BASE_PORT + (appId % 100) * 10); for (String ip : redisSentinelMachineList) { for (int j = 0; j < sentinelPerMachine; j++) { //如果端口存在就自增 while (checkHostPortExist(ip, port)) { port++; } redisSentinelNodeList.add(new RedisSentinelNode(ip, port)); port++; } } return redisSentinelNodeList; } /*@Override public List generatePikaNodeList(long appId, List pikaMachineList, int masterPerMachine) { // 最终结果 List pikaNodeList = new ArrayList(); // 起始节点 int masterPort = (int) (ConstUtils.PIKA_BASE_PORT + (appId % 10) * 10); // 记录本次每个机器分配的port Map> ipPortSetMap = new HashMap>(); // 如果是一对,那只只要主从 int machineLength = pikaMachineList.size() == 2 ? 1 : pikaMachineList.size(); for (int i = 0; i < machineLength; i++) { String masterHost = pikaMachineList.get(i); String slaveHost = pikaMachineList.get((i + 1) % pikaMachineList.size()); for (int j = 0; j < masterPerMachine; j++) { // master node while (checkHostPortExist(ipPortSetMap, masterHost, masterPort)) { masterPort++; } pikaNodeList.add(new PikaNode(masterHost, masterPort, InstanceRoleEnum.MASTER.getRole(), "", 0)); // slave node int slavePort = masterPort + ConstUtils.PIKA_SLAVE_PORT_INCREASE; while (checkHostPortExist(ipPortSetMap, slaveHost, slavePort)) { slavePort++; } pikaNodeList.add(new PikaNode(slaveHost, slavePort, InstanceRoleEnum.SLAVE.getRole(), masterHost, masterPort)); masterPort += 1; } } return pikaNodeList; }*/ /** * 每台端口从baseport开始自增1 */ @Override public List generateNutCrackerNodeList(long appId, List nutCrackerMachineList, int nutCrackerPerMachine) { // // 最终结果 // List nutCrackerNodeList = new ArrayList(); // // 起始节点 // int port =(int) (ConstUtils.NUT_CRACKER_BASE_PORT + (appId % 10) * 10); // for (String ip : nutCrackerMachineList) { // int initPort = port; // for (int j = 0; j < nutCrackerPerMachine; j++) { // //如果端口存在就自增 // while (checkNutCrackerHostPortExist(ip, initPort)) { // initPort++; // } // nutCrackerNodeList.add(new NutCrackerNode(ip, initPort)); // initPort++; // } // } // return nutCrackerNodeList; // @todo fulei return null; } /*@Override public List generateCodisProxyList(long appId, List codisProxyMachineList, int codisProxyPerMachine) { // 最终结果 List codisProxyNodeList = new ArrayList(); // 起始节点 int port; if (appEnvName.equals(AppEnvNameEnum.afun.getName())) { port = ConstUtils.CODIS_PROXY_BASE_PORT; } else { port = (int) (ConstUtils.CODIS_PROXY_BASE_PORT + (appId % 10) * 10); } for (String ip : codisProxyMachineList) { int initPort = port; for (int j = 0; j < codisProxyPerMachine; j++) { //如果端口存在就自增 while (checkCodisProxyHostPortExist(ip, initPort)) { initPort++; } codisProxyNodeList.add(new CodisProxyNode(ip, initPort)); initPort++; } } return codisProxyNodeList; }*/ /*@Override public List generateCodisDashboardList(long appId, List codisDashboardMachineList) { // 最终结果 List codisDashboardNodeList = new ArrayList(); int port = ConstUtils.CODIS_DASHBOARD_BASE_PORT; for (String ip : codisDashboardMachineList) { // 如果端口存在就自增 while (checkDashboardHostPortExist(ip, port)) { port++; } codisDashboardNodeList.add(new CodisDashboardNode(ip, port)); port++; } return codisDashboardNodeList; }*/ @Override public boolean checkHostPortExist(String ip, int port) { InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(ip, port); if (instanceInfo != null) { return true; } //只检测一次 boolean isRedisRun = redisCenter.isRun(ip, port, 1); if (isRedisRun) { appWechatUtil.noticeWildInstance(ip, port); logger.warn(BaseTask.marker, "{}:{} process is not in instance_info table", ip, port); return true; } return false; } private boolean checkHostPortExist(Map> ipPortSetMap, String host, int port) { Set portSet = ipPortSetMap.get(host); if (CollectionUtils.isNotEmpty(portSet) && portSet.contains(port)) { return true; } else { if (portSet == null) { Set set = new HashSet(); set.add(port); ipPortSetMap.put(host, set); } else { ipPortSetMap.get(host).add(port); } return checkHostPortExist(host, port); } } /** * 暂时和nut cracker一样 * * @return */ /*private boolean checkCodisProxyHostPortExist(String ip, int port) { List instanceInfoList = instanceDao.getInstanceByIpAndStatPort(ip, port); if (CollectionUtils.isNotEmpty(instanceInfoList)) { return true; } else { return checkHostPortExist(ip, port); } }*/ private boolean checkNutCrackerHostPortExist(String ip, int port) { // List instanceInfoList = instanceDao.getInstanceByIpAndStatPort(ip, port); // if (CollectionUtils.isNotEmpty(instanceInfoList)) { // return true; // } else { // return checkHostPortExist(ip, port); // } // @todo fulei return true; } public boolean checkDashboardHostPortExist(String ip, int port) { InstanceInfo instanceInfo = instanceDao.getAllInstByIpAndPort(ip, port); if (instanceInfo != null) { return true; } return false; } private boolean checkRedisMigrateToolPortExist(String ip, int port) { // @todo fulei return true; // RedisMigrateToolInstance redisMigrateToolInstance = redisMigrateToolInstanceDao.getByHostAndPort(ip, port); // if (redisMigrateToolInstance != null) { // return true; // } // //只检测一次 // boolean isRedisRun = redisCenter.isRun(ip, port, 1); // if (isRedisRun) { // appWechatUtil.noticeWildInstance(ip, port); // logger.warn(BaseTask.marker, "{}:{} process is not in instance_info table", ip, port); // return true; // } // return false; } /*@Override public List generateRedisPortNodeList(long sourceAppId, long targetAppId, List slaveInstanceInfoList, List proxyInstanceInfoList) { List redisPortNodeList = new ArrayList(); for (int i = 0; i < slaveInstanceInfoList.size(); i++) { //proxy索引 int index = i % proxyInstanceInfoList.size(); InstanceInfo proxyInstanceInfo = proxyInstanceInfoList.get(index); InstanceInfo slaveInstanceInfo = slaveInstanceInfoList.get(i); String redisPortHost = slaveInstanceInfo.getIp(); int redisPortPort = slaveInstanceInfoList.get(i).getPort() + ConstUtils.REDIS_PORT_PORT_INCREASE; String sourceHost = slaveInstanceInfo.getIp(); int sourcePort = slaveInstanceInfo.getPort(); String targetHost = proxyInstanceInfo.getIp(); int targetPort = proxyInstanceInfo.getPort(); while (checkRedisPortExist(redisPortHost, redisPortPort, sourceHost, sourcePort, targetHost, targetPort)) { redisPortPort++; } RedisPortNode redisPortNode = new RedisPortNode(); redisPortNode.setIp(redisPortHost); redisPortNode.setPort(redisPortPort); redisPortNode.setSourceInstanceId(slaveInstanceInfo.getId()); redisPortNode.setSourceIp(sourceHost); redisPortNode.setSourcePort(sourcePort); redisPortNode.setTargetInstanceId(proxyInstanceInfo.getId()); redisPortNode.setTargetIp(targetHost); redisPortNode.setTargetPort(targetPort); redisPortNodeList.add(redisPortNode); } return redisPortNodeList; }*/ @Override public RedisServerNode generateRedisServerNode(long appId, String host, int maxMemory, InstanceRoleEnum instanceRoleEnum) { synchronized (host.intern()) { try { //防止端口重复 @TODO也可以用本地缓存做端口限制 TimeUnit.SECONDS.sleep(3); int port = (int) (ConstUtils.REDIS_SERVER_BASE_PORT + (appId % 10) * 10); if (InstanceRoleEnum.SLAVE.equals(instanceRoleEnum)) { port += ConstUtils.SLAVE_PORT_INCREASE; } while (checkHostPortExist(host, port)) { logger.info(BaseTask.marker, "appId {} host {} port is {}", appId, host, port); port++; } logger.info(BaseTask.marker, "final appId {} host {} port is {}", appId, host, port); return new RedisServerNode(host, port, maxMemory); } catch (Exception e) { logger.error(BaseTask.marker, e.getMessage(), e); return null; } } } /*@Override public PikaNode generatePikaNode(long appId, String host, int maxMemory, InstanceRoleEnum instanceRoleEnum) { synchronized (host.intern()) { try { //防止端口重复 @TODO也可以用本地缓存做端口限制 TimeUnit.SECONDS.sleep(3); int port = (int) (ConstUtils.PIKA_BASE_PORT + (appId % 10) * 10); if (InstanceRoleEnum.SLAVE.equals(instanceRoleEnum)) { port += ConstUtils.PIKA_SLAVE_PORT_INCREASE; } while (checkHostPortExist(host, port)) { logger.info(BaseTask.marker, "appId {} host {} port is {}", appId, host, port); port++; } logger.info(BaseTask.marker, "final appId {} host {} port is {}", appId, host, port); return new PikaNode(host, port); } catch (Exception e) { logger.error(BaseTask.marker, e.getMessage(), e); return null; } } }*/ /*@Override public List generateRedisMigrateToolNodeList(int rmtCount, String machineLogicName) { //最终结果 List redisMigrateToolNodeList = new ArrayList(); //所有rmt机器 List redisMigrateToolMachineList = machineInfoDao.getMachineInfoByKsp(KspNodeEnum.MIGRATE_TOOL.getType()); if (appEnvName.equals(AppEnvNameEnum.afun.getName())) { redisMigrateToolMachineList = machineInfoDao.getMachineInfoByKsp("afun-redis-migrate-tool"); if (CollectionUtils.isNotEmpty(redisMigrateToolMachineList)) { String host = redisMigrateToolMachineList.get(0).getIp(); int port = ConstUtils.REDIS_MIGRATE_TOOL_PORT; //检查表和心跳 if (!checkRedisMigrateToolPortExist(host, port)) { redisMigrateToolNodeList.add(new RedisMigrateToolNode(host, port)); } } } else { redisMigrateToolMachineList = machineInfoDao.getMachineInfoByKsp(KspNodeEnum.MIGRATE_TOOL.getType()); for (MachineInfo redisMigrateToolMachine : redisMigrateToolMachineList) { MachineRoom machineRoom = machineRoomDao.getByName(redisMigrateToolMachine.getMachineRoomName()); if (!machineLogicName.equals(machineRoom.getLogicName())) { continue; } if (redisMigrateToolNodeList.size() >= rmtCount) { break; } String host = redisMigrateToolMachine.getIp(); int port = ConstUtils.REDIS_MIGRATE_TOOL_PORT; //检查表和心跳 if (!checkRedisMigrateToolPortExist(host, port)) { redisMigrateToolNodeList.add(new RedisMigrateToolNode(host, port)); } } } return redisMigrateToolNodeList; }*/ } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/MigrateServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.async.AsyncService; import com.sohu.cache.async.KeyCallable; import com.sohu.cache.dao.InstanceDao; import com.sohu.cache.dao.InstanceStatsDao; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.exception.SSHException; import com.sohu.cache.machine.MachineCenter; import com.sohu.cache.redis.RedisCenter; import com.sohu.cache.redis.RedisDeployCenter; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.stats.instance.InstanceDeployCenter; import com.sohu.cache.task.constant.InstanceRoleEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.MigrateService; import com.sohu.cache.web.vo.RedisClusterNode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import redis.clients.jedis.HostAndPort; import java.util.*; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * @Author: zengyizhao * @CreateTime: 2023/2/28 15:33 * @Description: 迁移服务 * @Version: 1.0 */ @Slf4j @Service("migrateService") public class MigrateServiceImpl implements MigrateService { @Autowired private RedisCenter redisCenter; @Autowired protected AppService appService; @Autowired private SSHService sshService; @Autowired private MachineCenter machineCenter; @Autowired private AsyncService asyncService; @Autowired private RedisDeployCenter redisDeployCenter; @Autowired private InstanceDao instanceDao; @Autowired private InstanceStatsDao instanceStatsDao; @Autowired private InstanceDeployCenter instanceDeployCenter; @Override public void forceMigrate(String sourceIp, String targetIp) throws SSHException { /** * 1. 检查目标容器的连通性 * 2. 获取需要迁移的实例信息 * 3. 遍历实例:(只对cluster实例迁移) * 3.1 standalone/sentinel节点跳过 * 3.2 如果实例是master:添加新的从节点;获取master节点slave0;执行failover ;下线老节点 * 3.3 如果是slave节点:添加新从节点;下线老的从节点 * 4. 输出报告:下线节点数 ,迁移节点数 */ log.info("container forceMigrate start sourceIp:{} targetIp:{}", sourceIp, targetIp); //1.检查目标容器的连通性 String execute = sshService.execute(targetIp, "echo ok"); //2.获取机器所有实例 List instanceList = machineCenter.getMachineInstanceInfo(sourceIp); log.info("container forceMigrate instances:{} list size:{}", instanceList, instanceList.size()); List resultList = null; // 4.遍历实例,按照appId分组 if (!CollectionUtils.isEmpty(instanceList)) { //按照appId进行分组 Map> appInstanceMap = new HashMap<>(); instanceList.forEach(instanceInfo -> { if (instanceInfo.getType() != ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { return; } if (appInstanceMap.containsKey(instanceInfo.getAppId())) { appInstanceMap.get(instanceInfo.getAppId()).add(instanceInfo); } else { List instanceInfoList = new ArrayList<>(); instanceInfoList.add(instanceInfo); appInstanceMap.put(instanceInfo.getAppId(), instanceInfoList); } }); Set appSet = appInstanceMap.keySet(); String key = "force-migrate-instance-" + sourceIp + "-" + targetIp; List doForceMigrateResult = appSet.stream().map(appId -> { return asyncService.submitFutureWithRst(new KeyCallable(key + appId) { public Boolean execute() { try { //一键强制迁移 return forceMigrateAppInstances(targetIp, appId, appInstanceMap.get(appId)); } catch (Exception e) { log.error("doForceMigrateInstance ", e.getMessage(), e); return false; } } }); }).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(doForceMigrateResult)) { resultList = doForceMigrateResult.stream().map(future -> { try { return future.get(); } catch (Exception e) { log.error(e.getMessage()); } return false; }).collect(Collectors.toList()); } } log.info("container forceMigrate end sourceIp:{} targetIp:{}, result:{}", sourceIp, targetIp, resultList); } public boolean forceMigrateAppInstances(String targetIp, Long appId, List instanceList) throws SSHException { log.info("container forceMigrate AppInstances start appId:{} targetIp:{}, instance:{}", appId, targetIp, instanceList); List failInstanceList = new ArrayList<>(); instanceList = instanceList.stream() .filter(instanceInfo -> instanceInfo.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) .collect(Collectors.toList()); //先执行能正确获取角色的节点,如为执行成功,则添加到非正常节点中 for (InstanceInfo instanceInfo : instanceList) { String role = redisCenter.getInstanceRole(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); log.info("instanceInfo:{} {} role:{} start migrate", instanceInfo.getIp(), instanceInfo.getPort(),role); if (instanceInfo.isOnline()) { // a)当前为master节点 if (InstanceRoleEnum.MASTER.getInfo().equals(role)) { if (!handleMasterMigrate(instanceInfo, targetIp)) { failInstanceList.add(instanceInfo); } } // b).当前为slave节点 if (InstanceRoleEnum.SLAVE.getInfo().equals(role)) { if (!handleSlaveMigrate(instanceInfo, targetIp)) { failInstanceList.add(instanceInfo); } } } else { failInstanceList.add(instanceInfo); } } log.info("container forceMigrate AppInstances appId:{} targetIp:{}, need to retry instances:{}", appId, targetIp, failInstanceList); //强制迁移非正常节点 int retryTimes = 3; while (failInstanceList.size() > 0 && retryTimes > 0) { //获取拓扑信息 Map appClusterNode = this.getAppClusterNode(appId); //每个实例传入拓扑信息进行处理 for (int i = 0; i < failInstanceList.size(); ) { InstanceInfo instanceInfo = failInstanceList.get(i); RedisClusterNode clusterNode = appClusterNode.get(instanceInfo.getHostPort()); if (clusterNode != null) { boolean handlerResult = false; if ("master".equals(clusterNode.getRole())) { try { Optional slaveNodeOptional = appClusterNode.values().stream() .filter(node -> clusterNode.getHostPort().equals(node.getMasterHostPort()) && node.isConnected() && !node.isFail()) .findFirst(); if (slaveNodeOptional.isPresent()) { String hostPort = slaveNodeOptional.get().getHostPort(); String[] hostPortArray = hostPort.split(":"); InstanceInfo slaveInstance = instanceDao.getInstByIpAndPort(hostPortArray[0], Integer.valueOf(hostPortArray[1])); handlerResult = handleUnknownInstanceMigrate(instanceInfo, slaveInstance, true, targetIp, true); } } catch (Exception e) { log.error("container forceMigrate AppInstances appId:{} targetIp:{}, forceMigrate master fail instance:{}, error: {}", appId, targetIp, instanceInfo, e.getMessage()); e.printStackTrace(); } } else { try { Optional masterNodeOptional = appClusterNode.values().stream() .filter(node -> clusterNode.getMasterHostPort().equals(node.getHostPort()) && node.isConnected() && !node.isFail()) .findFirst(); if (masterNodeOptional.isPresent()) { String hostPort = masterNodeOptional.get().getHostPort(); Set slaves = appClusterNode.values().stream() .filter(node -> hostPort.equals(node.getMasterHostPort()) && !node.getHostPort().equals(clusterNode.getHostPort())) .collect(Collectors.toSet()); boolean addSlave = true; if (CollectionUtils.isNotEmpty(slaves)) { addSlave = false; } String[] hostPortArray = hostPort.split(":"); InstanceInfo masterInstance = instanceDao.getInstByIpAndPort(hostPortArray[0], Integer.valueOf(hostPortArray[1])); handlerResult = handleUnknownInstanceMigrate(masterInstance, instanceInfo, false, targetIp, addSlave); } } catch (Exception e) { log.error("container forceMigrate AppInstances appId:{} targetIp:{}, forceMigrate slave fail instance:{}, error: {}", appId, targetIp, instanceInfo, e.getMessage()); e.printStackTrace(); } } if (handlerResult) { failInstanceList.remove(i); } else { i++; } } } log.warn("container forceMigrate AppInstances appId:{} targetIp:{}, after one more retry, fail instance left:{}", appId, targetIp, failInstanceList); retryTimes--; } if (CollectionUtils.isNotEmpty(failInstanceList)) { log.warn("container forceMigrate AppInstances appId:{} targetIp:{}, forceMigrate fail instance:{}", appId, targetIp, failInstanceList); return false; } return true; } private boolean handleMasterMigrate(InstanceInfo instanceInfo, String targetIp) { try { //1)获取master节点slave0 AppDesc appdesc = appService.getByAppId(instanceInfo.getAppId()); // HostAndPort slave0 = redisCenter.getSlave0(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); HostAndPort slave0 = null; if (instanceInfo.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { slave0 = redisCenter.getSlave0(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); } //2)执行failover force if (slave0 == null) { return false; } InstanceInfo masterInst = instanceDao.getInstByIpAndPort(slave0.getHost(), slave0.getPort()); boolean checkFailover = this.failoverAndCheck(masterInst); if (!checkFailover) { // 如果failover失败 ,则不下线源节点,继续轮训下个节点 return false; } TimeUnit.SECONDS.sleep(5); //3) 下线节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(instanceInfo.getAppId(), instanceInfo.getId()); log.info("forceMigrate handleMasterMigrate appid:{} offline node master:{} to {}, result :{}", instanceInfo.getAppId(), instanceInfo.getHostPort(), targetIp, isOffline); //4) 添加新的从节点 Boolean isSuccess = false; if (instanceInfo.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); } // Boolean isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); log.info("forceMigrate handleMasterMigrate appid:{} offline node master:{} result:{}, add new slave :{} result:{}", instanceInfo.getAppId(), instanceInfo.getHostPort(), isOffline, targetIp, isSuccess); if (isSuccess) { return true; } else { // 添加从节点 失败,则退出 检查原因 log.error("forceMigrate handleMasterMigrate add slave {}:{} fail", instanceInfo.getAppId(), masterInst.getId()); } } catch (Exception e) { log.error("container forceMigrate handleMasterMigrate targetIp:{}, forceMigrate fail instance:{}, error: {}", targetIp, instanceInfo, e.getMessage()); } return false; } private boolean handleSlaveMigrate(InstanceInfo instanceInfo, String targetIp) { AppDesc appdesc = appService.getByAppId(instanceInfo.getAppId()); try { HostAndPort masterInfo = redisCenter.getMaster(instanceInfo.getIp(), instanceInfo.getPort(), appdesc.getAppPassword()); if (masterInfo == null) { return false; } if (StringUtils.isNotEmpty(masterInfo.getHost()) && masterInfo.getPort() > 0) { InstanceInfo masterInst = instanceDao.getInstByIpAndPort(masterInfo.getHost(), masterInfo.getPort()); if (masterInst == null) { return false; } //下线当前slave节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(instanceInfo.getAppId(), instanceInfo.getId()); log.info("forceMigrate handleSlaveMigrate appid:{} offline slave:{}, result :{}", instanceInfo.getAppId(), instanceInfo.getHostPort(), isOffline); //添加新的slave节点 Boolean isSuccess = false; if (instanceInfo.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); } //boolean isSuccess = redisDeployCenter.addSlave(instanceInfo.getAppId(), masterInst.getId(), targetIp); // sleep 5s TimeUnit.SECONDS.sleep(5); log.info("forceMigrate handleSlaveMigrate appid:{} offline slave:{} result:{},add slave:{} result:{}", instanceInfo.getAppId(), instanceInfo.getHostPort(), isOffline, targetIp, isSuccess); if (isSuccess) { return true; } } } catch (Exception e) { log.error("container forceMigrate handleSlaveMigrate targetIp:{}, forceMigrate fail instance:{}, error: {}", targetIp, instanceInfo, e.getMessage()); } return false; } private Map getAppClusterNode(long appId) { List appInstances = appService.getAppBasicInstanceInfo(appId); Set hostPortSet = appInstances.stream().filter(instanceInfo -> !instanceInfo.isOffline()) .map(instanceInfo -> instanceInfo.getHostPort()).collect(Collectors.toSet()); appInstances = appInstances.stream() .filter(instanceInfo -> instanceInfo.isOnline()).collect(Collectors.toList()); Map clusterNode = new HashMap<>(); for (int i = 0; i < appInstances.size(); i++) { clusterNode = this.getClusterNodeByInstance(hostPortSet, appInstances.get(i)); if (MapUtils.isNotEmpty(clusterNode)) { break; } } return clusterNode; } private Map getClusterNodeByInstance(Set hostPortSet, InstanceInfo instanceInfo) { try { String clusterNodes = redisCenter.getClusterNodes(instanceInfo.getAppId(), instanceInfo.getIp(), instanceInfo.getPort()); if (StringUtils.isBlank(clusterNodes)) { return null; } final Map nodeMap = new HashMap<>(); hostPortSet.forEach(hostPort -> nodeMap.put(hostPort, null)); String[] clusterNodeArray = clusterNodes.split("\n"); for (int i = 0; i < clusterNodeArray.length; i++) { final String nodeInfo = clusterNodeArray[i]; Optional optional = hostPortSet.stream().filter(hostPort -> nodeInfo.contains(hostPort)).findFirst(); if (!optional.isPresent()) { continue; } if (StringUtils.isNotBlank(nodeInfo)) { String[] nodeInfoPartArray = nodeInfo.split(" "); RedisClusterNode clusterNode = new RedisClusterNode(); clusterNode.setHostPort(optional.get()); if (nodeInfo.contains("connected")) { clusterNode.setConnected(true); } if (nodeInfo.contains("fail")) { clusterNode.setFail(true); } if (nodeInfo.contains("master")) { clusterNode.setRole("master"); } if (nodeInfo.contains("slave")) { clusterNode.setRole("slave"); String masterId = nodeInfoPartArray[3]; for (String clusterNodeStr : clusterNodeArray) { if (clusterNodeStr.contains("master") && clusterNodeStr.contains(masterId)) { String[] masterNodeInfoPartArray = clusterNodeStr.split(" "); String masterHostPort = masterNodeInfoPartArray[1]; if (masterHostPort.contains("@")) { masterHostPort = masterHostPort.substring(0, masterHostPort.indexOf("@")); } clusterNode.setMasterHostPort(masterHostPort); } } } nodeMap.put(optional.get(), clusterNode); } } return nodeMap; } catch (Exception e) { log.error("forceMigrate getClusterNodeByInstance instance:{}, error:{}", instanceInfo, e.getMessage()); } return null; } private boolean handleUnknownInstanceMigrate(InstanceInfo masterInstance, InstanceInfo slaveInstance, boolean currentIsMaster, String targetIp, boolean addSlave) { try { if (currentIsMaster) { //1) failover boolean failoverRst = this.failoverAndCheck(slaveInstance); if (!failoverRst) { return false; } TimeUnit.SECONDS.sleep(5); //2) 下线节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(masterInstance.getAppId(), masterInstance.getId()); log.info("forceMigrate handleUnknownInstanceMigrate appid:{} offline node master:{} to {}, result :{}", masterInstance.getAppId(), masterInstance.getHostPort(), targetIp, isOffline); //3) 添加新的从节点 Boolean isSuccess = redisDeployCenter.addSlave(slaveInstance.getAppId(), slaveInstance.getId(), targetIp); log.info("forceMigrate handleUnknownInstanceMigrate appid:{} offline node master:{} result:{}, add new slave:{} result:{}", masterInstance.getAppId(), masterInstance.getHostPort(), isOffline, targetIp, isSuccess); if (isSuccess) { return true; } else { // 添加从节点 失败,则退出 检查原因 log.error("forceMigrate handleUnknownInstanceMigrate add slave {}:{} fail", slaveInstance.getAppId(), slaveInstance.getId()); } } else { //1) 下线节点 boolean isOffline = instanceDeployCenter.shutdownExistInstance(slaveInstance.getAppId(), slaveInstance.getId()); log.info("forceMigrate handleUnknownInstanceMigrate appid:{} offline node slave:{}, result :{}", slaveInstance.getAppId(), slaveInstance.getHostPort(), isOffline); //2) 添加新的从节点 Boolean isSuccess = false; if (addSlave) { isSuccess = redisDeployCenter.addSlave(masterInstance.getAppId(), masterInstance.getId(), targetIp); } log.info("forceMigrate handleUnknownInstanceMigrate appid:{} offline node slave:{} result:{}, addSlave Flag:{}, add new slave:{} result:{}", masterInstance.getAppId(), masterInstance.getHostPort(), isOffline, addSlave, targetIp, isSuccess); if ((addSlave && isSuccess) || !addSlave) { return true; } else { // 添加从节点失败,则退出 检查原因 log.error("forceMigrate handleUnknownInstanceMigrate add slave {}:{} fail", masterInstance.getAppId(), masterInstance.getId()); } } } catch (Exception e) { log.error("forceMigrate handleUnknownInstanceMigrate appid:{} master node:{}, slave node:{}, currentIsMaster:{}, targetIp:{}, error:{}", masterInstance.getAppId(), masterInstance.getHostPort(), slaveInstance.getHostPort(), currentIsMaster, targetIp, e.getMessage()); } return false; } private boolean failoverAndCheck(InstanceInfo slaveInstance) { try { boolean isFailover = redisDeployCenter.clusterFailover(slaveInstance.getAppId(), slaveInstance.getId(), "force"); int times = 0; boolean checkFailover = false; while (!checkFailover && times++ <= 5) { Boolean status = false; // Boolean status = redisCenter.getRedisFailoverForceStatus(slaveInstance.getAppId(), slaveInstance.getIp(), slaveInstance.getPort()); if (slaveInstance.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) { status = redisCenter.getRedisReplicationStatus(slaveInstance.getAppId(), slaveInstance.getIp(), slaveInstance.getPort()); } if (status) { checkFailover = status; } else { TimeUnit.SECONDS.sleep(6); log.info(" check slave replication status ,waiting 6s ...."); } } if (!checkFailover) { // 如果failover失败 ,则不下线源节点,继续轮训下个节点 return false; } return true; } catch (Exception e) { log.error("forceMigrate failoverAndCheck appId:{}, instance:{}, error: {}", slaveInstance.getAppId(), slaveInstance.getHostPort(), e.getMessage()); } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/ResourceServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.dao.ResourceDao; import com.sohu.cache.entity.AppUser; import com.sohu.cache.entity.SystemResource; import com.sohu.cache.exception.SSHException; import com.sohu.cache.protocol.MachineProtocol; import com.sohu.cache.ssh.SSHService; import com.sohu.cache.ssh.SSHTemplate; import com.sohu.cache.ssh.SSHUtil; import com.sohu.cache.task.constant.PushEnum; import com.sohu.cache.task.constant.ResourceEnum; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.ResourceService; import com.sohu.cache.web.util.DateUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * Created by chenshi on 2020/7/6. */ @Service("resourceService") public class ResourceServiceImpl implements ResourceService { private Logger logger = LoggerFactory.getLogger(ResourceService.class); @Autowired ResourceDao resourceDao; @Autowired SSHService sshService; @PostConstruct public void init() { List resourceList = this.getResourceList(ResourceEnum.REDIS.getValue()); ConstUtils.REDIS_RESOURCE = resourceList.stream().collect(Collectors.toMap(res -> Integer.valueOf(res.getId()), Function.identity())); } public SuccessEnum saveResource(SystemResource systemResouce) { try { resourceDao.save(systemResouce); } catch (Exception e) { logger.error("key {} value {} update faily" + e.getMessage(), e); return SuccessEnum.FAIL; } return SuccessEnum.SUCCESS; } public SuccessEnum updateResource(SystemResource systemResouce) { try { resourceDao.update(systemResouce); } catch (Exception e) { logger.error("key {} value {} update faily" + e.getMessage(), e); return SuccessEnum.FAIL; } return SuccessEnum.REPEAT; } public List getResourceList(int resourceType) { try { return resourceDao.getResourceList(resourceType); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } public List getResourceList(int resourceType, String searchName) { try { return resourceDao.getResourceListByName(resourceType, searchName); } catch (Exception e) { logger.error(e.getMessage(), e); return Collections.emptyList(); } } @Override public SuccessEnum pushScript(Integer repositoryId, Integer resourceId, String content, AppUser userInfo) { try { SystemResource repository = resourceDao.getResourceById(repositoryId); SystemResource resource = resourceDao.getResourceById(resourceId); // a).推送脚本 if (repository != null && resource != null && resource.getType() == ResourceEnum.SCRIPT.getValue()) { // 远程仓库地址ip/path String repos_ip = repository.getName(); String fileDir = String.format("%s%s", repository.getDir(), resource.getDir()); // 1. 先内容保存到本地 String localAbsolutePath = MachineProtocol.TMP_DIR + resource.getName(); File tmpDir = new File(MachineProtocol.TMP_DIR); if (!tmpDir.exists()) { if (!tmpDir.mkdirs()) { logger.error("cannot create /tmp/cachecloud directory."); } } Path path = Paths.get(MachineProtocol.TMP_DIR + resource.getName()); BufferedWriter bufferedWriter = null; try { bufferedWriter = Files.newBufferedWriter(path, Charset.forName(MachineProtocol.ENCODING_UTF8)); bufferedWriter.write(content); } catch (IOException e) { logger.error("write rmt file error, ip: {}, path: {}, content: {}", repos_ip, localAbsolutePath, content); return SuccessEnum.FAIL; } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (Exception e) { logger.error(e.getMessage(), e); } } } // 2. scp file to remote try { //2.1 备份老文件 String bakDir = fileDir + "/bak"; String filename = fileDir + "/" + resource.getName(); String bakfilename = bakDir + "/" + resource.getName() + "-" + DateUtil.formatYYYYMMddHHMMss(new Date()) + "-" + userInfo.getName(); String bakcmd = String.format("mkdir -p %s && cp -r %s %s", bakDir, filename, bakfilename); String bak_result = SSHUtil.execute(repos_ip, bakcmd); logger.info("bak_result: {}", bak_result); //2.2 上传新文件 SSHUtil.scpFileToRemote(repos_ip, localAbsolutePath, fileDir); } catch (SSHException e) { logger.error("message {}", e.getMessage(), e); return SuccessEnum.FAIL; } // 3. delete temp file File file = new File(localAbsolutePath); if (file.exists()) { boolean del = file.delete(); if (!del) { logger.warn("file.delete:{}", del); } } // 4.update push status resource.setIspush(PushEnum.YES.getValue()); resource.setUsername(userInfo.getName()); resource.setLastmodify(new Date()); resourceDao.update(resource); } } catch (Exception e) { logger.error("pushScript resource repositoryId:{} resourceId:{} error:{}", repositoryId, resourceId, e.getMessage(), e); return SuccessEnum.FAIL; } return SuccessEnum.SUCCESS; } @Override public SuccessEnum pushDir(Integer repositoryId, Integer resourceId, AppUser userInfo) { try { SystemResource repository = resourceDao.getResourceById(repositoryId); SystemResource resource = resourceDao.getResourceById(resourceId); if (repository != null && resource != null) { // 1.推送目录 SSHTemplate.Result result = sshService.executeWithResult(repository.getName(), String.format("mkdir -p %s", repository.getDir() + resource.getName())); if (!result.isSuccess()) { logger.error("pushDir resource repositoryId:{} resourceId:{} result:{}", repositoryId, resourceId, result); return SuccessEnum.FAIL; } // 2.update push status resource.setIspush(PushEnum.YES.getValue()); resource.setUsername(userInfo.getName()); resource.setLastmodify(new Date()); resourceDao.update(resource); } } catch (Exception e) { logger.error("pushDir resource repositoryId:{} resourceId:{} error:{}", repositoryId, resourceId, e.getMessage(), e); return SuccessEnum.FAIL; } return SuccessEnum.SUCCESS; } public SystemResource getResourceById(int repositoryId) { try { return resourceDao.getResourceById(repositoryId); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } public SystemResource getResourceByName(String resourceName) { try { return resourceDao.getResourceByName(resourceName); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } public String getRespositoryUrl(int resourceId, int respoitoryId) { try { SystemResource resource = resourceDao.getResourceById(resourceId); SystemResource repository = resourceDao.getResourceById(respoitoryId); String ip = repository.getName(); // validate ip connect if (!StringUtils.isEmpty(ip)) { return String.format("%s%s/%s", repository.getUrl(), resource.getDir(), resource.getName()); } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } public String getRemoteFileContent(int resourceId, int respoitoryId) { try { SystemResource resource = resourceDao.getResourceById(resourceId); SystemResource repository = resourceDao.getResourceById(respoitoryId); String ip = repository.getName(); // validate ip connect if (!StringUtils.isEmpty(ip)) { String command = String.format("cat %s%s/%s", repository.getDir(), resource.getDir(), resource.getName()); SSHTemplate.Result result = sshService.executeWithResult(ip, command); logger.info(result.getResult()); return result.getResult(); } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } public SystemResource getRepository() { try { List repositorylist = resourceDao.getResourceList(ResourceEnum.Repository.getValue()); if (!CollectionUtils.isEmpty(repositorylist)) { return repositorylist.get(0); } else { return null; } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } public Map getAppUseRedis() { Map resultMap = new HashMap<>(); try { List> mapList = resourceDao.getAppUseRedis(); if (!CollectionUtils.isEmpty(mapList)) { for (Map stat : mapList) { resultMap.put(MapUtils.getInteger(stat, "version_id"), MapUtils.getInteger(stat, "num")); } } } catch (Exception e) { logger.error("getAppUseRedis error :{}", e.getMessage(), e); } return resultMap; } @Override public SystemResource getRedisResourceByCache(Integer repositoryId) { SystemResource resource = null; try { Map resourceMap = ConstUtils.REDIS_RESOURCE; if (MapUtils.isNotEmpty(resourceMap)) { resource = resourceMap.get(repositoryId); } if (resource == null) { resource = this.getResourceById(repositoryId); if (resource != null) { ConstUtils.REDIS_RESOURCE.put(Integer.valueOf(resource.getId()), resource); } } return resource; } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public String getRedisVersion(Integer repositoryId) { String version = null; SystemResource redisResource = this.getRedisResourceByCache(repositoryId); if (redisResource != null) { String name = redisResource.getName(); if (name.contains("-")) { String[] nameArr = name.split("-"); if (nameArr != null && nameArr.length == 2) { String[] versionArr = nameArr[1].split("\\."); if (versionArr != null && versionArr.length == 3) { version = nameArr[1]; } } } } return version; } @Override public boolean checkRedisVersionGreater(Integer repositoryId, int[] versions) { SystemResource redisResource = this.getRedisResourceByCache(repositoryId); if (redisResource != null) { String name = redisResource.getName(); if (name.contains("-")) { String[] nameArr = name.split("-"); if (nameArr != null && nameArr.length == 2) { String[] versionArr = nameArr[1].split("\\."); if (versionArr != null && versionArr.length == 3) { for (int i = 0; i < versions.length; i++) { if (Integer.valueOf(versionArr[i]) < versions[i]) { return false; } } return true; } } } } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/ServerDataServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.dao.ServerStatusDao; import com.sohu.cache.entity.ServerInfo; import com.sohu.cache.entity.ServerStatus; import com.sohu.cache.server.data.Server; import com.sohu.cache.web.service.ServerDataService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ServerDataServiceImpl implements ServerDataService { private static final Logger logger = LoggerFactory.getLogger(ServerDataServiceImpl.class); @Autowired private ServerStatusDao serverStatusDao; @Override public ServerInfo queryServerInfo(String ip) { try { return serverStatusDao.queryServerInfo(ip); } catch (Exception e) { logger.error("query err:"+ip, e); } return null; } public List getAllServerInfo(){ try { return serverStatusDao.getAllServerInfo(); } catch (Exception e) { logger.error(e.getMessage(),e); } return null; } @Override public void saveServerInfo(String ip, String dist) { if(dist == null) { return; } dist = dist.trim(); if(dist.length() == 0) { return; } try { serverStatusDao.saveServerInfo(ip, dist); } catch (Exception e) { logger.error("saveServerInfo err:"+ip+" dist="+dist, e); } } public Integer saveAndUpdateServerInfo(Server server) { if(server.getHost() == null || server.getNmon() == null || server.getCpus() == 0 || server.getCpuModel() == null || server.getKernel() == null || server.getUlimit() == null) { return null; } try { return serverStatusDao.saveAndUpdateServerInfo(server); } catch (Exception e) { logger.error("saveAndUpdateServerInfo err server="+server, e); } return null; } @Override public List queryServerStatus(String ip, String date) { try { return serverStatusDao.queryServerStatus(ip, date); } catch (Exception e) { logger.error("queryServerStatus err ip="+ip+" date="+date, e); } return new ArrayList(0); } @Override public List queryServerOverview(String ip, String date) { try { return serverStatusDao.queryServerOverview(ip, date); } catch (Exception e) { logger.error("queryServerOverview err ip="+ip+" date="+date, e); } return new ArrayList(0); } @Override public List queryServerCpu(String ip, String date) { try { return serverStatusDao.queryServerCpu(ip, date); } catch (Exception e) { logger.error("queryServerCpu err ip="+ip+" date="+date, e); } return new ArrayList(0); } @Override public List queryServerNet(String ip, String date) { try { return serverStatusDao.queryServerNet(ip, date); } catch (Exception e) { logger.error("queryServerNet err ip="+ip+" date="+date, e); } return new ArrayList(0); } @Override public List queryServerDisk(String ip, String date) { try { return serverStatusDao.queryServerDisk(ip, date); } catch (Exception e) { logger.error("queryServerDisk err ip="+ip+" date="+date, e); } return new ArrayList(0); } @Override public void saveServerStat(Server server) { if(server == null || server.getDateTime() == null) { return; } try { serverStatusDao.saveServerStat(server); } catch (Exception e) { logger.error("saveServerStat err server="+server, e); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/ToolServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.AppUserDao; import com.sohu.cache.dao.MachineDao; import com.sohu.cache.entity.*; import com.sohu.cache.task.constant.TopoloyExamContants; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.service.AppService; import com.sohu.cache.web.service.ToolService; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.text.MessageFormat; import java.util.*; import java.util.stream.Collectors; /** * Created by rucao on 2018/12/11 */ @Service public class ToolServiceImpl implements ToolService { private final static String APPID = "appId"; private final static String TYPE = "type"; private final static String STATUS = "status"; private final static String DESC = "desc"; private final static String SENTINEL_DESC = "instanceId:{0},ip:{1}"; private final static String MASTER_SALVE = "masterIp:{0},salveIp:{1}"; private Logger logger = LoggerFactory.getLogger(ToolServiceImpl.class); @Resource private AppDao appDao; @Resource private MachineDao machineDao; @Resource private AppService appService; @Resource private AppUserDao appUserDao; @Override public List topologyExamByAppid(long appId) { List examResult = new ArrayList(); checkTopologyByAppid(appId, examResult); return examResult; } @Override public void topologyExam(List appidList) { List examResult = new ArrayList<>(); for (long appId : appidList) { checkTopologyByAppid(appId, examResult); } } @Override public void restAppDescOfficer() { List appDescList = appDao.getAllApps(); appDescList.stream().forEach(appDesc -> { try { String officer = appDesc.getOfficer(); if (StringUtils.isNotEmpty(officer)) { List nameList = Arrays.asList(officer.split(";|,| |;|,|、")); String officer_new = String.join(",", getUserIdListByNames(nameList)); appDesc.setOfficer(officer_new); if (appDao.update(appDesc) > 0) { logger.info("update appDesc success, appId:{}, officer:{}", appDesc.getAppId(), officer_new); } else { logger.info("update appDesc fail, appId:{}, officer:{}", appDesc.getAppId(), officer_new); } } }catch (Exception e){ logger.error("update appDesc error, appId:{}", appDesc.getAppId()); } }); } private List getUserIdListByNames(List nameList) { return nameList.stream() .map(name -> NumberUtils.isNumber(name) ? name : getUserIdByName(name)) .collect(Collectors.toList()); } private String getUserIdByName(String name) { List appUsers = appUserDao.getUserList(name); if (CollectionUtils.isNotEmpty(appUsers) && appUsers.size() > 0) { return String.valueOf(appUsers.get(0).getId()); } else { AppUser user = appUserDao.getByName(name); if(user!=null){ return String.valueOf(user.getId()); }else { AppUser appUser = appUserDao.getByEmail(name); return appUser == null ? "" : String.valueOf(appUser.getId()); } } } public void checkTopologyByAppid(long appId, List examResult) { try { AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc.getType() == ConstUtils.CACHE_REDIS_SENTINEL) {//redis-sentinel logger.info("redis-sentinel应用"); sentinelExam(appId, examResult); } else if (appDesc.getType() == ConstUtils.CACHE_TYPE_REDIS_CLUSTER) {//redis-cluster logger.info("redis-cluster应用"); clusterExam(appId, examResult); } } catch (Exception e) { logger.error("appid:{}, exception:{}", appId, e.getMessage()); } } private String getRealIp(String ip) { MachineInfo machineInfo = machineDao.getMachineInfoByIp(ip); if (machineInfo.getVirtual() == 1 && !StringUtils.isEmpty(machineInfo.getRealIp())) { return machineInfo.getRealIp(); } else { return ip; } } private void sentinelExam(final long appId, List examResult) { List instances = appService.getAppInstanceInfo(appId); //sentinel set Map sent_realIps = new HashMap(); //master_slave Map> master_slave = new HashMap>(); for (InstanceInfo inst : instances) { if (inst.getStatus() == 1 && inst.getRoleDesc().equals("sentinel")) { String desc = MapUtils.getString(sent_realIps, getRealIp(inst.getIp()), ""); sent_realIps.put(getRealIp(inst.getIp()), desc + "\n" + MessageFormat.format(SENTINEL_DESC, inst.getId(), inst.getIp())); } else if (inst.getStatus() == 1 && inst.getRoleDesc().equals("master")) { } else if (inst.getStatus() == 1 && inst.getRoleDesc().equals("slave")) { String masterHost = inst.getMasterHost(); List slaves = (ArrayList) MapUtils.getObject(master_slave, masterHost, new ArrayList()); slaves.add(inst.getIp()); master_slave.put(masterHost, slaves); } } //sentinel result if (sent_realIps.size() < 3) { //String tmp = ""; StringBuilder tmpBuilder = new StringBuilder(); for (Map.Entry realIps : sent_realIps.entrySet()) { tmpBuilder.append("realIp::") .append(realIps.getValue()) .append("
") .append(realIps.getValue()) .append("
"); } final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, "redis_sentinel"); put(STATUS, TopoloyExamContants.NODESNUM_DESC); put(DESC, descStr); }} ); logger.info("sentinel节点分布在少于3个物理机,应用:{0}", appId); } //master-slave result StringBuilder tmpBuilder1 = new StringBuilder(); for (Map.Entry> res : master_slave.entrySet()) { for (String salveIp : res.getValue()) { if (getRealIp(salveIp).equals(getRealIp(res.getKey()))) { tmpBuilder1.append(MessageFormat.format(MASTER_SALVE, res.getKey(), salveIp)) .append("
"); } } } if (tmpBuilder1.length() > 0) { final String descStr = tmpBuilder1.toString(); examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, "redis_sentinel"); put(STATUS, "master-slave节点不能在一台物理机上"); put(DESC, descStr); }} ); logger.info("master-slave节点不能在一台物理机上,应用: {0}", appId); } } private void clusterExam(final long appId, List examResult) { List instances = appService.getAppInstanceInfo(appId); //mater节点数 List masters = new ArrayList<>(); //master物理机数量 Map master_realIps = new HashMap(); Map realIpMap = new HashMap(); int slaveNum = 0; //master_slave Map> master_slave = new HashMap>(); for (InstanceInfo inst : instances) { if (inst.getStatus() == 1) {//实例正常启用 if (inst.getRoleDesc().equals("master")) { //master_realIps.add(getRealIp(inst.getIp())); masters.add(inst.getIp()); String desc = MapUtils.getString(master_realIps, getRealIp(inst.getIp()), ""); master_realIps.put(getRealIp(inst.getIp()), desc + "\n" + MessageFormat.format(SENTINEL_DESC, inst.getId(), inst.getIp())); String desc1 = MapUtils.getString(realIpMap, getRealIp(inst.getIp()), ""); realIpMap.put(getRealIp(inst.getIp()), desc1 + "," + inst.getId()); String masterId = String.valueOf(inst.getId()); String masterHost = inst.getIp(); String key = masterId + "_" + masterHost; List slaves = (ArrayList) MapUtils.getObject(master_slave, key, new ArrayList()); master_slave.put(key, slaves); } else if (inst.getRoleDesc().equals("slave")) { slaveNum++; String masterHost = inst.getMasterHost(); String masterId = String.valueOf(inst.getMasterInstanceId()); String slaveIp = inst.getIp(); String key = masterId + "_" + masterHost; List slaves = (ArrayList) MapUtils.getObject(master_slave, key, new ArrayList()); if (!slaves.contains(slaveIp)) { slaves.add(slaveIp); } master_slave.put(key, slaves); } } } if (master_realIps.size() < 3) { StringBuilder tmpBuilder = new StringBuilder(); for (Map.Entry realIps : master_realIps.entrySet()) { tmpBuilder.append("realIp::") .append(realIps.getKey()) .append("\n") .append(realIps.getValue()) .append("\n"); } final String descStr = tmpBuilder.toString(); examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, TopoloyExamContants.REDIS_CLUSTER); put(STATUS, TopoloyExamContants.NODESNUM_DESC); put(DESC, descStr); }} ); } //2. master-slave result StringBuilder tmpBuilder1 = new StringBuilder(); for (Map.Entry> res : master_slave.entrySet()) { for (String salveIp : res.getValue()) { String masterHost = res.getKey().split("_")[1]; if (getRealIp(salveIp).equals(masterHost)) { tmpBuilder1.append(MessageFormat.format(MASTER_SALVE, res.getKey(), salveIp)) .append("\n"); } } //检查master是否有slave if (slaveNum != 0) { if (res.getValue().size() == 0) { examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, TopoloyExamContants.REDIS_CLUSTER); put(STATUS, TopoloyExamContants.SLAVE_NOT_EXIST); put(DESC, MessageFormat.format(MASTER_SALVE, res.getKey(), "null")); }} ); } } } if (tmpBuilder1.length() > 0) { final String descStr = tmpBuilder1.toString(); examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, TopoloyExamContants.REDIS_CLUSTER); put(STATUS, TopoloyExamContants.MASTER_SLAVE_DESC); put(DESC, descStr); }} ); } //3. 故障转移 for (Map.Entry entry : realIpMap.entrySet()) { String[] instList = entry.getValue().split(","); int num = instList.length; //String desc = ""; StringBuilder descBuilder = new StringBuilder(); int count = 0; for (int i = 0; i < num; i++) { //desc += "instanceId::" + instList[i] + " "; descBuilder.append("instanceId::") .append(instList[i]) .append(" "); if (!instList[i].isEmpty()) { count++; } } descBuilder.append(" 物理机ip::").append(entry.getKey()); final String descStr = descBuilder.toString(); if (masters.size() - count < masters.size() / 2 + 1) { examResult.add( new HashMap() {{ put(APPID, String.valueOf(appId)); put(TYPE, "redis_cluster"); put(STATUS, "集群中一台物理机下线不满足自动故障转移条件"); put(DESC, descStr); }} ); logger.info("集群中某一台物理机下线不满足自动故障转移条件,应用: " + appId); } } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/UserLoginStatusCookieServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.entity.AppUser; import com.sohu.cache.login.LoginComponent; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.EnvUtil; import com.sohu.cache.util.StringUtil; import com.sohu.cache.web.service.UserLoginStatusService; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.util.AESCoder; import com.sohu.cache.web.util.WebUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Random; /** * cookie保护登录状态 * * @author leifu */ @Service("userLoginStatusService") public class UserLoginStatusCookieServiceImpl implements UserLoginStatusService { private Logger logger = LoggerFactory.getLogger(UserLoginStatusCookieServiceImpl.class); @Autowired private LoginComponent loginComponent; @Autowired protected UserService userService; @Autowired private Environment environment; private static final String CONCATE_STR = "&&"; @Override public String getUserNameFromLoginStatus(HttpServletRequest request) { if (EnvUtil.isLocal(environment)) { //todo for local return "admin"; } String userName = null; String userCookie = null; String cookie = WebUtil.getLoginCookieValue(request); try { userCookie = AESCoder.decrypt(cookie, ConstUtils.USER_LOGIN_ENCRY_KEY); } catch (Exception e) { logger.error("getUserNameFromLoginStatus decrypt error: ", e); } if(StringUtil.isBlank(userCookie)){ return null; } String[] userInfos = userCookie.split(CONCATE_STR); if(userInfos != null && userInfos.length > 0){ userName = userInfos[0]; } if (StringUtils.isNotBlank(userName)) { return userName; } return null; } @Override public String getUserNameFromTicket(HttpServletRequest request) { String ticket = request.getParameter("ticket"); if (StringUtils.isNotBlank(ticket)) { String email = loginComponent.getEmail(ticket); if (StringUtils.isNotBlank(email) && email.contains("@")) { String userName = email.substring(0, email.indexOf("@")); return userName; } } return null; } @Override public String getRedirectUrl(HttpServletRequest request) { return loginComponent.getRedirectUrl(request); } @Override public String getLogoutUrl() { return loginComponent.getLogoutUrl(); } @Override public String getRegisterUrl(AppUser user) { if (user != null && user.getType() == -1) { return "/user/register?success=1"; } return "/user/register"; } @Override public void addLoginStatus(HttpServletRequest request, HttpServletResponse response, String userName) { if(userName == null){ userName = ""; }else{ userName = userName + CONCATE_STR + getRandomStr4Encrypt(); try { userName = AESCoder.encrypt(userName, ConstUtils.USER_LOGIN_ENCRY_KEY); } catch (Exception e) { logger.error("addLoginStatus encrypt error: ",e); } } Cookie cookie = new Cookie(LOGIN_USER_STATUS_NAME, userName); cookie.setDomain(request.getServerName()); cookie.setPath("/"); cookie.setMaxAge(-1); response.addCookie(cookie); } @Override public void removeLoginStatus(HttpServletRequest request, HttpServletResponse response) { addLoginStatus(request, response, ""); } private String getRandomStr4Encrypt(){ return String.valueOf(new Random().nextInt(Integer.MAX_VALUE)); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/service/impl/UserServiceImpl.java ================================================ package com.sohu.cache.web.service.impl; import com.sohu.cache.constant.AppUserAlertEnum; import com.sohu.cache.dao.AppBizDao; import com.sohu.cache.dao.AppDao; import com.sohu.cache.dao.AppToUserDao; import com.sohu.cache.dao.AppUserDao; import com.sohu.cache.entity.AppBiz; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppToUser; import com.sohu.cache.entity.AppUser; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.vo.AppUserVo; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 用户管理实现 * * @author leifu * @Date 2014年10月27日 * @Time 上午9:57:43 */ @Service public class UserServiceImpl implements UserService { private Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); /** * 用户dao */ @Autowired private AppUserDao appUserDao; /** * 业务组dao */ @Autowired private AppBizDao appBizDao; /** * 用户应用关系dao */ @Autowired private AppToUserDao appToUserDao; @Resource private AppDao appDao; @Override public AppUser get(Long userId) { return appUserDao.get(userId); } @Override public List getUserList(String chName) { return appUserDao.getUserList(chName); } /** * 通过中文名和业务组名获取用户 * @param chName * @param bizName * @return */ @Override public List getUserWithBizList(String chName, String bizName) { return appUserDao.getUserWithBizList(chName, bizName); } @Override public List getAllUser() { return appUserDao.getAllUser(); } @Override public List getByAppId(Long appId) { if (appId == null || appId < 0) { return Collections.emptyList(); } List resultList = new ArrayList(); List appToUsers = appToUserDao.getByAppId(appId); if (appToUsers != null && appToUsers.size() > 0) { for (AppToUser appToUser : appToUsers) { Long userId = appToUser.getUserId(); if (userId == null) { continue; } AppUser user = appUserDao.get(userId); if (user == null) { continue; } resultList.add(user); } } return resultList; } @Override public List getAlertByAppId(Long appId) { if (appId == null || appId < 0) { return Collections.emptyList(); } List resultList = new ArrayList(); List appToUsers = appToUserDao.getByAppId(appId); if (appToUsers != null && appToUsers.size() > 0) { for (AppToUser appToUser : appToUsers) { Long userId = appToUser.getUserId(); if (userId == null) { continue; } AppUser user = appUserDao.get(userId); if (user == null || user.getIsAlert() == AppUserAlertEnum.NO.value()) { continue; } resultList.add(user); } } return resultList; } @Override public AppUser getByName(String name) { try { return appUserDao.getByName(name); } catch (Exception e) { logger.error(e.getMessage(), e); return null; } } @Override public SuccessEnum save(AppUser appUser) { try { appUserDao.save(appUser); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum update(AppUser appUser) { try { appUserDao.update(appUser); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum delete(Long userId) { try { appUserDao.delete(userId); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum resetPwd(Long userId) { try { appUserDao.updatePwd(userId, ConstUtils.DEFAULT_USER_PASSWORD); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum updatePwd(Long userId, String password) { try { appUserDao.updatePwd(userId, password); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public String getOfficerName(Long appId) { if (appId == null || appId < 0) { return ""; } AppDesc appDesc = appDao.getAppDescById(appId); if (appDesc == null) { return ""; } else { return getOfficerName(appDesc.getOfficer()); } } public String getOfficerName(String officer) { String officerName = ""; if (StringUtils.isNotEmpty(officer)) { List officerList = Arrays.stream(officer.split(",")) .filter(userId -> get(NumberUtils.toLong(userId)) != null) .map(userId -> get(NumberUtils.toLong(userId))).collect(Collectors.toList()); List userStrList = officerList.stream().map(user -> user.getChName() + "(" + user.getName() + ")").collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(userStrList)) { officerName = StringUtils.join(userStrList, ","); } } return officerName; } /** * 获取某个应用下的所有负责人 * @param officer * @return */ public List getOfficerUserByUserIds(String officer){ List officerList = new ArrayList<>(); if (StringUtils.isNotEmpty(officer)) { officerList = Arrays.stream(officer.split(",")) .map(userId -> get(NumberUtils.toLong(userId))).filter(appUser -> appUser != null).collect(Collectors.toList()); } return officerList; } /** * 接手用户 * @param toRemoveUser * @param toChargeUser * @return */ public SuccessEnum takeoverUser(AppUser toRemoveUser, AppUser toChargeUser){ try{ if(toRemoveUser != null && toChargeUser != null && toRemoveUser != toChargeUser){ List removeList = appToUserDao.getByUserId(toRemoveUser.getId()); Set handleAppList = removeList.stream().map(appToUser -> appToUser.getAppId()).collect(Collectors.toSet()); List chargeList = appToUserDao.getByUserId(toChargeUser.getId()); Set existAppList = chargeList.stream().map(appToUser -> appToUser.getAppId()).collect(Collectors.toSet()); handleAppList.forEach(appId ->{ if(existAppList.contains(appId)){ appToUserDao.deleteAppToUser(appId, toRemoveUser.getId()); }else{ appToUserDao.takeOverAppToUser(appId, toRemoveUser.getId(), toChargeUser.getId()); } }); return SuccessEnum.SUCCESS; } return SuccessEnum.FAIL; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public AppBiz getBiz(Long bizId) { return appBizDao.get(bizId); } @Override public List getBizList() { return appBizDao.getBizList(); } @Override public SuccessEnum saveBiz(AppBiz appBiz) { try { appBizDao.save(appBiz); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum updateBiz(AppBiz appBiz) { try { appBizDao.update(appBiz); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } @Override public SuccessEnum deleteBiz(Long bizId) { try { appBizDao.delete(bizId); return SuccessEnum.SUCCESS; } catch (Exception e) { logger.error(e.getMessage(), e); return SuccessEnum.FAIL; } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/AESCoder.java ================================================ package com.sohu.cache.web.util; import com.sohu.cache.util.StringUtil; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.security.Key; public class AESCoder { /** * 密钥算法 * java6支持56位密钥,bouncycastle支持64位 * */ public static final String KEY_ALGORITHM="AES"; /** * 加密/解密算法/工作模式/填充方式 * * JAVA6 支持PKCS5PADDING填充方式 * Bouncy castle支持PKCS7Padding填充方式 * */ public static final String CIPHER_ALGORITHM="AES/ECB/PKCS5Padding"; /** * * 生成密钥,java6只支持56位密钥,bouncycastle支持64位密钥 * @return byte[] 二进制密钥 * */ public static byte[] initkey() throws Exception{ //实例化密钥生成器 KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM); //初始化密钥生成器,AES要求密钥长度为128位、192位、256位 kg.init(256); //生成密钥 SecretKey secretKey=kg.generateKey(); //获取二进制密钥编码形式 return secretKey.getEncoded(); } /** * 转换密钥 * @param key 二进制密钥 * @return Key 密钥 * */ public static Key toKey(byte[] key) throws Exception{ //实例化DES密钥 //生成密钥 SecretKey secretKey=new SecretKeySpec(key,KEY_ALGORITHM); return secretKey; } /** * 加密数据 * @param data 待加密数据 * @return byte[] 加密后的数据 * */ public static String encrypt(String data, String key) throws Exception{ if(StringUtil.isBlank(data)){ return ""; } byte[] encrypt = encrypt(data.getBytes(), key.getBytes()); return parseByte2HexStr(encrypt); } /** * 加密数据 * @param data 待加密数据 * @param key 密钥 * @return byte[] 加密后的数据 * */ public static byte[] encrypt(byte[] data,byte[] key) throws Exception{ //还原密钥 Key k=toKey(key); /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); //初始化,设置为加密模式 cipher.init(Cipher.ENCRYPT_MODE, k); //执行操作 return cipher.doFinal(data); } /** * 解密数据 * @param data 待解密数据 * @return byte[] 解密后的数据 * */ public static String decrypt(String data, String key) throws Exception{ if(StringUtil.isBlank(data)){ return null; } byte[] dataByte = parseHexStr2Byte(data); if(dataByte == null || dataByte.length < 1){ return null; } byte[] decrypt = decrypt(dataByte, key.getBytes()); return new String(decrypt, "UTF-8"); } /** * 解密数据 * @param data 待解密数据 * @param key 密钥 * @return byte[] 解密后的数据 * */ public static byte[] decrypt(byte[] data,byte[] key) throws Exception{ //欢迎密钥 Key k =toKey(key); /** * 实例化 * 使用 PKCS7PADDING 填充方式,按如下方式实现,就是调用bouncycastle组件实现 * Cipher.getInstance(CIPHER_ALGORITHM,"BC") */ Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM); //初始化,设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, k); //执行操作 return cipher.doFinal(data); } /** * 将16进制转换为二进制 * * @param hexStr 字符串 * @return 字节数组 */ public static byte[] parseHexStr2Byte(String hexStr) { if (hexStr.length() < 1) { return null; } byte[] result = new byte[hexStr.length() / 2]; for (int i = 0; i < hexStr.length() / 2; i++) { int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16); int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16); result[i] = (byte) (high * 16 + low); } return result; } /** * 将二进制转换成16进制 * * @param buf 字节数组 * @return 字符串 */ public static String parseByte2HexStr(byte buf[]) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < buf.length; i++) { String hex = Integer.toHexString(buf[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } sb.append(hex.toUpperCase()); } return sb.toString(); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/AppEmailUtil.java ================================================ package com.sohu.cache.web.util; import com.sohu.cache.alert.EmailComponent; import com.sohu.cache.constant.AppAuditType; import com.sohu.cache.constant.AppCheckEnum; import com.sohu.cache.constant.RedisConfigTemplateChangeEnum; import com.sohu.cache.entity.*; import com.sohu.cache.stats.app.AppStatsCenter; import com.sohu.cache.util.ConstUtils; import com.sohu.cache.util.EnvUtil; import com.sohu.cache.web.enums.SuccessEnum; import com.sohu.cache.web.service.UserService; import com.sohu.cache.web.vo.AppDetailVO; import freemarker.template.Configuration; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import java.util.*; import java.util.Map.Entry; import java.util.stream.Collectors; /** * 邮件通知应用的申请流程(方法内是具体的文案) * * @author leifu */ @Component @Slf4j public class AppEmailUtil { private Logger logger = LoggerFactory.getLogger(AppEmailUtil.class); @Autowired(required = false) private EmailComponent emailComponent; @Autowired private UserService userService; @Autowired private Configuration configuration; @Autowired private AppStatsCenter appStatsCenter; @Autowired private Environment environment; /** * 应用状态通知 * * @param appDesc * @param appAudit */ public void noticeAppResult(AppDesc appDesc, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } List ccEmailList = getCCEmailList(appDesc, appAudit); String officerIds = appDesc.getOfficer(); appDesc.setOfficer(userService.getOfficerName(officerIds)); Map context = new HashMap<>(); context.put("appDesc", appDesc); context.put("appAudit", appAudit); context.put("appDailyData", new AppDailyData()); context.put("instanceAlertValueResultList", new ArrayList()); String mailContent = FreemakerUtils.createText("appAudit.ftl", configuration, context); AppUser appUser = userService.get(appDesc.getUserId()); List receiveEmailList = new ArrayList<>(); userService.getOfficerUserByUserIds(officerIds).forEach(user -> receiveEmailList.add(user.getEmail())); if(CollectionUtils.isEmpty(receiveEmailList) && appUser != null) { receiveEmailList.add(appUser.getEmail()); } emailComponent.sendMail("【CacheCloud】状态通知", mailContent, receiveEmailList, ccEmailList); } /** * 应用状态通知 * * @param applyUser * @param appDesc * @param appAudit */ public void noticeAppResultWithApplyUser(AppUser applyUser, AppDesc appDesc, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } List ccEmailList = getCCEmailList(appDesc, appAudit); String officerIds = appDesc.getOfficer(); appDesc.setOfficer(userService.getOfficerName(officerIds)); Map context = new HashMap<>(); context.put("appDesc", appDesc); context.put("appAudit", appAudit); context.put("appDailyData", new AppDailyData()); context.put("instanceAlertValueResultList", new ArrayList()); String mailContent = FreemakerUtils.createText("appAudit.ftl", configuration, context); AppUser appUser = userService.get(appDesc.getUserId()); List receiveEmailList = new ArrayList<>(); userService.getOfficerUserByUserIds(officerIds).forEach(user -> receiveEmailList.add(user.getEmail())); if(CollectionUtils.isEmpty(receiveEmailList) && appUser != null) { receiveEmailList.add(appUser.getEmail()); } receiveEmailList.add(applyUser.getEmail()); List appOfficeList = receiveEmailList.stream().distinct().collect(Collectors.toList()); emailComponent.sendMail("【CacheCloud】状态通知", mailContent, appOfficeList, ccEmailList); } /** * 应用状态通知 * * @param appUser * @param appAudit */ public void noticeAuditResult(AppUser appUser, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } List ccEmailList = Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA)); Map context = new HashMap<>(); context.put("appAudit", appAudit); context.put("appDailyData", new AppDailyData()); context.put("instanceAlertValueResultList", new ArrayList()); String mailContent = FreemakerUtils.createText("appAudit.ftl", configuration, context); List receiveEmailList = new ArrayList<>(); if(appUser != null){ receiveEmailList.add(appUser.getEmail()); } emailComponent.sendMail("【CacheCloud】状态通知", mailContent, receiveEmailList, ccEmailList); } /** * API应用状态通知 * * @param appDesc * @param appAudit */ public void noticeAppResultByApi(AppDesc appDesc, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } List ccEmailList = getCCEmailList(appDesc, appAudit); appDesc.setOfficer(userService.getOfficerName(appDesc.getOfficer())); Map context = new HashMap<>(); context.put("appDesc", appDesc); context.put("appAudit", appAudit); context.put("appDailyData", new AppDailyData()); context.put("instanceAlertValueResultList", new ArrayList()); String mailContent = FreemakerUtils.createText("appAudit.ftl", configuration, context); AppUser appUser = userService.get(appDesc.getUserId()); emailComponent.sendMail("【CacheCloud】API应用申请通知", mailContent, Arrays.asList(appUser.getEmail()), ccEmailList); } /** * 重要应用抄送 * * @param appDesc * @param appAudit * @return */ private List getCCEmailList(AppDesc appDesc, AppAudit appAudit) { Set ccEmailSet = new LinkedHashSet(); for (String email : emailComponent.getAdminEmail().split(ConstUtils.COMMA)) { ccEmailSet.add(email); } //S级别,且是开通邮件 if (appDesc.isSuperImportant() && AppAuditType.APP_AUDIT.getValue() == appAudit.getType()) { ccEmailSet.addAll(ConstUtils.LEADER_EMAIL_LIST); } return new ArrayList(ccEmailSet); } /** * 贡献者通知 * * @param groupName * @param applyReason * @param appUser */ public void noticeBecomeContributor(String groupName, String applyReason, AppUser appUser) { if (EnvUtil.isDev(environment)) { return; } StringBuffer mailContent = new StringBuffer(); mailContent.append(appUser.getChName() + "(项目组:" + groupName + ")申请成为CacheCloud贡献者
"); mailContent.append("申请理由:
" + applyReason); emailComponent.sendMail("【CacheCloud】状态通知", mailContent.toString(), Arrays.asList(appUser.getEmail()), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } /** * 注册用户通知 * * @param appUser * @param appAudit */ public void noticeUserResult(AppUser appUser, AppAudit appAudit) { if (EnvUtil.isDev(environment)) { return; } if (appAudit == null) { return; } StringBuffer mailContent = new StringBuffer(); if (AppCheckEnum.APP_WATING_CHECK.value().equals(appAudit.getStatus())) { mailContent.append(appUser.getChName() + "申请想成为CacheCloud用户,请管理员帮忙处理!
"); } else if (AppCheckEnum.APP_PASS.value().equals(appAudit.getStatus())) { mailContent.append("您的用户申请已经审批通过,您可以登录正常Cachecloud了!
"); } else if (AppCheckEnum.APP_REJECT.value().equals(appAudit.getStatus())) { mailContent.append("您的用户申请被驳回,原因是: " + appAudit.getRefuseReason()); } emailComponent.sendMail("【CacheCloud】状态通知", mailContent.toString(), Arrays.asList(appUser.getEmail()), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } /** * 下线应用通知 * * @param appUser * @param appId * @param isSuccess */ public void noticeOfflineApp(AppUser appUser, Long appId, boolean isSuccess) { if (EnvUtil.isDev(environment)) { return; } AppDetailVO appDetailVO = appStatsCenter.getAppDetail(appId); StringBuilder mailContent = new StringBuilder(); mailContent.append(appUser.getChName()).append(",对应用appid=").append(appId); mailContent.append("进行下线,操作结果是").append(isSuccess ? "下线任务执行成功" : "下线任务失败,请关注任务流日志"); mailContent.append(",请知晓!"); emailComponent.sendMail("【CacheCloud】状态通知", mailContent.toString(), appDetailVO.getEmailList(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } public void sendRedisConfigTemplateChangeEmail(AppUser appUser, String versionName, InstanceConfig instanceConfig, SuccessEnum successEnum, RedisConfigTemplateChangeEnum redisConfigTemplateChangeEnum) { if (EnvUtil.isDev(environment)) { return; } String mailTitle = "【CacheCloud】-Redis配置模板修改通知"; String mailContent = String.format("%s 对 %s 配置模板 进行了%s,操作结果是%s,具体为(key=%s,value=%s,状态为%s)", appUser.getChName(), versionName, redisConfigTemplateChangeEnum.getInfo(), successEnum.info(), instanceConfig.getConfigKey(), instanceConfig.getConfigValue(), instanceConfig.getStatusDesc()); emailComponent.sendMail(mailTitle, mailContent.toString(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } public void sendAddRedisVersionEmail(AppUser appUser, String versionName, SuccessEnum successEnum) { if (EnvUtil.isDev(environment)) { return; } String mailTitle = "【CacheCloud】- 新增Redis版本通知"; String mailContent = String.format("%s 新增Redis版本:%s ,状态为:%s)", appUser.getChName(), versionName, successEnum.info()); emailComponent.sendMail(mailTitle, mailContent.toString(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } public void sendSystemConfigDifEmail(AppUser appUser, Map systemDifConfigMap, SuccessEnum successEnum) { if (EnvUtil.isDev(environment)) { return; } if (MapUtils.isEmpty(systemDifConfigMap)) { return; } String mailTitle = "【CacheCloud】-系统配置修改通知"; StringBuffer mailContent = new StringBuffer(); mailContent.append(appUser.getChName() + "修改了系统配置,修改结果:" + successEnum.info() + "
"); mailContent.append("具体配置如下:
"); for (Entry entry : systemDifConfigMap.entrySet()) { mailContent.append(entry.getKey() + "-->" + entry.getValue() + "
"); } emailComponent.sendMail(mailTitle, mailContent.toString(), Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } /** * 系统通知 * * @param noticeContent * @return */ public boolean noticeAllUser(String noticeContent) { if (EnvUtil.isDev(environment)) { return false; } if (StringUtils.isBlank(noticeContent)) { return false; } try { String mailTitle = "【CacheCloud】-系统通知"; StringBuffer mailContent = new StringBuffer(); String[] noticeArray = noticeContent.split(ConstUtils.NEXT_LINE); for (String noticeLine : noticeArray) { mailContent.append(noticeLine).append("
"); } List emailList = new ArrayList(); List appUserList = userService.getUserList(null); if (CollectionUtils.isEmpty(appUserList)) { return false; } for (AppUser appUser : appUserList) { String email = appUser.getEmail(); if (StringUtils.isBlank(email)) { continue; } emailList.add(email); } return emailComponent.sendMail(mailTitle, mailContent.toString(), emailList, Arrays.asList(emailComponent.getAdminEmail().split(ConstUtils.COMMA))); } catch (Exception e) { logger.error(e.getMessage(), e); } return false; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/DateUtil.java ================================================ package com.sohu.cache.web.util; import com.sohu.cache.entity.TimeBetween; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * @author leifu * @Time 2014年8月31日 */ public class DateUtil { private final static Logger logger = LoggerFactory.getLogger(DateUtil.class); private final static String COLLECT_TIME_FORMAT = "yyyyMMddHHmmss"; /* * yyyyMMddHHmm格式format */ public static String formatYYYYMMddHHMM(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmm"); return sdf.format(date); } /* * yyyyMMddHHmmss格式format */ public static String formatYYYYMMddHHMMss(Date date) { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); return sdf.format(date); } /* * yyyy-MM-dd HH:mm:ss格式format */ public static String formatYYYYMMddHHMMSS(Date date) { if (date == null) { return null; } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } /* * yyyyMMddHHmm格式parse */ public static Date parse(String dateStr, String format) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(format); return sdf.parse(dateStr); } /* * yyyyMMddHHmm格式parse */ public static Date parseYYYYMMddHHMM(String dateStr) throws ParseException { return parse(dateStr, "yyyyMMddHHmm"); } /** * yyyyMMddHH格式parse * * @throws ParseException */ public static Date parseYYYYMMddHH(String dateStr) throws ParseException { return parse(dateStr, "yyyyMMddHH"); } /* * yyyy-MM-dd格式parse */ public static Date parseYYYY_MM_dd(String dateStr) throws ParseException { return parse(dateStr, "yyyy-MM-dd"); } /** * yyyyMMdd格式parse */ public static Date parseYYYYMMdd(String dateStr) throws ParseException { return parse(dateStr, "yyyyMMdd"); } public static Date getDateByFormat(String date, String format) { SimpleDateFormat sf = new SimpleDateFormat(format); Date result = null; try { result = sf.parse(date); } catch (Exception e) { logger.error(e.getMessage(), e); } return result; } public static String formatDate(Date date, String format) { SimpleDateFormat sf = new SimpleDateFormat(format); return sf.format(date); } public static String formatYYYYMMdd(Date date) { SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd"); return sf.format(date); } public static String formatYYYY_MM_dd(Date date) { SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); return sf.format(date); } public static String formatHHMM(Date date) { SimpleDateFormat sf = new SimpleDateFormat("HHmm"); return sf.format(date); } public static TimeBetween fillWithDateFormat(String searchDate) throws ParseException { final String dateFormat = "yyyy-MM-dd"; Date startDate; Date endDate; if (StringUtils.isBlank(searchDate)) { // 如果为空默认取今天 SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); startDate = sdf.parse(sdf.format(new Date())); } else { startDate = com.sohu.cache.web.util.DateUtil.parse(searchDate, dateFormat); } endDate = DateUtils.addDays(startDate, 1); // 查询后台需要 long startTime = NumberUtils.toLong(com.sohu.cache.web.util.DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(com.sohu.cache.web.util.DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } public static TimeBetween fillWithMinDateFormat(String searchDate, String dateFormat) throws ParseException { Date startDate; Date endDate; if (StringUtils.isBlank(searchDate)) { // 如果为空默认取今天 SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); startDate = sdf.parse(sdf.format(new Date())); } else { startDate = com.sohu.cache.web.util.DateUtil.parse(searchDate, dateFormat); } endDate = DateUtils.addMinutes(startDate, 1); // 查询后台需要 long startTime = NumberUtils.toLong(com.sohu.cache.web.util.DateUtil.formatDate(startDate, COLLECT_TIME_FORMAT)); long endTime = NumberUtils.toLong(com.sohu.cache.web.util.DateUtil.formatDate(endDate, COLLECT_TIME_FORMAT)); return new TimeBetween(startTime, endTime, startDate, endDate); } public static Date customDateByHHMM(int hh, int mm){ Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, hh); calendar.set(Calendar.MINUTE, mm); calendar.set(Calendar.SECOND, 0); return calendar.getTime(); } public static boolean timeLessDiffAfter(Date date1, Date date2, int diffSecond){ return (date2.getTime()/1000 > date1.getTime()/1000) && (date2.getTime() - date1.getTime()) / 1000 <= diffSecond; } public static boolean timeMoreDiffAfter(Date date1, Date date2, int diffSecond){ return (date2.getTime() - date1.getTime()) / 1000 >= diffSecond; } public static Date getBeginOfDay(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } public static Date getBeginOfTomorrow(Date date){ Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.DATE, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } public static String getTimeBeforePointedMinute(Date date, int mm){ Date newDate = DateUtils.addMinutes(date, 0 - mm); SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmm00"); return sf.format(newDate); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/FreemakerUtils.java ================================================ package com.sohu.cache.web.util; import freemarker.template.Configuration; import freemarker.template.Template; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; import java.text.DecimalFormat; import java.util.Map; /** * @Author: rucao * @Date: 2020/10/14 10:11 */ public class FreemakerUtils { protected static final Logger logger = LoggerFactory.getLogger(FreemakerUtils.class); public synchronized static String createText(String templateName, Configuration configuration, Map model) { if (configuration != null) { try { Template template = configuration.getTemplate(templateName); model.put("ccDomain", IpUtil.domain); model.put("decimalFormat", new DecimalFormat("###,###")); String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, model); return html; } catch (Exception e) { logger.error(e.getLocalizedMessage(), e); } } return ""; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/IpUtil.java ================================================ package com.sohu.cache.web.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; /** * ip工具 * * @author leifu */ @Component public class IpUtil { public static String domain; @Value("${server.port}") private int port; public static Logger logger = LoggerFactory.getLogger(IpUtil.class); public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } public int getLocalPort() { return port; } public String getLocalIP() { InetAddress inetAddress = getLocalHostLANAddress(); return inetAddress.getHostAddress(); } public String getCurrentIpPort() { return getLocalIP() + ":" + port; } public InetAddress getLocalHostLANAddress() { try { InetAddress candidateAddress = null; // 遍历所有的网络接口 for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) { NetworkInterface iface = (NetworkInterface) ifaces.nextElement(); // 所有的接口下遍历IP for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) { InetAddress inetAddr = (InetAddress) inetAddrs.nextElement(); if (!inetAddr.isLoopbackAddress()) {// 排除loopback类型地址 if (inetAddr.isSiteLocalAddress()) { // 优先site-local地址 return inetAddr; } else if (candidateAddress == null) { candidateAddress = inetAddr; } } } } if (candidateAddress != null) { return candidateAddress; } // 如果没有发现 non-loopback地址.用次选方案 InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); return jdkSuppliedAddress; } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } @Value("${server.domain}") public void setDomain(String ccdomain){ domain = ccdomain; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/Page.java ================================================ package com.sohu.cache.web.util; /** * 分页对象 * @author leifu * @Date 2015年2月10日 * @Time 下午6:38:18 */ public class Page implements java.io.Serializable { private static final long serialVersionUID = 7887139614696114877L; /** * 当前页数 */ private int pageNo; /** * 每页的记录数 */ private int pageSize; /** * 总记录数 */ private int totalCount; public Page(int pageNo, int pageSize, int totalCount) { this.pageNo = pageNo; this.pageSize = pageSize; this.totalCount = totalCount; } /** * 取总页数 */ public int getTotalPages() { if (totalCount % pageSize == 0) return totalCount / pageSize; else return totalCount / pageSize + 1; } /** * 获取任一页第一条数据的位置,startIndex从0开始 */ public int getStart() { return (pageNo - 1) * pageSize; } public int getNumberOfPages() { int totalPageCount = getTotalPages(); return totalPageCount >= 10 ? 10 : totalPageCount; } public int getPageNo() { return pageNo; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/SimpleFileUtil.java ================================================ package com.sohu.cache.web.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sohu.cache.web.controller.AppController; /** * 简单文件读取 * @author leifu * @Date 2015年3月2日 * @Time 下午2:12:15 */ public class SimpleFileUtil { private static final Logger logger = LoggerFactory.getLogger(SimpleFileUtil.class); /** * 从class环境读取文件成List * @param fileName * @return */ public static List getListFromFile(String fileName, String encoding) { List list = new ArrayList(); InputStream is = null; BufferedReader br = null; try { is = AppController.class.getClassLoader().getResourceAsStream(fileName); br = new BufferedReader(new InputStreamReader(is, encoding)); String line = null; while ((line = br.readLine()) != null) { list.add(line); } } catch (IOException e) { logger.error(e.getMessage(), e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { logger.error(e.getMessage(), e); } } if (br != null) { try { br.close(); } catch (IOException e) { logger.error(e.getMessage(), e); } } } return list; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/util/WebUtil.java ================================================ package com.sohu.cache.web.util; import org.apache.commons.lang3.StringUtils; import org.springframework.web.util.WebUtils; import javax.servlet.ServletRequest; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * web相关工具 * @Description: * @author yongfeigao * @date 2018年6月12日 */ public class WebUtil { public static final String LOGIN_USER_STATUS_NAME = "CACHE_CLOUD_USER_STATUS"; /** * 从request中获取客户端ip * * @param request * @return */ public static String getIp(ServletRequest request) { HttpServletRequest req = (HttpServletRequest) request; String addr = getHeaderValue(req, "X-Forwarded-For"); if (StringUtils.isNotEmpty(addr) && addr.contains(",")) { addr = addr.split(",")[0]; } if (StringUtils.isEmpty(addr)) { addr = getHeaderValue(req, "X-Real-IP"); } if (StringUtils.isEmpty(addr)) { addr = req.getRemoteAddr(); } return addr; } /** * 获取请求的完整url * @param request * @return */ public static String getUrl(HttpServletRequest request) { String url = request.getRequestURL().toString(); String queryString = request.getQueryString(); if(queryString != null) { url += "?" + request.getQueryString(); } return url; } /** * 获取ServletRequest header value * @param request * @param name * @return */ public static String getHeaderValue(HttpServletRequest request, String name) { String v = request.getHeader(name); if(v == null) { return null; } return v.trim(); } /** * 从request属性中获取对象 * @param request * @return */ public static void setEmailAttribute(ServletRequest request, String email) { request.setAttribute("email", email); } /** * 从request属性中获取对象 * @param request * @return */ public static String getEmailAttribute(ServletRequest request) { Object email = request.getAttribute("email"); if(email == null) { return null; } return email.toString(); } /** * 从request属性中获取对象 * @param request * @return */ public static void setAttribute(ServletRequest request, String name, Object obj) { request.setAttribute(name, obj); } /** * 设置对象到request属性中 * @param request * @return */ public static Object getAttribute(ServletRequest request, String name) { return request.getAttribute(name); } /** * 输出内容到页面 * @param response * @param result * @throws IOException */ public static void print(HttpServletResponse response, String result) throws IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.print(result); out.flush(); out.close(); out = null; } /** * 获取登录的cookie的值 * * @param request * @return */ public static String getLoginCookieValue(HttpServletRequest request) { Cookie cookie = WebUtils.getCookie(request, LOGIN_USER_STATUS_NAME); if(cookie != null) { return cookie.getValue(); } return null; } /** * 获取登录的cookie * * @param request * @return */ public static Cookie getLoginCookie(HttpServletRequest request) { return WebUtils.getCookie(request, LOGIN_USER_STATUS_NAME); } /** * 设置登录的cookie */ public static void setLoginCookie(HttpServletResponse response, String value) { Cookie cookie = new Cookie(LOGIN_USER_STATUS_NAME, value); cookie.setPath("/"); response.addCookie(cookie); } /** * 移除登录的cookie */ public static void deleteLoginCookie(HttpServletResponse response) { Cookie cookie = new Cookie(LOGIN_USER_STATUS_NAME, ""); cookie.setPath("/"); cookie.setMaxAge(0); response.addCookie(cookie); } /** * 跳转 * @param response * @param request * @param path * @throws IOException */ public static void redirect(HttpServletResponse response, HttpServletRequest request, String path) throws IOException { response.sendRedirect(request.getContextPath() + path); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AlertConfig.java ================================================ package com.sohu.cache.web.vo; public class AlertConfig { private String value; private String info; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((value == null) ? 0 : value.hashCode()); result = prime * result + ((info == null) ? 0 : info.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AlertConfig other = (AlertConfig) obj; if (value == null) { if (other.value != null){ return false; } } else if (!value.equals(other.value)){ return false; } if (info == null) { if (other.info != null){ return false; } } else if (!info.equals(other.info)){ return false; } return true; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppDetailVO.java ================================================ package com.sohu.cache.web.vo; import java.util.ArrayList; import java.util.List; import lombok.Data; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.entity.AppUser; /** * 应用详情 * @author leifu * @Time 2014年8月29日 */ @Data public class AppDetailVO { private AppDesc appDesc; /** * 内存空间 */ private long mem; /** * 当前内存 */ private long currentMem; /** * 机器数 */ private int machineNum; /** * 主节点数 */ private int masterNum; /** * 从节点数 */ private int slaveNum; /** * 哨兵节点数 */ private int sentinelNum; /** * 当前对象数 */ private long currentObjNum; /** * 当前连接数 */ private int conn; /** * 内存使用报警 */ private double memUseThreshold; /** * 命中率使用报警 */ private double hitPercentThreshold; /** * 内存使用率 */ private double memUsePercent; /** * 最大碎片率 */ private double highestMemFragRatio; /** * 最大碎片率的实例id */ private long instIdWithHighestMemFragRatio; /** * 命中率 */ private double hitPercent; /** * 应用授权的用户 */ private List appUsers; /** * 应用报警的用户 */ private List alertUsers; /** * 当前磁盘占用 */ private long currentDisk; /** * 磁盘使用率 */ private double diskUsePercent; public List getPhoneList(){ List phoneList = new ArrayList(); if(CollectionUtils.isNotEmpty(appUsers)){ for(AppUser appUser : appUsers){ String mobile = appUser.getMobile(); if(StringUtils.isNotBlank(mobile)){ phoneList.add(appUser.getMobile()); } } } return phoneList; } public List getWeChatList(){ List weChatList = new ArrayList(); if(CollectionUtils.isNotEmpty(alertUsers)){ for(AppUser appUser : alertUsers){ String weChat = appUser.getWeChat(); if(StringUtils.isNotBlank(weChat)){ weChatList.add(appUser.getWeChat()); } } } return weChatList; } public List getEmailList(){ List emailList = new ArrayList(); if(CollectionUtils.isNotEmpty(alertUsers)){ for(AppUser appUser : alertUsers){ String email = appUser.getEmail(); if(StringUtils.isNotBlank(email)){ emailList.add(appUser.getEmail()); } } } return emailList; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppRedisCommandCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 命令校验结果 */ @Data public class AppRedisCommandCheckResult implements Serializable { private Date createTime; private String createTimeStr; /** * 宿主机ip */ private String machineIps; /** * pod ip */ private String podIp; /** * 命令 */ private String command; /** * 配置项 */ private List instanceCheckList; /** * redis版本 */ private boolean success; public String getCreateTimeStr(){ return DateUtil.formatYYYYMMddHHMMSS(createTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppRedisCommandCheckVo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/29 11:11 * @Description: 应用redis 配置校验 */ @Data public class AppRedisCommandCheckVo { /** * 宿主机ip */ private String machineIps; /** * pod ip */ private String podIp; /** * 命令 */ private String command; /** * 检测方式 */ private Integer checkType; /** * info检测 * info一级指标项 */ private String infoIndicate; /** * info检测 * 配置项 */ private String indicateName; /** * info检测 * 最大重试次数 */ private Integer maxTry = 40; /** * 比较值 */ private String expectValue; /** * log检测 * 允许的log距离当前时间的范围,以分钟计(如10分钟以内) */ private Integer minuteInternal = 10; public Integer getMaxTry(){ if(maxTry == null){ return 40; } return maxTry; } public Integer getMinuteInternal(){ if(minuteInternal == null){ return 10; } return minuteInternal; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppRedisConfigCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.entity.AppDesc; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import org.apache.commons.collections.CollectionUtils; import java.io.Serializable; import java.util.Date; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 配置校验 */ @Data public class AppRedisConfigCheckResult implements Serializable { /** * 检测时间 */ private Date createTime; /** * redis版本 */ private Integer versionId; /** * 应用id */ private AppDesc appDesc; /** * 配置项 */ private String configName; /** * 比较类型 */ private int compareType; /** * 比较值 */ private String expectValue; /** * 配置项 */ private List instanceCheckList; /** * redis版本 */ private boolean success; private Long appId; private String createTimeStr; public Long getAppId(){ if(appDesc != null){ return appDesc.getAppId(); } return null; } private String instanceIds; public String getInstanceIds(){ final StringBuilder sb = new StringBuilder(); if(CollectionUtils.isNotEmpty(instanceCheckList)){ instanceCheckList.forEach(instanceCheckResult -> { if(!instanceCheckResult.isSuccess()){ sb.append(instanceCheckResult.getInstanceInfo().getId()); sb.append(","); } }); if(sb.length() > 1){ sb.deleteCharAt(sb.length() - 1); } } return sb.toString(); } public String getCreateTimeStr(){ return DateUtil.formatYYYYMMddHHMMSS(createTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppRedisConfigCheckVo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 配置校验 */ @Data public class AppRedisConfigCheckVo { /** * 应用id */ private Long appId; /** * redis版本 */ private Integer versionId; /** * 配置项 */ private String configName; /** * 比较类型 */ private int compareType; /** * 比较值 */ private String expectValue; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppRedisConfigVo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; import org.springframework.util.CollectionUtils; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 配置参数名和值 */ @Data public class AppRedisConfigVo { /** * 应用id */ private Long appId; /** * 修改配置、重启日志记录id */ private Long recordId; /** * 是否更新配置 */ private boolean configFlag; /** * 是否允许主从切换 */ private boolean transferFlag; /** * 操作的实例 */ private List instanceList; /** * 配置名称 */ private List configList; /** * 是否快速完成滚动重启(修改配置,滚动重启) * 如果为是,则在操作每个主从分组中,不再sleep等待(等待的目的是:客户端刷新集群拓扑) */ private boolean quickFinishFlag; public List getInstanceList() { if(CollectionUtils.isEmpty(instanceList)){ return null; } for (Integer instanceId : instanceList) { if(instanceId == 0){ return null; } } return instanceList; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/AppUserVo.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.entity.AppUser; import lombok.Data; /** * 用户及所属业务组 * @author zengyizhao * @Time 2023年1月17日 */ @Data public class AppUserVo extends AppUser{ /** * 业务组名称 */ private String bizName; /** * 业务组描述 */ private String bizDesc; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/ExecuteResult.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/17 16:13 * @Description: 执行结果及信息提示 */ @Data public class ExecuteResult { /** * 是否成功 */ private boolean success; /** * 操作结果提示 */ private String message; public ExecuteResult(){ } public ExecuteResult(boolean success, String message) { this.success = success; this.message = message; } public static ExecuteResult ok(){ return new ExecuteResult(true, null); } public static ExecuteResult ok(String message){ return new ExecuteResult(true, message); } public static ExecuteResult error(){ return new ExecuteResult(false, null); } public static ExecuteResult error(String message){ return new ExecuteResult(false, message); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/GeneralResponse.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/17 16:13 * @Description: 返回结果类 */ @Data public class GeneralResponse { /** * 是否成功 */ private boolean success; /** * 操作状态码 */ private int status; /** * 操作结果提示 */ private String error; /** * 对象结果 */ private T data; public GeneralResponse(){ } public GeneralResponse(boolean success, int status, String error, T data) { this.success = success; this.status = status; this.error = error; this.data = data; } public static GeneralResponse ok(){ return new GeneralResponse(true, 200, null, null); } public static GeneralResponse ok(T data){ return new GeneralResponse(true, 200, null, data); } public static GeneralResponse error(int status, String error){ return new GeneralResponse(false, status, error, null); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/InstanceRedisCommandCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.entity.InstanceInfo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 命令校验结果 */ @Data public class InstanceRedisCommandCheckResult { /** * 校验结果 */ private boolean success; /** * 错误信息 */ private String message; /** * 实例信息 */ private InstanceInfo instanceInfo; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/InstanceRedisConfigCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.entity.InstanceInfo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 配置校验 */ @Data public class InstanceRedisConfigCheckResult { /** * 校验结果 */ private boolean success; /** * 配置项 */ private String configName; /** * 配置预期值 */ private String expectValue; /** * 实际值 */ private String realValue; /** * 实例信息 */ private InstanceInfo instanceInfo; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/MachineEnv.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.web.enums.CheckEnum; import lombok.Data; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by chenshi on 2021/1/12. */ @Data public class MachineEnv { private static Logger logger = LoggerFactory.getLogger(MachineEnv.class); /** * 容器环境参数 */ //内存分配策略设置为1:表示内核允许分配所有的物理内存 private String overcommit_memory; private final static String overcommit_memory_warnning = "1"; //swap策略设置为0:关闭swap,避免内存io转换磁盘io导致阻塞 private String swappines = "0"; private final static String swappines_warnning = "0"; //thp设置:never,防止fork过程中消耗大内存拷贝导致阻塞 private String transparent_hugepage_enable; private final static String transparent_hugepage_enable_warnning = "always madvise [never]"; private String transparent_hugepage_defrag; private final static String transparent_hugepage_defrag_warnning = "always defer madvise [never]"; private final static String thp_judge = "[never]"; //nproc用户线程数: * soft nproc 4096 private String nproc; private final static String nproc_warnning = "* soft nproc 4096"; /** * 宿主环境参数 */ //tcp连接队列数:512 private String somaxconn; private final static String somaxconn_warnning = "511"; private final static int somaxconn_less_warnning = 511; //redis fsync slow log private int fsync_delay_times; private final static int fsync_delay_times_warnning = 10; //cachecloud用户最大线程数量,当前宿主环境为4096 private int nproc_threads = 1024; private final static int nproc_threads_warnning = 1024; // ssh pass版本 private String sshPass; private final static String sshPass_warnning = ""; // 文件句柄数量 private int unlimit_used; private int unlimit; private final static int unlimit_warnning = 40000; // 磁盘信息 private String diskUsed; private final static int diskUsed_warnning = 80; // 实例数量 private int instanceNum; /** * 容器资源 */ public MachineEnv(String overcommit_memory, String swappines, String transparent_hugepage_enable, String transparent_hugepage_defrag, String nproc) { this.overcommit_memory = overcommit_memory; this.swappines = swappines; this.transparent_hugepage_enable = transparent_hugepage_enable; this.transparent_hugepage_defrag = transparent_hugepage_defrag; this.nproc = nproc; } /** * 宿主资源 */ public MachineEnv(String somaxconn, int fsync_delay_times, int nproc_threads, String sshPass, int unlimit_used, int unlimit, String diskUsed, int instanceNum) { this.somaxconn = somaxconn; this.fsync_delay_times = fsync_delay_times; this.nproc_threads = nproc_threads; this.sshPass = sshPass; this.unlimit_used = unlimit_used; this.unlimit = unlimit; this.diskUsed = diskUsed; this.instanceNum = instanceNum; } public static MachineEnv getDefaultEnv() { return new MachineEnv("-1","-1","-1","-1","-1","-1",-1,-1,"-1",-1,-1,"-1",-1); } public MachineEnv(String overcommit_memory, String swappines, String transparent_hugepage_enable, String transparent_hugepage_defrag, String nproc, String somaxconn, int fsync_delay_times, int nproc_threads, String sshPass, int unlimit_used, int unlimit, String diskUsed, int instanceNum) { this.overcommit_memory = overcommit_memory; this.swappines = swappines; this.transparent_hugepage_enable = transparent_hugepage_enable; this.transparent_hugepage_defrag = transparent_hugepage_defrag; this.nproc = nproc; this.somaxconn = somaxconn; this.fsync_delay_times = fsync_delay_times; this.nproc_threads = nproc_threads; this.sshPass = sshPass; this.unlimit_used = unlimit_used; this.unlimit = unlimit; this.diskUsed = diskUsed; this.instanceNum = instanceNum; } public static int checkContainer(MachineEnv env) { try { if (env.overcommit_memory.equals(overcommit_memory_warnning) && env.transparent_hugepage_enable.contains(thp_judge) && env.transparent_hugepage_defrag.contains(thp_judge) && env.swappines.equals(swappines_warnning) && env.nproc.equals(nproc_warnning)) { return CheckEnum.CONSISTENCE.getValue(); } return CheckEnum.INCONSISTENCE.getValue(); } catch (Exception e) { logger.error("MachineEnvUtil checkContainer error env:{} {}", env, e.getMessage()); return CheckEnum.EXCEPTION.getValue(); } } public static int checkHost(MachineEnv env) { try { int diskuse_precent = 0; try { diskuse_precent = Integer.parseInt(env.diskUsed.split("%")[0]); } catch (Exception e) { logger.error("disk used {} parse error:{}", env.diskUsed,e.getMessage()); } if (env.nproc_threads <= nproc_threads_warnning && env.fsync_delay_times <= fsync_delay_times_warnning && env.somaxconn.equals(somaxconn_warnning) && env.unlimit_used < unlimit_warnning && diskuse_precent < diskUsed_warnning) { return CheckEnum.CONSISTENCE.getValue(); } return CheckEnum.INCONSISTENCE.getValue(); } catch (Exception e) { logger.error("MachineEnvUtil checkMachine error env:{} {}", env, e.getMessage(), e); return CheckEnum.EXCEPTION.getValue(); } } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/MachineStatsVo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; @Data public class MachineStatsVo { private String machineRoom; private long totalMachineMem; private long totalMachineFreeMem; private long totalInstanceMaxMem; private long totalInstanceUsedMem; private long totalMachineDisk; private long totalMachineFreeDisk; private long totalInstanceApplyDisk; private long totalInstanceUsedDisk; private double machineDiskUsedRatio; private double instanceMemUsedRatio; private double instanceDiskUsedRatio; public double getMachineMemUsedRatio() { if (totalMachineMem == 0) { return 0; } return (totalMachineMem - totalMachineFreeMem) * 100.0 / totalMachineMem * 1.0; } public double getMachineDiskUsedRatio() { return (totalMachineDisk - totalMachineFreeDisk) * 100.0 / totalMachineDisk * 1.0; } public double getInstanceMemUsedRatio() { if (totalInstanceMaxMem == 0) { return 0; } return totalInstanceUsedMem * 100.0 / totalInstanceMaxMem * 1.0; } public double getInstanceDiskUsedRatio() { if (totalInstanceApplyDisk == 0) { return 0; } return (totalInstanceUsedDisk) * 100.0 / (totalInstanceApplyDisk * 1024 * 1024 * 1.0); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/MasterSlaveGroupBo.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.entity.InstanceInfo; import com.sohu.cache.web.enums.MasterSlaveExistEnum; import lombok.Data; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/10/20 18:55 * @Description: 主从分组辅助类 */ @Data public class MasterSlaveGroupBo { private InstanceInfo master; private List slaveList; private MasterSlaveExistEnum masterSlaveExistEnum; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisClusterNode.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; import java.util.List; /** * @Author: zengyizhao * @CreateTime: 2023/2/27 18:43 * @Description: redis node信息(cluster node) * @Version: 1.0 */ @Data public class RedisClusterNode { private String hostPort; private String role; private boolean fail; private boolean connected; private List slots; private String masterHostPort; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisCommandCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import java.io.Serializable; import java.util.Date; import java.util.List; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: 应用redis 命令校验结果 */ @Data public class RedisCommandCheckResult implements Serializable { private Date createTime; private String createTimeStr; /** * 宿主机ip */ private String machineIps; /** * pod ip */ private String podIp; /** * 命令 */ private String command; /** * 配置项 */ private String key; /** * 操作人 */ private String userName; /** * redis版本 */ private boolean success; public String getCreateTimeStr(){ return DateUtil.formatYYYYMMddHHMMSS(createTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisConfigCheckResult.java ================================================ package com.sohu.cache.web.vo; import com.sohu.cache.web.util.DateUtil; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: redis 配置校验结果 */ @Data public class RedisConfigCheckResult implements Serializable { /** * 检测时间 */ private Date createTime; /** * redis版本 */ private Integer versionId; /** * 配置项 */ private String configName; /** * 比较类型 */ private int compareType; /** * 比较值 */ private String expectValue; /** * 比较值 */ private String userName; /** * 配置项 */ private String key; /** * redis版本 */ private boolean success; private String createTimeStr; public String getCreateTimeStr(){ return DateUtil.formatYYYYMMddHHMMSS(createTime); } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisConfigVo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; /** * @Author: zengyizhao * @DateTime: 2021/9/14 11:11 * @Description: redis 配置参数名和值 */ @Data public class RedisConfigVo { /** * 配置名称 */ private String configName; /** * 配置值 */ private String configValue; } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisInfo.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; import java.util.List; /** *

* Description: Redis 主-从关系 vo *

* * @author chenshi * @version 1.0 * @date 2018/9/21 */ @Data public class RedisInfo { private int sid; private String ip; private int port; private String version; private String role; List redisInfoList; public RedisInfo(String ip, int port) { this.ip = ip; this.port = port; } public RedisInfo(String ip, int port, String version, String role) { this.ip = ip; this.port = port; this.version = version; this.role = role; } public RedisInfo(int sid, String ip, int port, String version, String role) { this.sid = sid; this.ip = ip; this.port = port; this.version = version; this.role = role; } public RedisInfo(String ip, String role) { this.ip = ip; this.role = role; } public RedisInfo(String ip, int port, String version, String role, List redisInfoList) { this.ip = ip; this.port = port; this.version = version; this.role = role; this.redisInfoList = redisInfoList; } public String getIpAndPortInfo(RedisInfo redisInfo) { return redisInfo.getIp() + ":" + redisInfo.getPort(); } public String getRedisInfo(RedisInfo redisInfo) { if (redisInfo.getPort() == 0) { return redisInfo.getIp() + ":xxxx " + redisInfo.getRole() + " \n"; } return redisInfo.getIp() + ":" + redisInfo.getPort() + " " + redisInfo.getRole() + " \n"; } public String getInfo(RedisInfo redisInfo) { return redisInfo.getIp() + ":" + redisInfo.getPort() + " " + redisInfo.getRole() + " " + redisInfo.getVersion() + " \n"; } } ================================================ FILE: cachecloud-web/src/main/java/com/sohu/cache/web/vo/RedisSlowLog.java ================================================ package com.sohu.cache.web.vo; import lombok.Data; import java.util.Date; /** * Created by yijunzhang on 14-10-14. */ @Data public class RedisSlowLog { /** * 慢查询id */ private long id; /** * 执行时间点 */ private String timeStamp; /** * 慢查询执行时间(微秒) */ private long executionTime; private String command; /** * 执行日期时间 */ private Date date; public Date getDate() { return (Date) date.clone(); } public void setDate(Date date) { this.date = (Date) date.clone(); } } ================================================ FILE: cachecloud-web/src/main/resources/application-local.yml ================================================ spring: application: name: cloud.cachecloud-web.local import: classpath:spring/spring.xml freemarker: cache: false settings: template_update_delay: 0 server: port: 8080 #ip/域名地址 domain: http://127.0.0.1:8080 servlet: jsp: init-parameters: development: true #jsp 热部署 cachecloud: primary: jdbcUrl: jdbc:mysql://127.0.0.1:3306/cachecloud_open?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&connectTimeout=3000&socketTimeout=10000&serverTimezone=Asia/Shanghai username: cachecloud-open password: cachecloud-open minimumIdle: 1 maximumPoolSize: 3 redis: #配置cachecloud-web需要的redis,用户存储任务流log enable: true #if config redis, suggest config true main: host: 127.0.0.1 port: 6379 password: #区分资源 web: clients: 127.0.0.1 aof: rewrite: ignore-appIds: ================================================ FILE: cachecloud-web/src/main/resources/application-online.yml ================================================ spring: application: name: cloud.cachecloud-web.open.online import: classpath:spring/spring.xml freemarker: cache: false settings: template_update_delay: 0 server: port: 8080 domain: 127.0.0.1:8080 cachecloud: primary: jdbcUrl: jdbc:mysql://127.0.0.1:3306/cachecloud-open?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&connectTimeout=3000&socketTimeout=10000&serverTimezone=Asia/Shanghai username: cachecloud-open password: cachecloud-open minimumIdle: 10 maximumPoolSize: 50 redis: #配置cachecloud-web需要的redis,用户存储任务流log enable: true #if config redis, suggest config true main: host: 127.0.0.1 port: 6379 password: web: clients: 127.0.0.1 aof: rewrite: ignore-appIds: ================================================ FILE: cachecloud-web/src/main/resources/application-open.yml ================================================ spring: application: name: cloud.cachecloud-web.open import: classpath:spring/spring.xml freemarker: cache: false settings: template_update_delay: 0 server: port: 8080 domain: 127.0.0.1:8080 cachecloud: primary: jdbcUrl: jdbc:mysql://127.0.0.1:3306/cachecloud-open?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&connectTimeout=3000&socketTimeout=10000&serverTimezone=Asia/Shanghai username: cachecloud-open password: cachecloud-open minimumIdle: 10 maximumPoolSize: 50 redis: #配置cachecloud-web需要的redis,用户存储任务流log enable: true #if config redis, suggest config true main: host: 127.0.0.1 port: 6379 password: web: clients: 127.0.0.1 aof: rewrite: ignore-appIds: ================================================ FILE: cachecloud-web/src/main/resources/application-test.yml ================================================ spring: application: name: cloud.cachecloud-web.open.test import: classpath:spring/spring.xml freemarker: cache: false settings: template_update_delay: 0 server: port: 8080 domain: 127.0.0.1:8080 cachecloud: primary: jdbcUrl: jdbc:mysql://127.0.0.1:3306/cachecloud-open?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&connectTimeout=3000&socketTimeout=10000&serverTimezone=Asia/Shanghai username: cachecloud-open password: cachecloud-open minimumIdle: 3 maximumPoolSize: 20 redis: #配置cachecloud-web需要的redis,用户存储任务流log enable: true #if config redis, suggest config true main: host: 127.0.0.1 port: 6379 password: web: clients: 127.0.0.1 aof: rewrite: ignore-appIds: ================================================ FILE: cachecloud-web/src/main/resources/application.yml ================================================ spring: profiles: active: local main: allow-bean-definition-overriding: true mvc: servlet: load-on-startup: 1 # path: / static-path-pattern: /assets/**, /img/** log-resolved-exception: true contentnegotiation: favor-path-extension: true pathmatch: matching-strategy: ant-path-matcher use-suffix-pattern: true use-registered-suffix-pattern: true web: resources: static-locations: classpath:assets/,classpath:static/img/ freemarker: enabled: true cache: false content-type: text/html charset: UTF-8 suffix: .html order: 1 expose-request-attributes: false prefer-file-system-access: true # 千位数 逗号分隔问题修复 settings: number_format: 0.## apiBuiltinEnabled: true template_update_delay: 0 request-context-attribute: request http: encoding: charset: UTF-8 enabled: true force: true cachecloud: primary: driverClassName: com.mysql.cj.jdbc.Driver validationQuery: select 1 from dual connectionTimeout: 60000 idleTimeout: 600000 management: server: port: 8888 endpoint: prometheus: enabled: true health: show-details: always shutdown: #关闭不安全控制endpoints enabled: false restart: enabled: false pause: enabled: false heapdump: enabled: false refresh: enabled: false auditevents: enabled: false jolokia: enabled: false env: post: enabled: false ================================================ FILE: cachecloud-web/src/main/resources/assets/css/buttons.css ================================================ /*! @license * * Buttons * Copyright 2012-2014 Alex Wolfe and Rob Levin * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Compass (optional) * * We recommend the use of autoprefixer instead of Compass * when using buttons. However, buttons does support Compass. * simply change $ubtn-use-compass to true and uncomment the * @import 'compass' code below to use Compass. */ /* * Required Files * * These files include the variables and options * and base css styles that are required to generate buttons. */ /* * $ubtn prefix (reserved) * * This prefix stands for Unicorn Button - ubtn * We provide a prefix to the Sass Variables to * prevent namespace collisions that could occur if * you import buttons as part of your Sass build process. * We kindly ask you not to use the prefix $ubtn in your project * in order to avoid possilbe name conflicts. Thanks! */ /* * Button Namespace (ex .button or .btn) * */ /* * Button Defaults * * Some default settings that are used throughout the button library. * Changes to these settings will be picked up by all of the other modules. * The colors used here are the default colors for the base button (gray). * The font size and height are used to set the base size for the buttons. * The size values will be used to calculate the larger and smaller button sizes. */ /* * Button Colors * * $ubtn-colors is used to generate the different button colors. * Edit or add colors to the list below and recompile. * Each block contains the (name, background, color) * The class is generated using the name: (ex .button-primary) */ /* * Button Shapes * * $ubtn-shapes is used to generate the different button shapes. * Edit or add shapes to the list below and recompile. * Each block contains the (name, border-radius). * The class is generated using the name: (ex .button-square). */ /* * Button Sizes * * $ubtn-sizes is used to generate the different button sizes. * Edit or add colors to the list below and recompile. * Each block contains the (name, size multiplier). * The class is generated using the name: (ex .button-giant). */ /* * Color Mixin * * Iterates through the list of colors and creates * */ /* * No Animation * * Sets animation property to none */ /* * Clearfix * * Clears floats inside the container */ /* * Base Button Style * * The default values for the .button class */ .button { color: #666; background-color: #EEE; border-color: #EEE; font-weight: 300; font-size: 16px; font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; text-decoration: none; text-align: center; line-height: 40px; height: 40px; padding: 0 40px; margin: 0; display: inline-block; appearance: none; cursor: pointer; border: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -webkit-transition-property: all; transition-property: all; -webkit-transition-duration: .3s; transition-duration: .3s; /* * Disabled State * * The disabled state uses the class .disabled, is-disabled, * and the form attribute disabled="disabled". * The use of !important is only added because this is a state * that must be applied to all buttons when in a disabled state. */ } .button:visited { color: #666; } .button:hover, .button:focus { background-color: #f6f6f6; text-decoration: none; outline: none; } .button:active, .button.active, .button.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.3); text-decoration: none; background-color: #eeeeee; border-color: #cfcfcf; color: #d4d4d4; -webkit-transition-duration: 0s; transition-duration: 0s; -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); } .button.disabled, .button.is-disabled, .button:disabled { top: 0 !important; background: #EEE !important; border: 1px solid #DDD !important; text-shadow: 0 1px 1px white !important; color: #CCC !important; cursor: default !important; appearance: none !important; -webkit-box-shadow: none !important; box-shadow: none !important; opacity: .8 !important; } /* * Base Button Tyography * */ .button-uppercase { text-transform: uppercase; } .button-lowercase { text-transform: lowercase; } .button-capitalize { text-transform: capitalize; } .button-small-caps { font-variant: small-caps; } .button-icon-txt-large { font-size: 36px !important; } /* * Base padding * */ .button-width-small { padding: 0 10px !important; } /* * Base Colors * * Create colors for buttons * (.button-primary, .button-secondary, etc.) */ .button-primary, .button-primary-flat { background-color: #1B9AF7; border-color: #1B9AF7; color: #FFF; } .button-primary:visited, .button-primary-flat:visited { color: #FFF; } .button-primary:hover, .button-primary:focus, .button-primary-flat:hover, .button-primary-flat:focus { background-color: #4cb0f9; border-color: #4cb0f9; color: #FFF; } .button-primary:active, .button-primary.active, .button-primary.is-active, .button-primary-flat:active, .button-primary-flat.active, .button-primary-flat.is-active { background-color: #2798eb; border-color: #2798eb; color: #0880d7; } .button-plain, .button-plain-flat { background-color: #FFF; border-color: #FFF; color: #1B9AF7; } .button-plain:visited, .button-plain-flat:visited { color: #1B9AF7; } .button-plain:hover, .button-plain:focus, .button-plain-flat:hover, .button-plain-flat:focus { background-color: white; border-color: white; color: #1B9AF7; } .button-plain:active, .button-plain.active, .button-plain.is-active, .button-plain-flat:active, .button-plain-flat.active, .button-plain-flat.is-active { background-color: white; border-color: white; color: #e6e6e6; } .button-inverse, .button-inverse-flat { background-color: #222; border-color: #222; color: #EEE; } .button-inverse:visited, .button-inverse-flat:visited { color: #EEE; } .button-inverse:hover, .button-inverse:focus, .button-inverse-flat:hover, .button-inverse-flat:focus { background-color: #3c3c3c; border-color: #3c3c3c; color: #EEE; } .button-inverse:active, .button-inverse.active, .button-inverse.is-active, .button-inverse-flat:active, .button-inverse-flat.active, .button-inverse-flat.is-active { background-color: #222222; border-color: #222222; color: #090909; } .button-action, .button-action-flat { background-color: #A5DE37; border-color: #A5DE37; color: #FFF; } .button-action:visited, .button-action-flat:visited { color: #FFF; } .button-action:hover, .button-action:focus, .button-action-flat:hover, .button-action-flat:focus { background-color: #b9e563; border-color: #b9e563; color: #FFF; } .button-action:active, .button-action.active, .button-action.is-active, .button-action-flat:active, .button-action-flat.active, .button-action-flat.is-active { background-color: #a1d243; border-color: #a1d243; color: #8bc220; } .button-highlight, .button-highlight-flat { background-color: #FEAE1B; border-color: #FEAE1B; color: #FFF; } .button-highlight:visited, .button-highlight-flat:visited { color: #FFF; } .button-highlight:hover, .button-highlight:focus, .button-highlight-flat:hover, .button-highlight-flat:focus { background-color: #fec04e; border-color: #fec04e; color: #FFF; } .button-highlight:active, .button-highlight.active, .button-highlight.is-active, .button-highlight-flat:active, .button-highlight-flat.active, .button-highlight-flat.is-active { background-color: #f3ab26; border-color: #f3ab26; color: #e59501; } .button-caution, .button-caution-flat { background-color: #FF4351; border-color: #FF4351; color: #FFF; } .button-caution:visited, .button-caution-flat:visited { color: #FFF; } .button-caution:hover, .button-caution:focus, .button-caution-flat:hover, .button-caution-flat:focus { background-color: #ff7680; border-color: #ff7680; color: #FFF; } .button-caution:active, .button-caution.active, .button-caution.is-active, .button-caution-flat:active, .button-caution-flat.active, .button-caution-flat.is-active { background-color: #f64c59; border-color: #f64c59; color: #ff1022; } .button-royal, .button-royal-flat { background-color: #7B72E9; border-color: #7B72E9; color: #FFF; } .button-royal:visited, .button-royal-flat:visited { color: #FFF; } .button-royal:hover, .button-royal:focus, .button-royal-flat:hover, .button-royal-flat:focus { background-color: #a49ef0; border-color: #a49ef0; color: #FFF; } .button-royal:active, .button-royal.active, .button-royal.is-active, .button-royal-flat:active, .button-royal-flat.active, .button-royal-flat.is-active { background-color: #827ae1; border-color: #827ae1; color: #5246e2; } /* * Base Layout Styles * * Very Miminal Layout Styles */ .button-block, .button-stacked { display: block; } /* * Button Types (optional) * * All of the files below represent the various button * types (including shapes & sizes). None of these files * are required. Simple remove the uneeded type below and * the button type will be excluded from the final build */ /* * Button Shapes * * This file creates the various button shapes * (ex. Circle, Rounded, Pill) */ .button-square { border-radius: 0; } .button-box { border-radius: 10px; } .button-rounded { border-radius: 4px; } .button-pill { border-radius: 200px; } .button-circle { border-radius: 100%; } /* * Size Adjustment for equal height & widht buttons * * Remove padding and set a fixed width. */ .button-circle, .button-box, .button-square { padding: 0 !important; width: 40px; } .button-circle.button-giant, .button-box.button-giant, .button-square.button-giant { width: 70px; } .button-circle.button-jumbo, .button-box.button-jumbo, .button-square.button-jumbo { width: 60px; } .button-circle.button-large, .button-box.button-large, .button-square.button-large { width: 50px; } .button-circle.button-normal, .button-box.button-normal, .button-square.button-normal { width: 40px; } .button-circle.button-small, .button-box.button-small, .button-square.button-small { width: 30px; } .button-circle.button-tiny, .button-box.button-tiny, .button-square.button-tiny { width: 24px; } /* * Border Buttons * * These buttons have no fill they only have a * border to define their hit target. */ .button-border, .button-border-thin, .button-border-thick { background: none; border-width: 2px; border-style: solid; line-height: 36px; } .button-border:hover, .button-border-thin:hover, .button-border-thick:hover { background-color: rgba(255, 255, 255, 0.9); } .button-border:active, .button-border-thin:active, .button-border-thick:active, .button-border.active, .active.button-border-thin, .active.button-border-thick, .button-border.is-active, .is-active.button-border-thin, .is-active.button-border-thick { -webkit-box-shadow: none; box-shadow: none; text-shadow: none; -webkit-transition-property: all; transition-property: all; -webkit-transition-duration: .3s; transition-duration: .3s; } /* * Border Optional Sizes * * A slight variation in border thickness */ .button-border-thin { border-width: 1px; } .button-border-thick { border-width: 3px; } /* * Border Button Colors * * Create colors for buttons * (.button-primary, .button-secondary, etc.) */ .button-border, .button-border-thin, .button-border-thick, .button-border-thin, .button-border-thick { /* * Border Button Size Adjustment * * The line-height must be adjusted to compinsate for * the width of the border. */ } .button-border.button-primary, .button-primary.button-border-thin, .button-primary.button-border-thick, .button-border-thin.button-primary, .button-border-thick.button-primary { color: #1B9AF7; } .button-border.button-primary:hover, .button-primary.button-border-thin:hover, .button-primary.button-border-thick:hover, .button-border.button-primary:focus, .button-primary.button-border-thin:focus, .button-primary.button-border-thick:focus, .button-border-thin.button-primary:hover, .button-border-thin.button-primary:focus, .button-border-thick.button-primary:hover, .button-border-thick.button-primary:focus { background-color: rgba(76, 176, 249, 0.9); color: rgba(255, 255, 255, 0.9); } .button-border.button-primary:active, .button-primary.button-border-thin:active, .button-primary.button-border-thick:active, .button-border.button-primary.active, .button-primary.active.button-border-thin, .button-primary.active.button-border-thick, .button-border.button-primary.is-active, .button-primary.is-active.button-border-thin, .button-primary.is-active.button-border-thick, .button-border-thin.button-primary:active, .button-border-thin.button-primary.active, .button-border-thin.button-primary.is-active, .button-border-thick.button-primary:active, .button-border-thick.button-primary.active, .button-border-thick.button-primary.is-active { background-color: rgba(39, 152, 235, 0.7); color: rgba(255, 255, 255, 0.5); opacity: .3; } .button-border.button-plain, .button-plain.button-border-thin, .button-plain.button-border-thick, .button-border-thin.button-plain, .button-border-thick.button-plain { color: #FFF; } .button-border.button-plain:hover, .button-plain.button-border-thin:hover, .button-plain.button-border-thick:hover, .button-border.button-plain:focus, .button-plain.button-border-thin:focus, .button-plain.button-border-thick:focus, .button-border-thin.button-plain:hover, .button-border-thin.button-plain:focus, .button-border-thick.button-plain:hover, .button-border-thick.button-plain:focus { background-color: rgba(255, 255, 255, 0.9); color: rgba(27, 154, 247, 0.9); } .button-border.button-plain:active, .button-plain.button-border-thin:active, .button-plain.button-border-thick:active, .button-border.button-plain.active, .button-plain.active.button-border-thin, .button-plain.active.button-border-thick, .button-border.button-plain.is-active, .button-plain.is-active.button-border-thin, .button-plain.is-active.button-border-thick, .button-border-thin.button-plain:active, .button-border-thin.button-plain.active, .button-border-thin.button-plain.is-active, .button-border-thick.button-plain:active, .button-border-thick.button-plain.active, .button-border-thick.button-plain.is-active { background-color: rgba(255, 255, 255, 0.7); color: rgba(27, 154, 247, 0.5); opacity: .3; } .button-border.button-inverse, .button-inverse.button-border-thin, .button-inverse.button-border-thick, .button-border-thin.button-inverse, .button-border-thick.button-inverse { color: #222; } .button-border.button-inverse:hover, .button-inverse.button-border-thin:hover, .button-inverse.button-border-thick:hover, .button-border.button-inverse:focus, .button-inverse.button-border-thin:focus, .button-inverse.button-border-thick:focus, .button-border-thin.button-inverse:hover, .button-border-thin.button-inverse:focus, .button-border-thick.button-inverse:hover, .button-border-thick.button-inverse:focus { background-color: rgba(60, 60, 60, 0.9); color: rgba(238, 238, 238, 0.9); } .button-border.button-inverse:active, .button-inverse.button-border-thin:active, .button-inverse.button-border-thick:active, .button-border.button-inverse.active, .button-inverse.active.button-border-thin, .button-inverse.active.button-border-thick, .button-border.button-inverse.is-active, .button-inverse.is-active.button-border-thin, .button-inverse.is-active.button-border-thick, .button-border-thin.button-inverse:active, .button-border-thin.button-inverse.active, .button-border-thin.button-inverse.is-active, .button-border-thick.button-inverse:active, .button-border-thick.button-inverse.active, .button-border-thick.button-inverse.is-active { background-color: rgba(34, 34, 34, 0.7); color: rgba(238, 238, 238, 0.5); opacity: .3; } .button-border.button-action, .button-action.button-border-thin, .button-action.button-border-thick, .button-border-thin.button-action, .button-border-thick.button-action { color: #A5DE37; } .button-border.button-action:hover, .button-action.button-border-thin:hover, .button-action.button-border-thick:hover, .button-border.button-action:focus, .button-action.button-border-thin:focus, .button-action.button-border-thick:focus, .button-border-thin.button-action:hover, .button-border-thin.button-action:focus, .button-border-thick.button-action:hover, .button-border-thick.button-action:focus { background-color: rgba(185, 229, 99, 0.9); color: rgba(255, 255, 255, 0.9); } .button-border.button-action:active, .button-action.button-border-thin:active, .button-action.button-border-thick:active, .button-border.button-action.active, .button-action.active.button-border-thin, .button-action.active.button-border-thick, .button-border.button-action.is-active, .button-action.is-active.button-border-thin, .button-action.is-active.button-border-thick, .button-border-thin.button-action:active, .button-border-thin.button-action.active, .button-border-thin.button-action.is-active, .button-border-thick.button-action:active, .button-border-thick.button-action.active, .button-border-thick.button-action.is-active { background-color: rgba(161, 210, 67, 0.7); color: rgba(255, 255, 255, 0.5); opacity: .3; } .button-border.button-highlight, .button-highlight.button-border-thin, .button-highlight.button-border-thick, .button-border-thin.button-highlight, .button-border-thick.button-highlight { color: #FEAE1B; } .button-border.button-highlight:hover, .button-highlight.button-border-thin:hover, .button-highlight.button-border-thick:hover, .button-border.button-highlight:focus, .button-highlight.button-border-thin:focus, .button-highlight.button-border-thick:focus, .button-border-thin.button-highlight:hover, .button-border-thin.button-highlight:focus, .button-border-thick.button-highlight:hover, .button-border-thick.button-highlight:focus { background-color: rgba(254, 192, 78, 0.9); color: rgba(255, 255, 255, 0.9); } .button-border.button-highlight:active, .button-highlight.button-border-thin:active, .button-highlight.button-border-thick:active, .button-border.button-highlight.active, .button-highlight.active.button-border-thin, .button-highlight.active.button-border-thick, .button-border.button-highlight.is-active, .button-highlight.is-active.button-border-thin, .button-highlight.is-active.button-border-thick, .button-border-thin.button-highlight:active, .button-border-thin.button-highlight.active, .button-border-thin.button-highlight.is-active, .button-border-thick.button-highlight:active, .button-border-thick.button-highlight.active, .button-border-thick.button-highlight.is-active { background-color: rgba(243, 171, 38, 0.7); color: rgba(255, 255, 255, 0.5); opacity: .3; } .button-border.button-caution, .button-caution.button-border-thin, .button-caution.button-border-thick, .button-border-thin.button-caution, .button-border-thick.button-caution { color: #FF4351; } .button-border.button-caution:hover, .button-caution.button-border-thin:hover, .button-caution.button-border-thick:hover, .button-border.button-caution:focus, .button-caution.button-border-thin:focus, .button-caution.button-border-thick:focus, .button-border-thin.button-caution:hover, .button-border-thin.button-caution:focus, .button-border-thick.button-caution:hover, .button-border-thick.button-caution:focus { background-color: rgba(255, 118, 128, 0.9); color: rgba(255, 255, 255, 0.9); } .button-border.button-caution:active, .button-caution.button-border-thin:active, .button-caution.button-border-thick:active, .button-border.button-caution.active, .button-caution.active.button-border-thin, .button-caution.active.button-border-thick, .button-border.button-caution.is-active, .button-caution.is-active.button-border-thin, .button-caution.is-active.button-border-thick, .button-border-thin.button-caution:active, .button-border-thin.button-caution.active, .button-border-thin.button-caution.is-active, .button-border-thick.button-caution:active, .button-border-thick.button-caution.active, .button-border-thick.button-caution.is-active { background-color: rgba(246, 76, 89, 0.7); color: rgba(255, 255, 255, 0.5); opacity: .3; } .button-border.button-royal, .button-royal.button-border-thin, .button-royal.button-border-thick, .button-border-thin.button-royal, .button-border-thick.button-royal { color: #7B72E9; } .button-border.button-royal:hover, .button-royal.button-border-thin:hover, .button-royal.button-border-thick:hover, .button-border.button-royal:focus, .button-royal.button-border-thin:focus, .button-royal.button-border-thick:focus, .button-border-thin.button-royal:hover, .button-border-thin.button-royal:focus, .button-border-thick.button-royal:hover, .button-border-thick.button-royal:focus { background-color: rgba(164, 158, 240, 0.9); color: rgba(255, 255, 255, 0.9); } .button-border.button-royal:active, .button-royal.button-border-thin:active, .button-royal.button-border-thick:active, .button-border.button-royal.active, .button-royal.active.button-border-thin, .button-royal.active.button-border-thick, .button-border.button-royal.is-active, .button-royal.is-active.button-border-thin, .button-royal.is-active.button-border-thick, .button-border-thin.button-royal:active, .button-border-thin.button-royal.active, .button-border-thin.button-royal.is-active, .button-border-thick.button-royal:active, .button-border-thick.button-royal.active, .button-border-thick.button-royal.is-active { background-color: rgba(130, 122, 225, 0.7); color: rgba(255, 255, 255, 0.5); opacity: .3; } .button-border.button-giant, .button-giant.button-border-thin, .button-giant.button-border-thick, .button-border-thin.button-giant, .button-border-thick.button-giant { line-height: 66px; } .button-border.button-jumbo, .button-jumbo.button-border-thin, .button-jumbo.button-border-thick, .button-border-thin.button-jumbo, .button-border-thick.button-jumbo { line-height: 56px; } .button-border.button-large, .button-large.button-border-thin, .button-large.button-border-thick, .button-border-thin.button-large, .button-border-thick.button-large { line-height: 46px; } .button-border.button-normal, .button-normal.button-border-thin, .button-normal.button-border-thick, .button-border-thin.button-normal, .button-border-thick.button-normal { line-height: 36px; } .button-border.button-small, .button-small.button-border-thin, .button-small.button-border-thick, .button-border-thin.button-small, .button-border-thick.button-small { line-height: 26px; } .button-border.button-tiny, .button-tiny.button-border-thin, .button-tiny.button-border-thick, .button-border-thin.button-tiny, .button-border-thick.button-tiny { line-height: 20px; } /* * Border Buttons * * These buttons have no fill they only have a * border to define their hit target. */ .button-borderless { background: none; border: none; padding: 0 8px !important; color: #EEE; font-size: 20.8px; font-weight: 200; /* * Borderless Button Colors * * Create colors for buttons * (.button-primary, .button-secondary, etc.) */ /* * Borderles Size Adjustment * * The font-size must be large to compinsate for * the lack of a hit target. */ } .button-borderless:hover, .button-borderless:focus { background: none; } .button-borderless:active, .button-borderless.active, .button-borderless.is-active { -webkit-box-shadow: none; box-shadow: none; text-shadow: none; -webkit-transition-property: all; transition-property: all; -webkit-transition-duration: .3s; transition-duration: .3s; opacity: .3; } .button-borderless.button-primary { color: #1B9AF7; } .button-borderless.button-plain { color: #FFF; } .button-borderless.button-inverse { color: #222; } .button-borderless.button-action { color: #A5DE37; } .button-borderless.button-highlight { color: #FEAE1B; } .button-borderless.button-caution { color: #FF4351; } .button-borderless.button-royal { color: #7B72E9; } .button-borderless.button-giant { font-size: 36.4px; height: 52.4px; line-height: 52.4px; } .button-borderless.button-jumbo { font-size: 31.2px; height: 47.2px; line-height: 47.2px; } .button-borderless.button-large { font-size: 26px; height: 42px; line-height: 42px; } .button-borderless.button-normal { font-size: 20.8px; height: 36.8px; line-height: 36.8px; } .button-borderless.button-small { font-size: 15.6px; height: 31.6px; line-height: 31.6px; } .button-borderless.button-tiny { font-size: 12.48px; height: 28.48px; line-height: 28.48px; } /* * Raised Buttons * * A classic looking button that offers * great depth and affordance. */ .button-raised { border-color: #e1e1e1; border-style: solid; border-width: 1px; line-height: 38px; background: -webkit-gradient(linear, left top, left bottom, from(#f6f6f6), to(#e1e1e1)); background: linear-gradient(#f6f6f6, #e1e1e1); -webkit-box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0 1px 2px rgba(0, 0, 0, 0.15); box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.3), 0 1px 2px rgba(0, 0, 0, 0.15); } .button-raised:hover, .button-raised:focus { background: -webkit-gradient(linear, left top, left bottom, from(white), to(gainsboro)); background: linear-gradient(top, white, gainsboro); } .button-raised:active, .button-raised.active, .button-raised.is-active { background: #eeeeee; -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2), 0px 1px 0px white; box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2), 0px 1px 0px white; } /* * Raised Button Colors * * Create colors for raised buttons */ .button-raised.button-primary { border-color: #088ef0; background: -webkit-gradient(linear, left top, left bottom, from(#34a5f8), to(#088ef0)); background: linear-gradient(#34a5f8, #088ef0); } .button-raised.button-primary:hover, .button-raised.button-primary:focus { background: -webkit-gradient(linear, left top, left bottom, from(#42abf8), to(#0888e6)); background: linear-gradient(top, #42abf8, #0888e6); } .button-raised.button-primary:active, .button-raised.button-primary.active, .button-raised.button-primary.is-active { border-color: #0880d7; background: #2798eb; } .button-raised.button-plain { border-color: #f2f2f2; background: -webkit-gradient(linear, left top, left bottom, from(white), to(#f2f2f2)); background: linear-gradient(white, #f2f2f2); } .button-raised.button-plain:hover, .button-raised.button-plain:focus { background: -webkit-gradient(linear, left top, left bottom, from(white), to(#ededed)); background: linear-gradient(top, white, #ededed); } .button-raised.button-plain:active, .button-raised.button-plain.active, .button-raised.button-plain.is-active { border-color: #e6e6e6; background: white; } .button-raised.button-inverse { border-color: #151515; background: -webkit-gradient(linear, left top, left bottom, from(#2f2f2f), to(#151515)); background: linear-gradient(#2f2f2f, #151515); } .button-raised.button-inverse:hover, .button-raised.button-inverse:focus { background: -webkit-gradient(linear, left top, left bottom, from(#363636), to(#101010)); background: linear-gradient(top, #363636, #101010); } .button-raised.button-inverse:active, .button-raised.button-inverse.active, .button-raised.button-inverse.is-active { border-color: #090909; background: #222222; } .button-raised.button-action { border-color: #9ad824; background: -webkit-gradient(linear, left top, left bottom, from(#afe24d), to(#9ad824)); background: linear-gradient(#afe24d, #9ad824); } .button-raised.button-action:hover, .button-raised.button-action:focus { background: -webkit-gradient(linear, left top, left bottom, from(#b5e45a), to(#94cf22)); background: linear-gradient(top, #b5e45a, #94cf22); } .button-raised.button-action:active, .button-raised.button-action.active, .button-raised.button-action.is-active { border-color: #8bc220; background: #a1d243; } .button-raised.button-highlight { border-color: #fea502; background: -webkit-gradient(linear, left top, left bottom, from(#feb734), to(#fea502)); background: linear-gradient(#feb734, #fea502); } .button-raised.button-highlight:hover, .button-raised.button-highlight:focus { background: -webkit-gradient(linear, left top, left bottom, from(#febc44), to(#f49f01)); background: linear-gradient(top, #febc44, #f49f01); } .button-raised.button-highlight:active, .button-raised.button-highlight.active, .button-raised.button-highlight.is-active { border-color: #e59501; background: #f3ab26; } .button-raised.button-caution { border-color: #ff2939; background: -webkit-gradient(linear, left top, left bottom, from(#ff5c69), to(#ff2939)); background: linear-gradient(#ff5c69, #ff2939); } .button-raised.button-caution:hover, .button-raised.button-caution:focus { background: -webkit-gradient(linear, left top, left bottom, from(#ff6c77), to(#ff1f30)); background: linear-gradient(top, #ff6c77, #ff1f30); } .button-raised.button-caution:active, .button-raised.button-caution.active, .button-raised.button-caution.is-active { border-color: #ff1022; background: #f64c59; } .button-raised.button-royal { border-color: #665ce6; background: -webkit-gradient(linear, left top, left bottom, from(#9088ec), to(#665ce6)); background: linear-gradient(#9088ec, #665ce6); } .button-raised.button-royal:hover, .button-raised.button-royal:focus { background: -webkit-gradient(linear, left top, left bottom, from(#9c95ef), to(#5e53e4)); background: linear-gradient(top, #9c95ef, #5e53e4); } .button-raised.button-royal:active, .button-raised.button-royal.active, .button-raised.button-royal.is-active { border-color: #5246e2; background: #827ae1; } /* * 3D Buttons * * These buttons have a heavy three dimensional * style that mimics the visual appearance of a * real life button. */ .button-3d { position: relative; top: 0; -webkit-box-shadow: 0 7px 0 #bbbbbb, 0 8px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 7px 0 #bbbbbb, 0 8px 3px rgba(0, 0, 0, 0.2); } .button-3d:hover, .button-3d:focus { -webkit-box-shadow: 0 7px 0 #bbbbbb, 0 8px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 7px 0 #bbbbbb, 0 8px 3px rgba(0, 0, 0, 0.2); } .button-3d:active, .button-3d.active, .button-3d.is-active { top: 5px; -webkit-transition-property: all; transition-property: all; -webkit-transition-duration: .15s; transition-duration: .15s; -webkit-box-shadow: 0 2px 0 #bbbbbb, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #bbbbbb, 0 3px 3px rgba(0, 0, 0, 0.2); } /* * 3D Button Colors * * Create colors for buttons * (.button-primary, .button-secondary, etc.) */ .button-3d.button-primary { -webkit-box-shadow: 0 7px 0 #0880d7, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #0880d7, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-primary:hover, .button-3d.button-primary:focus { -webkit-box-shadow: 0 7px 0 #077ace, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #077ace, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-primary:active, .button-3d.button-primary.active, .button-3d.button-primary.is-active { -webkit-box-shadow: 0 2px 0 #0662a6, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #0662a6, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-plain { -webkit-box-shadow: 0 7px 0 #e6e6e6, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #e6e6e6, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-plain:hover, .button-3d.button-plain:focus { -webkit-box-shadow: 0 7px 0 #e0e0e0, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #e0e0e0, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-plain:active, .button-3d.button-plain.active, .button-3d.button-plain.is-active { -webkit-box-shadow: 0 2px 0 #cccccc, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #cccccc, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-inverse { -webkit-box-shadow: 0 7px 0 #090909, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #090909, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-inverse:hover, .button-3d.button-inverse:focus { -webkit-box-shadow: 0 7px 0 #030303, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #030303, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-inverse:active, .button-3d.button-inverse.active, .button-3d.button-inverse.is-active { -webkit-box-shadow: 0 2px 0 black, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 black, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-action { -webkit-box-shadow: 0 7px 0 #8bc220, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #8bc220, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-action:hover, .button-3d.button-action:focus { -webkit-box-shadow: 0 7px 0 #84b91f, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #84b91f, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-action:active, .button-3d.button-action.active, .button-3d.button-action.is-active { -webkit-box-shadow: 0 2px 0 #6b9619, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #6b9619, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-highlight { -webkit-box-shadow: 0 7px 0 #e59501, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #e59501, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-highlight:hover, .button-3d.button-highlight:focus { -webkit-box-shadow: 0 7px 0 #db8e01, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #db8e01, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-highlight:active, .button-3d.button-highlight.active, .button-3d.button-highlight.is-active { -webkit-box-shadow: 0 2px 0 #b27401, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #b27401, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-caution { -webkit-box-shadow: 0 7px 0 #ff1022, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #ff1022, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-caution:hover, .button-3d.button-caution:focus { -webkit-box-shadow: 0 7px 0 #ff0618, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #ff0618, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-caution:active, .button-3d.button-caution.active, .button-3d.button-caution.is-active { -webkit-box-shadow: 0 2px 0 #dc0010, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #dc0010, 0 3px 3px rgba(0, 0, 0, 0.2); } .button-3d.button-royal { -webkit-box-shadow: 0 7px 0 #5246e2, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #5246e2, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-royal:hover, .button-3d.button-royal:focus { -webkit-box-shadow: 0 7px 0 #493de1, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #493de1, 0 8px 3px rgba(0, 0, 0, 0.3); } .button-3d.button-royal:active, .button-3d.button-royal.active, .button-3d.button-royal.is-active { -webkit-box-shadow: 0 2px 0 #2f21d4, 0 3px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 0 #2f21d4, 0 3px 3px rgba(0, 0, 0, 0.2); } /* * Glowing Buttons * * A pulse like glow that appears * rythmically around the edges of * a button. */ /* * Glow animation mixin for Compass users * */ /* * Glowing Keyframes * */ @-webkit-keyframes glowing { from { -webkit-box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(44, 154, 219, 0.8); box-shadow: 0 0 20px rgba(44, 154, 219, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); } } @keyframes glowing { from { -webkit-box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(44, 154, 219, 0.8); box-shadow: 0 0 20px rgba(44, 154, 219, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); box-shadow: 0 0 0 rgba(44, 154, 219, 0.3); } } /* * Glowing Keyframes for various colors * */ @-webkit-keyframes glowing-primary { from { -webkit-box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(27, 154, 247, 0.8); box-shadow: 0 0 20px rgba(27, 154, 247, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); } } @keyframes glowing-primary { from { -webkit-box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(27, 154, 247, 0.8); box-shadow: 0 0 20px rgba(27, 154, 247, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); box-shadow: 0 0 0 rgba(27, 154, 247, 0.3); } } @-webkit-keyframes glowing-plain { from { -webkit-box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(255, 255, 255, 0.8); box-shadow: 0 0 20px rgba(255, 255, 255, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); } } @keyframes glowing-plain { from { -webkit-box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(255, 255, 255, 0.8); box-shadow: 0 0 20px rgba(255, 255, 255, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); box-shadow: 0 0 0 rgba(255, 255, 255, 0.3); } } @-webkit-keyframes glowing-inverse { from { -webkit-box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(34, 34, 34, 0.8); box-shadow: 0 0 20px rgba(34, 34, 34, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); } } @keyframes glowing-inverse { from { -webkit-box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(34, 34, 34, 0.8); box-shadow: 0 0 20px rgba(34, 34, 34, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); box-shadow: 0 0 0 rgba(34, 34, 34, 0.3); } } @-webkit-keyframes glowing-action { from { -webkit-box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(165, 222, 55, 0.8); box-shadow: 0 0 20px rgba(165, 222, 55, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); } } @keyframes glowing-action { from { -webkit-box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(165, 222, 55, 0.8); box-shadow: 0 0 20px rgba(165, 222, 55, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); box-shadow: 0 0 0 rgba(165, 222, 55, 0.3); } } @-webkit-keyframes glowing-highlight { from { -webkit-box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(254, 174, 27, 0.8); box-shadow: 0 0 20px rgba(254, 174, 27, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); } } @keyframes glowing-highlight { from { -webkit-box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(254, 174, 27, 0.8); box-shadow: 0 0 20px rgba(254, 174, 27, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); box-shadow: 0 0 0 rgba(254, 174, 27, 0.3); } } @-webkit-keyframes glowing-caution { from { -webkit-box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(255, 67, 81, 0.8); box-shadow: 0 0 20px rgba(255, 67, 81, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); } } @keyframes glowing-caution { from { -webkit-box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(255, 67, 81, 0.8); box-shadow: 0 0 20px rgba(255, 67, 81, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); box-shadow: 0 0 0 rgba(255, 67, 81, 0.3); } } @-webkit-keyframes glowing-royal { from { -webkit-box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(123, 114, 233, 0.8); box-shadow: 0 0 20px rgba(123, 114, 233, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); } } @keyframes glowing-royal { from { -webkit-box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); } 50% { -webkit-box-shadow: 0 0 20px rgba(123, 114, 233, 0.8); box-shadow: 0 0 20px rgba(123, 114, 233, 0.8); } to { -webkit-box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); box-shadow: 0 0 0 rgba(123, 114, 233, 0.3); } } /* * Glowing Buttons Base Styes * * A pulse like glow that appears * rythmically around the edges of * a button. */ .button-glow { -webkit-animation-duration: 3s; animation-duration: 3s; -webkit-animation-iteration-count: infinite; animation-iteration-count: infinite; -webkit-animation-name: glowing; animation-name: glowing; } .button-glow:active, .button-glow.active, .button-glow.is-active { -webkit-animation-name: none; animation-name: none; } /* * Glowing Button Colors * * Create colors for glowing buttons */ .button-glow.button-primary { -webkit-animation-name: glowing-primary; animation-name: glowing-primary; } .button-glow.button-plain { -webkit-animation-name: glowing-plain; animation-name: glowing-plain; } .button-glow.button-inverse { -webkit-animation-name: glowing-inverse; animation-name: glowing-inverse; } .button-glow.button-action { -webkit-animation-name: glowing-action; animation-name: glowing-action; } .button-glow.button-highlight { -webkit-animation-name: glowing-highlight; animation-name: glowing-highlight; } .button-glow.button-caution { -webkit-animation-name: glowing-caution; animation-name: glowing-caution; } .button-glow.button-royal { -webkit-animation-name: glowing-royal; animation-name: glowing-royal; } /* * Dropdown menu buttons * * A dropdown menu appears * when a button is pressed */ /* * Dropdown Container * */ .button-dropdown { position: relative; overflow: visible; display: inline-block; } /* * Dropdown List Style * */ .button-dropdown-list { display: none; position: absolute; padding: 0; margin: 0; top: 0; left: 0; z-index: 1000; min-width: 100%; list-style-type: none; background: rgba(255, 255, 255, 0.95); border-style: solid; border-width: 1px; border-color: #d4d4d4; font-family: "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; -webkit-box-shadow: 0 2px 7px rgba(0, 0, 0, 0.2); box-shadow: 0 2px 7px rgba(0, 0, 0, 0.2); border-radius: 3px; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; /* * Dropdown Below * */ /* * Dropdown Above * */ } .button-dropdown-list.is-below { top: 100%; border-top: none; border-radius: 0 0 3px 3px; } .button-dropdown-list.is-above { bottom: 100%; top: auto; border-bottom: none; border-radius: 3px 3px 0 0; -webkit-box-shadow: 0 -2px 7px rgba(0, 0, 0, 0.2); box-shadow: 0 -2px 7px rgba(0, 0, 0, 0.2); } /* * Dropdown Buttons * */ .button-dropdown-list > li { padding: 0; margin: 0; display: block; } .button-dropdown-list > li > a { display: block; line-height: 40px; font-size: 12.8px; padding: 5px 10px; float: none; color: #666; text-decoration: none; } .button-dropdown-list > li > a:hover { color: #5e5e5e; background: #f6f6f6; text-decoration: none; } .button-dropdown-divider { border-top: 1px solid #e6e6e6; } /* * Dropdown Colors * * Create colors for buttons * (.button-primary, .button-secondary, etc.) */ .button-dropdown.button-dropdown-primary .button-dropdown-list { background: rgba(27, 154, 247, 0.95); border-color: #0880d7; } .button-dropdown.button-dropdown-primary .button-dropdown-list .button-dropdown-divider { border-color: #0888e6; } .button-dropdown.button-dropdown-primary .button-dropdown-list > li > a { color: #FFF; } .button-dropdown.button-dropdown-primary .button-dropdown-list > li > a:hover { color: #f2f2f2; background: #088ef0; } .button-dropdown.button-dropdown-plain .button-dropdown-list { background: rgba(255, 255, 255, 0.95); border-color: #e6e6e6; } .button-dropdown.button-dropdown-plain .button-dropdown-list .button-dropdown-divider { border-color: #ededed; } .button-dropdown.button-dropdown-plain .button-dropdown-list > li > a { color: #1B9AF7; } .button-dropdown.button-dropdown-plain .button-dropdown-list > li > a:hover { color: #088ef0; background: #f2f2f2; } .button-dropdown.button-dropdown-inverse .button-dropdown-list { background: rgba(34, 34, 34, 0.95); border-color: #090909; } .button-dropdown.button-dropdown-inverse .button-dropdown-list .button-dropdown-divider { border-color: #101010; } .button-dropdown.button-dropdown-inverse .button-dropdown-list > li > a { color: #EEE; } .button-dropdown.button-dropdown-inverse .button-dropdown-list > li > a:hover { color: #e1e1e1; background: #151515; } .button-dropdown.button-dropdown-action .button-dropdown-list { background: rgba(165, 222, 55, 0.95); border-color: #8bc220; } .button-dropdown.button-dropdown-action .button-dropdown-list .button-dropdown-divider { border-color: #94cf22; } .button-dropdown.button-dropdown-action .button-dropdown-list > li > a { color: #FFF; } .button-dropdown.button-dropdown-action .button-dropdown-list > li > a:hover { color: #f2f2f2; background: #9ad824; } .button-dropdown.button-dropdown-highlight .button-dropdown-list { background: rgba(254, 174, 27, 0.95); border-color: #e59501; } .button-dropdown.button-dropdown-highlight .button-dropdown-list .button-dropdown-divider { border-color: #f49f01; } .button-dropdown.button-dropdown-highlight .button-dropdown-list > li > a { color: #FFF; } .button-dropdown.button-dropdown-highlight .button-dropdown-list > li > a:hover { color: #f2f2f2; background: #fea502; } .button-dropdown.button-dropdown-caution .button-dropdown-list { background: rgba(255, 67, 81, 0.95); border-color: #ff1022; } .button-dropdown.button-dropdown-caution .button-dropdown-list .button-dropdown-divider { border-color: #ff1f30; } .button-dropdown.button-dropdown-caution .button-dropdown-list > li > a { color: #FFF; } .button-dropdown.button-dropdown-caution .button-dropdown-list > li > a:hover { color: #f2f2f2; background: #ff2939; } .button-dropdown.button-dropdown-royal .button-dropdown-list { background: rgba(123, 114, 233, 0.95); border-color: #5246e2; } .button-dropdown.button-dropdown-royal .button-dropdown-list .button-dropdown-divider { border-color: #5e53e4; } .button-dropdown.button-dropdown-royal .button-dropdown-list > li > a { color: #FFF; } .button-dropdown.button-dropdown-royal .button-dropdown-list > li > a:hover { color: #f2f2f2; background: #665ce6; } /* * Buton Groups * * A group of related buttons * displayed edge to edge */ .button-group { position: relative; display: inline-block; } .button-group:after { content: " "; display: block; clear: both; } .button-group .button, .button-group .button-dropdown { float: left; } .button-group .button:not(:first-child):not(:last-child), .button-group .button-dropdown:not(:first-child):not(:last-child) { border-radius: 0; border-right: none; } .button-group .button:first-child, .button-group .button-dropdown:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: none; } .button-group .button:last-child, .button-group .button-dropdown:last-child { border-top-left-radius: 0; border-bottom-left-radius: 0; } /* * Button Wrapper * * A wrap around effect to highlight * the shape of the button and offer * a subtle visual effect. */ .button-wrap { border: 1px solid #e3e3e3; display: inline-block; padding: 9px; background: -webkit-gradient(linear, left top, left bottom, from(#f2f2f2), to(#FFF)); background: linear-gradient(#f2f2f2, #FFF); border-radius: 200px; -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.04); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.04); } /* * Long Shadow Buttons * * A visual effect adding a flat shadow to the text of a button */ /* * Long Shadow Function * * Loops $length times building a long shadow. Defaults downward right */ /* * LONG SHADOW MIXIN * */ /* * Shadow Right * */ .button-longshadow, .button-longshadow-right { overflow: hidden; } .button-longshadow.button-primary, .button-longshadow-right.button-primary { text-shadow: 0px 0px #0880d7, 1px 1px #0880d7, 2px 2px #0880d7, 3px 3px #0880d7, 4px 4px #0880d7, 5px 5px #0880d7, 6px 6px #0880d7, 7px 7px #0880d7, 8px 8px #0880d7, 9px 9px #0880d7, 10px 10px #0880d7, 11px 11px #0880d7, 12px 12px #0880d7, 13px 13px #0880d7, 14px 14px #0880d7, 15px 15px #0880d7, 16px 16px #0880d7, 17px 17px #0880d7, 18px 18px #0880d7, 19px 19px #0880d7, 20px 20px #0880d7, 21px 21px #0880d7, 22px 22px #0880d7, 23px 23px #0880d7, 24px 24px #0880d7, 25px 25px #0880d7, 26px 26px #0880d7, 27px 27px #0880d7, 28px 28px #0880d7, 29px 29px #0880d7, 30px 30px #0880d7, 31px 31px #0880d7, 32px 32px #0880d7, 33px 33px #0880d7, 34px 34px #0880d7, 35px 35px #0880d7, 36px 36px #0880d7, 37px 37px #0880d7, 38px 38px #0880d7, 39px 39px #0880d7, 40px 40px #0880d7, 41px 41px #0880d7, 42px 42px #0880d7, 43px 43px #0880d7, 44px 44px #0880d7, 45px 45px #0880d7, 46px 46px #0880d7, 47px 47px #0880d7, 48px 48px #0880d7, 49px 49px #0880d7, 50px 50px #0880d7, 51px 51px #0880d7, 52px 52px #0880d7, 53px 53px #0880d7, 54px 54px #0880d7, 55px 55px #0880d7, 56px 56px #0880d7, 57px 57px #0880d7, 58px 58px #0880d7, 59px 59px #0880d7, 60px 60px #0880d7, 61px 61px #0880d7, 62px 62px #0880d7, 63px 63px #0880d7, 64px 64px #0880d7, 65px 65px #0880d7, 66px 66px #0880d7, 67px 67px #0880d7, 68px 68px #0880d7, 69px 69px #0880d7, 70px 70px #0880d7, 71px 71px #0880d7, 72px 72px #0880d7, 73px 73px #0880d7, 74px 74px #0880d7, 75px 75px #0880d7, 76px 76px #0880d7, 77px 77px #0880d7, 78px 78px #0880d7, 79px 79px #0880d7, 80px 80px #0880d7, 81px 81px #0880d7, 82px 82px #0880d7, 83px 83px #0880d7, 84px 84px #0880d7, 85px 85px #0880d7; } .button-longshadow.button-primary:active, .button-longshadow.button-primary.active, .button-longshadow.button-primary.is-active, .button-longshadow-right.button-primary:active, .button-longshadow-right.button-primary.active, .button-longshadow-right.button-primary.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-plain, .button-longshadow-right.button-plain { text-shadow: 0px 0px #e6e6e6, 1px 1px #e6e6e6, 2px 2px #e6e6e6, 3px 3px #e6e6e6, 4px 4px #e6e6e6, 5px 5px #e6e6e6, 6px 6px #e6e6e6, 7px 7px #e6e6e6, 8px 8px #e6e6e6, 9px 9px #e6e6e6, 10px 10px #e6e6e6, 11px 11px #e6e6e6, 12px 12px #e6e6e6, 13px 13px #e6e6e6, 14px 14px #e6e6e6, 15px 15px #e6e6e6, 16px 16px #e6e6e6, 17px 17px #e6e6e6, 18px 18px #e6e6e6, 19px 19px #e6e6e6, 20px 20px #e6e6e6, 21px 21px #e6e6e6, 22px 22px #e6e6e6, 23px 23px #e6e6e6, 24px 24px #e6e6e6, 25px 25px #e6e6e6, 26px 26px #e6e6e6, 27px 27px #e6e6e6, 28px 28px #e6e6e6, 29px 29px #e6e6e6, 30px 30px #e6e6e6, 31px 31px #e6e6e6, 32px 32px #e6e6e6, 33px 33px #e6e6e6, 34px 34px #e6e6e6, 35px 35px #e6e6e6, 36px 36px #e6e6e6, 37px 37px #e6e6e6, 38px 38px #e6e6e6, 39px 39px #e6e6e6, 40px 40px #e6e6e6, 41px 41px #e6e6e6, 42px 42px #e6e6e6, 43px 43px #e6e6e6, 44px 44px #e6e6e6, 45px 45px #e6e6e6, 46px 46px #e6e6e6, 47px 47px #e6e6e6, 48px 48px #e6e6e6, 49px 49px #e6e6e6, 50px 50px #e6e6e6, 51px 51px #e6e6e6, 52px 52px #e6e6e6, 53px 53px #e6e6e6, 54px 54px #e6e6e6, 55px 55px #e6e6e6, 56px 56px #e6e6e6, 57px 57px #e6e6e6, 58px 58px #e6e6e6, 59px 59px #e6e6e6, 60px 60px #e6e6e6, 61px 61px #e6e6e6, 62px 62px #e6e6e6, 63px 63px #e6e6e6, 64px 64px #e6e6e6, 65px 65px #e6e6e6, 66px 66px #e6e6e6, 67px 67px #e6e6e6, 68px 68px #e6e6e6, 69px 69px #e6e6e6, 70px 70px #e6e6e6, 71px 71px #e6e6e6, 72px 72px #e6e6e6, 73px 73px #e6e6e6, 74px 74px #e6e6e6, 75px 75px #e6e6e6, 76px 76px #e6e6e6, 77px 77px #e6e6e6, 78px 78px #e6e6e6, 79px 79px #e6e6e6, 80px 80px #e6e6e6, 81px 81px #e6e6e6, 82px 82px #e6e6e6, 83px 83px #e6e6e6, 84px 84px #e6e6e6, 85px 85px #e6e6e6; } .button-longshadow.button-plain:active, .button-longshadow.button-plain.active, .button-longshadow.button-plain.is-active, .button-longshadow-right.button-plain:active, .button-longshadow-right.button-plain.active, .button-longshadow-right.button-plain.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-inverse, .button-longshadow-right.button-inverse { text-shadow: 0px 0px #090909, 1px 1px #090909, 2px 2px #090909, 3px 3px #090909, 4px 4px #090909, 5px 5px #090909, 6px 6px #090909, 7px 7px #090909, 8px 8px #090909, 9px 9px #090909, 10px 10px #090909, 11px 11px #090909, 12px 12px #090909, 13px 13px #090909, 14px 14px #090909, 15px 15px #090909, 16px 16px #090909, 17px 17px #090909, 18px 18px #090909, 19px 19px #090909, 20px 20px #090909, 21px 21px #090909, 22px 22px #090909, 23px 23px #090909, 24px 24px #090909, 25px 25px #090909, 26px 26px #090909, 27px 27px #090909, 28px 28px #090909, 29px 29px #090909, 30px 30px #090909, 31px 31px #090909, 32px 32px #090909, 33px 33px #090909, 34px 34px #090909, 35px 35px #090909, 36px 36px #090909, 37px 37px #090909, 38px 38px #090909, 39px 39px #090909, 40px 40px #090909, 41px 41px #090909, 42px 42px #090909, 43px 43px #090909, 44px 44px #090909, 45px 45px #090909, 46px 46px #090909, 47px 47px #090909, 48px 48px #090909, 49px 49px #090909, 50px 50px #090909, 51px 51px #090909, 52px 52px #090909, 53px 53px #090909, 54px 54px #090909, 55px 55px #090909, 56px 56px #090909, 57px 57px #090909, 58px 58px #090909, 59px 59px #090909, 60px 60px #090909, 61px 61px #090909, 62px 62px #090909, 63px 63px #090909, 64px 64px #090909, 65px 65px #090909, 66px 66px #090909, 67px 67px #090909, 68px 68px #090909, 69px 69px #090909, 70px 70px #090909, 71px 71px #090909, 72px 72px #090909, 73px 73px #090909, 74px 74px #090909, 75px 75px #090909, 76px 76px #090909, 77px 77px #090909, 78px 78px #090909, 79px 79px #090909, 80px 80px #090909, 81px 81px #090909, 82px 82px #090909, 83px 83px #090909, 84px 84px #090909, 85px 85px #090909; } .button-longshadow.button-inverse:active, .button-longshadow.button-inverse.active, .button-longshadow.button-inverse.is-active, .button-longshadow-right.button-inverse:active, .button-longshadow-right.button-inverse.active, .button-longshadow-right.button-inverse.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-action, .button-longshadow-right.button-action { text-shadow: 0px 0px #8bc220, 1px 1px #8bc220, 2px 2px #8bc220, 3px 3px #8bc220, 4px 4px #8bc220, 5px 5px #8bc220, 6px 6px #8bc220, 7px 7px #8bc220, 8px 8px #8bc220, 9px 9px #8bc220, 10px 10px #8bc220, 11px 11px #8bc220, 12px 12px #8bc220, 13px 13px #8bc220, 14px 14px #8bc220, 15px 15px #8bc220, 16px 16px #8bc220, 17px 17px #8bc220, 18px 18px #8bc220, 19px 19px #8bc220, 20px 20px #8bc220, 21px 21px #8bc220, 22px 22px #8bc220, 23px 23px #8bc220, 24px 24px #8bc220, 25px 25px #8bc220, 26px 26px #8bc220, 27px 27px #8bc220, 28px 28px #8bc220, 29px 29px #8bc220, 30px 30px #8bc220, 31px 31px #8bc220, 32px 32px #8bc220, 33px 33px #8bc220, 34px 34px #8bc220, 35px 35px #8bc220, 36px 36px #8bc220, 37px 37px #8bc220, 38px 38px #8bc220, 39px 39px #8bc220, 40px 40px #8bc220, 41px 41px #8bc220, 42px 42px #8bc220, 43px 43px #8bc220, 44px 44px #8bc220, 45px 45px #8bc220, 46px 46px #8bc220, 47px 47px #8bc220, 48px 48px #8bc220, 49px 49px #8bc220, 50px 50px #8bc220, 51px 51px #8bc220, 52px 52px #8bc220, 53px 53px #8bc220, 54px 54px #8bc220, 55px 55px #8bc220, 56px 56px #8bc220, 57px 57px #8bc220, 58px 58px #8bc220, 59px 59px #8bc220, 60px 60px #8bc220, 61px 61px #8bc220, 62px 62px #8bc220, 63px 63px #8bc220, 64px 64px #8bc220, 65px 65px #8bc220, 66px 66px #8bc220, 67px 67px #8bc220, 68px 68px #8bc220, 69px 69px #8bc220, 70px 70px #8bc220, 71px 71px #8bc220, 72px 72px #8bc220, 73px 73px #8bc220, 74px 74px #8bc220, 75px 75px #8bc220, 76px 76px #8bc220, 77px 77px #8bc220, 78px 78px #8bc220, 79px 79px #8bc220, 80px 80px #8bc220, 81px 81px #8bc220, 82px 82px #8bc220, 83px 83px #8bc220, 84px 84px #8bc220, 85px 85px #8bc220; } .button-longshadow.button-action:active, .button-longshadow.button-action.active, .button-longshadow.button-action.is-active, .button-longshadow-right.button-action:active, .button-longshadow-right.button-action.active, .button-longshadow-right.button-action.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-highlight, .button-longshadow-right.button-highlight { text-shadow: 0px 0px #e59501, 1px 1px #e59501, 2px 2px #e59501, 3px 3px #e59501, 4px 4px #e59501, 5px 5px #e59501, 6px 6px #e59501, 7px 7px #e59501, 8px 8px #e59501, 9px 9px #e59501, 10px 10px #e59501, 11px 11px #e59501, 12px 12px #e59501, 13px 13px #e59501, 14px 14px #e59501, 15px 15px #e59501, 16px 16px #e59501, 17px 17px #e59501, 18px 18px #e59501, 19px 19px #e59501, 20px 20px #e59501, 21px 21px #e59501, 22px 22px #e59501, 23px 23px #e59501, 24px 24px #e59501, 25px 25px #e59501, 26px 26px #e59501, 27px 27px #e59501, 28px 28px #e59501, 29px 29px #e59501, 30px 30px #e59501, 31px 31px #e59501, 32px 32px #e59501, 33px 33px #e59501, 34px 34px #e59501, 35px 35px #e59501, 36px 36px #e59501, 37px 37px #e59501, 38px 38px #e59501, 39px 39px #e59501, 40px 40px #e59501, 41px 41px #e59501, 42px 42px #e59501, 43px 43px #e59501, 44px 44px #e59501, 45px 45px #e59501, 46px 46px #e59501, 47px 47px #e59501, 48px 48px #e59501, 49px 49px #e59501, 50px 50px #e59501, 51px 51px #e59501, 52px 52px #e59501, 53px 53px #e59501, 54px 54px #e59501, 55px 55px #e59501, 56px 56px #e59501, 57px 57px #e59501, 58px 58px #e59501, 59px 59px #e59501, 60px 60px #e59501, 61px 61px #e59501, 62px 62px #e59501, 63px 63px #e59501, 64px 64px #e59501, 65px 65px #e59501, 66px 66px #e59501, 67px 67px #e59501, 68px 68px #e59501, 69px 69px #e59501, 70px 70px #e59501, 71px 71px #e59501, 72px 72px #e59501, 73px 73px #e59501, 74px 74px #e59501, 75px 75px #e59501, 76px 76px #e59501, 77px 77px #e59501, 78px 78px #e59501, 79px 79px #e59501, 80px 80px #e59501, 81px 81px #e59501, 82px 82px #e59501, 83px 83px #e59501, 84px 84px #e59501, 85px 85px #e59501; } .button-longshadow.button-highlight:active, .button-longshadow.button-highlight.active, .button-longshadow.button-highlight.is-active, .button-longshadow-right.button-highlight:active, .button-longshadow-right.button-highlight.active, .button-longshadow-right.button-highlight.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-caution, .button-longshadow-right.button-caution { text-shadow: 0px 0px #ff1022, 1px 1px #ff1022, 2px 2px #ff1022, 3px 3px #ff1022, 4px 4px #ff1022, 5px 5px #ff1022, 6px 6px #ff1022, 7px 7px #ff1022, 8px 8px #ff1022, 9px 9px #ff1022, 10px 10px #ff1022, 11px 11px #ff1022, 12px 12px #ff1022, 13px 13px #ff1022, 14px 14px #ff1022, 15px 15px #ff1022, 16px 16px #ff1022, 17px 17px #ff1022, 18px 18px #ff1022, 19px 19px #ff1022, 20px 20px #ff1022, 21px 21px #ff1022, 22px 22px #ff1022, 23px 23px #ff1022, 24px 24px #ff1022, 25px 25px #ff1022, 26px 26px #ff1022, 27px 27px #ff1022, 28px 28px #ff1022, 29px 29px #ff1022, 30px 30px #ff1022, 31px 31px #ff1022, 32px 32px #ff1022, 33px 33px #ff1022, 34px 34px #ff1022, 35px 35px #ff1022, 36px 36px #ff1022, 37px 37px #ff1022, 38px 38px #ff1022, 39px 39px #ff1022, 40px 40px #ff1022, 41px 41px #ff1022, 42px 42px #ff1022, 43px 43px #ff1022, 44px 44px #ff1022, 45px 45px #ff1022, 46px 46px #ff1022, 47px 47px #ff1022, 48px 48px #ff1022, 49px 49px #ff1022, 50px 50px #ff1022, 51px 51px #ff1022, 52px 52px #ff1022, 53px 53px #ff1022, 54px 54px #ff1022, 55px 55px #ff1022, 56px 56px #ff1022, 57px 57px #ff1022, 58px 58px #ff1022, 59px 59px #ff1022, 60px 60px #ff1022, 61px 61px #ff1022, 62px 62px #ff1022, 63px 63px #ff1022, 64px 64px #ff1022, 65px 65px #ff1022, 66px 66px #ff1022, 67px 67px #ff1022, 68px 68px #ff1022, 69px 69px #ff1022, 70px 70px #ff1022, 71px 71px #ff1022, 72px 72px #ff1022, 73px 73px #ff1022, 74px 74px #ff1022, 75px 75px #ff1022, 76px 76px #ff1022, 77px 77px #ff1022, 78px 78px #ff1022, 79px 79px #ff1022, 80px 80px #ff1022, 81px 81px #ff1022, 82px 82px #ff1022, 83px 83px #ff1022, 84px 84px #ff1022, 85px 85px #ff1022; } .button-longshadow.button-caution:active, .button-longshadow.button-caution.active, .button-longshadow.button-caution.is-active, .button-longshadow-right.button-caution:active, .button-longshadow-right.button-caution.active, .button-longshadow-right.button-caution.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow.button-royal, .button-longshadow-right.button-royal { text-shadow: 0px 0px #5246e2, 1px 1px #5246e2, 2px 2px #5246e2, 3px 3px #5246e2, 4px 4px #5246e2, 5px 5px #5246e2, 6px 6px #5246e2, 7px 7px #5246e2, 8px 8px #5246e2, 9px 9px #5246e2, 10px 10px #5246e2, 11px 11px #5246e2, 12px 12px #5246e2, 13px 13px #5246e2, 14px 14px #5246e2, 15px 15px #5246e2, 16px 16px #5246e2, 17px 17px #5246e2, 18px 18px #5246e2, 19px 19px #5246e2, 20px 20px #5246e2, 21px 21px #5246e2, 22px 22px #5246e2, 23px 23px #5246e2, 24px 24px #5246e2, 25px 25px #5246e2, 26px 26px #5246e2, 27px 27px #5246e2, 28px 28px #5246e2, 29px 29px #5246e2, 30px 30px #5246e2, 31px 31px #5246e2, 32px 32px #5246e2, 33px 33px #5246e2, 34px 34px #5246e2, 35px 35px #5246e2, 36px 36px #5246e2, 37px 37px #5246e2, 38px 38px #5246e2, 39px 39px #5246e2, 40px 40px #5246e2, 41px 41px #5246e2, 42px 42px #5246e2, 43px 43px #5246e2, 44px 44px #5246e2, 45px 45px #5246e2, 46px 46px #5246e2, 47px 47px #5246e2, 48px 48px #5246e2, 49px 49px #5246e2, 50px 50px #5246e2, 51px 51px #5246e2, 52px 52px #5246e2, 53px 53px #5246e2, 54px 54px #5246e2, 55px 55px #5246e2, 56px 56px #5246e2, 57px 57px #5246e2, 58px 58px #5246e2, 59px 59px #5246e2, 60px 60px #5246e2, 61px 61px #5246e2, 62px 62px #5246e2, 63px 63px #5246e2, 64px 64px #5246e2, 65px 65px #5246e2, 66px 66px #5246e2, 67px 67px #5246e2, 68px 68px #5246e2, 69px 69px #5246e2, 70px 70px #5246e2, 71px 71px #5246e2, 72px 72px #5246e2, 73px 73px #5246e2, 74px 74px #5246e2, 75px 75px #5246e2, 76px 76px #5246e2, 77px 77px #5246e2, 78px 78px #5246e2, 79px 79px #5246e2, 80px 80px #5246e2, 81px 81px #5246e2, 82px 82px #5246e2, 83px 83px #5246e2, 84px 84px #5246e2, 85px 85px #5246e2; } .button-longshadow.button-royal:active, .button-longshadow.button-royal.active, .button-longshadow.button-royal.is-active, .button-longshadow-right.button-royal:active, .button-longshadow-right.button-royal.active, .button-longshadow-right.button-royal.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } /* * Shadow Left * */ .button-longshadow-left { overflow: hidden; } .button-longshadow-left.button-primary { text-shadow: 0px 0px #0880d7, -1px 1px #0880d7, -2px 2px #0880d7, -3px 3px #0880d7, -4px 4px #0880d7, -5px 5px #0880d7, -6px 6px #0880d7, -7px 7px #0880d7, -8px 8px #0880d7, -9px 9px #0880d7, -10px 10px #0880d7, -11px 11px #0880d7, -12px 12px #0880d7, -13px 13px #0880d7, -14px 14px #0880d7, -15px 15px #0880d7, -16px 16px #0880d7, -17px 17px #0880d7, -18px 18px #0880d7, -19px 19px #0880d7, -20px 20px #0880d7, -21px 21px #0880d7, -22px 22px #0880d7, -23px 23px #0880d7, -24px 24px #0880d7, -25px 25px #0880d7, -26px 26px #0880d7, -27px 27px #0880d7, -28px 28px #0880d7, -29px 29px #0880d7, -30px 30px #0880d7, -31px 31px #0880d7, -32px 32px #0880d7, -33px 33px #0880d7, -34px 34px #0880d7, -35px 35px #0880d7, -36px 36px #0880d7, -37px 37px #0880d7, -38px 38px #0880d7, -39px 39px #0880d7, -40px 40px #0880d7, -41px 41px #0880d7, -42px 42px #0880d7, -43px 43px #0880d7, -44px 44px #0880d7, -45px 45px #0880d7, -46px 46px #0880d7, -47px 47px #0880d7, -48px 48px #0880d7, -49px 49px #0880d7, -50px 50px #0880d7, -51px 51px #0880d7, -52px 52px #0880d7, -53px 53px #0880d7, -54px 54px #0880d7, -55px 55px #0880d7, -56px 56px #0880d7, -57px 57px #0880d7, -58px 58px #0880d7, -59px 59px #0880d7, -60px 60px #0880d7, -61px 61px #0880d7, -62px 62px #0880d7, -63px 63px #0880d7, -64px 64px #0880d7, -65px 65px #0880d7, -66px 66px #0880d7, -67px 67px #0880d7, -68px 68px #0880d7, -69px 69px #0880d7, -70px 70px #0880d7, -71px 71px #0880d7, -72px 72px #0880d7, -73px 73px #0880d7, -74px 74px #0880d7, -75px 75px #0880d7, -76px 76px #0880d7, -77px 77px #0880d7, -78px 78px #0880d7, -79px 79px #0880d7, -80px 80px #0880d7, -81px 81px #0880d7, -82px 82px #0880d7, -83px 83px #0880d7, -84px 84px #0880d7, -85px 85px #0880d7; } .button-longshadow-left.button-primary:active, .button-longshadow-left.button-primary.active, .button-longshadow-left.button-primary.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-plain { text-shadow: 0px 0px #e6e6e6, -1px 1px #e6e6e6, -2px 2px #e6e6e6, -3px 3px #e6e6e6, -4px 4px #e6e6e6, -5px 5px #e6e6e6, -6px 6px #e6e6e6, -7px 7px #e6e6e6, -8px 8px #e6e6e6, -9px 9px #e6e6e6, -10px 10px #e6e6e6, -11px 11px #e6e6e6, -12px 12px #e6e6e6, -13px 13px #e6e6e6, -14px 14px #e6e6e6, -15px 15px #e6e6e6, -16px 16px #e6e6e6, -17px 17px #e6e6e6, -18px 18px #e6e6e6, -19px 19px #e6e6e6, -20px 20px #e6e6e6, -21px 21px #e6e6e6, -22px 22px #e6e6e6, -23px 23px #e6e6e6, -24px 24px #e6e6e6, -25px 25px #e6e6e6, -26px 26px #e6e6e6, -27px 27px #e6e6e6, -28px 28px #e6e6e6, -29px 29px #e6e6e6, -30px 30px #e6e6e6, -31px 31px #e6e6e6, -32px 32px #e6e6e6, -33px 33px #e6e6e6, -34px 34px #e6e6e6, -35px 35px #e6e6e6, -36px 36px #e6e6e6, -37px 37px #e6e6e6, -38px 38px #e6e6e6, -39px 39px #e6e6e6, -40px 40px #e6e6e6, -41px 41px #e6e6e6, -42px 42px #e6e6e6, -43px 43px #e6e6e6, -44px 44px #e6e6e6, -45px 45px #e6e6e6, -46px 46px #e6e6e6, -47px 47px #e6e6e6, -48px 48px #e6e6e6, -49px 49px #e6e6e6, -50px 50px #e6e6e6, -51px 51px #e6e6e6, -52px 52px #e6e6e6, -53px 53px #e6e6e6, -54px 54px #e6e6e6, -55px 55px #e6e6e6, -56px 56px #e6e6e6, -57px 57px #e6e6e6, -58px 58px #e6e6e6, -59px 59px #e6e6e6, -60px 60px #e6e6e6, -61px 61px #e6e6e6, -62px 62px #e6e6e6, -63px 63px #e6e6e6, -64px 64px #e6e6e6, -65px 65px #e6e6e6, -66px 66px #e6e6e6, -67px 67px #e6e6e6, -68px 68px #e6e6e6, -69px 69px #e6e6e6, -70px 70px #e6e6e6, -71px 71px #e6e6e6, -72px 72px #e6e6e6, -73px 73px #e6e6e6, -74px 74px #e6e6e6, -75px 75px #e6e6e6, -76px 76px #e6e6e6, -77px 77px #e6e6e6, -78px 78px #e6e6e6, -79px 79px #e6e6e6, -80px 80px #e6e6e6, -81px 81px #e6e6e6, -82px 82px #e6e6e6, -83px 83px #e6e6e6, -84px 84px #e6e6e6, -85px 85px #e6e6e6; } .button-longshadow-left.button-plain:active, .button-longshadow-left.button-plain.active, .button-longshadow-left.button-plain.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-inverse { text-shadow: 0px 0px #090909, -1px 1px #090909, -2px 2px #090909, -3px 3px #090909, -4px 4px #090909, -5px 5px #090909, -6px 6px #090909, -7px 7px #090909, -8px 8px #090909, -9px 9px #090909, -10px 10px #090909, -11px 11px #090909, -12px 12px #090909, -13px 13px #090909, -14px 14px #090909, -15px 15px #090909, -16px 16px #090909, -17px 17px #090909, -18px 18px #090909, -19px 19px #090909, -20px 20px #090909, -21px 21px #090909, -22px 22px #090909, -23px 23px #090909, -24px 24px #090909, -25px 25px #090909, -26px 26px #090909, -27px 27px #090909, -28px 28px #090909, -29px 29px #090909, -30px 30px #090909, -31px 31px #090909, -32px 32px #090909, -33px 33px #090909, -34px 34px #090909, -35px 35px #090909, -36px 36px #090909, -37px 37px #090909, -38px 38px #090909, -39px 39px #090909, -40px 40px #090909, -41px 41px #090909, -42px 42px #090909, -43px 43px #090909, -44px 44px #090909, -45px 45px #090909, -46px 46px #090909, -47px 47px #090909, -48px 48px #090909, -49px 49px #090909, -50px 50px #090909, -51px 51px #090909, -52px 52px #090909, -53px 53px #090909, -54px 54px #090909, -55px 55px #090909, -56px 56px #090909, -57px 57px #090909, -58px 58px #090909, -59px 59px #090909, -60px 60px #090909, -61px 61px #090909, -62px 62px #090909, -63px 63px #090909, -64px 64px #090909, -65px 65px #090909, -66px 66px #090909, -67px 67px #090909, -68px 68px #090909, -69px 69px #090909, -70px 70px #090909, -71px 71px #090909, -72px 72px #090909, -73px 73px #090909, -74px 74px #090909, -75px 75px #090909, -76px 76px #090909, -77px 77px #090909, -78px 78px #090909, -79px 79px #090909, -80px 80px #090909, -81px 81px #090909, -82px 82px #090909, -83px 83px #090909, -84px 84px #090909, -85px 85px #090909; } .button-longshadow-left.button-inverse:active, .button-longshadow-left.button-inverse.active, .button-longshadow-left.button-inverse.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-action { text-shadow: 0px 0px #8bc220, -1px 1px #8bc220, -2px 2px #8bc220, -3px 3px #8bc220, -4px 4px #8bc220, -5px 5px #8bc220, -6px 6px #8bc220, -7px 7px #8bc220, -8px 8px #8bc220, -9px 9px #8bc220, -10px 10px #8bc220, -11px 11px #8bc220, -12px 12px #8bc220, -13px 13px #8bc220, -14px 14px #8bc220, -15px 15px #8bc220, -16px 16px #8bc220, -17px 17px #8bc220, -18px 18px #8bc220, -19px 19px #8bc220, -20px 20px #8bc220, -21px 21px #8bc220, -22px 22px #8bc220, -23px 23px #8bc220, -24px 24px #8bc220, -25px 25px #8bc220, -26px 26px #8bc220, -27px 27px #8bc220, -28px 28px #8bc220, -29px 29px #8bc220, -30px 30px #8bc220, -31px 31px #8bc220, -32px 32px #8bc220, -33px 33px #8bc220, -34px 34px #8bc220, -35px 35px #8bc220, -36px 36px #8bc220, -37px 37px #8bc220, -38px 38px #8bc220, -39px 39px #8bc220, -40px 40px #8bc220, -41px 41px #8bc220, -42px 42px #8bc220, -43px 43px #8bc220, -44px 44px #8bc220, -45px 45px #8bc220, -46px 46px #8bc220, -47px 47px #8bc220, -48px 48px #8bc220, -49px 49px #8bc220, -50px 50px #8bc220, -51px 51px #8bc220, -52px 52px #8bc220, -53px 53px #8bc220, -54px 54px #8bc220, -55px 55px #8bc220, -56px 56px #8bc220, -57px 57px #8bc220, -58px 58px #8bc220, -59px 59px #8bc220, -60px 60px #8bc220, -61px 61px #8bc220, -62px 62px #8bc220, -63px 63px #8bc220, -64px 64px #8bc220, -65px 65px #8bc220, -66px 66px #8bc220, -67px 67px #8bc220, -68px 68px #8bc220, -69px 69px #8bc220, -70px 70px #8bc220, -71px 71px #8bc220, -72px 72px #8bc220, -73px 73px #8bc220, -74px 74px #8bc220, -75px 75px #8bc220, -76px 76px #8bc220, -77px 77px #8bc220, -78px 78px #8bc220, -79px 79px #8bc220, -80px 80px #8bc220, -81px 81px #8bc220, -82px 82px #8bc220, -83px 83px #8bc220, -84px 84px #8bc220, -85px 85px #8bc220; } .button-longshadow-left.button-action:active, .button-longshadow-left.button-action.active, .button-longshadow-left.button-action.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-highlight { text-shadow: 0px 0px #e59501, -1px 1px #e59501, -2px 2px #e59501, -3px 3px #e59501, -4px 4px #e59501, -5px 5px #e59501, -6px 6px #e59501, -7px 7px #e59501, -8px 8px #e59501, -9px 9px #e59501, -10px 10px #e59501, -11px 11px #e59501, -12px 12px #e59501, -13px 13px #e59501, -14px 14px #e59501, -15px 15px #e59501, -16px 16px #e59501, -17px 17px #e59501, -18px 18px #e59501, -19px 19px #e59501, -20px 20px #e59501, -21px 21px #e59501, -22px 22px #e59501, -23px 23px #e59501, -24px 24px #e59501, -25px 25px #e59501, -26px 26px #e59501, -27px 27px #e59501, -28px 28px #e59501, -29px 29px #e59501, -30px 30px #e59501, -31px 31px #e59501, -32px 32px #e59501, -33px 33px #e59501, -34px 34px #e59501, -35px 35px #e59501, -36px 36px #e59501, -37px 37px #e59501, -38px 38px #e59501, -39px 39px #e59501, -40px 40px #e59501, -41px 41px #e59501, -42px 42px #e59501, -43px 43px #e59501, -44px 44px #e59501, -45px 45px #e59501, -46px 46px #e59501, -47px 47px #e59501, -48px 48px #e59501, -49px 49px #e59501, -50px 50px #e59501, -51px 51px #e59501, -52px 52px #e59501, -53px 53px #e59501, -54px 54px #e59501, -55px 55px #e59501, -56px 56px #e59501, -57px 57px #e59501, -58px 58px #e59501, -59px 59px #e59501, -60px 60px #e59501, -61px 61px #e59501, -62px 62px #e59501, -63px 63px #e59501, -64px 64px #e59501, -65px 65px #e59501, -66px 66px #e59501, -67px 67px #e59501, -68px 68px #e59501, -69px 69px #e59501, -70px 70px #e59501, -71px 71px #e59501, -72px 72px #e59501, -73px 73px #e59501, -74px 74px #e59501, -75px 75px #e59501, -76px 76px #e59501, -77px 77px #e59501, -78px 78px #e59501, -79px 79px #e59501, -80px 80px #e59501, -81px 81px #e59501, -82px 82px #e59501, -83px 83px #e59501, -84px 84px #e59501, -85px 85px #e59501; } .button-longshadow-left.button-highlight:active, .button-longshadow-left.button-highlight.active, .button-longshadow-left.button-highlight.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-caution { text-shadow: 0px 0px #ff1022, -1px 1px #ff1022, -2px 2px #ff1022, -3px 3px #ff1022, -4px 4px #ff1022, -5px 5px #ff1022, -6px 6px #ff1022, -7px 7px #ff1022, -8px 8px #ff1022, -9px 9px #ff1022, -10px 10px #ff1022, -11px 11px #ff1022, -12px 12px #ff1022, -13px 13px #ff1022, -14px 14px #ff1022, -15px 15px #ff1022, -16px 16px #ff1022, -17px 17px #ff1022, -18px 18px #ff1022, -19px 19px #ff1022, -20px 20px #ff1022, -21px 21px #ff1022, -22px 22px #ff1022, -23px 23px #ff1022, -24px 24px #ff1022, -25px 25px #ff1022, -26px 26px #ff1022, -27px 27px #ff1022, -28px 28px #ff1022, -29px 29px #ff1022, -30px 30px #ff1022, -31px 31px #ff1022, -32px 32px #ff1022, -33px 33px #ff1022, -34px 34px #ff1022, -35px 35px #ff1022, -36px 36px #ff1022, -37px 37px #ff1022, -38px 38px #ff1022, -39px 39px #ff1022, -40px 40px #ff1022, -41px 41px #ff1022, -42px 42px #ff1022, -43px 43px #ff1022, -44px 44px #ff1022, -45px 45px #ff1022, -46px 46px #ff1022, -47px 47px #ff1022, -48px 48px #ff1022, -49px 49px #ff1022, -50px 50px #ff1022, -51px 51px #ff1022, -52px 52px #ff1022, -53px 53px #ff1022, -54px 54px #ff1022, -55px 55px #ff1022, -56px 56px #ff1022, -57px 57px #ff1022, -58px 58px #ff1022, -59px 59px #ff1022, -60px 60px #ff1022, -61px 61px #ff1022, -62px 62px #ff1022, -63px 63px #ff1022, -64px 64px #ff1022, -65px 65px #ff1022, -66px 66px #ff1022, -67px 67px #ff1022, -68px 68px #ff1022, -69px 69px #ff1022, -70px 70px #ff1022, -71px 71px #ff1022, -72px 72px #ff1022, -73px 73px #ff1022, -74px 74px #ff1022, -75px 75px #ff1022, -76px 76px #ff1022, -77px 77px #ff1022, -78px 78px #ff1022, -79px 79px #ff1022, -80px 80px #ff1022, -81px 81px #ff1022, -82px 82px #ff1022, -83px 83px #ff1022, -84px 84px #ff1022, -85px 85px #ff1022; } .button-longshadow-left.button-caution:active, .button-longshadow-left.button-caution.active, .button-longshadow-left.button-caution.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } .button-longshadow-left.button-royal { text-shadow: 0px 0px #5246e2, -1px 1px #5246e2, -2px 2px #5246e2, -3px 3px #5246e2, -4px 4px #5246e2, -5px 5px #5246e2, -6px 6px #5246e2, -7px 7px #5246e2, -8px 8px #5246e2, -9px 9px #5246e2, -10px 10px #5246e2, -11px 11px #5246e2, -12px 12px #5246e2, -13px 13px #5246e2, -14px 14px #5246e2, -15px 15px #5246e2, -16px 16px #5246e2, -17px 17px #5246e2, -18px 18px #5246e2, -19px 19px #5246e2, -20px 20px #5246e2, -21px 21px #5246e2, -22px 22px #5246e2, -23px 23px #5246e2, -24px 24px #5246e2, -25px 25px #5246e2, -26px 26px #5246e2, -27px 27px #5246e2, -28px 28px #5246e2, -29px 29px #5246e2, -30px 30px #5246e2, -31px 31px #5246e2, -32px 32px #5246e2, -33px 33px #5246e2, -34px 34px #5246e2, -35px 35px #5246e2, -36px 36px #5246e2, -37px 37px #5246e2, -38px 38px #5246e2, -39px 39px #5246e2, -40px 40px #5246e2, -41px 41px #5246e2, -42px 42px #5246e2, -43px 43px #5246e2, -44px 44px #5246e2, -45px 45px #5246e2, -46px 46px #5246e2, -47px 47px #5246e2, -48px 48px #5246e2, -49px 49px #5246e2, -50px 50px #5246e2, -51px 51px #5246e2, -52px 52px #5246e2, -53px 53px #5246e2, -54px 54px #5246e2, -55px 55px #5246e2, -56px 56px #5246e2, -57px 57px #5246e2, -58px 58px #5246e2, -59px 59px #5246e2, -60px 60px #5246e2, -61px 61px #5246e2, -62px 62px #5246e2, -63px 63px #5246e2, -64px 64px #5246e2, -65px 65px #5246e2, -66px 66px #5246e2, -67px 67px #5246e2, -68px 68px #5246e2, -69px 69px #5246e2, -70px 70px #5246e2, -71px 71px #5246e2, -72px 72px #5246e2, -73px 73px #5246e2, -74px 74px #5246e2, -75px 75px #5246e2, -76px 76px #5246e2, -77px 77px #5246e2, -78px 78px #5246e2, -79px 79px #5246e2, -80px 80px #5246e2, -81px 81px #5246e2, -82px 82px #5246e2, -83px 83px #5246e2, -84px 84px #5246e2, -85px 85px #5246e2; } .button-longshadow-left.button-royal:active, .button-longshadow-left.button-royal.active, .button-longshadow-left.button-royal.is-active { text-shadow: 0 1px 0 rgba(255, 255, 255, 0.4); } /* * Button Sizes * * This file creates the various button sizes * (ex. .button-large, .button-small, etc.) */ .button-giant { font-size: 28px; height: 70px; line-height: 70px; padding: 0 70px; } .button-jumbo { font-size: 24px; height: 60px; line-height: 60px; padding: 0 60px; } .button-large { font-size: 20px; height: 50px; line-height: 50px; padding: 0 50px; } .button-normal { font-size: 16px; height: 40px; line-height: 40px; padding: 0 40px; } .button-small { font-size: 12px; height: 30px; line-height: 30px; padding: 0 30px; } .button-tiny { font-size: 9.6px; height: 24px; line-height: 24px; padding: 0 24px; } ================================================ FILE: cachecloud-web/src/main/resources/assets/css/common.css ================================================ .bs-wizard { margin-top: 40px; } /*Form Wizard*/ .bs-wizard { border-bottom: solid 1px #e0e0e0; padding: 0 0 10px 0; } .bs-wizard > .bs-wizard-step { padding: 0; position: relative; } .bs-wizard > .bs-wizard-step + .bs-wizard-step { } .bs-wizard > .bs-wizard-step .bs-wizard-stepnum { color: #595959; font-size: 16px; margin-bottom: 5px; } .bs-wizard > .bs-wizard-step .bs-wizard-info { color: #999; font-size: 14px; } .bs-wizard > .bs-wizard-step > .bs-wizard-dot { position: absolute; width: 30px; height: 30px; display: block; background: #fbe8aa; top: 45px; left: 50%; margin-top: -15px; margin-left: -15px; border-radius: 50%; } .bs-wizard > .bs-wizard-step > .bs-wizard-dot:after { content: ' '; width: 14px; height: 14px; background: #fbbd19; border-radius: 50px; position: absolute; top: 8px; left: 8px; } .bs-wizard > .bs-wizard-step > .progress { position: relative; border-radius: 0px; height: 8px; box-shadow: none; margin: 20px 0; } .bs-wizard > .bs-wizard-step > .progress > .progress-bar { width: 0px; box-shadow: none; background: #fbe8aa; } .bs-wizard > .bs-wizard-step.complete > .progress > .progress-bar { width: 100%; } .bs-wizard > .bs-wizard-step.active > .progress > .progress-bar { width: 50%; } .bs-wizard > .bs-wizard-step:first-child.active > .progress > .progress-bar { width: 0%; } .bs-wizard > .bs-wizard-step:last-child.active > .progress > .progress-bar { width: 100%; } .bs-wizard > .bs-wizard-step.disabled > .bs-wizard-dot { background-color: #f5f5f5; } .bs-wizard > .bs-wizard-step.disabled > .bs-wizard-dot:after { opacity: 0; } .bs-wizard > .bs-wizard-step:first-child > .progress { left: 50%; width: 50%; } .bs-wizard > .bs-wizard-step:last-child > .progress { width: 50%; } .bs-wizard > .bs-wizard-step.disabled a.bs-wizard-dot { pointer-events: none; } /*END Form Wizard*/ ================================================ FILE: cachecloud-web/src/main/resources/assets/css/custom.css ================================================ .progress-fs-1 { font-size: 1rem; font-weight: 400; line-height: 1.5; } .table-sm > .progress-fs-1 { font-size: .75rem; font-weight: 400; line-height: 1.5; } .progress-bar > span { font-weight: bolder !important; text-align: start; } .progress { height: auto; border-radius: var(--bs-progress-border-radius); } ================================================ FILE: cachecloud-web/src/main/resources/assets/css/githubmd.css ================================================ .markdown-body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 16px; line-height: 1.5; word-wrap: break-word } .markdown-body::before { display: table; content: "" } .markdown-body::after { display: table; clear: both; content: "" } .markdown-body>*:first-child { margin-top: 0 !important } .markdown-body>*:last-child { margin-bottom: 0 !important } .markdown-body a:not([href]) { color: inherit; text-decoration: none } .markdown-body .absent { color: #cb2431 } .markdown-body .anchor { float: left; padding-right: 4px; margin-left: -20px; line-height: 1 } .markdown-body .anchor:focus { outline: none } .markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { margin-top: 0; margin-bottom: 16px } .markdown-body hr { height: 0.25em; padding: 0; margin: 24px 0; background-color: #e1e4e8; border: 0 } .markdown-body blockquote { padding: 0 1em; color: #6a737d; border-left: 0.25em solid #dfe2e5 } .markdown-body blockquote>:first-child { margin-top: 0 } .markdown-body blockquote>:last-child { margin-bottom: 0 } .markdown-body kbd { display: inline-block; padding: 3px 5px; font-size: 11px; line-height: 10px; color: #444d56; vertical-align: middle; background-color: #fafbfc; border: solid 1px #c6cbd1; border-bottom-color: #959da5; border-radius: 3px; box-shadow: inset 0 -1px 0 #959da5 } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { margin-top: 24px; margin-bottom: 16px; font-weight: 600; line-height: 1.25 } .markdown-body h1 .octicon-link, .markdown-body h2 .octicon-link, .markdown-body h3 .octicon-link, .markdown-body h4 .octicon-link, .markdown-body h5 .octicon-link, .markdown-body h6 .octicon-link { color: #1b1f23; vertical-align: middle; visibility: hidden } .markdown-body h1:hover .anchor, .markdown-body h2:hover .anchor, .markdown-body h3:hover .anchor, .markdown-body h4:hover .anchor, .markdown-body h5:hover .anchor, .markdown-body h6:hover .anchor { text-decoration: none } .markdown-body h1:hover .anchor .octicon-link, .markdown-body h2:hover .anchor .octicon-link, .markdown-body h3:hover .anchor .octicon-link, .markdown-body h4:hover .anchor .octicon-link, .markdown-body h5:hover .anchor .octicon-link, .markdown-body h6:hover .anchor .octicon-link { visibility: visible } .markdown-body h1 tt, .markdown-body h1 code, .markdown-body h2 tt, .markdown-body h2 code, .markdown-body h3 tt, .markdown-body h3 code, .markdown-body h4 tt, .markdown-body h4 code, .markdown-body h5 tt, .markdown-body h5 code, .markdown-body h6 tt, .markdown-body h6 code { font-size: inherit } .markdown-body h1 { padding-bottom: 0.3em; font-size: 2em; border-bottom: 1px solid #eaecef } .markdown-body h2 { padding-bottom: 0.3em; font-size: 1.5em; border-bottom: 1px solid #eaecef } .markdown-body h3 { font-size: 1.25em } .markdown-body h4 { font-size: 1em } .markdown-body h5 { font-size: 0.875em } .markdown-body h6 { font-size: 0.85em; color: #6a737d } ================================================ FILE: cachecloud-web/src/main/resources/assets/css/jobindex.css ================================================ /** * Template Name: NiceAdmin * Updated: Mar 09 2023 with Bootstrap v5.2.3 * Template URL: https://bootstrapmade.com/nice-admin-bootstrap-admin-html-template/ * Author: BootstrapMade.com * License: https://bootstrapmade.com/license/ */ /*-------------------------------------------------------------- # General --------------------------------------------------------------*/ label { margin-right: 3rem !important; display: flex !important; justify-content: flex-end !important; } ================================================ FILE: cachecloud-web/src/main/resources/assets/css/mem-cloud.css ================================================ table, td{ font:100% Arial, Helvetica, sans-serif; } table{width:100%;border-collapse:collapse;margin:1em 0;} th, td{text-align:left;padding:.5em;border:1px solid #fff;} td{background:#e5f1f4;} /* tablecloth styles */ tr.even td{background:#e5f1f4;} tr.odd td{background:#f8fbfc;} th.over, tr.even th.over, tr.odd th.over{background:#4a98af;} th.down, tr.even th.down, tr.odd th.down{background:#bce774;} th.selected, tr.even th.selected, tr.odd th.selected{} td.over, tr.even td.over, tr.odd td.over{background:#ecfbd4;} td.down, tr.even td.down, tr.odd td.down{background:#bce774;color:#fff;} td.selected, tr.even td.selected, tr.odd td.selected{background:#bce774;color:#555;} /* use this if you want to apply different styling to empty table cells*/ td.empty, tr.odd td.empty, tr.even td.empty{background:#fff;} .margin-custom-bottom0{ margin-bottom:0px; padding: 0px 0px; } .margin-custom-top10{ margin-top: 10px; } div.console { font-size: 14px; word-wrap: break-word;} div.console div.jquery-console-inner { width:100%; height:400px; background:#333; padding:0.5em; overflow:auto } div.console div.jquery-console-prompt-box { color:#fff; font-family:monospace; } div.console div.jquery-console-focus span.jquery-console-cursor { background:#fefefe; color:#333; font-weight:bold } div.console div.jquery-console-message-error { color:#ef0505; font-family:sans-serif; font-weight:bold; padding:0.1em; } div.console div.jquery-console-message-value { color:#1ad027; font-family:monospace; padding:0.1em; } div.console div.jquery-console-message-type { color:#52666f; font-family:monospace; padding:0.1em; } div.console span.jquery-console-prompt-label { font-weight:bold } ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/adminlte.css ================================================ /*! * AdminLTE v3.2.0 * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ /*! * Bootstrap v4.6.1 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: #fd7e14; --yellow: #ffc107; --green: #28a745; --teal: #20c997; --cyan: #17a2b8; --white: #fff; --gray: #6c757d; --gray-dark: #343a40; --primary: #007bff; --secondary: #6c757d; --success: #28a745; --info: #17a2b8; --warning: #ffc107; --danger: #dc3545; --light: #f8f9fa; --dark: #343a40; --breakpoint-xs: 0; --breakpoint-sm: 576px; --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; --font-family-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus:not(:focus-visible) { outline: 0 !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; } a:hover { color: #0056b3; text-decoration: none; } a:not([href]):not([class]) { color: inherit; text-decoration: none; } a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg { overflow: hidden; vertical-align: middle; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #6c757d; text-align: left; caption-side: bottom; } th { text-align: inherit; text-align: -webkit-match-parent; } label { display: inline-block; margin-bottom: 0.5rem; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } [role="button"] { cursor: pointer; } select { word-wrap: normal; } button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) { cursor: pointer; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; cursor: pointer; } template { display: none; } [hidden] { display: none !important; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; font-family: inherit; font-weight: 500; line-height: 1.2; color: inherit; } h1, .h1 { font-size: 2.5rem; } h2, .h2 { font-size: 2rem; } h3, .h3 { font-size: 1.75rem; } h4, .h4 { font-size: 1.5rem; } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: 6rem; font-weight: 300; line-height: 1.2; } .display-2 { font-size: 5.5rem; font-weight: 300; line-height: 1.2; } .display-3 { font-size: 4.5rem; font-weight: 300; line-height: 1.2; } .display-4 { font-size: 3.5rem; font-weight: 300; line-height: 1.2; } hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } small, .small { font-size: 80%; font-weight: 400; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 90%; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote-footer { display: block; font-size: 80%; color: #6c757d; } .blockquote-footer::before { content: "\2014\00A0"; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.25rem; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 90%; color: #6c757d; } code { font-size: 87.5%; color: #e83e8c; word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 87.5%; color: #fff; background-color: #212529; border-radius: 0.2rem; box-shadow: inset 0 -0.1rem 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; box-shadow: none; } pre { display: block; font-size: 87.5%; color: #212529; } pre code { font-size: inherit; color: inherit; word-break: normal; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container, .container-fluid, .container-sm, .container-md, .container-lg, .container-xl { width: 100%; padding-right: 7.5px; padding-left: 7.5px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container, .container-sm { max-width: 540px; } } @media (min-width: 768px) { .container, .container-sm, .container-md { max-width: 720px; } } @media (min-width: 992px) { .container, .container-sm, .container-md, .container-lg { max-width: 960px; } } @media (min-width: 1200px) { .container, .container-sm, .container-md, .container-lg, .container-xl { max-width: 1140px; } } .row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -7.5px; margin-left: -7.5px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; padding-right: 7.5px; padding-left: 7.5px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -ms-flex-order: -1; order: -1; } .order-last { -ms-flex-order: 13; order: 13; } .order-0 { -ms-flex-order: 0; order: 0; } .order-1 { -ms-flex-order: 1; order: 1; } .order-2 { -ms-flex-order: 2; order: 2; } .order-3 { -ms-flex-order: 3; order: 3; } .order-4 { -ms-flex-order: 4; order: 4; } .order-5 { -ms-flex-order: 5; order: 5; } .order-6 { -ms-flex-order: 6; order: 6; } .order-7 { -ms-flex-order: 7; order: 7; } .order-8 { -ms-flex-order: 8; order: 8; } .order-9 { -ms-flex-order: 9; order: 9; } .order-10 { -ms-flex-order: 10; order: 10; } .order-11 { -ms-flex-order: 11; order: 11; } .order-12 { -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-sm-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-sm-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-sm-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-sm-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-sm-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-sm-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-sm-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -ms-flex-order: -1; order: -1; } .order-sm-last { -ms-flex-order: 13; order: 13; } .order-sm-0 { -ms-flex-order: 0; order: 0; } .order-sm-1 { -ms-flex-order: 1; order: 1; } .order-sm-2 { -ms-flex-order: 2; order: 2; } .order-sm-3 { -ms-flex-order: 3; order: 3; } .order-sm-4 { -ms-flex-order: 4; order: 4; } .order-sm-5 { -ms-flex-order: 5; order: 5; } .order-sm-6 { -ms-flex-order: 6; order: 6; } .order-sm-7 { -ms-flex-order: 7; order: 7; } .order-sm-8 { -ms-flex-order: 8; order: 8; } .order-sm-9 { -ms-flex-order: 9; order: 9; } .order-sm-10 { -ms-flex-order: 10; order: 10; } .order-sm-11 { -ms-flex-order: 11; order: 11; } .order-sm-12 { -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-md-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-md-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-md-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-md-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-md-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-md-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-md-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -ms-flex-order: -1; order: -1; } .order-md-last { -ms-flex-order: 13; order: 13; } .order-md-0 { -ms-flex-order: 0; order: 0; } .order-md-1 { -ms-flex-order: 1; order: 1; } .order-md-2 { -ms-flex-order: 2; order: 2; } .order-md-3 { -ms-flex-order: 3; order: 3; } .order-md-4 { -ms-flex-order: 4; order: 4; } .order-md-5 { -ms-flex-order: 5; order: 5; } .order-md-6 { -ms-flex-order: 6; order: 6; } .order-md-7 { -ms-flex-order: 7; order: 7; } .order-md-8 { -ms-flex-order: 8; order: 8; } .order-md-9 { -ms-flex-order: 9; order: 9; } .order-md-10 { -ms-flex-order: 10; order: 10; } .order-md-11 { -ms-flex-order: 11; order: 11; } .order-md-12 { -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-lg-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-lg-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-lg-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-lg-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-lg-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-lg-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-lg-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -ms-flex-order: -1; order: -1; } .order-lg-last { -ms-flex-order: 13; order: 13; } .order-lg-0 { -ms-flex-order: 0; order: 0; } .order-lg-1 { -ms-flex-order: 1; order: 1; } .order-lg-2 { -ms-flex-order: 2; order: 2; } .order-lg-3 { -ms-flex-order: 3; order: 3; } .order-lg-4 { -ms-flex-order: 4; order: 4; } .order-lg-5 { -ms-flex-order: 5; order: 5; } .order-lg-6 { -ms-flex-order: 6; order: 6; } .order-lg-7 { -ms-flex-order: 7; order: 7; } .order-lg-8 { -ms-flex-order: 8; order: 8; } .order-lg-9 { -ms-flex-order: 9; order: 9; } .order-lg-10 { -ms-flex-order: 10; order: 10; } .order-lg-11 { -ms-flex-order: 11; order: 11; } .order-lg-12 { -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-xl-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-xl-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-xl-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-xl-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-xl-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-xl-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-xl-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -ms-flex-order: -1; order: -1; } .order-xl-last { -ms-flex-order: 13; order: 13; } .order-xl-0 { -ms-flex-order: 0; order: 0; } .order-xl-1 { -ms-flex-order: 1; order: 1; } .order-xl-2 { -ms-flex-order: 2; order: 2; } .order-xl-3 { -ms-flex-order: 3; order: 3; } .order-xl-4 { -ms-flex-order: 4; order: 4; } .order-xl-5 { -ms-flex-order: 5; order: 5; } .order-xl-6 { -ms-flex-order: 6; order: 6; } .order-xl-7 { -ms-flex-order: 7; order: 7; } .order-xl-8 { -ms-flex-order: 8; order: 8; } .order-xl-9 { -ms-flex-order: 9; order: 9; } .order-xl-10 { -ms-flex-order: 10; order: 10; } .order-xl-11 { -ms-flex-order: 11; order: 11; } .order-xl-12 { -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .table { width: 100%; margin-bottom: 1rem; color: #212529; background-color: transparent; } .table th, .table td { padding: 0.75rem; vertical-align: top; border-top: 1px solid #dee2e6; } .table thead th { vertical-align: bottom; border-bottom: 2px solid #dee2e6; } .table tbody + tbody { border-top: 2px solid #dee2e6; } .table-sm th, .table-sm td { padding: 0.3rem; } .table-bordered { border: 1px solid #dee2e6; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6; } .table-bordered thead th, .table-bordered thead td { border-bottom-width: 2px; } .table-borderless th, .table-borderless td, .table-borderless thead th, .table-borderless tbody + tbody { border: 0; } .table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0, 0, 0, 0.05); } .table-hover tbody tr:hover { color: #212529; background-color: rgba(0, 0, 0, 0.075); } .table-primary, .table-primary > th, .table-primary > td { background-color: #b8daff; } .table-primary th, .table-primary td, .table-primary thead th, .table-primary tbody + tbody { border-color: #7abaff; } .table-hover .table-primary:hover { background-color: #9fcdff; } .table-hover .table-primary:hover > td, .table-hover .table-primary:hover > th { background-color: #9fcdff; } .table-secondary, .table-secondary > th, .table-secondary > td { background-color: #d6d8db; } .table-secondary th, .table-secondary td, .table-secondary thead th, .table-secondary tbody + tbody { border-color: #b3b7bb; } .table-hover .table-secondary:hover { background-color: #c8cbcf; } .table-hover .table-secondary:hover > td, .table-hover .table-secondary:hover > th { background-color: #c8cbcf; } .table-success, .table-success > th, .table-success > td { background-color: #c3e6cb; } .table-success th, .table-success td, .table-success thead th, .table-success tbody + tbody { border-color: #8fd19e; } .table-hover .table-success:hover { background-color: #b1dfbb; } .table-hover .table-success:hover > td, .table-hover .table-success:hover > th { background-color: #b1dfbb; } .table-info, .table-info > th, .table-info > td { background-color: #bee5eb; } .table-info th, .table-info td, .table-info thead th, .table-info tbody + tbody { border-color: #86cfda; } .table-hover .table-info:hover { background-color: #abdde5; } .table-hover .table-info:hover > td, .table-hover .table-info:hover > th { background-color: #abdde5; } .table-warning, .table-warning > th, .table-warning > td { background-color: #ffeeba; } .table-warning th, .table-warning td, .table-warning thead th, .table-warning tbody + tbody { border-color: #ffdf7e; } .table-hover .table-warning:hover { background-color: #ffe8a1; } .table-hover .table-warning:hover > td, .table-hover .table-warning:hover > th { background-color: #ffe8a1; } .table-danger, .table-danger > th, .table-danger > td { background-color: #f5c6cb; } .table-danger th, .table-danger td, .table-danger thead th, .table-danger tbody + tbody { border-color: #ed969e; } .table-hover .table-danger:hover { background-color: #f1b0b7; } .table-hover .table-danger:hover > td, .table-hover .table-danger:hover > th { background-color: #f1b0b7; } .table-light, .table-light > th, .table-light > td { background-color: #fdfdfe; } .table-light th, .table-light td, .table-light thead th, .table-light tbody + tbody { border-color: #fbfcfc; } .table-hover .table-light:hover { background-color: #ececf6; } .table-hover .table-light:hover > td, .table-hover .table-light:hover > th { background-color: #ececf6; } .table-dark, .table-dark > th, .table-dark > td { background-color: #c6c8ca; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #95999c; } .table-hover .table-dark:hover { background-color: #b9bbbe; } .table-hover .table-dark:hover > td, .table-hover .table-dark:hover > th { background-color: #b9bbbe; } .table-active, .table-active > th, .table-active > td { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover > td, .table-hover .table-active:hover > th { background-color: rgba(0, 0, 0, 0.075); } .table .thead-dark th { color: #fff; background-color: #212529; border-color: #383f45; } .table .thead-light th { color: #495057; background-color: #e9ecef; border-color: #dee2e6; } .table-dark { color: #fff; background-color: #212529; } .table-dark th, .table-dark td, .table-dark thead th { border-color: #383f45; } .table-dark.table-bordered { border: 0; } .table-dark.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.05); } .table-dark.table-hover tbody tr:hover { color: #fff; background-color: rgba(255, 255, 255, 0.075); } @media (max-width: 575.98px) { .table-responsive-sm { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-sm > .table-bordered { border: 0; } } @media (max-width: 767.98px) { .table-responsive-md { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-md > .table-bordered { border: 0; } } @media (max-width: 991.98px) { .table-responsive-lg { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-lg > .table-bordered { border: 0; } } @media (max-width: 1199.98px) { .table-responsive-xl { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-xl > .table-bordered { border: 0; } } .table-responsive { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive > .table-bordered { border: 0; } .form-control { display: block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control:focus { color: #495057; background-color: #fff; border-color: #80bdff; outline: 0; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); } .form-control::-webkit-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-moz-placeholder { color: #939ba2; opacity: 1; } .form-control:-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::placeholder { color: #939ba2; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control { -webkit-appearance: none; -moz-appearance: none; appearance: none; } select.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } select.form-control:focus::-ms-value { color: #495057; background-color: #fff; } .form-control-file, .form-control-range { display: block; width: 100%; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; line-height: 1.5; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; line-height: 1.5; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; font-size: 1rem; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } .form-control-sm { height: calc(1.8125rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .form-control-lg { height: calc(2.875rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } select.form-control[size], select.form-control[multiple] { height: auto; } textarea.form-control { height: auto; } .form-group { margin-bottom: 1rem; } .form-text { display: block; margin-top: 0.25rem; } .form-row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; } .form-row > .col, .form-row > [class*="col-"] { padding-right: 5px; padding-left: 5px; } .form-check { position: relative; display: block; padding-left: 1.25rem; } .form-check-input { position: absolute; margin-top: 0.3rem; margin-left: -1.25rem; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { color: #6c757d; } .form-check-label { margin-bottom: 0; } .form-check-inline { display: -ms-inline-flexbox; display: inline-flex; -ms-flex-align: center; align-items: center; padding-left: 0; margin-right: 0.75rem; } .form-check-inline .form-check-input { position: static; margin-top: 0; margin-right: 0.3125rem; margin-left: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #28a745; } .valid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(40, 167, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .valid-tooltip, .form-row > [class*="col-"] > .valid-tooltip { left: 5px; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #28a745; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated select.form-control:valid, select.form-control.is-valid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:valid, .custom-select.is-valid { border-color: #28a745; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #28a745; } .was-validated .form-check-input:valid ~ .valid-feedback, .was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, .form-check-input.is-valid ~ .valid-tooltip { display: block; } .was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { border-color: #34ce57; background-color: #34ce57; } .was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { border-color: #28a745; } .was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .invalid-tooltip, .form-row > [class*="col-"] > .invalid-tooltip { left: 5px; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated select.form-control:invalid, select.form-control.is-invalid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:invalid, .custom-select.is-invalid { border-color: #dc3545; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .was-validated .form-check-input:invalid ~ .invalid-feedback, .was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, .form-check-input.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { border-color: #e4606d; background-color: #e4606d; } .was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { border-color: #dc3545; } .was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .form-inline { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; } .form-inline .form-check { width: 100%; } @media (min-width: 576px) { .form-inline label { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; margin-bottom: 0; } .form-inline .form-group { display: -ms-flexbox; display: flex; -ms-flex: 0 0 auto; flex: 0 0 auto; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; margin-bottom: 0; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-plaintext { display: inline-block; } .form-inline .input-group, .form-inline .custom-select { width: auto; } .form-inline .form-check { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: auto; padding-left: 0; } .form-inline .form-check-input { position: relative; -ms-flex-negative: 0; flex-shrink: 0; margin-top: 0; margin-right: 0.25rem; margin-left: 0; } .form-inline .custom-control { -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; } .form-inline .custom-control-label { margin-bottom: 0; } } .btn { display: inline-block; font-weight: 400; color: #212529; text-align: center; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: #212529; text-decoration: none; } .btn:focus, .btn.focus { outline: 0; box-shadow: none; } .btn.disabled, .btn:disabled { opacity: 0.65; box-shadow: none; } .btn:not(:disabled):not(.disabled) { cursor: pointer; } .btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { box-shadow: none; } a.btn.disabled, fieldset:disabled a.btn { pointer-events: none; } .btn-primary { color: #fff; background-color: #007bff; border-color: #007bff; box-shadow: none; } .btn-primary:hover { color: #fff; background-color: #0069d9; border-color: #0062cc; } .btn-primary:focus, .btn-primary.focus { color: #fff; background-color: #0069d9; border-color: #0062cc; box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0062cc; border-color: #005cbf; } .btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; box-shadow: none; } .btn-secondary:hover { color: #fff; background-color: #5a6268; border-color: #545b62; } .btn-secondary:focus, .btn-secondary.focus { color: #fff; background-color: #5a6268; border-color: #545b62; box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #545b62; border-color: #4e555b; } .btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-success { color: #fff; background-color: #28a745; border-color: #28a745; box-shadow: none; } .btn-success:hover { color: #fff; background-color: #218838; border-color: #1e7e34; } .btn-success:focus, .btn-success.focus { color: #fff; background-color: #218838; border-color: #1e7e34; box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-success.disabled, .btn-success:disabled { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #1e7e34; border-color: #1c7430; } .btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-info { color: #fff; background-color: #17a2b8; border-color: #17a2b8; box-shadow: none; } .btn-info:hover { color: #fff; background-color: #138496; border-color: #117a8b; } .btn-info:focus, .btn-info.focus { color: #fff; background-color: #138496; border-color: #117a8b; box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-info.disabled, .btn-info:disabled { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, .show > .btn-info.dropdown-toggle { color: #fff; background-color: #117a8b; border-color: #10707f; } .btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-warning { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; box-shadow: none; } .btn-warning:hover { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; } .btn-warning:focus, .btn-warning.focus { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-warning.disabled, .btn-warning:disabled { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, .show > .btn-warning.dropdown-toggle { color: #1f2d3d; background-color: #d39e00; border-color: #c69500; } .btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; box-shadow: none; } .btn-danger:hover { color: #fff; background-color: #c82333; border-color: #bd2130; } .btn-danger:focus, .btn-danger.focus { color: #fff; background-color: #c82333; border-color: #bd2130; box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-danger.disabled, .btn-danger:disabled { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #bd2130; border-color: #b21f2d; } .btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: none; } .btn-light:hover { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; } .btn-light:focus, .btn-light.focus { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-light.disabled, .btn-light:disabled { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, .show > .btn-light.dropdown-toggle { color: #1f2d3d; background-color: #dae0e5; border-color: #d3d9df; } .btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-dark { color: #fff; background-color: #343a40; border-color: #343a40; box-shadow: none; } .btn-dark:hover { color: #fff; background-color: #23272b; border-color: #1d2124; } .btn-dark:focus, .btn-dark.focus { color: #fff; background-color: #23272b; border-color: #1d2124; box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-dark.disabled, .btn-dark:disabled { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1d2124; border-color: #171a1d; } .btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-outline-primary { color: #007bff; border-color: #007bff; } .btn-outline-primary:hover { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:focus, .btn-outline-primary.focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-primary.disabled, .btn-outline-primary:disabled { color: #007bff; background-color: transparent; } .btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:focus, .btn-outline-secondary.focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-secondary.disabled, .btn-outline-secondary:disabled { color: #6c757d; background-color: transparent; } .btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-success { color: #28a745; border-color: #28a745; } .btn-outline-success:hover { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:focus, .btn-outline-success.focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-success.disabled, .btn-outline-success:disabled { color: #28a745; background-color: transparent; } .btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-info { color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:hover { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:focus, .btn-outline-info.focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-info.disabled, .btn-outline-info:disabled { color: #17a2b8; background-color: transparent; } .btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-warning { color: #ffc107; border-color: #ffc107; } .btn-outline-warning:hover { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:focus, .btn-outline-warning.focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-warning.disabled, .btn-outline-warning:disabled { color: #ffc107; background-color: transparent; } .btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-danger { color: #dc3545; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:focus, .btn-outline-danger.focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-danger.disabled, .btn-outline-danger:disabled { color: #dc3545; background-color: transparent; } .btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:hover { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:focus, .btn-outline-light.focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-dark { color: #343a40; border-color: #343a40; } .btn-outline-dark:hover { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:focus, .btn-outline-dark.focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-outline-dark.disabled, .btn-outline-dark:disabled { color: #343a40; background-color: transparent; } .btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-link { font-weight: 400; color: #007bff; text-decoration: none; } .btn-link:hover { color: #0056b3; text-decoration: none; } .btn-link:focus, .btn-link.focus { text-decoration: none; } .btn-link:disabled, .btn-link.disabled { color: #6c757d; pointer-events: none; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 0.5rem; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .dropup, .dropright, .dropdown, .dropleft { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 10rem; padding: 0.5rem 0; margin: 0.125rem 0 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.175); } .dropdown-menu-left { right: auto; left: 0; } .dropdown-menu-right { right: 0; left: auto; } @media (min-width: 576px) { .dropdown-menu-sm-left { right: auto; left: 0; } .dropdown-menu-sm-right { right: 0; left: auto; } } @media (min-width: 768px) { .dropdown-menu-md-left { right: auto; left: 0; } .dropdown-menu-md-right { right: 0; left: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-left { right: auto; left: 0; } .dropdown-menu-lg-right { right: 0; left: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-left { right: auto; left: 0; } .dropdown-menu-xl-right { right: 0; left: auto; } } .dropup .dropdown-menu { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-menu { top: 0; right: auto; left: 100%; margin-top: 0; margin-left: 0.125rem; } .dropright .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropright .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-toggle::after { vertical-align: 0; } .dropleft .dropdown-menu { top: 0; right: 100%; left: auto; margin-top: 0; margin-right: 0.125rem; } .dropleft .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropleft .dropdown-toggle::after { display: none; } .dropleft .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropleft .dropdown-toggle:empty::after { margin-left: 0; } .dropleft .dropdown-toggle::before { vertical-align: 0; } .dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { right: auto; bottom: auto; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid #e9ecef; } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: #16181b; text-decoration: none; background-color: #f8f9fa; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #007bff; } .dropdown-item.disabled, .dropdown-item:disabled { color: #6c757d; pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1rem; margin-bottom: 0; font-size: 0.875rem; color: #6c757d; white-space: nowrap; } .dropdown-item-text { display: block; padding: 0.25rem 1rem; color: #212529; } .btn-group, .btn-group-vertical { position: relative; display: -ms-inline-flexbox; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover { z-index: 1; } .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-pack: start; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) { margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropright .dropdown-toggle-split::after { margin-left: 0; } .dropleft .dropdown-toggle-split::before { margin-right: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group.show .dropdown-toggle { box-shadow: none; } .btn-group.show .dropdown-toggle.btn-link { box-shadow: none; } .btn-group-vertical { -ms-flex-direction: column; flex-direction: column; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: center; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-toggle > .btn, .btn-group-toggle > .btn-group > .btn { margin-bottom: 0; } .btn-group-toggle > .btn input[type="radio"], .btn-group-toggle > .btn input[type="checkbox"], .btn-group-toggle > .btn-group > .btn input[type="radio"], .btn-group-toggle > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: stretch; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-control-plaintext, .input-group > .custom-select, .input-group > .custom-file { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; width: 1%; min-width: 0; margin-bottom: 0; } .input-group > .form-control + .form-control, .input-group > .form-control + .custom-select, .input-group > .form-control + .custom-file, .input-group > .form-control-plaintext + .form-control, .input-group > .form-control-plaintext + .custom-select, .input-group > .form-control-plaintext + .custom-file, .input-group > .custom-select + .form-control, .input-group > .custom-select + .custom-select, .input-group > .custom-select + .custom-file, .input-group > .custom-file + .form-control, .input-group > .custom-file + .custom-select, .input-group > .custom-file + .custom-file { margin-left: -1px; } .input-group > .form-control:focus, .input-group > .custom-select:focus, .input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { z-index: 3; } .input-group > .custom-file .custom-file-input:focus { z-index: 4; } .input-group > .form-control:not(:first-child), .input-group > .custom-select:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group > .custom-file { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; } .input-group > .custom-file:not(:last-child) .custom-file-label, .input-group > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .custom-file:not(:first-child) .custom-file-label { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group:not(.has-validation) > .form-control:not(:last-child), .input-group:not(.has-validation) > .custom-select:not(:last-child), .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label, .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group.has-validation > .form-control:nth-last-child(n + 3), .input-group.has-validation > .custom-select:nth-last-child(n + 3), .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label, .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-prepend, .input-group-append { display: -ms-flexbox; display: flex; } .input-group-prepend .btn, .input-group-append .btn { position: relative; z-index: 2; } .input-group-prepend .btn:focus, .input-group-append .btn:focus { z-index: 3; } .input-group-prepend .btn + .btn, .input-group-prepend .btn + .input-group-text, .input-group-prepend .input-group-text + .input-group-text, .input-group-prepend .input-group-text + .btn, .input-group-append .btn + .btn, .input-group-append .btn + .input-group-text, .input-group-append .input-group-text + .input-group-text, .input-group-append .input-group-text + .btn { margin-left: -1px; } .input-group-prepend { margin-right: -1px; } .input-group-append { margin-left: -1px; } .input-group-text { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.375rem 0.75rem; margin-bottom: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-text input[type="radio"], .input-group-text input[type="checkbox"] { margin-top: 0; } .input-group-lg > .form-control:not(textarea), .input-group-lg > .custom-select { height: calc(2.875rem + 2px); } .input-group-lg > .form-control, .input-group-lg > .custom-select, .input-group-lg > .input-group-prepend > .input-group-text, .input-group-lg > .input-group-append > .input-group-text, .input-group-lg > .input-group-prepend > .btn, .input-group-lg > .input-group-append > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .input-group-sm > .form-control:not(textarea), .input-group-sm > .custom-select { height: calc(1.8125rem + 2px); } .input-group-sm > .form-control, .input-group-sm > .custom-select, .input-group-sm > .input-group-prepend > .input-group-text, .input-group-sm > .input-group-append > .input-group-text, .input-group-sm > .input-group-prepend > .btn, .input-group-sm > .input-group-append > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .input-group-lg > .custom-select, .input-group-sm > .custom-select { padding-right: 1.75rem; } .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .btn, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .input-group-text, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .btn, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .input-group-text, .input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .input-group-append > .btn, .input-group > .input-group-append > .input-group-text, .input-group > .input-group-prepend:not(:first-child) > .btn, .input-group > .input-group-prepend:not(:first-child) > .input-group-text, .input-group > .input-group-prepend:first-child > .btn:not(:first-child), .input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .custom-control { position: relative; z-index: 1; display: block; min-height: 1.5rem; padding-left: 1.5rem; -webkit-print-color-adjust: exact; color-adjust: exact; } .custom-control-inline { display: -ms-inline-flexbox; display: inline-flex; margin-right: 1rem; } .custom-control-input { position: absolute; left: 0; z-index: -1; width: 1rem; height: 1.25rem; opacity: 0; } .custom-control-input:checked ~ .custom-control-label::before { color: #fff; border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-control-input:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input:not(:disabled):active ~ .custom-control-label::before { color: #fff; background-color: #b3d7ff; border-color: #b3d7ff; box-shadow: none; } .custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label { color: #6c757d; } .custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before { background-color: #e9ecef; } .custom-control-label { position: relative; margin-bottom: 0; vertical-align: top; } .custom-control-label::before { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; pointer-events: none; content: ""; background-color: #dee2e6; border: #adb5bd solid 1px; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-control-label::after { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; content: ""; background: 50% / 50% 50% no-repeat; } .custom-checkbox .custom-control-label::before { border-radius: 0.25rem; } .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-radio .custom-control-label::before { border-radius: 50%; } .custom-radio .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } .custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-switch { padding-left: 2.25rem; } .custom-switch .custom-control-label::before { left: -2.25rem; width: 1.75rem; pointer-events: all; border-radius: 0.5rem; } .custom-switch .custom-control-label::after { top: calc(0.25rem + 2px); left: calc(-2.25rem + 2px); width: calc(1rem - 4px); height: calc(1rem - 4px); background-color: #adb5bd; border-radius: 0.5rem; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-switch .custom-control-label::after { transition: none; } } .custom-switch .custom-control-input:checked ~ .custom-control-label::after { background-color: #dee2e6; -webkit-transform: translateX(0.75rem); transform: translateX(0.75rem); } .custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-select { display: inline-block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; vertical-align: middle; background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-select:focus { border-color: #80bdff; outline: 0; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); } .custom-select:focus::-ms-value { color: #495057; background-color: #fff; } .custom-select[multiple], .custom-select[size]:not([size="1"]) { height: auto; padding-right: 0.75rem; background-image: none; } .custom-select:disabled { color: #6c757d; background-color: #e9ecef; } .custom-select::-ms-expand { display: none; } .custom-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } .custom-select-sm { height: calc(1.8125rem + 2px); padding-top: 0.25rem; padding-bottom: 0.25rem; padding-left: 0.5rem; font-size: 75%; } .custom-select-lg { height: calc(2.875rem + 2px); padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 1rem; font-size: 125%; } .custom-file { position: relative; display: inline-block; width: 100%; height: calc(2.25rem + 2px); margin-bottom: 0; } .custom-file-input { position: relative; z-index: 2; width: 100%; height: calc(2.25rem + 2px); margin: 0; overflow: hidden; opacity: 0; } .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; box-shadow: none; } .custom-file-input[disabled] ~ .custom-file-label, .custom-file-input:disabled ~ .custom-file-label { background-color: #e9ecef; } .custom-file-input:lang(en) ~ .custom-file-label::after { content: "Browse"; } .custom-file-input ~ .custom-file-label[data-browse]::after { content: attr(data-browse); } .custom-file-label { position: absolute; top: 0; right: 0; left: 0; z-index: 1; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; overflow: hidden; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: none; } .custom-file-label::after { position: absolute; top: 0; right: 0; bottom: 0; z-index: 3; display: block; height: 2.25rem; padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; content: "Browse"; background-color: #e9ecef; border-left: inherit; border-radius: 0 0.25rem 0.25rem 0; } .custom-range { width: 100%; height: 1rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-range:focus { outline: 0; } .custom-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range::-moz-focus-outer { border: 0; } .custom-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .custom-range::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .custom-range::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-thumb { width: 1rem; height: 1rem; margin-top: 0; margin-right: 0; margin-left: 0; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-ms-thumb { -ms-transition: none; transition: none; } } .custom-range::-ms-thumb:active { background-color: #b3d7ff; } .custom-range::-ms-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: transparent; border-color: transparent; border-width: 0.5rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-fill-lower { background-color: #dee2e6; border-radius: 1rem; } .custom-range::-ms-fill-upper { margin-right: 15px; background-color: #dee2e6; border-radius: 1rem; } .custom-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .custom-range:disabled::-webkit-slider-runnable-track { cursor: default; } .custom-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .custom-range:disabled::-moz-range-track { cursor: default; } .custom-range:disabled::-ms-thumb { background-color: #adb5bd; } .custom-control-label::before, .custom-file-label, .custom-select { transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-control-label::before, .custom-file-label, .custom-select { transition: none; } } .nav { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; } .nav-link:hover, .nav-link:focus { text-decoration: none; } .nav-link.disabled { color: #6c757d; pointer-events: none; cursor: default; } .nav-tabs { border-bottom: 1px solid #dee2e6; } .nav-tabs .nav-link { margin-bottom: -1px; border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { border-color: #e9ecef #e9ecef #dee2e6; } .nav-tabs .nav-link.disabled { color: #6c757d; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #dee2e6 #dee2e6 #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #007bff; } .nav-fill > .nav-link, .nav-fill .nav-item { -ms-flex: 1 1 auto; flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; text-align: center; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; padding: 0.5rem 0.5rem; } .navbar .container, .navbar .container-fluid, .navbar .container-sm, .navbar .container-md, .navbar .container-lg, .navbar .container-xl { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; } .navbar-brand { display: inline-block; padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 0.5rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-nav { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-text { display: inline-block; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { -ms-flex-preferred-size: 100%; flex-basis: 100%; -ms-flex-positive: 1; flex-grow: 1; -ms-flex-align: center; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .navbar-toggler:hover, .navbar-toggler:focus { text-decoration: none; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; content: ""; background: 50% / 100% 100% no-repeat; } .navbar-nav-scroll { max-height: 75vh; overflow-y: auto; } @media (max-width: 575.98px) { .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 576px) { .navbar-expand-sm { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } } @media (max-width: 767.98px) { .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 768px) { .navbar-expand-md { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-md .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } } @media (max-width: 991.98px) { .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 992px) { .navbar-expand-lg { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } } @media (max-width: 1199.98px) { .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 1200px) { .navbar-expand-xl { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } } .navbar-expand { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { padding-right: 0; padding-left: 0; } .navbar-expand .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.5); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-text a { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { color: white; } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.75); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-text a { color: #fff; } .navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { color: #fff; } .card { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 0 solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { -ms-flex: 1 1 auto; flex: 1 1 auto; min-height: 1px; padding: 1.25rem; } .card-title { margin-bottom: 0.75rem; } .card-subtitle { margin-top: -0.375rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1.25rem; } .card-header { padding: 0.75rem 1.25rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 0 solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 0) calc(0.25rem - 0) 0 0; } .card-footer { padding: 0.75rem 1.25rem; background-color: rgba(0, 0, 0, 0.03); border-top: 0 solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 0) calc(0.25rem - 0); } .card-header-tabs { margin-right: -0.625rem; margin-bottom: -0.75rem; margin-left: -0.625rem; border-bottom: 0; } .card-header-pills { margin-right: -0.625rem; margin-left: -0.625rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1.25rem; border-radius: calc(0.25rem - 0); } .card-img, .card-img-top, .card-img-bottom { -ms-flex-negative: 0; flex-shrink: 0; width: 100%; } .card-img, .card-img-top { border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card-img, .card-img-bottom { border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card-deck .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-deck { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; margin-right: -7.5px; margin-left: -7.5px; } .card-deck .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-right: 7.5px; margin-bottom: 0; margin-left: 7.5px; } } .card-group > .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-group { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; } .card-group > .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } } .card-columns .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-columns { -webkit-column-count: 3; -moz-column-count: 3; column-count: 3; -webkit-column-gap: 1.25rem; -moz-column-gap: 1.25rem; column-gap: 1.25rem; orphans: 1; widows: 1; } .card-columns .card { display: inline-block; width: 100%; } } .accordion { overflow-anchor: none; } .accordion > .card { overflow: hidden; } .accordion > .card:not(:last-of-type) { border-bottom: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .accordion > .card:not(:first-of-type) { border-top-left-radius: 0; border-top-right-radius: 0; } .accordion > .card > .card-header { border-radius: 0; margin-bottom: 0; } .breadcrumb { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0.75rem 1rem; margin-bottom: 1rem; list-style: none; background-color: #e9ecef; border-radius: 0.25rem; } .breadcrumb-item + .breadcrumb-item { padding-left: 0.5rem; } .breadcrumb-item + .breadcrumb-item::before { float: left; padding-right: 0.5rem; color: #6c757d; content: "/"; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: underline; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: none; } .breadcrumb-item.active { color: #6c757d; } .pagination { display: -ms-flexbox; display: flex; padding-left: 0; list-style: none; border-radius: 0.25rem; } .page-link { position: relative; display: block; padding: 0.5rem 0.75rem; margin-left: -1px; line-height: 1.25; color: #007bff; background-color: #fff; border: 1px solid #dee2e6; } .page-link:hover { z-index: 2; color: #0056b3; text-decoration: none; background-color: #e9ecef; border-color: #dee2e6; } .page-link:focus { z-index: 3; outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .page-item.active .page-link { z-index: 3; color: #fff; background-color: #007bff; border-color: #007bff; } .page-item.disabled .page-link { color: #6c757d; pointer-events: none; cursor: auto; background-color: #fff; border-color: #dee2e6; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; line-height: 1.5; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .badge { transition: none; } } a.badge:hover, a.badge:focus { text-decoration: none; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .badge-pill { padding-right: 0.6em; padding-left: 0.6em; border-radius: 10rem; } .badge-primary { color: #fff; background-color: #007bff; } a.badge-primary:hover, a.badge-primary:focus { color: #fff; background-color: #0062cc; } a.badge-primary:focus, a.badge-primary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .badge-secondary { color: #fff; background-color: #6c757d; } a.badge-secondary:hover, a.badge-secondary:focus { color: #fff; background-color: #545b62; } a.badge-secondary:focus, a.badge-secondary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); } .badge-success { color: #fff; background-color: #28a745; } a.badge-success:hover, a.badge-success:focus { color: #fff; background-color: #1e7e34; } a.badge-success:focus, a.badge-success.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .badge-info { color: #fff; background-color: #17a2b8; } a.badge-info:hover, a.badge-info:focus { color: #fff; background-color: #117a8b; } a.badge-info:focus, a.badge-info.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .badge-warning { color: #1f2d3d; background-color: #ffc107; } a.badge-warning:hover, a.badge-warning:focus { color: #1f2d3d; background-color: #d39e00; } a.badge-warning:focus, a.badge-warning.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .badge-danger { color: #fff; background-color: #dc3545; } a.badge-danger:hover, a.badge-danger:focus { color: #fff; background-color: #bd2130; } a.badge-danger:focus, a.badge-danger.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .badge-light { color: #1f2d3d; background-color: #f8f9fa; } a.badge-light:hover, a.badge-light:focus { color: #1f2d3d; background-color: #dae0e5; } a.badge-light:focus, a.badge-light.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .badge-dark { color: #fff; background-color: #343a40; } a.badge-dark:hover, a.badge-dark:focus { color: #fff; background-color: #1d2124; } a.badge-dark:focus, a.badge-dark.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; background-color: #e9ecef; border-radius: 0.3rem; } @media (min-width: 576px) { .jumbotron { padding: 4rem 2rem; } } .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; } .alert { position: relative; padding: 0.75rem 1.25rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 4rem; } .alert-dismissible .close, .alert-dismissible .mailbox-attachment-close { position: absolute; top: 0; right: 0; z-index: 2; padding: 0.75rem 1.25rem; color: inherit; } .alert-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-primary hr { border-top-color: #9fcdff; } .alert-primary .alert-link { color: #002752; } .alert-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-secondary hr { border-top-color: #c8cbcf; } .alert-secondary .alert-link { color: #202326; } .alert-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-success hr { border-top-color: #b1dfbb; } .alert-success .alert-link { color: #0b2e13; } .alert-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-info hr { border-top-color: #abdde5; } .alert-info .alert-link { color: #062c33; } .alert-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-warning hr { border-top-color: #ffe8a1; } .alert-warning .alert-link { color: #533f03; } .alert-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-danger hr { border-top-color: #f1b0b7; } .alert-danger .alert-link { color: #491217; } .alert-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-light hr { border-top-color: #ececf6; } .alert-light .alert-link { color: #686868; } .alert-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-dark hr { border-top-color: #b9bbbe; } .alert-dark .alert-link { color: #040505; } @-webkit-keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } .progress { display: -ms-flexbox; display: flex; height: 1rem; overflow: hidden; line-height: 0; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; box-shadow: inset 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1); } .progress-bar { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; overflow: hidden; color: #fff; text-align: center; white-space: nowrap; background-color: #007bff; transition: width 0.6s ease; } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: 1s linear infinite progress-bar-stripes; animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { -webkit-animation: none; animation: none; } } .media { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; } .media-body { -ms-flex: 1; flex: 1; } .list-group { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; border-radius: 0.25rem; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.75rem 1.25rem; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } .list-group-item:last-child { border-bottom-right-radius: inherit; border-bottom-left-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: #6c757d; pointer-events: none; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: -1px; border-top-width: 1px; } .list-group-horizontal { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } @media (min-width: 576px) { .list-group-horizontal-sm { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 768px) { .list-group-horizontal-md { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 992px) { .list-group-horizontal-lg { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 1200px) { .list-group-horizontal-xl { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 1px; } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #004085; background-color: #b8daff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #004085; background-color: #9fcdff; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #004085; border-color: #004085; } .list-group-item-secondary { color: #383d41; background-color: #d6d8db; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #383d41; background-color: #c8cbcf; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #383d41; border-color: #383d41; } .list-group-item-success { color: #155724; background-color: #c3e6cb; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #155724; background-color: #b1dfbb; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #155724; border-color: #155724; } .list-group-item-info { color: #0c5460; background-color: #bee5eb; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #0c5460; background-color: #abdde5; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #0c5460; border-color: #0c5460; } .list-group-item-warning { color: #856404; background-color: #ffeeba; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #856404; background-color: #ffe8a1; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #856404; border-color: #856404; } .list-group-item-danger { color: #721c24; background-color: #f5c6cb; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #721c24; background-color: #f1b0b7; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #721c24; border-color: #721c24; } .list-group-item-light { color: #818182; background-color: #fdfdfe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #818182; background-color: #ececf6; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #818182; border-color: #818182; } .list-group-item-dark { color: #1b1e21; background-color: #c6c8ca; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #1b1e21; background-color: #b9bbbe; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #1b1e21; border-color: #1b1e21; } .close, .mailbox-attachment-close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover, .mailbox-attachment-close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .mailbox-attachment-close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus, .mailbox-attachment-close:not(:disabled):not(.disabled):focus { opacity: .75; } button.close, button.mailbox-attachment-close { padding: 0; background-color: transparent; border: 0; } a.close.disabled, a.disabled.mailbox-attachment-close { pointer-events: none; } .toast { -ms-flex-preferred-size: 350px; flex-basis: 350px; max-width: 350px; font-size: 0.875rem; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); opacity: 0; border-radius: 0.25rem; } .toast:not(:last-child) { margin-bottom: 0.75rem; } .toast.showing { opacity: 1; } .toast.show { display: block; opacity: 1; } .toast.hide { display: none; } .toast-header { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.25rem 0.75rem; color: #6c757d; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .toast-body { padding: 0.75rem; } .modal-open { overflow: hidden; } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal { position: fixed; top: 0; left: 0; z-index: 1050; display: none; width: 100%; height: 100%; overflow: hidden; outline: 0; } .modal-dialog { position: relative; width: auto; margin: 0.5rem; pointer-events: none; } .modal.fade .modal-dialog { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; -webkit-transform: translate(0, -50px); transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { -webkit-transform: none; transform: none; } .modal.modal-static .modal-dialog { -webkit-transform: scale(1.02); transform: scale(1.02); } .modal-dialog-scrollable { display: -ms-flexbox; display: flex; max-height: calc(100% - 1rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 1rem); overflow: hidden; } .modal-dialog-scrollable .modal-header, .modal-dialog-scrollable .modal-footer { -ms-flex-negative: 0; flex-shrink: 0; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; min-height: calc(100% - 1rem); } .modal-dialog-centered::before { display: block; height: calc(100vh - 1rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; content: ""; } .modal-dialog-centered.modal-dialog-scrollable { -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; height: 100%; } .modal-dialog-centered.modal-dialog-scrollable .modal-content { max-height: none; } .modal-dialog-centered.modal-dialog-scrollable::before { content: none; } .modal-content { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; width: 100%; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.5); outline: 0; } .modal-backdrop { position: fixed; top: 0; left: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: justify; justify-content: space-between; padding: 1rem; border-bottom: 1px solid #e9ecef; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .modal-header .close, .modal-header .mailbox-attachment-close { padding: 1rem; margin: -1rem -1rem -1rem auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1rem; } .modal-footer { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: end; justify-content: flex-end; padding: 0.75rem; border-top: 1px solid #e9ecef; border-bottom-right-radius: calc(0.3rem - 1px); border-bottom-left-radius: calc(0.3rem - 1px); } .modal-footer > * { margin: 0.25rem; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 1.75rem auto; } .modal-dialog-scrollable { max-height: calc(100% - 3.5rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 3.5rem); } .modal-dialog-centered { min-height: calc(100% - 3.5rem); } .modal-dialog-centered::before { height: calc(100vh - 3.5rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; } .modal-content { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.5); } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { max-width: 800px; } } @media (min-width: 1200px) { .modal-xl { max-width: 1140px; } } .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .tooltip .arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { padding: 0.4rem 0; } .bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { bottom: 0; } .bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { top: 0; border-width: 0.4rem 0.4rem 0; border-top-color: #000; } .bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { padding: 0 0.4rem; } .bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { left: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { right: 0; border-width: 0.4rem 0.4rem 0.4rem 0; border-right-color: #000; } .bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { padding: 0.4rem 0; } .bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { top: 0; } .bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { bottom: 0; border-width: 0 0.4rem 0.4rem; border-bottom-color: #000; } .bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { padding: 0 0.4rem; } .bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { right: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { left: 0; border-width: 0.4rem 0 0.4rem 0.4rem; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: block; max-width: 276px; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.2); } .popover .arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; margin: 0 0.3rem; } .popover .arrow::before, .popover .arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; } .bs-popover-top, .bs-popover-auto[x-placement^="top"] { margin-bottom: 0.5rem; } .bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow { bottom: calc(-0.5rem - 1px); } .bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before { bottom: 0; border-width: 0.5rem 0.5rem 0; border-top-color: rgba(0, 0, 0, 0.25); } .bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^="top"] > .arrow::after { bottom: 1px; border-width: 0.5rem 0.5rem 0; border-top-color: #fff; } .bs-popover-right, .bs-popover-auto[x-placement^="right"] { margin-left: 0.5rem; } .bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow { left: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^="right"] > .arrow::before { left: 0; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: rgba(0, 0, 0, 0.25); } .bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^="right"] > .arrow::after { left: 1px; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: #fff; } .bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { margin-top: 0.5rem; } .bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow { top: calc(-0.5rem - 1px); } .bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before { top: 0; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: rgba(0, 0, 0, 0.25); } .bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^="bottom"] > .arrow::after { top: 1px; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: #fff; } .bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 1rem; margin-left: -0.5rem; content: ""; border-bottom: 1px solid #f7f7f7; } .bs-popover-left, .bs-popover-auto[x-placement^="left"] { margin-right: 0.5rem; } .bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow { right: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^="left"] > .arrow::before { right: 0; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: rgba(0, 0, 0, 0.25); } .bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^="left"] > .arrow::after { right: 1px; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: #fff; } .popover-header { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 0.5rem 0.75rem; color: #212529; } .carousel { position: relative; } .carousel.pointer-event { -ms-touch-action: pan-y; touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; width: 100%; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: -webkit-transform 0.6s ease; transition: transform 0.6s ease; transition: transform 0.6s ease, -webkit-transform 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-left), .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-right), .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; -webkit-transform: none; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-left, .carousel-fade .carousel-item-prev.carousel-item-right { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: 50% / 100% 100% no-repeat; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 15; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; } .carousel-indicators li { box-sizing: content-box; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: .5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators li { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; } @-webkit-keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } .spinner-border { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; border: 0.25em solid currentColor; border-right-color: transparent; border-radius: 50%; -webkit-animation: .75s linear infinite spinner-border; animation: .75s linear infinite spinner-border; } .spinner-border-sm { width: 1rem; height: 1rem; border-width: 0.2em; } @-webkit-keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } .spinner-grow { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; background-color: currentColor; border-radius: 50%; opacity: 0; -webkit-animation: .75s linear infinite spinner-grow; animation: .75s linear infinite spinner-grow; } .spinner-grow-sm { width: 1rem; height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { -webkit-animation-duration: 1.5s; animation-duration: 1.5s; } } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .bg-primary { background-color: #007bff !important; } a.bg-primary:hover, a.bg-primary:focus, button.bg-primary:hover, button.bg-primary:focus { background-color: #0062cc !important; } .bg-secondary { background-color: #6c757d !important; } a.bg-secondary:hover, a.bg-secondary:focus, button.bg-secondary:hover, button.bg-secondary:focus { background-color: #545b62 !important; } .bg-success { background-color: #28a745 !important; } a.bg-success:hover, a.bg-success:focus, button.bg-success:hover, button.bg-success:focus { background-color: #1e7e34 !important; } .bg-info { background-color: #17a2b8 !important; } a.bg-info:hover, a.bg-info:focus, button.bg-info:hover, button.bg-info:focus { background-color: #117a8b !important; } .bg-warning { background-color: #ffc107 !important; } a.bg-warning:hover, a.bg-warning:focus, button.bg-warning:hover, button.bg-warning:focus { background-color: #d39e00 !important; } .bg-danger { background-color: #dc3545 !important; } a.bg-danger:hover, a.bg-danger:focus, button.bg-danger:hover, button.bg-danger:focus { background-color: #bd2130 !important; } .bg-light { background-color: #f8f9fa !important; } a.bg-light:hover, a.bg-light:focus, button.bg-light:hover, button.bg-light:focus { background-color: #dae0e5 !important; } .bg-dark { background-color: #343a40 !important; } a.bg-dark:hover, a.bg-dark:focus, button.bg-dark:hover, button.bg-dark:focus { background-color: #1d2124 !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .border { border: 1px solid #dee2e6 !important; } .border-top { border-top: 1px solid #dee2e6 !important; } .border-right { border-right: 1px solid #dee2e6 !important; } .border-bottom { border-bottom: 1px solid #dee2e6 !important; } .border-left { border-left: 1px solid #dee2e6 !important; } .border-0 { border: 0 !important; } .border-top-0 { border-top: 0 !important; } .border-right-0 { border-right: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-left-0 { border-left: 0 !important; } .border-primary { border-color: #007bff !important; } .border-secondary { border-color: #6c757d !important; } .border-success { border-color: #28a745 !important; } .border-info { border-color: #17a2b8 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #343a40 !important; } .border-white { border-color: #fff !important; } .rounded-sm { border-radius: 0.2rem !important; } .rounded { border-radius: 0.25rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-right { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-left { border-top-left-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-lg { border-radius: 0.3rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: 50rem !important; } .rounded-0 { border-radius: 0 !important; } .clearfix::after { display: block; clear: both; content: ""; } .d-none { display: none !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: -ms-flexbox !important; display: flex !important; } .d-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } @media (min-width: 576px) { .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: -ms-flexbox !important; display: flex !important; } .d-sm-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 768px) { .d-md-none { display: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: -ms-flexbox !important; display: flex !important; } .d-md-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 992px) { .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: -ms-flexbox !important; display: flex !important; } .d-lg-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 1200px) { .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: -ms-flexbox !important; display: flex !important; } .d-xl-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media print { .d-print-none { display: none !important; } .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: -ms-flexbox !important; display: flex !important; } .d-print-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } .embed-responsive { position: relative; display: block; width: 100%; padding: 0; overflow: hidden; } .embed-responsive::before { display: block; content: ""; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-21by9::before { padding-top: 42.857143%; } .embed-responsive-16by9::before { padding-top: 56.25%; } .embed-responsive-4by3::before { padding-top: 75%; } .embed-responsive-1by1::before { padding-top: 100%; } .flex-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-sm-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-sm-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-sm-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-sm-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-sm-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-sm-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-md-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-md-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-md-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-md-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-md-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-md-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-lg-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-lg-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-lg-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-lg-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-lg-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-lg-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-xl-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-xl-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-xl-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-xl-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-xl-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-xl-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } .float-left { float: left !important; } .float-right { float: right !important; } .float-none { float: none !important; } @media (min-width: 576px) { .float-sm-left { float: left !important; } .float-sm-right { float: right !important; } .float-sm-none { float: none !important; } } @media (min-width: 768px) { .float-md-left { float: left !important; } .float-md-right { float: right !important; } .float-md-none { float: none !important; } } @media (min-width: 992px) { .float-lg-left { float: left !important; } .float-lg-right { float: right !important; } .float-lg-none { float: none !important; } } @media (min-width: 1200px) { .float-xl-left { float: left !important; } .float-xl-right { float: right !important; } .float-xl-none { float: none !important; } } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } @supports ((position: -webkit-sticky) or (position: sticky)) { .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } .min-vw-100 { min-width: 100vw !important; } .min-vh-100 { min-height: 100vh !important; } .vw-100 { width: 100vw !important; } .vh-100 { height: 100vh !important; } .m-0 { margin: 0 !important; } .mt-0, .my-0 { margin-top: 0 !important; } .mr-0, .mx-0 { margin-right: 0 !important; } .mb-0, .my-0 { margin-bottom: 0 !important; } .ml-0, .mx-0 { margin-left: 0 !important; } .m-1 { margin: 0.25rem !important; } .mt-1, .my-1 { margin-top: 0.25rem !important; } .mr-1, .mx-1 { margin-right: 0.25rem !important; } .mb-1, .my-1 { margin-bottom: 0.25rem !important; } .ml-1, .mx-1 { margin-left: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .mt-2, .my-2 { margin-top: 0.5rem !important; } .mr-2, .mx-2 { margin-right: 0.5rem !important; } .mb-2, .my-2 { margin-bottom: 0.5rem !important; } .ml-2, .mx-2 { margin-left: 0.5rem !important; } .m-3 { margin: 1rem !important; } .mt-3, .my-3 { margin-top: 1rem !important; } .mr-3, .mx-3 { margin-right: 1rem !important; } .mb-3, .my-3 { margin-bottom: 1rem !important; } .ml-3, .mx-3 { margin-left: 1rem !important; } .m-4 { margin: 1.5rem !important; } .mt-4, .my-4 { margin-top: 1.5rem !important; } .mr-4, .mx-4 { margin-right: 1.5rem !important; } .mb-4, .my-4 { margin-bottom: 1.5rem !important; } .ml-4, .mx-4 { margin-left: 1.5rem !important; } .m-5 { margin: 3rem !important; } .mt-5, .my-5 { margin-top: 3rem !important; } .mr-5, .mx-5 { margin-right: 3rem !important; } .mb-5, .my-5 { margin-bottom: 3rem !important; } .ml-5, .mx-5 { margin-left: 3rem !important; } .p-0 { padding: 0 !important; } .pt-0, .py-0 { padding-top: 0 !important; } .pr-0, .px-0 { padding-right: 0 !important; } .pb-0, .py-0 { padding-bottom: 0 !important; } .pl-0, .px-0 { padding-left: 0 !important; } .p-1 { padding: 0.25rem !important; } .pt-1, .py-1 { padding-top: 0.25rem !important; } .pr-1, .px-1 { padding-right: 0.25rem !important; } .pb-1, .py-1 { padding-bottom: 0.25rem !important; } .pl-1, .px-1 { padding-left: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .pt-2, .py-2 { padding-top: 0.5rem !important; } .pr-2, .px-2 { padding-right: 0.5rem !important; } .pb-2, .py-2 { padding-bottom: 0.5rem !important; } .pl-2, .px-2 { padding-left: 0.5rem !important; } .p-3 { padding: 1rem !important; } .pt-3, .py-3 { padding-top: 1rem !important; } .pr-3, .px-3 { padding-right: 1rem !important; } .pb-3, .py-3 { padding-bottom: 1rem !important; } .pl-3, .px-3 { padding-left: 1rem !important; } .p-4 { padding: 1.5rem !important; } .pt-4, .py-4 { padding-top: 1.5rem !important; } .pr-4, .px-4 { padding-right: 1.5rem !important; } .pb-4, .py-4 { padding-bottom: 1.5rem !important; } .pl-4, .px-4 { padding-left: 1.5rem !important; } .p-5 { padding: 3rem !important; } .pt-5, .py-5 { padding-top: 3rem !important; } .pr-5, .px-5 { padding-right: 3rem !important; } .pb-5, .py-5 { padding-bottom: 3rem !important; } .pl-5, .px-5 { padding-left: 3rem !important; } .m-n1 { margin: -0.25rem !important; } .mt-n1, .my-n1 { margin-top: -0.25rem !important; } .mr-n1, .mx-n1 { margin-right: -0.25rem !important; } .mb-n1, .my-n1 { margin-bottom: -0.25rem !important; } .ml-n1, .mx-n1 { margin-left: -0.25rem !important; } .m-n2 { margin: -0.5rem !important; } .mt-n2, .my-n2 { margin-top: -0.5rem !important; } .mr-n2, .mx-n2 { margin-right: -0.5rem !important; } .mb-n2, .my-n2 { margin-bottom: -0.5rem !important; } .ml-n2, .mx-n2 { margin-left: -0.5rem !important; } .m-n3 { margin: -1rem !important; } .mt-n3, .my-n3 { margin-top: -1rem !important; } .mr-n3, .mx-n3 { margin-right: -1rem !important; } .mb-n3, .my-n3 { margin-bottom: -1rem !important; } .ml-n3, .mx-n3 { margin-left: -1rem !important; } .m-n4 { margin: -1.5rem !important; } .mt-n4, .my-n4 { margin-top: -1.5rem !important; } .mr-n4, .mx-n4 { margin-right: -1.5rem !important; } .mb-n4, .my-n4 { margin-bottom: -1.5rem !important; } .ml-n4, .mx-n4 { margin-left: -1.5rem !important; } .m-n5 { margin: -3rem !important; } .mt-n5, .my-n5 { margin-top: -3rem !important; } .mr-n5, .mx-n5 { margin-right: -3rem !important; } .mb-n5, .my-n5 { margin-bottom: -3rem !important; } .ml-n5, .mx-n5 { margin-left: -3rem !important; } .m-auto { margin: auto !important; } .mt-auto, .my-auto { margin-top: auto !important; } .mr-auto, .mx-auto { margin-right: auto !important; } .mb-auto, .my-auto { margin-bottom: auto !important; } .ml-auto, .mx-auto { margin-left: auto !important; } @media (min-width: 576px) { .m-sm-0 { margin: 0 !important; } .mt-sm-0, .my-sm-0 { margin-top: 0 !important; } .mr-sm-0, .mx-sm-0 { margin-right: 0 !important; } .mb-sm-0, .my-sm-0 { margin-bottom: 0 !important; } .ml-sm-0, .mx-sm-0 { margin-left: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .mt-sm-1, .my-sm-1 { margin-top: 0.25rem !important; } .mr-sm-1, .mx-sm-1 { margin-right: 0.25rem !important; } .mb-sm-1, .my-sm-1 { margin-bottom: 0.25rem !important; } .ml-sm-1, .mx-sm-1 { margin-left: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .mt-sm-2, .my-sm-2 { margin-top: 0.5rem !important; } .mr-sm-2, .mx-sm-2 { margin-right: 0.5rem !important; } .mb-sm-2, .my-sm-2 { margin-bottom: 0.5rem !important; } .ml-sm-2, .mx-sm-2 { margin-left: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .mt-sm-3, .my-sm-3 { margin-top: 1rem !important; } .mr-sm-3, .mx-sm-3 { margin-right: 1rem !important; } .mb-sm-3, .my-sm-3 { margin-bottom: 1rem !important; } .ml-sm-3, .mx-sm-3 { margin-left: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .mt-sm-4, .my-sm-4 { margin-top: 1.5rem !important; } .mr-sm-4, .mx-sm-4 { margin-right: 1.5rem !important; } .mb-sm-4, .my-sm-4 { margin-bottom: 1.5rem !important; } .ml-sm-4, .mx-sm-4 { margin-left: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .mt-sm-5, .my-sm-5 { margin-top: 3rem !important; } .mr-sm-5, .mx-sm-5 { margin-right: 3rem !important; } .mb-sm-5, .my-sm-5 { margin-bottom: 3rem !important; } .ml-sm-5, .mx-sm-5 { margin-left: 3rem !important; } .p-sm-0 { padding: 0 !important; } .pt-sm-0, .py-sm-0 { padding-top: 0 !important; } .pr-sm-0, .px-sm-0 { padding-right: 0 !important; } .pb-sm-0, .py-sm-0 { padding-bottom: 0 !important; } .pl-sm-0, .px-sm-0 { padding-left: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .pt-sm-1, .py-sm-1 { padding-top: 0.25rem !important; } .pr-sm-1, .px-sm-1 { padding-right: 0.25rem !important; } .pb-sm-1, .py-sm-1 { padding-bottom: 0.25rem !important; } .pl-sm-1, .px-sm-1 { padding-left: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .pt-sm-2, .py-sm-2 { padding-top: 0.5rem !important; } .pr-sm-2, .px-sm-2 { padding-right: 0.5rem !important; } .pb-sm-2, .py-sm-2 { padding-bottom: 0.5rem !important; } .pl-sm-2, .px-sm-2 { padding-left: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .pt-sm-3, .py-sm-3 { padding-top: 1rem !important; } .pr-sm-3, .px-sm-3 { padding-right: 1rem !important; } .pb-sm-3, .py-sm-3 { padding-bottom: 1rem !important; } .pl-sm-3, .px-sm-3 { padding-left: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .pt-sm-4, .py-sm-4 { padding-top: 1.5rem !important; } .pr-sm-4, .px-sm-4 { padding-right: 1.5rem !important; } .pb-sm-4, .py-sm-4 { padding-bottom: 1.5rem !important; } .pl-sm-4, .px-sm-4 { padding-left: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .pt-sm-5, .py-sm-5 { padding-top: 3rem !important; } .pr-sm-5, .px-sm-5 { padding-right: 3rem !important; } .pb-sm-5, .py-sm-5 { padding-bottom: 3rem !important; } .pl-sm-5, .px-sm-5 { padding-left: 3rem !important; } .m-sm-n1 { margin: -0.25rem !important; } .mt-sm-n1, .my-sm-n1 { margin-top: -0.25rem !important; } .mr-sm-n1, .mx-sm-n1 { margin-right: -0.25rem !important; } .mb-sm-n1, .my-sm-n1 { margin-bottom: -0.25rem !important; } .ml-sm-n1, .mx-sm-n1 { margin-left: -0.25rem !important; } .m-sm-n2 { margin: -0.5rem !important; } .mt-sm-n2, .my-sm-n2 { margin-top: -0.5rem !important; } .mr-sm-n2, .mx-sm-n2 { margin-right: -0.5rem !important; } .mb-sm-n2, .my-sm-n2 { margin-bottom: -0.5rem !important; } .ml-sm-n2, .mx-sm-n2 { margin-left: -0.5rem !important; } .m-sm-n3 { margin: -1rem !important; } .mt-sm-n3, .my-sm-n3 { margin-top: -1rem !important; } .mr-sm-n3, .mx-sm-n3 { margin-right: -1rem !important; } .mb-sm-n3, .my-sm-n3 { margin-bottom: -1rem !important; } .ml-sm-n3, .mx-sm-n3 { margin-left: -1rem !important; } .m-sm-n4 { margin: -1.5rem !important; } .mt-sm-n4, .my-sm-n4 { margin-top: -1.5rem !important; } .mr-sm-n4, .mx-sm-n4 { margin-right: -1.5rem !important; } .mb-sm-n4, .my-sm-n4 { margin-bottom: -1.5rem !important; } .ml-sm-n4, .mx-sm-n4 { margin-left: -1.5rem !important; } .m-sm-n5 { margin: -3rem !important; } .mt-sm-n5, .my-sm-n5 { margin-top: -3rem !important; } .mr-sm-n5, .mx-sm-n5 { margin-right: -3rem !important; } .mb-sm-n5, .my-sm-n5 { margin-bottom: -3rem !important; } .ml-sm-n5, .mx-sm-n5 { margin-left: -3rem !important; } .m-sm-auto { margin: auto !important; } .mt-sm-auto, .my-sm-auto { margin-top: auto !important; } .mr-sm-auto, .mx-sm-auto { margin-right: auto !important; } .mb-sm-auto, .my-sm-auto { margin-bottom: auto !important; } .ml-sm-auto, .mx-sm-auto { margin-left: auto !important; } } @media (min-width: 768px) { .m-md-0 { margin: 0 !important; } .mt-md-0, .my-md-0 { margin-top: 0 !important; } .mr-md-0, .mx-md-0 { margin-right: 0 !important; } .mb-md-0, .my-md-0 { margin-bottom: 0 !important; } .ml-md-0, .mx-md-0 { margin-left: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .mt-md-1, .my-md-1 { margin-top: 0.25rem !important; } .mr-md-1, .mx-md-1 { margin-right: 0.25rem !important; } .mb-md-1, .my-md-1 { margin-bottom: 0.25rem !important; } .ml-md-1, .mx-md-1 { margin-left: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .mt-md-2, .my-md-2 { margin-top: 0.5rem !important; } .mr-md-2, .mx-md-2 { margin-right: 0.5rem !important; } .mb-md-2, .my-md-2 { margin-bottom: 0.5rem !important; } .ml-md-2, .mx-md-2 { margin-left: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .mt-md-3, .my-md-3 { margin-top: 1rem !important; } .mr-md-3, .mx-md-3 { margin-right: 1rem !important; } .mb-md-3, .my-md-3 { margin-bottom: 1rem !important; } .ml-md-3, .mx-md-3 { margin-left: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .mt-md-4, .my-md-4 { margin-top: 1.5rem !important; } .mr-md-4, .mx-md-4 { margin-right: 1.5rem !important; } .mb-md-4, .my-md-4 { margin-bottom: 1.5rem !important; } .ml-md-4, .mx-md-4 { margin-left: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .mt-md-5, .my-md-5 { margin-top: 3rem !important; } .mr-md-5, .mx-md-5 { margin-right: 3rem !important; } .mb-md-5, .my-md-5 { margin-bottom: 3rem !important; } .ml-md-5, .mx-md-5 { margin-left: 3rem !important; } .p-md-0 { padding: 0 !important; } .pt-md-0, .py-md-0 { padding-top: 0 !important; } .pr-md-0, .px-md-0 { padding-right: 0 !important; } .pb-md-0, .py-md-0 { padding-bottom: 0 !important; } .pl-md-0, .px-md-0 { padding-left: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .pt-md-1, .py-md-1 { padding-top: 0.25rem !important; } .pr-md-1, .px-md-1 { padding-right: 0.25rem !important; } .pb-md-1, .py-md-1 { padding-bottom: 0.25rem !important; } .pl-md-1, .px-md-1 { padding-left: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .pt-md-2, .py-md-2 { padding-top: 0.5rem !important; } .pr-md-2, .px-md-2 { padding-right: 0.5rem !important; } .pb-md-2, .py-md-2 { padding-bottom: 0.5rem !important; } .pl-md-2, .px-md-2 { padding-left: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .pt-md-3, .py-md-3 { padding-top: 1rem !important; } .pr-md-3, .px-md-3 { padding-right: 1rem !important; } .pb-md-3, .py-md-3 { padding-bottom: 1rem !important; } .pl-md-3, .px-md-3 { padding-left: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .pt-md-4, .py-md-4 { padding-top: 1.5rem !important; } .pr-md-4, .px-md-4 { padding-right: 1.5rem !important; } .pb-md-4, .py-md-4 { padding-bottom: 1.5rem !important; } .pl-md-4, .px-md-4 { padding-left: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .pt-md-5, .py-md-5 { padding-top: 3rem !important; } .pr-md-5, .px-md-5 { padding-right: 3rem !important; } .pb-md-5, .py-md-5 { padding-bottom: 3rem !important; } .pl-md-5, .px-md-5 { padding-left: 3rem !important; } .m-md-n1 { margin: -0.25rem !important; } .mt-md-n1, .my-md-n1 { margin-top: -0.25rem !important; } .mr-md-n1, .mx-md-n1 { margin-right: -0.25rem !important; } .mb-md-n1, .my-md-n1 { margin-bottom: -0.25rem !important; } .ml-md-n1, .mx-md-n1 { margin-left: -0.25rem !important; } .m-md-n2 { margin: -0.5rem !important; } .mt-md-n2, .my-md-n2 { margin-top: -0.5rem !important; } .mr-md-n2, .mx-md-n2 { margin-right: -0.5rem !important; } .mb-md-n2, .my-md-n2 { margin-bottom: -0.5rem !important; } .ml-md-n2, .mx-md-n2 { margin-left: -0.5rem !important; } .m-md-n3 { margin: -1rem !important; } .mt-md-n3, .my-md-n3 { margin-top: -1rem !important; } .mr-md-n3, .mx-md-n3 { margin-right: -1rem !important; } .mb-md-n3, .my-md-n3 { margin-bottom: -1rem !important; } .ml-md-n3, .mx-md-n3 { margin-left: -1rem !important; } .m-md-n4 { margin: -1.5rem !important; } .mt-md-n4, .my-md-n4 { margin-top: -1.5rem !important; } .mr-md-n4, .mx-md-n4 { margin-right: -1.5rem !important; } .mb-md-n4, .my-md-n4 { margin-bottom: -1.5rem !important; } .ml-md-n4, .mx-md-n4 { margin-left: -1.5rem !important; } .m-md-n5 { margin: -3rem !important; } .mt-md-n5, .my-md-n5 { margin-top: -3rem !important; } .mr-md-n5, .mx-md-n5 { margin-right: -3rem !important; } .mb-md-n5, .my-md-n5 { margin-bottom: -3rem !important; } .ml-md-n5, .mx-md-n5 { margin-left: -3rem !important; } .m-md-auto { margin: auto !important; } .mt-md-auto, .my-md-auto { margin-top: auto !important; } .mr-md-auto, .mx-md-auto { margin-right: auto !important; } .mb-md-auto, .my-md-auto { margin-bottom: auto !important; } .ml-md-auto, .mx-md-auto { margin-left: auto !important; } } @media (min-width: 992px) { .m-lg-0 { margin: 0 !important; } .mt-lg-0, .my-lg-0 { margin-top: 0 !important; } .mr-lg-0, .mx-lg-0 { margin-right: 0 !important; } .mb-lg-0, .my-lg-0 { margin-bottom: 0 !important; } .ml-lg-0, .mx-lg-0 { margin-left: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .mt-lg-1, .my-lg-1 { margin-top: 0.25rem !important; } .mr-lg-1, .mx-lg-1 { margin-right: 0.25rem !important; } .mb-lg-1, .my-lg-1 { margin-bottom: 0.25rem !important; } .ml-lg-1, .mx-lg-1 { margin-left: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .mt-lg-2, .my-lg-2 { margin-top: 0.5rem !important; } .mr-lg-2, .mx-lg-2 { margin-right: 0.5rem !important; } .mb-lg-2, .my-lg-2 { margin-bottom: 0.5rem !important; } .ml-lg-2, .mx-lg-2 { margin-left: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .mt-lg-3, .my-lg-3 { margin-top: 1rem !important; } .mr-lg-3, .mx-lg-3 { margin-right: 1rem !important; } .mb-lg-3, .my-lg-3 { margin-bottom: 1rem !important; } .ml-lg-3, .mx-lg-3 { margin-left: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .mt-lg-4, .my-lg-4 { margin-top: 1.5rem !important; } .mr-lg-4, .mx-lg-4 { margin-right: 1.5rem !important; } .mb-lg-4, .my-lg-4 { margin-bottom: 1.5rem !important; } .ml-lg-4, .mx-lg-4 { margin-left: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .mt-lg-5, .my-lg-5 { margin-top: 3rem !important; } .mr-lg-5, .mx-lg-5 { margin-right: 3rem !important; } .mb-lg-5, .my-lg-5 { margin-bottom: 3rem !important; } .ml-lg-5, .mx-lg-5 { margin-left: 3rem !important; } .p-lg-0 { padding: 0 !important; } .pt-lg-0, .py-lg-0 { padding-top: 0 !important; } .pr-lg-0, .px-lg-0 { padding-right: 0 !important; } .pb-lg-0, .py-lg-0 { padding-bottom: 0 !important; } .pl-lg-0, .px-lg-0 { padding-left: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .pt-lg-1, .py-lg-1 { padding-top: 0.25rem !important; } .pr-lg-1, .px-lg-1 { padding-right: 0.25rem !important; } .pb-lg-1, .py-lg-1 { padding-bottom: 0.25rem !important; } .pl-lg-1, .px-lg-1 { padding-left: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .pt-lg-2, .py-lg-2 { padding-top: 0.5rem !important; } .pr-lg-2, .px-lg-2 { padding-right: 0.5rem !important; } .pb-lg-2, .py-lg-2 { padding-bottom: 0.5rem !important; } .pl-lg-2, .px-lg-2 { padding-left: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .pt-lg-3, .py-lg-3 { padding-top: 1rem !important; } .pr-lg-3, .px-lg-3 { padding-right: 1rem !important; } .pb-lg-3, .py-lg-3 { padding-bottom: 1rem !important; } .pl-lg-3, .px-lg-3 { padding-left: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .pt-lg-4, .py-lg-4 { padding-top: 1.5rem !important; } .pr-lg-4, .px-lg-4 { padding-right: 1.5rem !important; } .pb-lg-4, .py-lg-4 { padding-bottom: 1.5rem !important; } .pl-lg-4, .px-lg-4 { padding-left: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .pt-lg-5, .py-lg-5 { padding-top: 3rem !important; } .pr-lg-5, .px-lg-5 { padding-right: 3rem !important; } .pb-lg-5, .py-lg-5 { padding-bottom: 3rem !important; } .pl-lg-5, .px-lg-5 { padding-left: 3rem !important; } .m-lg-n1 { margin: -0.25rem !important; } .mt-lg-n1, .my-lg-n1 { margin-top: -0.25rem !important; } .mr-lg-n1, .mx-lg-n1 { margin-right: -0.25rem !important; } .mb-lg-n1, .my-lg-n1 { margin-bottom: -0.25rem !important; } .ml-lg-n1, .mx-lg-n1 { margin-left: -0.25rem !important; } .m-lg-n2 { margin: -0.5rem !important; } .mt-lg-n2, .my-lg-n2 { margin-top: -0.5rem !important; } .mr-lg-n2, .mx-lg-n2 { margin-right: -0.5rem !important; } .mb-lg-n2, .my-lg-n2 { margin-bottom: -0.5rem !important; } .ml-lg-n2, .mx-lg-n2 { margin-left: -0.5rem !important; } .m-lg-n3 { margin: -1rem !important; } .mt-lg-n3, .my-lg-n3 { margin-top: -1rem !important; } .mr-lg-n3, .mx-lg-n3 { margin-right: -1rem !important; } .mb-lg-n3, .my-lg-n3 { margin-bottom: -1rem !important; } .ml-lg-n3, .mx-lg-n3 { margin-left: -1rem !important; } .m-lg-n4 { margin: -1.5rem !important; } .mt-lg-n4, .my-lg-n4 { margin-top: -1.5rem !important; } .mr-lg-n4, .mx-lg-n4 { margin-right: -1.5rem !important; } .mb-lg-n4, .my-lg-n4 { margin-bottom: -1.5rem !important; } .ml-lg-n4, .mx-lg-n4 { margin-left: -1.5rem !important; } .m-lg-n5 { margin: -3rem !important; } .mt-lg-n5, .my-lg-n5 { margin-top: -3rem !important; } .mr-lg-n5, .mx-lg-n5 { margin-right: -3rem !important; } .mb-lg-n5, .my-lg-n5 { margin-bottom: -3rem !important; } .ml-lg-n5, .mx-lg-n5 { margin-left: -3rem !important; } .m-lg-auto { margin: auto !important; } .mt-lg-auto, .my-lg-auto { margin-top: auto !important; } .mr-lg-auto, .mx-lg-auto { margin-right: auto !important; } .mb-lg-auto, .my-lg-auto { margin-bottom: auto !important; } .ml-lg-auto, .mx-lg-auto { margin-left: auto !important; } } @media (min-width: 1200px) { .m-xl-0 { margin: 0 !important; } .mt-xl-0, .my-xl-0 { margin-top: 0 !important; } .mr-xl-0, .mx-xl-0 { margin-right: 0 !important; } .mb-xl-0, .my-xl-0 { margin-bottom: 0 !important; } .ml-xl-0, .mx-xl-0 { margin-left: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .mt-xl-1, .my-xl-1 { margin-top: 0.25rem !important; } .mr-xl-1, .mx-xl-1 { margin-right: 0.25rem !important; } .mb-xl-1, .my-xl-1 { margin-bottom: 0.25rem !important; } .ml-xl-1, .mx-xl-1 { margin-left: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .mt-xl-2, .my-xl-2 { margin-top: 0.5rem !important; } .mr-xl-2, .mx-xl-2 { margin-right: 0.5rem !important; } .mb-xl-2, .my-xl-2 { margin-bottom: 0.5rem !important; } .ml-xl-2, .mx-xl-2 { margin-left: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .mt-xl-3, .my-xl-3 { margin-top: 1rem !important; } .mr-xl-3, .mx-xl-3 { margin-right: 1rem !important; } .mb-xl-3, .my-xl-3 { margin-bottom: 1rem !important; } .ml-xl-3, .mx-xl-3 { margin-left: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .mt-xl-4, .my-xl-4 { margin-top: 1.5rem !important; } .mr-xl-4, .mx-xl-4 { margin-right: 1.5rem !important; } .mb-xl-4, .my-xl-4 { margin-bottom: 1.5rem !important; } .ml-xl-4, .mx-xl-4 { margin-left: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .mt-xl-5, .my-xl-5 { margin-top: 3rem !important; } .mr-xl-5, .mx-xl-5 { margin-right: 3rem !important; } .mb-xl-5, .my-xl-5 { margin-bottom: 3rem !important; } .ml-xl-5, .mx-xl-5 { margin-left: 3rem !important; } .p-xl-0 { padding: 0 !important; } .pt-xl-0, .py-xl-0 { padding-top: 0 !important; } .pr-xl-0, .px-xl-0 { padding-right: 0 !important; } .pb-xl-0, .py-xl-0 { padding-bottom: 0 !important; } .pl-xl-0, .px-xl-0 { padding-left: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .pt-xl-1, .py-xl-1 { padding-top: 0.25rem !important; } .pr-xl-1, .px-xl-1 { padding-right: 0.25rem !important; } .pb-xl-1, .py-xl-1 { padding-bottom: 0.25rem !important; } .pl-xl-1, .px-xl-1 { padding-left: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .pt-xl-2, .py-xl-2 { padding-top: 0.5rem !important; } .pr-xl-2, .px-xl-2 { padding-right: 0.5rem !important; } .pb-xl-2, .py-xl-2 { padding-bottom: 0.5rem !important; } .pl-xl-2, .px-xl-2 { padding-left: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .pt-xl-3, .py-xl-3 { padding-top: 1rem !important; } .pr-xl-3, .px-xl-3 { padding-right: 1rem !important; } .pb-xl-3, .py-xl-3 { padding-bottom: 1rem !important; } .pl-xl-3, .px-xl-3 { padding-left: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .pt-xl-4, .py-xl-4 { padding-top: 1.5rem !important; } .pr-xl-4, .px-xl-4 { padding-right: 1.5rem !important; } .pb-xl-4, .py-xl-4 { padding-bottom: 1.5rem !important; } .pl-xl-4, .px-xl-4 { padding-left: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .pt-xl-5, .py-xl-5 { padding-top: 3rem !important; } .pr-xl-5, .px-xl-5 { padding-right: 3rem !important; } .pb-xl-5, .py-xl-5 { padding-bottom: 3rem !important; } .pl-xl-5, .px-xl-5 { padding-left: 3rem !important; } .m-xl-n1 { margin: -0.25rem !important; } .mt-xl-n1, .my-xl-n1 { margin-top: -0.25rem !important; } .mr-xl-n1, .mx-xl-n1 { margin-right: -0.25rem !important; } .mb-xl-n1, .my-xl-n1 { margin-bottom: -0.25rem !important; } .ml-xl-n1, .mx-xl-n1 { margin-left: -0.25rem !important; } .m-xl-n2 { margin: -0.5rem !important; } .mt-xl-n2, .my-xl-n2 { margin-top: -0.5rem !important; } .mr-xl-n2, .mx-xl-n2 { margin-right: -0.5rem !important; } .mb-xl-n2, .my-xl-n2 { margin-bottom: -0.5rem !important; } .ml-xl-n2, .mx-xl-n2 { margin-left: -0.5rem !important; } .m-xl-n3 { margin: -1rem !important; } .mt-xl-n3, .my-xl-n3 { margin-top: -1rem !important; } .mr-xl-n3, .mx-xl-n3 { margin-right: -1rem !important; } .mb-xl-n3, .my-xl-n3 { margin-bottom: -1rem !important; } .ml-xl-n3, .mx-xl-n3 { margin-left: -1rem !important; } .m-xl-n4 { margin: -1.5rem !important; } .mt-xl-n4, .my-xl-n4 { margin-top: -1.5rem !important; } .mr-xl-n4, .mx-xl-n4 { margin-right: -1.5rem !important; } .mb-xl-n4, .my-xl-n4 { margin-bottom: -1.5rem !important; } .ml-xl-n4, .mx-xl-n4 { margin-left: -1.5rem !important; } .m-xl-n5 { margin: -3rem !important; } .mt-xl-n5, .my-xl-n5 { margin-top: -3rem !important; } .mr-xl-n5, .mx-xl-n5 { margin-right: -3rem !important; } .mb-xl-n5, .my-xl-n5 { margin-bottom: -3rem !important; } .ml-xl-n5, .mx-xl-n5 { margin-left: -3rem !important; } .m-xl-auto { margin: auto !important; } .mt-xl-auto, .my-xl-auto { margin-top: auto !important; } .mr-xl-auto, .mx-xl-auto { margin-right: auto !important; } .mb-xl-auto, .my-xl-auto { margin-bottom: auto !important; } .ml-xl-auto, .mx-xl-auto { margin-left: auto !important; } } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; pointer-events: auto; content: ""; background-color: rgba(0, 0, 0, 0); } .text-monospace { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; } .text-justify { text-align: justify !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .text-center { text-align: center !important; } @media (min-width: 576px) { .text-sm-left { text-align: left !important; } .text-sm-right { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .text-md-left { text-align: left !important; } .text-md-right { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .text-lg-left { text-align: left !important; } .text-lg-right { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .text-xl-left { text-align: left !important; } .text-xl-right { text-align: right !important; } .text-xl-center { text-align: center !important; } } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .font-weight-light { font-weight: 300 !important; } .font-weight-lighter { font-weight: lighter !important; } .font-weight-normal { font-weight: 400 !important; } .font-weight-bold { font-weight: 700 !important; } .font-weight-bolder { font-weight: bolder !important; } .font-italic { font-style: italic !important; } .text-white { color: #fff !important; } .text-primary { color: #000bff !important; } a.text-primary:hover, a.text-primary:focus { color: #0056b3 !important; } .text-secondary { color: #6c757d !important; } a.text-secondary:hover, a.text-secondary:focus { color: #494f54 !important; } .text-success { color: #28a745 !important; } a.text-success:hover, a.text-success:focus { color: #19692c !important; } .text-info { color: #17a2b8 !important; } a.text-info:hover, a.text-info:focus { color: #0f6674 !important; } .text-warning { color: #ffc107 !important; } a.text-warning:hover, a.text-warning:focus { color: #ba8b00 !important; } .text-danger { color: #dc3545 !important; } a.text-danger:hover, a.text-danger:focus { color: #a71d2a !important; } .text-light { color: #f8f9fa !important; } a.text-light:hover, a.text-light:focus { color: #cbd3da !important; } .text-dark { color: #343a40 !important; } a.text-dark:hover, a.text-dark:focus { color: #121416 !important; } .text-body { color: #212529 !important; } .text-muted { color: #6c757d !important; } .text-black-50 { color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { color: rgba(255, 255, 255, 0.5) !important; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .text-decoration-none { text-decoration: none !important; } .text-break { word-break: break-word !important; word-wrap: break-word !important; } .text-reset { color: inherit !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media print { *, *::before, *::after { text-shadow: none !important; box-shadow: none !important; } a:not(.btn) { text-decoration: underline; } abbr[title]::after { content: " (" attr(title) ")"; } pre { white-space: pre-wrap !important; } pre, blockquote { border: 1px solid #adb5bd; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } @page { size: a3; } body { min-width: 992px !important; } .container { min-width: 992px !important; } .navbar { display: none; } .badge { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6 !important; } .table-dark { color: inherit; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #dee2e6; } .table .thead-dark th { color: inherit; border-color: #dee2e6; } } @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .dark-mode :root { --lightblue: #86bad8; --navy: #002c59; --olive: #74c8a3; --lime: #67ffa9; --fuchsia: #f672d8; --maroon: #ed6c9b; --blue: #3f6791; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #e74c3c; --orange: #fd7e14; --yellow: #f39c12; --green: #00bc8c; --teal: #20c997; --cyan: #3498db; --white: #fff; --gray: #6c757d; --gray-dark: #343a40; --primary: #3f6791; --secondary: #6c757d; --success: #00bc8c; --info: #3498db; --warning: #f39c12; --danger: #e74c3c; --light: #f8f9fa; --dark: #343a40; } .animation__shake { -webkit-animation: shake 1500ms; animation: shake 1500ms; } .animation__wobble { -webkit-animation: wobble 1500ms; animation: wobble 1500ms; } .preloader { display: -ms-flexbox; display: flex; background-color: #f4f6f9; height: 100vh; width: 100%; transition: height 200ms linear; position: fixed; left: 0; top: 0; z-index: 9999; } .dark-mode .preloader { background-color: #454d55 !important; color: #fff; } html.scroll-smooth { scroll-behavior: smooth; } html, body, .wrapper { min-height: 100%; } .wrapper { position: relative; } .wrapper .content-wrapper { min-height: calc(100vh - calc(3.5rem + 1px) - calc(3.5rem + 1px)); } .layout-boxed .wrapper { box-shadow: 0 0 10 rgba(0, 0, 0, 0.3); } .layout-boxed .wrapper, .layout-boxed .wrapper::before { margin: 0 auto; max-width: 1250px; overflow: hidden; } .layout-boxed .wrapper .main-sidebar { left: inherit; } @supports not (-webkit-touch-callout: none) { .layout-fixed .wrapper .sidebar { height: calc(100vh - (3.5rem + 1px)); } .layout-fixed.text-sm .wrapper .sidebar { height: calc(100vh - (2.93725rem + 1px)); } } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link { height: calc(3.5rem + 1px); width: 4.6rem; } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse.text-sm .wrapper .brand-link { height: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lightblue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lightblue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-navy .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-navy .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-olive .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-olive .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lime .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lime .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-fuchsia .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-fuchsia .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-maroon .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-maroon .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-blue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-blue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-indigo .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-indigo .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-purple .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-purple .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-pink .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-pink .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-red .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-red .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-orange .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-orange .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-yellow .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-yellow .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-green .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-green .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-teal .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-teal .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-cyan .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-cyan .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-white .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-white .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .main-header.border-bottom-0 ~ .content-wrapper { margin-top: 3.5rem; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1033; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } @media (min-width: 576px) { .layout-sm-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-sm-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-sm-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-sm-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-sm-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-sm-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-sm-navbar-not-fixed .wrapper .sidebar, .layout-sm-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-sm-navbar-not-fixed .wrapper .main-header { position: static; } .layout-sm-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 768px) { .layout-md-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-md-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-md-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-md-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-md-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-md-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-md-navbar-not-fixed .wrapper .sidebar, .layout-md-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-md-navbar-not-fixed .wrapper .main-header { position: static; } .layout-md-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 992px) { .layout-lg-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-lg-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-lg-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-lg-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-lg-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-lg-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-lg-navbar-not-fixed .wrapper .sidebar, .layout-lg-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-lg-navbar-not-fixed .wrapper .main-header { position: static; } .layout-lg-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 1200px) { .layout-xl-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-xl-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-xl-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-xl-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-xl-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-xl-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-xl-navbar-not-fixed .wrapper .sidebar, .layout-xl-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-xl-navbar-not-fixed .wrapper .main-header { position: static; } .layout-xl-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-not-fixed .wrapper .main-footer { position: static; } .layout-footer-not-fixed .wrapper .content-wrapper { margin-bottom: 0; } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-footer-not-fixed .wrapper .main-footer { position: static; } @media (min-width: 576px) { .layout-sm-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-sm-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-sm-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-sm-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 768px) { .layout-md-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-md-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-md-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-md-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 992px) { .layout-lg-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-lg-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-lg-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-lg-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 1200px) { .layout-xl-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-xl-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-xl-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-xl-footer-not-fixed .wrapper .main-footer { position: static; } } .layout-top-nav .wrapper { margin-left: 0; } .layout-top-nav .wrapper .main-header .brand-image { margin-top: -.5rem; margin-right: .2rem; height: 33px; } .layout-top-nav .wrapper .main-sidebar { bottom: inherit; height: inherit; } .layout-top-nav .wrapper .content-wrapper, .layout-top-nav .wrapper .main-header, .layout-top-nav .wrapper .main-footer { margin-left: 0; } body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header::before { margin-left: 0; } @media (min-width: 768px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (max-width: 991.98px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-md .content-wrapper, .sidebar-collapse .sidebar-mini-md .main-footer, .sidebar-collapse .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-xs .content-wrapper, .sidebar-collapse .sidebar-mini-xs .main-footer, .sidebar-collapse .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } .content-wrapper { background-color: #f4f6f9; } .content-wrapper > .content { padding: 0 0.5rem; } .main-sidebar, .main-sidebar::before { transition: margin-left 0.3s ease-in-out, width 0.3s ease-in-out; width: 250px; } @media (prefers-reduced-motion: reduce) { .main-sidebar, .main-sidebar::before { transition: none; } } .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar, .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar::before { box-shadow: none !important; } .sidebar-collapse .main-sidebar, .sidebar-collapse .main-sidebar::before { margin-left: -250px; } .sidebar-collapse .main-sidebar .nav-sidebar.nav-child-indent .nav-treeview { padding: 0; } @media (max-width: 767.98px) { .main-sidebar, .main-sidebar::before { box-shadow: none !important; margin-left: -250px; } .sidebar-open .main-sidebar, .sidebar-open .main-sidebar::before { margin-left: 0; } } body:not(.layout-fixed) .main-sidebar { height: inherit; min-height: 100%; position: absolute; top: 0; } body:not(.layout-fixed) .main-sidebar .sidebar { overflow-y: auto; } .layout-fixed .brand-link { width: 250px; } .layout-fixed .main-sidebar { bottom: 0; float: none; left: 0; position: fixed; top: 0; } .layout-fixed .control-sidebar { bottom: 0; float: none; position: fixed; top: 0; } .layout-fixed .control-sidebar .control-sidebar-content { height: calc(100vh - calc(3.5rem + 1px)); overflow-y: auto; scrollbar-width: thin; scrollbar-color: #a9a9a9 transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar { width: .5rem; height: .5rem; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-track { background-color: transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-corner { background-color: transparent; } @supports (-webkit-touch-callout: none) { .layout-fixed .main-sidebar { height: inherit; } } .main-footer { background-color: #fff; border-top: 1px solid #dee2e6; color: #869099; padding: 1rem; } .text-sm .main-footer, .main-footer.text-sm { padding: 0.812rem; } .content-header { padding: 15px 0.5rem; } .text-sm .content-header { padding: 10px 0.5rem; } .content-header h1 { font-size: 1.8rem; margin: 0; } .text-sm .content-header h1 { font-size: 1.5rem; } .content-header .breadcrumb { background-color: transparent; line-height: 1.8rem; margin-bottom: 0; padding: 0; } .text-sm .content-header .breadcrumb { line-height: 1.5rem; } .hold-transition .content-wrapper, .hold-transition .main-header, .hold-transition .main-sidebar, .hold-transition .main-sidebar *, .hold-transition .control-sidebar, .hold-transition .control-sidebar *, .hold-transition .main-footer { transition: none !important; -webkit-animation-duration: 0s !important; animation-duration: 0s !important; } .dark-mode { background-color: #454d55 !important; color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } @media (min-width: 576px) { .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 768px) { .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 992px) { .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 1200px) { .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } .dark-mode .breadcrumb-item.active, .dark-mode .breadcrumb-item + .breadcrumb-item::before { color: #adb5bd; } .dark-mode .main-footer { background-color: #343a40; border-color: #4b545c; } .dark-mode .content-wrapper { background-color: #454d55; color: #fff; } .dark-mode .content-wrapper .content-header { color: #fff; } .main-header { border-bottom: 1px solid #dee2e6; z-index: 1034; } .main-header .nav-link { height: 2.5rem; position: relative; } .text-sm .main-header .nav-link, .main-header.text-sm .nav-link { height: 1.93725rem; padding: 0.35rem 1rem; } .text-sm .main-header .nav-link > .fa, .text-sm .main-header .nav-link > .fas, .text-sm .main-header .nav-link > .far, .text-sm .main-header .nav-link > .fab, .text-sm .main-header .nav-link > .fal, .text-sm .main-header .nav-link > .fad, .text-sm .main-header .nav-link > .svg-inline--fa, .text-sm .main-header .nav-link > .ion, .main-header.text-sm .nav-link > .fa, .main-header.text-sm .nav-link > .fas, .main-header.text-sm .nav-link > .far, .main-header.text-sm .nav-link > .fab, .main-header.text-sm .nav-link > .fal, .main-header.text-sm .nav-link > .fad, .main-header.text-sm .nav-link > .svg-inline--fa, .main-header.text-sm .nav-link > .ion { font-size: 0.875rem; } .main-header .navbar-nav .nav-item { margin: 0; } .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: auto; margin-top: -3px; right: 0; } @media (max-width: 575.98px) { .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: 0; right: auto; } } .main-header.dropdown-legacy .dropdown-menu { top: 3rem; margin-top: 0; } .navbar-img { height: calc(calc(3.5rem + 1px) * .5); width: auto; } .navbar-badge { font-size: .6rem; font-weight: 300; padding: 2px 4px; position: absolute; right: 5px; top: 9px; } .btn-navbar { background-color: transparent; border-left-width: 0; } .form-control-navbar { border-right-width: 0; } .form-control-navbar + .input-group-append { margin-left: 0; } .form-control-navbar, .btn-navbar { transition: none; } .navbar-dark .form-control-navbar, .navbar-dark .btn-navbar { background-color: #343a40; border-color: #6c757d; } .navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:focus, .navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #495057; border-color: #6c757d !important; color: #ced4da; } .navbar-light .form-control-navbar, .navbar-light .btn-navbar { background-color: #dadfe4; border-color: #ced4da; } .navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-moz-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:focus, .navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d3d9df; border-color: #c7ced5 !important; color: #ced4da; } .navbar-light .navbar-search-block .form-control-navbar:focus, .navbar-light .navbar-search-block .form-control-navbar:focus + .input-group-append .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-search-block { position: absolute; padding: 0 1rem; left: 0; top: 0; right: 0; bottom: 0; z-index: 10; display: none; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; background-color: initial; } .navbar-search-block.navbar-search-open { display: -ms-flexbox; display: flex; } .navbar-search-block .input-group { width: 100%; } .brand-link { display: block; font-size: 1.25rem; line-height: 1.5; padding: 0.8125rem 0.5rem; transition: width 0.3s ease-in-out; white-space: nowrap; } .brand-link:hover { color: #fff; text-decoration: none; } .text-sm .brand-link { font-size: inherit; } [class*="sidebar-dark"] .brand-link { border-bottom: 1px solid #4b545c; } [class*="sidebar-dark"] .brand-link, [class*="sidebar-dark"] .brand-link .pushmenu { color: rgba(255, 255, 255, 0.8); } [class*="sidebar-dark"] .brand-link:hover, [class*="sidebar-dark"] .brand-link .pushmenu:hover { color: #fff; } [class*="sidebar-light"] .brand-link { border-bottom: 1px solid #dee2e6; } [class*="sidebar-light"] .brand-link, [class*="sidebar-light"] .brand-link .pushmenu { color: rgba(0, 0, 0, 0.8); } [class*="sidebar-light"] .brand-link:hover, [class*="sidebar-light"] .brand-link .pushmenu:hover { color: #000; } .brand-link .pushmenu { margin-right: 0.5rem; font-size: 1rem; } .brand-link .brand-link { padding: 0; border-bottom: none; } .brand-link .brand-image { float: left; line-height: .8; margin-left: .8rem; margin-right: .5rem; margin-top: -3px; max-height: 33px; width: auto; } .brand-link .brand-image-xs { float: left; line-height: .8; margin-top: -.1rem; max-height: 33px; width: auto; } .brand-link .brand-image-xl { line-height: .8; max-height: 40px; width: auto; } .brand-link .brand-image-xl.single { margin-top: -.3rem; } .brand-link.text-sm .brand-image, .text-sm .brand-link .brand-image { height: 29px; margin-bottom: -.25rem; margin-left: .95rem; margin-top: -.25rem; } .brand-link.text-sm .brand-image-xs, .text-sm .brand-link .brand-image-xs { margin-top: -.2rem; max-height: 29px; } .brand-link.text-sm .brand-image-xl, .text-sm .brand-link .brand-image-xl { margin-top: -.225rem; max-height: 38px; } .main-sidebar { height: 100vh; overflow-y: hidden; z-index: 1038; } .main-sidebar a:-moz-focusring { border: 0; outline: none; } .sidebar { height: calc(100% - (3.5rem + 1px)); overflow-x: hidden; overflow-y: initial; padding-bottom: 0; padding-left: 0.5rem; padding-right: 0.5rem; padding-top: 0; scrollbar-color: #a9a9a9 transparent; scrollbar-width: none; } .sidebar::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .sidebar::-webkit-scrollbar-track { background-color: transparent; } .sidebar::-webkit-scrollbar-corner { background-color: transparent; } .sidebar::-webkit-scrollbar { width: 0; } .sidebar:hover { scrollbar-width: thin; } .sidebar:hover::-webkit-scrollbar { width: .5rem; height: .5rem; } .brand-link.border-bottom-0 ~ .sidebar { height: calc(100% - 3.5rem); } .user-panel { position: relative; } [class*="sidebar-dark"] .user-panel { border-bottom: 1px solid #4f5962; } [class*="sidebar-light"] .user-panel { border-bottom: 1px solid #dee2e6; } .user-panel, .user-panel .info { overflow: hidden; white-space: nowrap; } .user-panel .image { display: inline-block; padding-left: 0.8rem; } .user-panel img { height: auto; width: 2.1rem; } .user-panel .info { display: inline-block; padding: 5px 5px 5px 10px; } .user-panel .status, .user-panel .dropdown-menu { font-size: 0.875rem; } .nav-sidebar .nav-item > .nav-link { margin-bottom: .2rem; } .nav-sidebar .nav-item > .nav-link .right { transition: -webkit-transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s, -webkit-transform ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-sidebar .nav-item > .nav-link .right { transition: none; } } .nav-sidebar .nav-link > .right, .nav-sidebar .nav-link > p > .right { position: absolute; right: 1rem; top: .7rem; } .nav-sidebar .nav-link > .right i, .nav-sidebar .nav-link > .right span, .nav-sidebar .nav-link > p > .right i, .nav-sidebar .nav-link > p > .right span { margin-left: .5rem; } .nav-sidebar .nav-link > .right:nth-child(2), .nav-sidebar .nav-link > p > .right:nth-child(2) { right: 2.2rem; } .nav-sidebar .menu-open > .nav-treeview { display: block; } .nav-sidebar .menu-open > .nav-link svg.right, .nav-sidebar .menu-open > .nav-link i.right, .nav-sidebar .menu-is-opening > .nav-link svg.right, .nav-sidebar .menu-is-opening > .nav-link i.right { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .nav-sidebar > .nav-item { margin-bottom: 0; } .nav-sidebar > .nav-item .nav-icon { margin-left: .05rem; font-size: 1.2rem; margin-right: .2rem; text-align: center; width: 1.6rem; } .nav-sidebar > .nav-item .nav-icon.fa, .nav-sidebar > .nav-item .nav-icon.fas, .nav-sidebar > .nav-item .nav-icon.far, .nav-sidebar > .nav-item .nav-icon.fab, .nav-sidebar > .nav-item .nav-icon.fal, .nav-sidebar > .nav-item .nav-icon.fad, .nav-sidebar > .nav-item .nav-icon.svg-inline--fa, .nav-sidebar > .nav-item .nav-icon.ion { font-size: 1.1rem; } .nav-sidebar > .nav-item .float-right { margin-top: 3px; } .nav-sidebar .nav-treeview { display: none; list-style: none; padding: 0; } .nav-sidebar .nav-treeview > .nav-item > .nav-link > .nav-icon { width: 1.6rem; } .nav-sidebar.nav-child-indent .nav-treeview { transition: padding 0.3s ease-in-out; padding-left: 1rem; } .text-sm .nav-sidebar.nav-child-indent .nav-treeview { padding-left: .5rem; } .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .text-sm .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-sidebar .nav-header { font-size: .9rem; padding: 0.5rem 0.75rem; } .nav-sidebar .nav-link p { display: inline; margin: 0; white-space: normal; } .sidebar-is-opening .sidebar .nav-sidebar .nav-link p { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } #sidebar-overlay { background-color: rgba(0, 0, 0, 0.1); bottom: 0; display: none; left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } @media (max-width: 991.98px) { .sidebar-open #sidebar-overlay { display: block; } } [class*="sidebar-light-"] { background-color: #fff; } [class*="sidebar-light-"] .user-panel a:hover { color: #212529; } [class*="sidebar-light-"] .user-panel .status { background-color: rgba(0, 0, 0, 0.1); color: #343a40; } [class*="sidebar-light-"] .user-panel .status:hover, [class*="sidebar-light-"] .user-panel .status:focus, [class*="sidebar-light-"] .user-panel .status:active { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:active, [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:focus { color: #343a40; } [class*="sidebar-light-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-light-"] .nav-sidebar > .nav-item:hover > .nav-link { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link.active { color: #000; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-light-"] .nav-header { background-color: inherit; color: #292d32; } [class*="sidebar-light-"] .sidebar a { color: #343a40; } [class*="sidebar-light-"] .sidebar a:hover { text-decoration: none; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link { color: #777; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(0, 0, 0, 0.1); color: #000; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active:hover { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover { background-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-dark-"] { background-color: #343a40; } [class*="sidebar-dark-"] .user-panel a:hover { color: #fff; } [class*="sidebar-dark-"] .user-panel .status { background-color: rgba(255, 255, 255, 0.1); color: #c2c7d0; } [class*="sidebar-dark-"] .user-panel .status:hover, [class*="sidebar-dark-"] .user-panel .status:focus, [class*="sidebar-dark-"] .user-panel .status:active { background-color: rgba(247, 247, 247, 0.1); color: #fff; } [class*="sidebar-dark-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(242, 242, 242, 0.1); } [class*="sidebar-dark-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:active { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item:hover > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link.active { color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-dark-"] .nav-header { background-color: inherit; color: #d0d4db; } [class*="sidebar-dark-"] .sidebar a { color: #c2c7d0; } [class*="sidebar-dark-"] .sidebar a:hover, [class*="sidebar-dark-"] .sidebar a:focus { text-decoration: none; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:focus { background-color: rgba(255, 255, 255, 0.9); color: #343a40; } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(255, 255, 255, 0.9); } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(255, 255, 255, 0.9); } .sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-secondary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-success .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-info .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-warning .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-danger .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-light .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar > .nav-item > .nav-link.active { background-color: #f8f9fa; color: #1f2d3d; } .sidebar-dark-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f8f9fa; } .sidebar-dark-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-dark-lightblue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar > .nav-item > .nav-link.active { background-color: #3c8dbc; color: #fff; } .sidebar-dark-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3c8dbc; } .sidebar-dark-navy .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar > .nav-item > .nav-link.active { background-color: #001f3f; color: #fff; } .sidebar-dark-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #001f3f; } .sidebar-dark-olive .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar > .nav-item > .nav-link.active { background-color: #3d9970; color: #fff; } .sidebar-dark-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3d9970; } .sidebar-dark-lime .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar > .nav-item > .nav-link.active { background-color: #01ff70; color: #1f2d3d; } .sidebar-dark-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #01ff70; } .sidebar-dark-fuchsia .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar > .nav-item > .nav-link.active { background-color: #f012be; color: #fff; } .sidebar-dark-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f012be; } .sidebar-dark-maroon .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar > .nav-item > .nav-link.active { background-color: #d81b60; color: #fff; } .sidebar-dark-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #d81b60; } .sidebar-dark-blue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-indigo .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar > .nav-item > .nav-link.active { background-color: #6610f2; color: #fff; } .sidebar-dark-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6610f2; } .sidebar-dark-purple .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar > .nav-item > .nav-link.active { background-color: #6f42c1; color: #fff; } .sidebar-dark-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6f42c1; } .sidebar-dark-pink .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar > .nav-item > .nav-link.active { background-color: #e83e8c; color: #fff; } .sidebar-dark-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e83e8c; } .sidebar-dark-red .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-orange .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar > .nav-item > .nav-link.active { background-color: #fd7e14; color: #1f2d3d; } .sidebar-dark-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fd7e14; } .sidebar-dark-yellow .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-green .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-teal .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar > .nav-item > .nav-link.active { background-color: #20c997; color: #fff; } .sidebar-dark-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #20c997; } .sidebar-dark-cyan .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-white .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar > .nav-item > .nav-link.active { background-color: #fff; color: #1f2d3d; } .sidebar-dark-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fff; } .sidebar-dark-gray .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-gray-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-flat { margin: -0.25rem -0.5rem 0; } .nav-flat .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-flat .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .nav-flat:not(.nav-child-indent) .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: .4rem; } .nav-flat.nav-child-indent .nav-treeview { padding-left: 0; } .nav-flat.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview { border-left: .2rem solid; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-icon { margin-left: .55rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-link { padding-left: calc(1rem - .2rem); } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-icon { margin-left: .35rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: .15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.35rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon { margin-left: .4rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .nav-flat .nav-icon { transition: margin-left ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-flat .nav-icon { transition: none; } } .nav-flat .nav-treeview .nav-icon { margin-left: -.2rem; } .nav-flat.nav-sidebar > .nav-item .nav-treeview, .nav-flat.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } .nav-flat.nav-sidebar > .nav-item .nav-treeview .nav-item > .nav-link, .nav-flat.nav-sidebar > .nav-item > .nav-treeview .nav-item > .nav-link { border-left: .2rem solid; } .nav-legacy { margin: -0.25rem -0.5rem 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .text-sm .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .75rem; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { background-color: inherit; border-left: 3px solid transparent; box-shadow: none; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.55rem - 3px); } .text-sm .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } .text-sm .nav-legacy.nav-sidebar.nav-flat .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: calc(.75rem - 3px); } .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: margin-left ease-in-out 0.3s; margin-left: .6rem; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: none; } } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview { padding-left: 1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview { padding-left: .5rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .55rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: .36rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview { padding-left: 0; margin-left: 0; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .75rem; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #fff; } [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #fff; } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(0, 0, 0, 0.05); } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #000; } [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #000; } .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .sidebar-collapse .sidebar:not(:hover) .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: 0; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .nav-compact .nav-link, .nav-compact .nav-header { padding-top: 0.25rem; padding-bottom: 0.25rem; } .nav-compact .nav-header:not(:first-of-type) { padding-top: 0.75rem; padding-bottom: 0.25rem; } .nav-compact .nav-link > .right, .nav-compact .nav-link > p > .right { top: .465rem; } .text-sm .nav-compact .nav-link > .right, .text-sm .nav-compact .nav-link > p > .right { top: .7rem; } [class*="sidebar-dark"] .form-control-sidebar, [class*="sidebar-dark"] .btn-sidebar { background-color: #3f474e; border: 1px solid #56606a; color: white; } [class*="sidebar-dark"] .form-control-sidebar:focus, [class*="sidebar-dark"] .btn-sidebar:focus { border: 1px solid #7a8793; } [class*="sidebar-dark"] .btn-sidebar:hover { background-color: #454d55; } [class*="sidebar-dark"] .btn-sidebar:focus { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item { background-color: #454d55; border-color: #56606a; color: #c2c7d0; } [class*="sidebar-dark"] .list-group-item:hover { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item:focus { background-color: #515a63; } [class*="sidebar-dark"] .list-group-item .search-path { color: #adb5bd; } [class*="sidebar-light"] .form-control-sidebar, [class*="sidebar-light"] .btn-sidebar { background-color: #f2f2f2; border: 1px solid #d9d9d9; color: #1f2d3d; } [class*="sidebar-light"] .form-control-sidebar:focus, [class*="sidebar-light"] .btn-sidebar:focus { border: 1px solid #b3b3b3; } [class*="sidebar-light"] .btn-sidebar:hover { background-color: #ececec; } [class*="sidebar-light"] .btn-sidebar:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item { border-color: #d9d9d9; } [class*="sidebar-light"] .list-group-item:hover { background-color: #ececec; } [class*="sidebar-light"] .list-group-item:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item .search-path { color: #6c757d; } .sidebar .form-inline .input-group { width: 100%; -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .sidebar nav .form-inline { margin-bottom: .2rem; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs).sidebar-collapse .main-sidebar { margin-left: 0; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .content-wrapper, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-header, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-footer { z-index: 9999; position: relative; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .control-sidebar { z-index: 9999; } .sidebar-collapse .form-control-sidebar, .sidebar-collapse .form-control-sidebar ~ .input-group-append, .sidebar-collapse .sidebar-search-results { display: none; } [data-widget="sidebar-search"] input[type="search"]::-ms-clear, [data-widget="sidebar-search"] input[type="search"]::-ms-reveal { display: none; width: 0; height: 0; } [data-widget="sidebar-search"] input[type="search"]::-webkit-search-cancel-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-decoration, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-decoration { display: none; } .sidebar-search-results { position: relative; display: none; width: 100%; } .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-search-results .search-title { margin-bottom: -.1rem; } .sidebar-search-results .list-group { position: absolute; width: 100%; z-index: 1039; } .sidebar-search-results .list-group > .list-group-item { padding: 0.375rem 0.75rem; } .sidebar-search-results .list-group > .list-group-item:-moz-focusring { margin-top: 0; border-left: 1px solid transparent; border-top: 0; border-bottom: 1px solid transparent; } .sidebar-search-results .list-group > .list-group-item:first-child { margin-top: 0; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .sidebar-search-results .search-path { font-size: 80%; } .sidebar-search-open .btn, .sidebar-search-open .form-control { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } [class*="sidebar-dark"] .sidebar-custom { border-top: 1px solid #4f5962; } [class*="sidebar-light"] .sidebar-custom { border-top: 1px solid #dee2e6; } .layout-fixed.sidebar-collapse .hide-on-collapse { display: none; } .layout-fixed.sidebar-collapse:hover .hide-on-collapse { display: block; } .layout-fixed.text-sm .main-sidebar-custom .sidebar { height: calc(100% - ((2.93725rem + 3.8rem) + 1px)); } .layout-fixed.text-sm .main-sidebar-custom .sidebar-custom { height: 3.8rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom { height: -webkit-fill-available; height: -moz-available; height: -ms-stretch; height: stretch; } .layout-fixed .main-sidebar-custom .sidebar { height: calc(100% - ((3.5rem + 4rem) + 1px)); } .layout-fixed .main-sidebar-custom .sidebar-custom { height: 4rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom-lg .sidebar { height: calc(100% - ((3.5rem + 6rem) + 1px)); } .layout-fixed .main-sidebar-custom-lg .sidebar-custom { height: 6rem; } .layout-fixed .main-sidebar-custom-xl .sidebar { height: calc(100% - ((3.5rem + 8rem) + 1px)); } .layout-fixed .main-sidebar-custom-xl .sidebar-custom { height: 8rem; } .layout-fixed .main-sidebar-custom .pos-right, .layout-fixed .main-sidebar-custom-lg .pos-right, .layout-fixed .main-sidebar-custom-xl .pos-right { position: absolute; right: .5rem; } .sidebar-hidden .main-sidebar, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-sidebar { display: none !important; } .sidebar-hidden .content-wrapper, .sidebar-hidden .main-header, .sidebar-hidden.sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-header { margin-left: 0 !important; } .dark-mode .sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-primary .nav-sidebar > .nav-item > .nav-link.active { background-color: #3f6791; color: #fff; } .dark-mode .sidebar-dark-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3f6791; } .dark-mode .sidebar-dark-secondary .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-secondary .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .dark-mode .sidebar-dark-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .dark-mode .sidebar-dark-success .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-success .nav-sidebar > .nav-item > .nav-link.active { background-color: #00bc8c; color: #fff; } .dark-mode .sidebar-dark-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #00bc8c; } .dark-mode .sidebar-dark-info .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-info .nav-sidebar > .nav-item > .nav-link.active { background-color: #3498db; color: #fff; } .dark-mode .sidebar-dark-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3498db; } .dark-mode .sidebar-dark-warning .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-warning .nav-sidebar > .nav-item > .nav-link.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .sidebar-dark-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f39c12; } .dark-mode .sidebar-dark-danger .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-danger .nav-sidebar > .nav-item > .nav-link.active { background-color: #e74c3c; color: #fff; } .dark-mode .sidebar-dark-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e74c3c; } .dark-mode .sidebar-dark-light .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-light .nav-sidebar > .nav-item > .nav-link.active { background-color: #f8f9fa; color: #1f2d3d; } .dark-mode .sidebar-dark-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f8f9fa; } .dark-mode .sidebar-dark-dark .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .dark-mode .sidebar-dark-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .dark-mode .sidebar-dark-lightblue .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lightblue .nav-sidebar > .nav-item > .nav-link.active { background-color: #86bad8; color: #1f2d3d; } .dark-mode .sidebar-dark-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #86bad8; } .dark-mode .sidebar-dark-navy .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-navy .nav-sidebar > .nav-item > .nav-link.active { background-color: #002c59; color: #fff; } .dark-mode .sidebar-dark-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #002c59; } .dark-mode .sidebar-dark-olive .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-olive .nav-sidebar > .nav-item > .nav-link.active { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .sidebar-dark-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #74c8a3; } .dark-mode .sidebar-dark-lime .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lime .nav-sidebar > .nav-item > .nav-link.active { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .sidebar-dark-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #67ffa9; } .dark-mode .sidebar-dark-fuchsia .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-fuchsia .nav-sidebar > .nav-item > .nav-link.active { background-color: #f672d8; color: #1f2d3d; } .dark-mode .sidebar-dark-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f672d8; } .dark-mode .sidebar-dark-maroon .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-maroon .nav-sidebar > .nav-item > .nav-link.active { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .sidebar-dark-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ed6c9b; } .dark-mode .sidebar-dark-blue .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-blue .nav-sidebar > .nav-item > .nav-link.active { background-color: #3f6791; color: #fff; } .dark-mode .sidebar-dark-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3f6791; } .dark-mode .sidebar-dark-indigo .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-indigo .nav-sidebar > .nav-item > .nav-link.active { background-color: #6610f2; color: #fff; } .dark-mode .sidebar-dark-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6610f2; } .dark-mode .sidebar-dark-purple .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-purple .nav-sidebar > .nav-item > .nav-link.active { background-color: #6f42c1; color: #fff; } .dark-mode .sidebar-dark-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6f42c1; } .dark-mode .sidebar-dark-pink .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-pink .nav-sidebar > .nav-item > .nav-link.active { background-color: #e83e8c; color: #fff; } .dark-mode .sidebar-dark-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e83e8c; } .dark-mode .sidebar-dark-red .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-red .nav-sidebar > .nav-item > .nav-link.active { background-color: #e74c3c; color: #fff; } .dark-mode .sidebar-dark-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e74c3c; } .dark-mode .sidebar-dark-orange .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-orange .nav-sidebar > .nav-item > .nav-link.active { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .sidebar-dark-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fd7e14; } .dark-mode .sidebar-dark-yellow .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-yellow .nav-sidebar > .nav-item > .nav-link.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .sidebar-dark-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f39c12; } .dark-mode .sidebar-dark-green .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-green .nav-sidebar > .nav-item > .nav-link.active { background-color: #00bc8c; color: #fff; } .dark-mode .sidebar-dark-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #00bc8c; } .dark-mode .sidebar-dark-teal .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-teal .nav-sidebar > .nav-item > .nav-link.active { background-color: #20c997; color: #fff; } .dark-mode .sidebar-dark-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #20c997; } .dark-mode .sidebar-dark-cyan .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-cyan .nav-sidebar > .nav-item > .nav-link.active { background-color: #3498db; color: #fff; } .dark-mode .sidebar-dark-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3498db; } .dark-mode .sidebar-dark-white .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-white .nav-sidebar > .nav-item > .nav-link.active { background-color: #fff; color: #1f2d3d; } .dark-mode .sidebar-dark-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fff; } .dark-mode .sidebar-dark-gray .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .dark-mode .sidebar-dark-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .dark-mode .sidebar-dark-gray-dark .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .dark-mode .sidebar-dark-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .dark-mode [class*="sidebar-light-"] .sidebar a { color: #343a40; } .dark-mode [class*="sidebar-light-"] .sidebar a:hover { text-decoration: none; } .logo-xs, .logo-xl { opacity: 1; position: absolute; visibility: visible; } .logo-xs.brand-image-xs, .logo-xl.brand-image-xs { left: 18px; top: 12px; } .logo-xs.brand-image-xl, .logo-xl.brand-image-xl { left: 12px; top: 6px; } .logo-xs { opacity: 0; visibility: hidden; } .logo-xs.brand-image-xl { left: 16px; top: 8px; } .brand-link.logo-switch::before { content: "\00a0"; } @media (min-width: 992px) { .sidebar-mini .nav-sidebar, .sidebar-mini .nav-sidebar > .nav-header, .sidebar-mini .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-mini.sidebar-collapse .main-footer, .sidebar-mini.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar, .sidebar-mini.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini.sidebar-collapse .main-sidebar { box-shadow: none !important; } } @media (min-width: 768px) { .sidebar-mini-md .nav-sidebar, .sidebar-mini-md .nav-sidebar > .nav-header, .sidebar-mini-md .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-md.sidebar-collapse .content-wrapper, .sidebar-mini-md.sidebar-collapse .main-footer, .sidebar-mini-md.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-md.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar, .sidebar-mini-md.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-md.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-md.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md.sidebar-collapse .main-sidebar { box-shadow: none !important; } } .sidebar-mini-xs .nav-sidebar, .sidebar-mini-xs .nav-sidebar > .nav-header, .sidebar-mini-xs .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-xs.sidebar-collapse .content-wrapper, .sidebar-mini-xs.sidebar-collapse .main-footer, .sidebar-mini-xs.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-xs.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar, .sidebar-mini-xs.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-xs.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 3rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 4rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 5rem); } .sidebar-mini .main-sidebar .nav-legacy .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-mini .main-sidebar .nav-flat .nav-link, .sidebar-mini-md .main-sidebar .nav-flat .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { width: calc(250px - 0.5rem * 2); transition: width ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { transition: none; } } .sidebar-collapse.sidebar-mini .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar .sidebar-search-results { display: none; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar .nav-link { width: 3.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-legacy .nav-link { width: 4.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview { padding-left: 0 !important; margin-left: 0 !important; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link { width: calc(4.6rem - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append { display: -ms-flexbox; display: flex; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-compact .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover { width: 4.6rem; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-header { display: none; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .brand-link { width: 4.6rem !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .user-panel .image { float: none !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xs { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview { padding-left: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; display: inline-block; width: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon { margin-right: 0; } .nav-sidebar { position: relative; } .nav-sidebar:hover { overflow: visible; } .sidebar-form, .nav-sidebar > .nav-header { overflow: hidden; text-overflow: clip; } .nav-sidebar .nav-item > .nav-link { position: relative; } .nav-sidebar .nav-item > .nav-link > .float-right { margin-top: -7px; position: absolute; right: 10px; top: 50%; } .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: margin-left 0.3s linear, opacity 0.3s ease, visibility 0.3s ease; } @media (prefers-reduced-motion: reduce) { .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: none; } } html.control-sidebar-animate { overflow-x: hidden; } .control-sidebar { bottom: calc(3.5rem + 1px); position: absolute; top: calc(3.5rem + 1px); z-index: 1031; } .control-sidebar, .control-sidebar::before { bottom: calc(3.5rem + 1px); display: none; right: -250px; width: 250px; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar, .control-sidebar::before { transition: none; } } .control-sidebar::before { content: ""; display: block; position: fixed; top: 0; z-index: -1; } body.text-sm .control-sidebar { bottom: calc(2.9365rem + 1px); top: calc(2.93725rem + 1px); } .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .main-footer.text-sm ~ .control-sidebar { bottom: calc(2.9365rem + 1px); } .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: margin-right 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: none; } } .control-sidebar-open .control-sidebar { display: block !important; } .control-sidebar-open .control-sidebar, .control-sidebar-open .control-sidebar::before { right: 0; } .control-sidebar-open.control-sidebar-push .content-wrapper, .control-sidebar-open.control-sidebar-push .main-footer, .control-sidebar-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-slide-open .control-sidebar { display: block; } .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { right: 0; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { transition: none; } } .control-sidebar-slide-open.control-sidebar-push .content-wrapper, .control-sidebar-slide-open.control-sidebar-push .main-footer, .control-sidebar-slide-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-slide-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-dark { background-color: #343a40; } .control-sidebar-dark, .control-sidebar-dark a, .control-sidebar-dark .nav-link { color: #c2c7d0; } .control-sidebar-dark a:hover { color: #fff; } .control-sidebar-dark h1, .control-sidebar-dark h2, .control-sidebar-dark h3, .control-sidebar-dark h4, .control-sidebar-dark h5, .control-sidebar-dark h6, .control-sidebar-dark label { color: #fff; } .control-sidebar-dark .nav-tabs { background-color: rgba(255, 255, 255, 0.1); border-bottom: 0; margin-bottom: 5px; } .control-sidebar-dark .nav-tabs .nav-item { margin: 0; } .control-sidebar-dark .nav-tabs .nav-link { border-radius: 0; padding: 10px 20px; position: relative; text-align: center; } .control-sidebar-dark .nav-tabs .nav-link, .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border: 0; } .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border-bottom-color: transparent; border-left-color: transparent; border-top-color: transparent; color: #fff; } .control-sidebar-dark .nav-tabs .nav-link.active { background-color: #343a40; } .control-sidebar-dark .tab-pane { padding: 10px 15px; } .control-sidebar-light { color: #4b545c; background-color: #fff; border-left: 1px solid #dee2e6; } .text-sm .dropdown-menu { font-size: 0.875rem !important; } .text-sm .dropdown-toggle::after { vertical-align: .2rem; } .dropdown-item-title { font-size: 1rem; margin: 0; } .dropdown-icon::after { margin-left: 0; } .dropdown-menu-lg { max-width: 300px; min-width: 280px; padding: 0; } .dropdown-menu-lg .dropdown-divider { margin: 0; } .dropdown-menu-lg .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-lg p { margin: 0; white-space: normal; } .dropdown-submenu { position: relative; } .dropdown-submenu > a::after { border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; float: right; margin-left: .5rem; margin-top: .5rem; } .dropdown-submenu > .dropdown-menu { left: 100%; margin-left: 0; margin-top: 0; top: 0; } .dropdown-hover:hover > .dropdown-menu, .dropdown-hover.nav-item.dropdown:hover > .dropdown-menu, .dropdown-hover .dropdown-submenu:hover > .dropdown-menu, .dropdown-hover.dropdown-submenu:hover > .dropdown-menu { display: block; } .dropdown-menu-xl { max-width: 420px; min-width: 360px; padding: 0; } .dropdown-menu-xl .dropdown-divider { margin: 0; } .dropdown-menu-xl .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-xl p { margin: 0; white-space: normal; } .dropdown-footer, .dropdown-header { display: block; font-size: 0.875rem; padding: 0.5rem 1rem; text-align: center; } .open:not(.dropup) > .animated-dropdown-menu { -webkit-animation: flipInX 0.7s both; animation: flipInX 0.7s both; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; } .navbar-custom-menu > .navbar-nav > li { position: relative; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 0; left: auto; } @media (max-width: 767.98px) { .navbar-custom-menu > .navbar-nav { float: right; } .navbar-custom-menu > .navbar-nav > li { position: static; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 5%; left: auto; border: 1px solid #ddd; background-color: #fff; } } .navbar-nav > .user-menu > .nav-link::after { content: none; } .navbar-nav > .user-menu > .dropdown-menu { border-top-left-radius: 0; border-top-right-radius: 0; padding: 0; width: 280px; } .navbar-nav > .user-menu > .dropdown-menu, .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header { height: 175px; padding: 10px; text-align: center; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > img { z-index: 5; height: 90px; width: 90px; border: 3px solid; border-color: transparent; border-color: rgba(255, 255, 255, 0.2); } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p { z-index: 5; font-size: 17px; margin-top: 10px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p > small { display: block; font-size: 12px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom: 1px solid #495057; border-top: 1px solid #dee2e6; padding: 15px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body::after { display: block; clear: both; content: ""; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-body a { background-color: #fff !important; color: #495057 !important; } } .navbar-nav > .user-menu > .dropdown-menu > .user-footer { background-color: #f8f9fa; padding: 10px; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer::after { display: block; clear: both; content: ""; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default { color: #6c757d; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:hover { background-color: #f8f9fa; } } .navbar-nav > .user-menu .user-image { border-radius: 50%; float: left; height: 2.1rem; margin-right: 10px; margin-top: -2px; width: 2.1rem; } @media (min-width: 576px) { .navbar-nav > .user-menu .user-image { float: none; line-height: 10px; margin-right: .4rem; margin-top: -8px; } } .dark-mode .dropdown-menu { background-color: #343a40; color: #fff; } .dark-mode .dropdown-item { color: #fff; } .dark-mode .dropdown-item:focus, .dark-mode .dropdown-item:hover { background-color: #3f474e; } .dark-mode .dropdown-divider { border-color: #6c757d; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer { background-color: #3a4047; color: #fff; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default { color: #fff; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:hover, .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:focus { background-color: #3f474e; color: #dee2e6; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:focus { background-color: #454d55; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-color: #6c757d; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a { background-color: transparent !important; color: #fff !important; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a:hover, .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a:focus { color: #ced4da !important; } .nav-pills .nav-link { color: #6c757d; } .nav-pills .nav-link:not(.active):hover { color: #007bff; } .nav-pills .nav-item.dropdown.show .nav-link:hover { color: #fff; } .nav-tabs.flex-column { border-bottom: 0; border-right: 1px solid #dee2e6; } .nav-tabs.flex-column .nav-link { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; margin-right: -1px; } .nav-tabs.flex-column .nav-link:hover, .nav-tabs.flex-column .nav-link:focus { border-color: #e9ecef transparent #e9ecef #e9ecef; } .nav-tabs.flex-column .nav-link.active, .nav-tabs.flex-column .nav-item.show .nav-link { border-color: #dee2e6 transparent #dee2e6 #dee2e6; } .nav-tabs.flex-column.nav-tabs-right { border-left: 1px solid #dee2e6; border-right: 0; } .nav-tabs.flex-column.nav-tabs-right .nav-link { border-bottom-left-radius: 0; border-bottom-right-radius: 0.25rem; border-top-left-radius: 0; border-top-right-radius: 0.25rem; margin-left: -1px; } .nav-tabs.flex-column.nav-tabs-right .nav-link:hover, .nav-tabs.flex-column.nav-tabs-right .nav-link:focus { border-color: #e9ecef #e9ecef #e9ecef transparent; } .nav-tabs.flex-column.nav-tabs-right .nav-link.active, .nav-tabs.flex-column.nav-tabs-right .nav-item.show .nav-link { border-color: #dee2e6 #dee2e6 #dee2e6 transparent; } .navbar-no-expand { -ms-flex-direction: row; flex-direction: row; } .navbar-no-expand .nav-link { padding-left: 1rem; padding-right: 1rem; } .navbar-no-expand .dropdown-menu { position: absolute; } .navbar-light { background-color: #f8f9fa; } .navbar-dark { background-color: #343a40; border-color: #4b545c; } .navbar-primary { background-color: #007bff; color: #fff; } .navbar-primary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar, .navbar-primary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus, .navbar-primary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-primary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar, .navbar-primary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus, .navbar-primary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-secondary { background-color: #6c757d; color: #fff; } .navbar-secondary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar, .navbar-secondary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus, .navbar-secondary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-secondary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar, .navbar-secondary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus, .navbar-secondary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-success { background-color: #28a745; color: #fff; } .navbar-success.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar, .navbar-success.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus, .navbar-success.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-success.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar, .navbar-success.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus, .navbar-success.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-info { background-color: #17a2b8; color: #fff; } .navbar-info.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar, .navbar-info.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus, .navbar-info.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-info.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar, .navbar-info.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus, .navbar-info.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-warning { background-color: #ffc107; color: #1f2d3d; } .navbar-warning.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar, .navbar-warning.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus, .navbar-warning.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-warning.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar, .navbar-warning.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus, .navbar-warning.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-danger { background-color: #dc3545; color: #fff; } .navbar-danger.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar, .navbar-danger.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus, .navbar-danger.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-danger.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar, .navbar-danger.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus, .navbar-danger.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-lightblue { background-color: #3c8dbc; color: #fff; } .navbar-lightblue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar, .navbar-lightblue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3781ad; border-color: #317399; color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus, .navbar-lightblue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #367fa9; border-color: #317399 !important; color: #343a40; } .navbar-lightblue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar, .navbar-lightblue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #4897c5; border-color: #5ba2cb; color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus, .navbar-lightblue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4c99c6; border-color: #5ba2cb !important; color: #fff; } .navbar-navy { background-color: #001f3f; color: #fff; } .navbar-navy.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar, .navbar-navy.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00152b; border-color: #000811; color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus, .navbar-navy.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #001226; border-color: #000811 !important; color: #343a40; } .navbar-navy.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar, .navbar-navy.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #002953; border-color: #00366d; color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus, .navbar-navy.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #002c59; border-color: #00366d !important; color: #fff; } .navbar-olive { background-color: #3d9970; color: #fff; } .navbar-olive.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar, .navbar-olive.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #378a65; border-color: #307858; color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus, .navbar-olive.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #368763; border-color: #307858 !important; color: #343a40; } .navbar-olive.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar, .navbar-olive.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #43a87b; border-color: #4cb888; color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus, .navbar-olive.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #44ab7d; border-color: #4cb888 !important; color: #fff; } .navbar-lime { background-color: #01ff70; color: #1f2d3d; } .navbar-lime.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar, .navbar-lime.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00ec67; border-color: #00d25c; color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus, .navbar-lime.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00e765; border-color: #00d25c !important; color: #343a40; } .navbar-lime.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar, .navbar-lime.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #15ff7b; border-color: #2fff8a; color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus, .navbar-lime.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1bff7e; border-color: #2fff8a !important; color: #fff; } .navbar-fuchsia { background-color: #f012be; color: #fff; } .navbar-fuchsia.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar, .navbar-fuchsia.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df0eb0; border-color: #c70d9d; color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus, .navbar-fuchsia.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #db0ead; border-color: #c70d9d !important; color: #343a40; } .navbar-fuchsia.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar, .navbar-fuchsia.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f125c3; border-color: #f33dca; color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus, .navbar-fuchsia.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f22ac5; border-color: #f33dca !important; color: #fff; } .navbar-maroon { background-color: #d81b60; color: #fff; } .navbar-maroon.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar, .navbar-maroon.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #c61958; border-color: #af164e; color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus, .navbar-maroon.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #c11856; border-color: #af164e !important; color: #343a40; } .navbar-maroon.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar, .navbar-maroon.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e4246a; border-color: #e63a79; color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus, .navbar-maroon.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e4286d; border-color: #e63a79 !important; color: #fff; } .navbar-blue { background-color: #007bff; color: #fff; } .navbar-blue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar, .navbar-blue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus, .navbar-blue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-blue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar, .navbar-blue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus, .navbar-blue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-indigo { background-color: #6610f2; color: #fff; } .navbar-indigo.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar, .navbar-indigo.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #5d0ce1; border-color: #530bc9; color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus, .navbar-indigo.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #5b0cdd; border-color: #530bc9 !important; color: #343a40; } .navbar-indigo.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar, .navbar-indigo.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7223f3; border-color: #823cf4; color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus, .navbar-indigo.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7528f3; border-color: #823cf4 !important; color: #fff; } .navbar-purple { background-color: #6f42c1; color: #fff; } .navbar-purple.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar, .navbar-purple.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #663bb4; border-color: #5b35a0; color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus, .navbar-purple.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #643ab0; border-color: #5b35a0 !important; color: #343a40; } .navbar-purple.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar, .navbar-purple.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7b51c6; border-color: #8965cc; color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus, .navbar-purple.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7e55c7; border-color: #8965cc !important; color: #fff; } .navbar-pink { background-color: #e83e8c; color: #fff; } .navbar-pink.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar, .navbar-pink.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e62c81; border-color: #de1a74; color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus, .navbar-pink.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e5277e; border-color: #de1a74 !important; color: #343a40; } .navbar-pink.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar, .navbar-pink.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5097; border-color: #ed67a4; color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus, .navbar-pink.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #eb559a; border-color: #ed67a4 !important; color: #fff; } .navbar-red { background-color: #dc3545; color: #fff; } .navbar-red.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar, .navbar-red.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus, .navbar-red.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-red.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar, .navbar-red.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus, .navbar-red.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-orange { background-color: #fd7e14; color: #1f2d3d; } .navbar-orange.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar, .navbar-orange.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fa7302; border-color: #e16702; color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus, .navbar-orange.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f57102; border-color: #e16702 !important; color: #343a40; } .navbar-orange.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar, .navbar-orange.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fd8928; border-color: #fd9742; color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus, .navbar-orange.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #fd8c2d; border-color: #fd9742 !important; color: #fff; } .navbar-yellow { background-color: #ffc107; color: #1f2d3d; } .navbar-yellow.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar, .navbar-yellow.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus, .navbar-yellow.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-yellow.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar, .navbar-yellow.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus, .navbar-yellow.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-green { background-color: #28a745; color: #fff; } .navbar-green.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar, .navbar-green.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus, .navbar-green.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-green.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar, .navbar-green.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus, .navbar-green.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-teal { background-color: #20c997; color: #fff; } .navbar-teal.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar, .navbar-teal.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1db78a; border-color: #1aa179; color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus, .navbar-teal.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1cb386; border-color: #1aa179 !important; color: #343a40; } .navbar-teal.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar, .navbar-teal.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #23dba4; border-color: #38dfae; color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus, .navbar-teal.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #26dca6; border-color: #38dfae !important; color: #fff; } .navbar-cyan { background-color: #17a2b8; color: #fff; } .navbar-cyan.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar, .navbar-cyan.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus, .navbar-cyan.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-cyan.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar, .navbar-cyan.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus, .navbar-cyan.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-white { background-color: #fff; color: #1f2d3d; } .navbar-white.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar, .navbar-white.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: whitesmoke; border-color: #e8e8e8; color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus, .navbar-white.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f2f2f2; border-color: #e8e8e8 !important; color: #343a40; } .navbar-white.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar, .navbar-white.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: white; border-color: white; color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus, .navbar-white.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: white; border-color: white !important; color: #fff; } .navbar-gray { background-color: #6c757d; color: #fff; } .navbar-gray.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar, .navbar-gray.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus, .navbar-gray.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-gray.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar, .navbar-gray.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus, .navbar-gray.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-gray-dark { background-color: #343a40; color: #fff; } .navbar-gray-dark.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar, .navbar-gray-dark.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2b3035; border-color: #1f2327; color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus, .navbar-gray-dark.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #292d32; border-color: #1f2327 !important; color: #343a40; } .navbar-gray-dark.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar, .navbar-gray-dark.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3d444b; border-color: #495159; color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus, .navbar-gray-dark.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #3f474e; border-color: #495159 !important; color: #fff; } .navbar-nav-not-expanded { -ms-flex-direction: row; flex-direction: row; } .navbar-nav-not-expanded .dropdown-menu { position: absolute; } .navbar-nav-not-expanded .nav-link { padding-right: 1rem; padding-left: 1rem; } .dark-mode .nav-pills .nav-link { color: #ced4da; } .dark-mode .nav-tabs { border-color: #56606a; } .dark-mode .nav-tabs .nav-link:focus, .dark-mode .nav-tabs .nav-link:hover { border-color: #56606a; } .dark-mode .nav-tabs .nav-item.show .nav-link, .dark-mode .nav-tabs .nav-link.active { background-color: #343a40; border-color: #56606a #56606a transparent #56606a; color: #fff; } .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link.active, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:hover, .dark-mode .nav-tabs.flex-column .nav-link.active, .dark-mode .nav-tabs.flex-column .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-link:hover { border-color: #56606a transparent #56606a #56606a; } .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:hover, .dark-mode .nav-tabs.flex-column .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-link:hover { background-color: #3f474e; } .dark-mode .nav-tabs.flex-column.nav-tabs-right { border-color: #56606a; } .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link.active, .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link:focus, .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link:hover { border-color: #56606a #56606a #56606a transparent; } .dark-mode .navbar-light { background-color: #f8f9fa; } .dark-mode .navbar-dark { background-color: #343a40; border-color: #4b545c; } .dark-mode .navbar-primary { background-color: #3f6791; color: #fff; } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar, .dark-mode .navbar-primary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #395d83; border-color: #315071; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus, .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #375a7f; border-color: #315071 !important; color: #343a40; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar, .dark-mode .navbar-primary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45719f; border-color: #4d7eb1; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4774a3; border-color: #4d7eb1 !important; color: #fff; } .dark-mode .navbar-secondary { background-color: #6c757d; color: #fff; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar, .dark-mode .navbar-secondary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus, .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar, .dark-mode .navbar-secondary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .dark-mode .navbar-success { background-color: #00bc8c; color: #fff; } .dark-mode .navbar-success.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar, .dark-mode .navbar-success.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00a87d; border-color: #008e6a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus, .dark-mode .navbar-success.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00a379; border-color: #008e6a !important; color: #343a40; } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar, .dark-mode .navbar-success.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00d09b; border-color: #00eaae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00d69f; border-color: #00eaae !important; color: #fff; } .dark-mode .navbar-info { background-color: #3498db; color: #fff; } .dark-mode .navbar-info.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar, .dark-mode .navbar-info.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #268fd5; border-color: #2280bf; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus, .dark-mode .navbar-info.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #258cd1; border-color: #2280bf !important; color: #343a40; } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar, .dark-mode .navbar-info.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45a1de; border-color: #5bace2; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4aa3df; border-color: #5bace2 !important; color: #fff; } .dark-mode .navbar-warning { background-color: #f39c12; color: #1f2d3d; } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar, .dark-mode .navbar-warning.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e5910c; border-color: #cd820a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus, .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e08e0b; border-color: #cd820a !important; color: #343a40; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar, .dark-mode .navbar-warning.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f4a425; border-color: #f5ae3e; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f4a62a; border-color: #f5ae3e !important; color: #fff; } .dark-mode .navbar-danger { background-color: #e74c3c; color: #fff; } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar, .dark-mode .navbar-danger.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e53b2a; border-color: #da2d1b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus, .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e43725; border-color: #da2d1b !important; color: #343a40; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar, .dark-mode .navbar-danger.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e95d4e; border-color: #ec7265; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea6153; border-color: #ec7265 !important; color: #fff; } .dark-mode .navbar-lightblue { background-color: #86bad8; color: #1f2d3d; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar, .dark-mode .navbar-lightblue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #76b1d3; border-color: #63a6cd; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus, .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #72afd2; border-color: #63a6cd !important; color: #343a40; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar, .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #95c3dd; border-color: #a9cee3; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #99c5de; border-color: #a9cee3 !important; color: #fff; } .dark-mode .navbar-navy { background-color: #002c59; color: #fff; } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar, .dark-mode .navbar-navy.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #002244; border-color: #00152b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus, .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #001f3f; border-color: #00152b !important; color: #343a40; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar, .dark-mode .navbar-navy.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00366d; border-color: #004286; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #003872; border-color: #004286 !important; color: #fff; } .dark-mode .navbar-olive { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar, .dark-mode .navbar-olive.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #66c299; border-color: #53bb8d; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus, .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #62c096; border-color: #53bb8d !important; color: #343a40; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar, .dark-mode .navbar-olive.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #83ceac; border-color: #95d5b8; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #87cfaf; border-color: #95d5b8 !important; color: #fff; } .dark-mode .navbar-lime { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar, .dark-mode .navbar-lime.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #53ff9e; border-color: #39ff90; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus, .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4eff9b; border-color: #39ff90 !important; color: #343a40; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar, .dark-mode .navbar-lime.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7bffb5; border-color: #95ffc3; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #81ffb8; border-color: #95ffc3 !important; color: #fff; } .dark-mode .navbar-fuchsia { background-color: #f672d8; color: #1f2d3d; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar, .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f55fd3; border-color: #f347cc; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus, .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f55ad2; border-color: #f347cc !important; color: #343a40; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar, .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f785de; border-color: #f99de4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f88adf; border-color: #f99de4 !important; color: #fff; } .dark-mode .navbar-maroon { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar, .dark-mode .navbar-maroon.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5a8f; border-color: #e8447f; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus, .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea568c; border-color: #e8447f !important; color: #343a40; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar, .dark-mode .navbar-maroon.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ef7ea8; border-color: #f295b7; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f083ab; border-color: #f295b7 !important; color: #fff; } .dark-mode .navbar-blue { background-color: #3f6791; color: #fff; } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar, .dark-mode .navbar-blue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #395d83; border-color: #315071; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus, .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #375a7f; border-color: #315071 !important; color: #343a40; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar, .dark-mode .navbar-blue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45719f; border-color: #4d7eb1; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4774a3; border-color: #4d7eb1 !important; color: #fff; } .dark-mode .navbar-indigo { background-color: #6610f2; color: #fff; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar, .dark-mode .navbar-indigo.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #5d0ce1; border-color: #530bc9; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus, .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #5b0cdd; border-color: #530bc9 !important; color: #343a40; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar, .dark-mode .navbar-indigo.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7223f3; border-color: #823cf4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7528f3; border-color: #823cf4 !important; color: #fff; } .dark-mode .navbar-purple { background-color: #6f42c1; color: #fff; } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar, .dark-mode .navbar-purple.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #663bb4; border-color: #5b35a0; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus, .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #643ab0; border-color: #5b35a0 !important; color: #343a40; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar, .dark-mode .navbar-purple.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7b51c6; border-color: #8965cc; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7e55c7; border-color: #8965cc !important; color: #fff; } .dark-mode .navbar-pink { background-color: #e83e8c; color: #fff; } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar, .dark-mode .navbar-pink.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e62c81; border-color: #de1a74; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus, .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e5277e; border-color: #de1a74 !important; color: #343a40; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar, .dark-mode .navbar-pink.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5097; border-color: #ed67a4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #eb559a; border-color: #ed67a4 !important; color: #fff; } .dark-mode .navbar-red { background-color: #e74c3c; color: #fff; } .dark-mode .navbar-red.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar, .dark-mode .navbar-red.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e53b2a; border-color: #da2d1b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus, .dark-mode .navbar-red.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e43725; border-color: #da2d1b !important; color: #343a40; } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar, .dark-mode .navbar-red.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e95d4e; border-color: #ec7265; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea6153; border-color: #ec7265 !important; color: #fff; } .dark-mode .navbar-orange { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar, .dark-mode .navbar-orange.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fa7302; border-color: #e16702; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus, .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f57102; border-color: #e16702 !important; color: #343a40; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar, .dark-mode .navbar-orange.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fd8928; border-color: #fd9742; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #fd8c2d; border-color: #fd9742 !important; color: #fff; } .dark-mode .navbar-yellow { background-color: #f39c12; color: #1f2d3d; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar, .dark-mode .navbar-yellow.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e5910c; border-color: #cd820a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus, .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e08e0b; border-color: #cd820a !important; color: #343a40; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar, .dark-mode .navbar-yellow.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f4a425; border-color: #f5ae3e; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f4a62a; border-color: #f5ae3e !important; color: #fff; } .dark-mode .navbar-green { background-color: #00bc8c; color: #fff; } .dark-mode .navbar-green.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar, .dark-mode .navbar-green.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00a87d; border-color: #008e6a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus, .dark-mode .navbar-green.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00a379; border-color: #008e6a !important; color: #343a40; } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar, .dark-mode .navbar-green.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00d09b; border-color: #00eaae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00d69f; border-color: #00eaae !important; color: #fff; } .dark-mode .navbar-teal { background-color: #20c997; color: #fff; } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar, .dark-mode .navbar-teal.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1db78a; border-color: #1aa179; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus, .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1cb386; border-color: #1aa179 !important; color: #343a40; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar, .dark-mode .navbar-teal.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #23dba4; border-color: #38dfae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #26dca6; border-color: #38dfae !important; color: #fff; } .dark-mode .navbar-cyan { background-color: #3498db; color: #fff; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar, .dark-mode .navbar-cyan.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #268fd5; border-color: #2280bf; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus, .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #258cd1; border-color: #2280bf !important; color: #343a40; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar, .dark-mode .navbar-cyan.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45a1de; border-color: #5bace2; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4aa3df; border-color: #5bace2 !important; color: #fff; } .dark-mode .navbar-white { background-color: #fff; color: #1f2d3d; } .dark-mode .navbar-white.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar, .dark-mode .navbar-white.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: whitesmoke; border-color: #e8e8e8; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus, .dark-mode .navbar-white.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f2f2f2; border-color: #e8e8e8 !important; color: #343a40; } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar, .dark-mode .navbar-white.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: white; border-color: white; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: white; border-color: white !important; color: #fff; } .dark-mode .navbar-gray { background-color: #6c757d; color: #fff; } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar, .dark-mode .navbar-gray.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus, .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar, .dark-mode .navbar-gray.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .dark-mode .navbar-gray-dark { background-color: #343a40; color: #fff; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar, .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2b3035; border-color: #1f2327; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus, .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #292d32; border-color: #1f2327 !important; color: #343a40; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar, .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3d444b; border-color: #495159; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #3f474e; border-color: #495159 !important; color: #fff; } .pagination-month .page-item { justify-self: stretch; } .pagination-month .page-item .page-link { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; box-shadow: none; } .pagination-month .page-item:first-child .page-link, .pagination-month .page-item:last-child .page-link { height: 100%; font-size: 1.25rem; } .pagination-month .page-item .page-month { margin-bottom: 0; font-size: 1.25rem; font-weight: 700; } .pagination-month .page-item .page-year { margin-bottom: 0; } .pagination-month.pagination-lg .page-month { font-size: 1.5625rem; } .pagination-month.pagination-sm .page-month { font-size: 1rem; } .dark-mode .page-item.disabled a, .dark-mode .page-item.disabled .page-link { background-color: #3a4047 !important; border-color: #6c757d !important; color: #6c757d; } .dark-mode .page-item .page-link { color: #3f6791; } .dark-mode .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .page-item.active .page-link:hover, .dark-mode .page-item.active .page-link:focus { color: #ced4da !important; } .dark-mode .page-item:not(.active) .page-link { background-color: #343a40; border-color: #6c757d; } .dark-mode .page-item:not(.active) .page-link:hover, .dark-mode .page-item:not(.active) .page-link:focus { color: #4774a3; background-color: #3f474e; } .form-group.has-icon { position: relative; } .form-group.has-icon .form-control { padding-right: 35px; } .form-group.has-icon .form-icon { background-color: transparent; border: 0; cursor: pointer; font-size: 1rem; padding: 0.375rem 0.75rem; position: absolute; right: 3px; top: 0; } .btn-group-vertical .btn.btn-flat:first-of-type, .btn-group-vertical .btn.btn-flat:last-of-type { border-radius: 0; } .form-control-feedback.fa, .form-control-feedback.fas, .form-control-feedback.far, .form-control-feedback.fab, .form-control-feedback.fal, .form-control-feedback.fad, .form-control-feedback.svg-inline--fa, .form-control-feedback.ion { line-height: calc(2.25rem + 2px); } .input-lg + .form-control-feedback.fa, .input-lg + .form-control-feedback.fas, .input-lg + .form-control-feedback.far, .input-lg + .form-control-feedback.fab, .input-lg + .form-control-feedback.fal, .input-lg + .form-control-feedback.fad, .input-lg + .form-control-feedback.svg-inline--fa, .input-lg + .form-control-feedback.ion, .input-group-lg + .form-control-feedback.fa, .input-group-lg + .form-control-feedback.fas, .input-group-lg + .form-control-feedback.far, .input-group-lg + .form-control-feedback.fab, .input-group-lg + .form-control-feedback.fal, .input-group-lg + .form-control-feedback.fad, .input-group-lg + .form-control-feedback.svg-inline--fa, .input-group-lg + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .form-group-lg .form-control + .form-control-feedback.fa, .form-group-lg .form-control + .form-control-feedback.fas, .form-group-lg .form-control + .form-control-feedback.far, .form-group-lg .form-control + .form-control-feedback.fab, .form-group-lg .form-control + .form-control-feedback.fal, .form-group-lg .form-control + .form-control-feedback.fad, .form-group-lg .form-control + .form-control-feedback.svg-inline--fa, .form-group-lg .form-control + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .input-sm + .form-control-feedback.fa, .input-sm + .form-control-feedback.fas, .input-sm + .form-control-feedback.far, .input-sm + .form-control-feedback.fab, .input-sm + .form-control-feedback.fal, .input-sm + .form-control-feedback.fad, .input-sm + .form-control-feedback.svg-inline--fa, .input-sm + .form-control-feedback.ion, .input-group-sm + .form-control-feedback.fa, .input-group-sm + .form-control-feedback.fas, .input-group-sm + .form-control-feedback.far, .input-group-sm + .form-control-feedback.fab, .input-group-sm + .form-control-feedback.fal, .input-group-sm + .form-control-feedback.fad, .input-group-sm + .form-control-feedback.svg-inline--fa, .input-group-sm + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } .form-group-sm .form-control + .form-control-feedback.fa, .form-group-sm .form-control + .form-control-feedback.fas, .form-group-sm .form-control + .form-control-feedback.far, .form-group-sm .form-control + .form-control-feedback.fab, .form-group-sm .form-control + .form-control-feedback.fal, .form-group-sm .form-control + .form-control-feedback.fad, .form-group-sm .form-control + .form-control-feedback.svg-inline--fa, .form-group-sm .form-control + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } label:not(.form-check-label):not(.custom-file-label) { font-weight: 700; } .warning-feedback { font-size: 80%; color: #ffc107; display: none; margin-top: 0.25rem; width: 100%; } .warning-tooltip { border-radius: 0.25rem; font-size: 0.875rem; background-color: rgba(255, 193, 7, 0.9); color: #1f2d3d; display: none; line-height: 1.5; margin-top: .1rem; max-width: 100%; padding: 0.25rem 0.5rem; position: absolute; top: 100%; z-index: 5; } .form-control.is-warning { border-color: #ffc107; } .form-control.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .form-control.is-warning ~ .warning-feedback, .form-control.is-warning ~ .warning-tooltip { display: block; } textarea.form-control.is-warning { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .custom-select.is-warning { border-color: #ffc107; } .custom-select.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-select.is-warning ~ .warning-feedback, .custom-select.is-warning ~ .warning-tooltip { display: block; } .form-control-file.is-warning ~ .warning-feedback, .form-control-file.is-warning ~ .warning-tooltip { display: block; } .form-check-input.is-warning ~ .form-check-label { color: #ffc107; } .form-check-input.is-warning ~ .warning-feedback, .form-check-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning ~ .custom-control-label { color: #ffc107; } .custom-control-input.is-warning ~ .custom-control-label::before { border-color: #ffc107; } .custom-control-input.is-warning ~ .warning-feedback, .custom-control-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning:checked ~ .custom-control-label::before { background-color: #ffce3a; border-color: #ffce3a; } .custom-control-input.is-warning:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-control-input.is-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffc107; } .custom-file-input.is-warning ~ .custom-file-label { border-color: #ffc107; } .custom-file-input.is-warning ~ .warning-feedback, .custom-file-input.is-warning ~ .warning-tooltip { display: block; } .custom-file-input.is-warning:focus ~ .custom-file-label { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } body.text-sm .input-group-text { font-size: 0.875rem; } .form-control.form-control-border, .custom-select.form-control-border { border-top: 0; border-left: 0; border-right: 0; border-radius: 0; box-shadow: inherit; } .form-control.form-control-border.border-width-2, .custom-select.form-control-border.border-width-2 { border-bottom-width: 2px; } .form-control.form-control-border.border-width-3, .custom-select.form-control-border.border-width-3 { border-bottom-width: 3px; } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-primary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-primary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-secondary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-success .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-success .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-info .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-info .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-warning .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-warning .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-danger .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-danger .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-off-light .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::after { background-color: #aeb9c5; } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-on-light .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-off-lightblue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::after { background-color: #1d455b; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-color: #acd0e5; } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-off-navy .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::after { background-color: #006ad8; } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-off-olive .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::after { background-color: #193e2d; } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-on-olive .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::after { background-color: #99d6bb; } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-off-lime .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::after { background-color: #008138; } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-on-lime .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::after { background-color: #9affc6; } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-off-fuchsia .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::after { background-color: #7b0861; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-color: #f9a2e5; } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-off-maroon .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::after { background-color: #670d2e; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::after { background-color: #f29aba; } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-blue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-blue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-off-indigo .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::after { background-color: #33077c; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::after { background-color: #c3a1fa; } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-off-purple .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::after { background-color: #382063; } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-on-purple .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::after { background-color: #c7b5e7; } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-off-pink .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::after { background-color: #95124e; } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-on-pink .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c7dd; } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-red .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-red .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-off-orange .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::after { background-color: #904201; } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-on-orange .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::after { background-color: #fed1ac; } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-yellow .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-green .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-green .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-off-teal .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::after { background-color: #0e5b44; } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-on-teal .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::after { background-color: #94eed3; } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-cyan .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-off-white .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::after { background-color: #bfbfbf; } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-on-white .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-gray .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-gray .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-gray-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-range.custom-range-primary:focus { outline: none; } .custom-range.custom-range-primary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-secondary:focus { outline: none; } .custom-range.custom-range-secondary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-success:focus { outline: none; } .custom-range.custom-range-success:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-success::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-success::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-success::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-info:focus { outline: none; } .custom-range.custom-range-info:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-warning:focus { outline: none; } .custom-range.custom-range-warning:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-danger:focus { outline: none; } .custom-range.custom-range-danger:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-light:focus { outline: none; } .custom-range.custom-range-light:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light::-webkit-slider-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-light::-moz-range-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-light::-ms-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-ms-thumb:active { background-color: white; } .custom-range.custom-range-dark:focus { outline: none; } .custom-range.custom-range-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-ms-thumb:active { background-color: #88939e; } .custom-range.custom-range-lightblue:focus { outline: none; } .custom-range.custom-range-lightblue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue::-webkit-slider-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-webkit-slider-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-moz-range-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-moz-range-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-ms-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-ms-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-navy:focus { outline: none; } .custom-range.custom-range-navy:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy::-webkit-slider-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-webkit-slider-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-moz-range-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-moz-range-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-ms-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-ms-thumb:active { background-color: #0077f2; } .custom-range.custom-range-olive:focus { outline: none; } .custom-range.custom-range-olive:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive::-webkit-slider-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-webkit-slider-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-moz-range-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-moz-range-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-ms-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-ms-thumb:active { background-color: #abdec7; } .custom-range.custom-range-lime:focus { outline: none; } .custom-range.custom-range-lime:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime::-webkit-slider-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-webkit-slider-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-moz-range-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-moz-range-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-ms-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-ms-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-fuchsia:focus { outline: none; } .custom-range.custom-range-fuchsia:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia::-webkit-slider-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-webkit-slider-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-moz-range-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-moz-range-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-ms-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-ms-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-maroon:focus { outline: none; } .custom-range.custom-range-maroon:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon::-webkit-slider-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-webkit-slider-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-moz-range-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-moz-range-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-ms-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-ms-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-blue:focus { outline: none; } .custom-range.custom-range-blue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-indigo:focus { outline: none; } .custom-range.custom-range-indigo:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo::-webkit-slider-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-webkit-slider-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-moz-range-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-moz-range-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-ms-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-ms-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-purple:focus { outline: none; } .custom-range.custom-range-purple:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple::-webkit-slider-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-webkit-slider-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-moz-range-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-moz-range-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-ms-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-ms-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-pink:focus { outline: none; } .custom-range.custom-range-pink:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink::-webkit-slider-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-webkit-slider-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-moz-range-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-moz-range-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-ms-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-ms-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-red:focus { outline: none; } .custom-range.custom-range-red:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-orange:focus { outline: none; } .custom-range.custom-range-orange:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange::-webkit-slider-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-webkit-slider-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-moz-range-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-moz-range-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-ms-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-ms-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-yellow:focus { outline: none; } .custom-range.custom-range-yellow:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-green:focus { outline: none; } .custom-range.custom-range-green:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-green::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-green::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-green::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-teal:focus { outline: none; } .custom-range.custom-range-teal:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal::-webkit-slider-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-webkit-slider-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-moz-range-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-moz-range-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-ms-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-ms-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-cyan:focus { outline: none; } .custom-range.custom-range-cyan:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-white:focus { outline: none; } .custom-range.custom-range-white:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white::-webkit-slider-thumb { background-color: #fff; } .custom-range.custom-range-white::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-white::-moz-range-thumb { background-color: #fff; } .custom-range.custom-range-white::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-white::-ms-thumb { background-color: #fff; } .custom-range.custom-range-white::-ms-thumb:active { background-color: white; } .custom-range.custom-range-gray:focus { outline: none; } .custom-range.custom-range-gray:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray-dark:focus { outline: none; } .custom-range.custom-range-gray-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-ms-thumb:active { background-color: #88939e; } .custom-control-input-primary:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-primary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-primary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-primary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-primary:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-primary:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-secondary:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-secondary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-secondary:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-secondary:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-success:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-success.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-success.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-success:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-success:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-success:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-info:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-info.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-info.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-info:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-info:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-info:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-warning:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-warning.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-warning.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-warning:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-warning:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-danger:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-danger.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-danger.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-danger:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-danger:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-danger:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-light:checked ~ .custom-control-label::before { border-color: #f8f9fa; background-color: #f8f9fa; } .custom-control-input-light.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f8f9fa' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-light.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f8f9fa'/%3E%3C/svg%3E") !important; } .custom-control-input-light:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(248, 249, 250, 0.25); } .custom-control-input-light:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-light:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-lightblue:checked ~ .custom-control-label::before { border-color: #3c8dbc; background-color: #3c8dbc; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233c8dbc' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233c8dbc'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(60, 141, 188, 0.25); } .custom-control-input-lightblue:focus:not(:checked) ~ .custom-control-label::before { border-color: #99c5de; } .custom-control-input-lightblue:not(:disabled):active ~ .custom-control-label::before { background-color: #c0dbeb; border-color: #c0dbeb; } .custom-control-input-navy:checked ~ .custom-control-label::before { border-color: #001f3f; background-color: #001f3f; } .custom-control-input-navy.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23001f3f' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-navy.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23001f3f'/%3E%3C/svg%3E") !important; } .custom-control-input-navy:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 31, 63, 0.25); } .custom-control-input-navy:focus:not(:checked) ~ .custom-control-label::before { border-color: #005ebf; } .custom-control-input-navy:not(:disabled):active ~ .custom-control-label::before { background-color: #0077f2; border-color: #0077f2; } .custom-control-input-olive:checked ~ .custom-control-label::before { border-color: #3d9970; background-color: #3d9970; } .custom-control-input-olive.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233d9970' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-olive.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233d9970'/%3E%3C/svg%3E") !important; } .custom-control-input-olive:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(61, 153, 112, 0.25); } .custom-control-input-olive:focus:not(:checked) ~ .custom-control-label::before { border-color: #87cfaf; } .custom-control-input-olive:not(:disabled):active ~ .custom-control-label::before { background-color: #abdec7; border-color: #abdec7; } .custom-control-input-lime:checked ~ .custom-control-label::before { border-color: #01ff70; background-color: #01ff70; } .custom-control-input-lime.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2301ff70' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lime.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2301ff70'/%3E%3C/svg%3E") !important; } .custom-control-input-lime:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(1, 255, 112, 0.25); } .custom-control-input-lime:focus:not(:checked) ~ .custom-control-label::before { border-color: #81ffb8; } .custom-control-input-lime:not(:disabled):active ~ .custom-control-label::before { background-color: #b4ffd4; border-color: #b4ffd4; } .custom-control-input-fuchsia:checked ~ .custom-control-label::before { border-color: #f012be; background-color: #f012be; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f012be' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f012be'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(240, 18, 190, 0.25); } .custom-control-input-fuchsia:focus:not(:checked) ~ .custom-control-label::before { border-color: #f88adf; } .custom-control-input-fuchsia:not(:disabled):active ~ .custom-control-label::before { background-color: #fbbaec; border-color: #fbbaec; } .custom-control-input-maroon:checked ~ .custom-control-label::before { border-color: #d81b60; background-color: #d81b60; } .custom-control-input-maroon.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23d81b60' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23d81b60'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(216, 27, 96, 0.25); } .custom-control-input-maroon:focus:not(:checked) ~ .custom-control-label::before { border-color: #f083ab; } .custom-control-input-maroon:not(:disabled):active ~ .custom-control-label::before { background-color: #f5b0c9; border-color: #f5b0c9; } .custom-control-input-blue:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-blue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-blue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-blue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-blue:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-blue:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-indigo:checked ~ .custom-control-label::before { border-color: #6610f2; background-color: #6610f2; } .custom-control-input-indigo.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236610f2' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236610f2'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(102, 16, 242, 0.25); } .custom-control-input-indigo:focus:not(:checked) ~ .custom-control-label::before { border-color: #b389f9; } .custom-control-input-indigo:not(:disabled):active ~ .custom-control-label::before { background-color: #d2b9fb; border-color: #d2b9fb; } .custom-control-input-purple:checked ~ .custom-control-label::before { border-color: #6f42c1; background-color: #6f42c1; } .custom-control-input-purple.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236f42c1' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-purple.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236f42c1'/%3E%3C/svg%3E") !important; } .custom-control-input-purple:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(111, 66, 193, 0.25); } .custom-control-input-purple:focus:not(:checked) ~ .custom-control-label::before { border-color: #b8a2e0; } .custom-control-input-purple:not(:disabled):active ~ .custom-control-label::before { background-color: #d5c8ed; border-color: #d5c8ed; } .custom-control-input-pink:checked ~ .custom-control-label::before { border-color: #e83e8c; background-color: #e83e8c; } .custom-control-input-pink.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e83e8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-pink.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e83e8c'/%3E%3C/svg%3E") !important; } .custom-control-input-pink:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(232, 62, 140, 0.25); } .custom-control-input-pink:focus:not(:checked) ~ .custom-control-label::before { border-color: #f6b0d0; } .custom-control-input-pink:not(:disabled):active ~ .custom-control-label::before { background-color: #fbddeb; border-color: #fbddeb; } .custom-control-input-red:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-red.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-red.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-red:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-red:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-red:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-orange:checked ~ .custom-control-label::before { border-color: #fd7e14; background-color: #fd7e14; } .custom-control-input-orange.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fd7e14' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-orange.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fd7e14'/%3E%3C/svg%3E") !important; } .custom-control-input-orange:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(253, 126, 20, 0.25); } .custom-control-input-orange:focus:not(:checked) ~ .custom-control-label::before { border-color: #fec392; } .custom-control-input-orange:not(:disabled):active ~ .custom-control-label::before { background-color: #ffdfc5; border-color: #ffdfc5; } .custom-control-input-yellow:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-yellow.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-yellow:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-yellow:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-green:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-green.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-green.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-green:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-green:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-green:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-teal:checked ~ .custom-control-label::before { border-color: #20c997; background-color: #20c997; } .custom-control-input-teal.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2320c997' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-teal.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2320c997'/%3E%3C/svg%3E") !important; } .custom-control-input-teal:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(32, 201, 151, 0.25); } .custom-control-input-teal:focus:not(:checked) ~ .custom-control-label::before { border-color: #7eeaca; } .custom-control-input-teal:not(:disabled):active ~ .custom-control-label::before { background-color: #aaf1dc; border-color: #aaf1dc; } .custom-control-input-cyan:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-cyan.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-cyan:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-cyan:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-white:checked ~ .custom-control-label::before { border-color: #fff; background-color: #fff; } .custom-control-input-white.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-white.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") !important; } .custom-control-input-white:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 255, 255, 0.25); } .custom-control-input-white:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-white:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-gray:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-gray.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-gray:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-gray:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-gray:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-gray-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-gray-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-gray-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-outline ~ .custom-control-label::before { background-color: transparent !important; box-shadow: none; } .custom-control-input-outline:checked ~ .custom-control-label::before { background-color: transparent; } .navbar-dark .btn-navbar, .navbar-dark .form-control-navbar { background-color: #3f474e; border: 1px solid #56606a; color: white; } .navbar-dark .btn-navbar:hover { background-color: #454d55; } .navbar-dark .btn-navbar:focus { background-color: #4b545c; } .navbar-dark .form-control-navbar + .input-group-prepend > .btn-navbar, .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3f474e; color: #fff; border: 1px solid #56606a; border-left: none; } .dark-mode .form-control:not(.form-control-navbar):not(.form-control-sidebar), .dark-mode .custom-select, .dark-mode .custom-file-label, .dark-mode .custom-file-label::after, .dark-mode .custom-control-label::before, .dark-mode .input-group-text { background-color: #343a40; color: #fff; } .dark-mode .form-control:not(.form-control-navbar):not(.form-control-sidebar):not(.is-invalid):not(:focus), .dark-mode .custom-file-label, .dark-mode .custom-file-label::after { border-color: #6c757d; } .dark-mode select { background-color: #343a40; color: #fff; border-color: #6c757d; } .dark-mode .custom-select { background: #343a40 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23fff' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat; } .dark-mode .custom-select[multiple] { background: #343a40; } .dark-mode .input-group-text { border-color: #6c757d; } .dark-mode .custom-control-input:disabled ~ .custom-control-label::before, .dark-mode .custom-control-input[disabled] ~ .custom-control-label::before { background-color: #3f474e; border-color: #6c757d; color: #fff; } .dark-mode input:-webkit-autofill, .dark-mode input:-webkit-autofill:hover, .dark-mode input:-webkit-autofill:focus, .dark-mode textarea:-webkit-autofill, .dark-mode textarea:-webkit-autofill:hover, .dark-mode textarea:-webkit-autofill:focus, .dark-mode select:-webkit-autofill, .dark-mode select:-webkit-autofill:hover, .dark-mode select:-webkit-autofill:focus { -webkit-text-fill-color: #fff; } .dark-mode .custom-range::-webkit-slider-runnable-track { background-color: #454d55; } .dark-mode .custom-range::-moz-range-track { background-color: #454d55; } .dark-mode .custom-range::-ms-track { background-color: #454d55; } .dark-mode .custom-range.custom-range-primary:focus { outline: none; } .dark-mode .custom-range.custom-range-primary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary::-webkit-slider-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-webkit-slider-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-primary::-moz-range-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-moz-range-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-primary::-ms-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-ms-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-secondary:focus { outline: none; } .dark-mode .custom-range.custom-range-secondary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary::-webkit-slider-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-webkit-slider-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-secondary::-moz-range-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-moz-range-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-secondary::-ms-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-ms-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-success:focus { outline: none; } .dark-mode .custom-range.custom-range-success:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success::-webkit-slider-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-webkit-slider-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-success::-moz-range-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-moz-range-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-success::-ms-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-ms-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-info:focus { outline: none; } .dark-mode .custom-range.custom-range-info:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info::-webkit-slider-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-webkit-slider-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-info::-moz-range-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-moz-range-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-info::-ms-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-ms-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-warning:focus { outline: none; } .dark-mode .custom-range.custom-range-warning:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning::-webkit-slider-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-webkit-slider-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-warning::-moz-range-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-moz-range-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-warning::-ms-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-ms-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-danger:focus { outline: none; } .dark-mode .custom-range.custom-range-danger:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger::-webkit-slider-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-webkit-slider-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-danger::-moz-range-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-moz-range-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-danger::-ms-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-ms-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-light:focus { outline: none; } .dark-mode .custom-range.custom-range-light:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light::-webkit-slider-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-light::-moz-range-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-light::-ms-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-dark:focus { outline: none; } .dark-mode .custom-range.custom-range-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark::-webkit-slider-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-webkit-slider-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-dark::-moz-range-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-moz-range-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-dark::-ms-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-ms-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-lightblue:focus { outline: none; } .dark-mode .custom-range.custom-range-lightblue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue::-webkit-slider-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lightblue::-moz-range-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lightblue::-ms-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-navy:focus { outline: none; } .dark-mode .custom-range.custom-range-navy:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy::-webkit-slider-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-webkit-slider-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-navy::-moz-range-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-moz-range-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-navy::-ms-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-ms-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-olive:focus { outline: none; } .dark-mode .custom-range.custom-range-olive:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive::-webkit-slider-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-webkit-slider-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-olive::-moz-range-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-moz-range-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-olive::-ms-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-ms-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-lime:focus { outline: none; } .dark-mode .custom-range.custom-range-lime:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime::-webkit-slider-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lime::-moz-range-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lime::-ms-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia:focus { outline: none; } .dark-mode .custom-range.custom-range-fuchsia:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia::-webkit-slider-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia::-moz-range-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia::-ms-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon:focus { outline: none; } .dark-mode .custom-range.custom-range-maroon:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon::-webkit-slider-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon::-moz-range-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon::-ms-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-blue:focus { outline: none; } .dark-mode .custom-range.custom-range-blue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue::-webkit-slider-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-webkit-slider-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-blue::-moz-range-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-moz-range-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-blue::-ms-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-ms-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-indigo:focus { outline: none; } .dark-mode .custom-range.custom-range-indigo:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo::-webkit-slider-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-webkit-slider-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-indigo::-moz-range-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-moz-range-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-indigo::-ms-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-ms-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-purple:focus { outline: none; } .dark-mode .custom-range.custom-range-purple:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple::-webkit-slider-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-webkit-slider-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-purple::-moz-range-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-moz-range-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-purple::-ms-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-ms-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-pink:focus { outline: none; } .dark-mode .custom-range.custom-range-pink:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink::-webkit-slider-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-webkit-slider-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-pink::-moz-range-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-moz-range-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-pink::-ms-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-ms-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-red:focus { outline: none; } .dark-mode .custom-range.custom-range-red:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red::-webkit-slider-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-webkit-slider-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-red::-moz-range-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-moz-range-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-red::-ms-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-ms-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-orange:focus { outline: none; } .dark-mode .custom-range.custom-range-orange:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange::-webkit-slider-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-webkit-slider-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-orange::-moz-range-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-moz-range-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-orange::-ms-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-ms-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-yellow:focus { outline: none; } .dark-mode .custom-range.custom-range-yellow:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow::-webkit-slider-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-webkit-slider-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-yellow::-moz-range-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-moz-range-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-yellow::-ms-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-ms-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-green:focus { outline: none; } .dark-mode .custom-range.custom-range-green:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green::-webkit-slider-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-webkit-slider-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-green::-moz-range-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-moz-range-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-green::-ms-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-ms-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-teal:focus { outline: none; } .dark-mode .custom-range.custom-range-teal:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal::-webkit-slider-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-webkit-slider-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-teal::-moz-range-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-moz-range-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-teal::-ms-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-ms-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-cyan:focus { outline: none; } .dark-mode .custom-range.custom-range-cyan:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan::-webkit-slider-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-webkit-slider-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-cyan::-moz-range-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-moz-range-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-cyan::-ms-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-ms-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-white:focus { outline: none; } .dark-mode .custom-range.custom-range-white:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white::-webkit-slider-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-white::-moz-range-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-white::-ms-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-gray:focus { outline: none; } .dark-mode .custom-range.custom-range-gray:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray::-webkit-slider-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-webkit-slider-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray::-moz-range-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-moz-range-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray::-ms-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-ms-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray-dark:focus { outline: none; } .dark-mode .custom-range.custom-range-gray-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark::-webkit-slider-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-webkit-slider-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-gray-dark::-moz-range-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-moz-range-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-gray-dark::-ms-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-ms-thumb:active { background-color: #88939e; } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::after { background-color: #182838; } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::after { background-color: #97b4d2; } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::after { background-color: #003d2d; } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::after { background-color: #56ffd4; } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::after { background-color: #16527a; } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::after { background-color: #b6daf2; } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::after { background-color: #7f5006; } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::after { background-color: #fad9a4; } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::after { background-color: #921e12; } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c9c4; } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::after { background-color: #aeb9c5; } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::after { background-color: #367fa9; } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-color: #fafcfd; } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::after { background-color: #0077f2; } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::after { background-color: #368763; } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::after { background-color: #e2f3eb; } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::after { background-color: #00e765; } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::after { background-color: #db0ead; } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::after { background-color: #c11856; } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::after { background-color: #fef4f8; } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::after { background-color: #182838; } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::after { background-color: #97b4d2; } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::after { background-color: #33077c; } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::after { background-color: #c3a1fa; } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::after { background-color: #382063; } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::after { background-color: #c7b5e7; } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::after { background-color: #95124e; } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c7dd; } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::after { background-color: #921e12; } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c9c4; } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::after { background-color: #904201; } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::after { background-color: #fed1ac; } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::after { background-color: #7f5006; } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::after { background-color: #fad9a4; } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::after { background-color: #003d2d; } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::after { background-color: #56ffd4; } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::after { background-color: #0e5b44; } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::after { background-color: #94eed3; } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::after { background-color: #16527a; } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::after { background-color: #b6daf2; } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::after { background-color: #bfbfbf; } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .dark-mode .custom-control-input-primary:checked ~ .custom-control-label::before { border-color: #3f6791; background-color: #3f6791; } .dark-mode .custom-control-input-primary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233f6791' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-primary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233f6791'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-primary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(63, 103, 145, 0.25); } .dark-mode .custom-control-input-primary:focus:not(:checked) ~ .custom-control-label::before { border-color: #85a7ca; } .dark-mode .custom-control-input-primary:not(:disabled):active ~ .custom-control-label::before { background-color: #a9c1da; border-color: #a9c1da; } .dark-mode .custom-control-input-secondary:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .dark-mode .custom-control-input-secondary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-secondary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-secondary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .dark-mode .custom-control-input-secondary:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .dark-mode .custom-control-input-secondary:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .dark-mode .custom-control-input-success:checked ~ .custom-control-label::before { border-color: #00bc8c; background-color: #00bc8c; } .dark-mode .custom-control-input-success.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2300bc8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-success.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2300bc8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-success:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 188, 140, 0.25); } .dark-mode .custom-control-input-success:focus:not(:checked) ~ .custom-control-label::before { border-color: #3dffcd; } .dark-mode .custom-control-input-success:not(:disabled):active ~ .custom-control-label::before { background-color: #70ffda; border-color: #70ffda; } .dark-mode .custom-control-input-info:checked ~ .custom-control-label::before { border-color: #3498db; background-color: #3498db; } .dark-mode .custom-control-input-info.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233498db' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-info.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233498db'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-info:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 152, 219, 0.25); } .dark-mode .custom-control-input-info:focus:not(:checked) ~ .custom-control-label::before { border-color: #a0cfee; } .dark-mode .custom-control-input-info:not(:disabled):active ~ .custom-control-label::before { background-color: #cce5f6; border-color: #cce5f6; } .dark-mode .custom-control-input-warning:checked ~ .custom-control-label::before { border-color: #f39c12; background-color: #f39c12; } .dark-mode .custom-control-input-warning.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f39c12' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-warning.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f39c12'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-warning:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(243, 156, 18, 0.25); } .dark-mode .custom-control-input-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #f9cf8b; } .dark-mode .custom-control-input-warning:not(:disabled):active ~ .custom-control-label::before { background-color: #fce3bc; border-color: #fce3bc; } .dark-mode .custom-control-input-danger:checked ~ .custom-control-label::before { border-color: #e74c3c; background-color: #e74c3c; } .dark-mode .custom-control-input-danger.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e74c3c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-danger.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e74c3c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-danger:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(231, 76, 60, 0.25); } .dark-mode .custom-control-input-danger:focus:not(:checked) ~ .custom-control-label::before { border-color: #f5b4ae; } .dark-mode .custom-control-input-danger:not(:disabled):active ~ .custom-control-label::before { background-color: #fbdedb; border-color: #fbdedb; } .dark-mode .custom-control-input-light:checked ~ .custom-control-label::before { border-color: #f8f9fa; background-color: #f8f9fa; } .dark-mode .custom-control-input-light.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f8f9fa' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-light.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f8f9fa'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-light:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(248, 249, 250, 0.25); } .dark-mode .custom-control-input-light:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .dark-mode .custom-control-input-light:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .dark-mode .custom-control-input-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .dark-mode .custom-control-input-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .dark-mode .custom-control-input-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .dark-mode .custom-control-input-lightblue:checked ~ .custom-control-label::before { border-color: #86bad8; background-color: #86bad8; } .dark-mode .custom-control-input-lightblue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2386bad8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lightblue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2386bad8'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lightblue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(134, 186, 216, 0.25); } .dark-mode .custom-control-input-lightblue:focus:not(:checked) ~ .custom-control-label::before { border-color: #e6f1f7; } .dark-mode .custom-control-input-lightblue:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-navy:checked ~ .custom-control-label::before { border-color: #002c59; background-color: #002c59; } .dark-mode .custom-control-input-navy.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23002c59' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-navy.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23002c59'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-navy:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 44, 89, 0.25); } .dark-mode .custom-control-input-navy:focus:not(:checked) ~ .custom-control-label::before { border-color: #006ad8; } .dark-mode .custom-control-input-navy:not(:disabled):active ~ .custom-control-label::before { background-color: #0c84ff; border-color: #0c84ff; } .dark-mode .custom-control-input-olive:checked ~ .custom-control-label::before { border-color: #74c8a3; background-color: #74c8a3; } .dark-mode .custom-control-input-olive.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2374c8a3' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-olive.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2374c8a3'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-olive:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(116, 200, 163, 0.25); } .dark-mode .custom-control-input-olive:focus:not(:checked) ~ .custom-control-label::before { border-color: #cfecdf; } .dark-mode .custom-control-input-olive:not(:disabled):active ~ .custom-control-label::before { background-color: #f4fbf8; border-color: #f4fbf8; } .dark-mode .custom-control-input-lime:checked ~ .custom-control-label::before { border-color: #67ffa9; background-color: #67ffa9; } .dark-mode .custom-control-input-lime.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2367ffa9' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lime.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2367ffa9'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lime:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(103, 255, 169, 0.25); } .dark-mode .custom-control-input-lime:focus:not(:checked) ~ .custom-control-label::before { border-color: #e7fff1; } .dark-mode .custom-control-input-lime:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-fuchsia:checked ~ .custom-control-label::before { border-color: #f672d8; background-color: #f672d8; } .dark-mode .custom-control-input-fuchsia.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f672d8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-fuchsia.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f672d8'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-fuchsia:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(246, 114, 216, 0.25); } .dark-mode .custom-control-input-fuchsia:focus:not(:checked) ~ .custom-control-label::before { border-color: #feeaf9; } .dark-mode .custom-control-input-fuchsia:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-maroon:checked ~ .custom-control-label::before { border-color: #ed6c9b; background-color: #ed6c9b; } .dark-mode .custom-control-input-maroon.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ed6c9b' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-maroon.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ed6c9b'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-maroon:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(237, 108, 155, 0.25); } .dark-mode .custom-control-input-maroon:focus:not(:checked) ~ .custom-control-label::before { border-color: #fbdee8; } .dark-mode .custom-control-input-maroon:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-blue:checked ~ .custom-control-label::before { border-color: #3f6791; background-color: #3f6791; } .dark-mode .custom-control-input-blue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233f6791' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-blue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233f6791'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-blue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(63, 103, 145, 0.25); } .dark-mode .custom-control-input-blue:focus:not(:checked) ~ .custom-control-label::before { border-color: #85a7ca; } .dark-mode .custom-control-input-blue:not(:disabled):active ~ .custom-control-label::before { background-color: #a9c1da; border-color: #a9c1da; } .dark-mode .custom-control-input-indigo:checked ~ .custom-control-label::before { border-color: #6610f2; background-color: #6610f2; } .dark-mode .custom-control-input-indigo.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236610f2' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-indigo.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236610f2'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-indigo:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(102, 16, 242, 0.25); } .dark-mode .custom-control-input-indigo:focus:not(:checked) ~ .custom-control-label::before { border-color: #b389f9; } .dark-mode .custom-control-input-indigo:not(:disabled):active ~ .custom-control-label::before { background-color: #d2b9fb; border-color: #d2b9fb; } .dark-mode .custom-control-input-purple:checked ~ .custom-control-label::before { border-color: #6f42c1; background-color: #6f42c1; } .dark-mode .custom-control-input-purple.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236f42c1' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-purple.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236f42c1'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-purple:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(111, 66, 193, 0.25); } .dark-mode .custom-control-input-purple:focus:not(:checked) ~ .custom-control-label::before { border-color: #b8a2e0; } .dark-mode .custom-control-input-purple:not(:disabled):active ~ .custom-control-label::before { background-color: #d5c8ed; border-color: #d5c8ed; } .dark-mode .custom-control-input-pink:checked ~ .custom-control-label::before { border-color: #e83e8c; background-color: #e83e8c; } .dark-mode .custom-control-input-pink.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e83e8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-pink.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e83e8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-pink:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(232, 62, 140, 0.25); } .dark-mode .custom-control-input-pink:focus:not(:checked) ~ .custom-control-label::before { border-color: #f6b0d0; } .dark-mode .custom-control-input-pink:not(:disabled):active ~ .custom-control-label::before { background-color: #fbddeb; border-color: #fbddeb; } .dark-mode .custom-control-input-red:checked ~ .custom-control-label::before { border-color: #e74c3c; background-color: #e74c3c; } .dark-mode .custom-control-input-red.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e74c3c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-red.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e74c3c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-red:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(231, 76, 60, 0.25); } .dark-mode .custom-control-input-red:focus:not(:checked) ~ .custom-control-label::before { border-color: #f5b4ae; } .dark-mode .custom-control-input-red:not(:disabled):active ~ .custom-control-label::before { background-color: #fbdedb; border-color: #fbdedb; } .dark-mode .custom-control-input-orange:checked ~ .custom-control-label::before { border-color: #fd7e14; background-color: #fd7e14; } .dark-mode .custom-control-input-orange.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fd7e14' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-orange.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fd7e14'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-orange:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(253, 126, 20, 0.25); } .dark-mode .custom-control-input-orange:focus:not(:checked) ~ .custom-control-label::before { border-color: #fec392; } .dark-mode .custom-control-input-orange:not(:disabled):active ~ .custom-control-label::before { background-color: #ffdfc5; border-color: #ffdfc5; } .dark-mode .custom-control-input-yellow:checked ~ .custom-control-label::before { border-color: #f39c12; background-color: #f39c12; } .dark-mode .custom-control-input-yellow.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f39c12' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-yellow.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f39c12'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-yellow:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(243, 156, 18, 0.25); } .dark-mode .custom-control-input-yellow:focus:not(:checked) ~ .custom-control-label::before { border-color: #f9cf8b; } .dark-mode .custom-control-input-yellow:not(:disabled):active ~ .custom-control-label::before { background-color: #fce3bc; border-color: #fce3bc; } .dark-mode .custom-control-input-green:checked ~ .custom-control-label::before { border-color: #00bc8c; background-color: #00bc8c; } .dark-mode .custom-control-input-green.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2300bc8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-green.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2300bc8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-green:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 188, 140, 0.25); } .dark-mode .custom-control-input-green:focus:not(:checked) ~ .custom-control-label::before { border-color: #3dffcd; } .dark-mode .custom-control-input-green:not(:disabled):active ~ .custom-control-label::before { background-color: #70ffda; border-color: #70ffda; } .dark-mode .custom-control-input-teal:checked ~ .custom-control-label::before { border-color: #20c997; background-color: #20c997; } .dark-mode .custom-control-input-teal.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2320c997' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-teal.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2320c997'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-teal:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(32, 201, 151, 0.25); } .dark-mode .custom-control-input-teal:focus:not(:checked) ~ .custom-control-label::before { border-color: #7eeaca; } .dark-mode .custom-control-input-teal:not(:disabled):active ~ .custom-control-label::before { background-color: #aaf1dc; border-color: #aaf1dc; } .dark-mode .custom-control-input-cyan:checked ~ .custom-control-label::before { border-color: #3498db; background-color: #3498db; } .dark-mode .custom-control-input-cyan.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233498db' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-cyan.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233498db'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-cyan:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 152, 219, 0.25); } .dark-mode .custom-control-input-cyan:focus:not(:checked) ~ .custom-control-label::before { border-color: #a0cfee; } .dark-mode .custom-control-input-cyan:not(:disabled):active ~ .custom-control-label::before { background-color: #cce5f6; border-color: #cce5f6; } .dark-mode .custom-control-input-white:checked ~ .custom-control-label::before { border-color: #fff; background-color: #fff; } .dark-mode .custom-control-input-white.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-white.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-white:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 255, 255, 0.25); } .dark-mode .custom-control-input-white:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .dark-mode .custom-control-input-white:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-gray:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .dark-mode .custom-control-input-gray.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .dark-mode .custom-control-input-gray:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .dark-mode .custom-control-input-gray:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .dark-mode .custom-control-input-gray-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .dark-mode .custom-control-input-gray-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .dark-mode .custom-control-input-gray-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .dark-mode .custom-control-input-gray-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .progress { box-shadow: none; border-radius: 1px; } .progress.vertical { display: inline-block; height: 200px; margin-right: 10px; position: relative; width: 30px; } .progress.vertical > .progress-bar { bottom: 0; position: absolute; width: 100%; } .progress.vertical.sm, .progress.vertical.progress-sm { width: 20px; } .progress.vertical.xs, .progress.vertical.progress-xs { width: 10px; } .progress.vertical.xxs, .progress.vertical.progress-xxs { width: 3px; } .progress-group { margin-bottom: 0.5rem; } .progress-sm { height: 10px; } .progress-xs { height: 7px; } .progress-xxs { height: 3px; } .table tr > td .progress { margin: 0; } .dark-mode .progress { background: #454d55; } .card-primary:not(.card-outline) > .card-header { background-color: #007bff; } .card-primary:not(.card-outline) > .card-header, .card-primary:not(.card-outline) > .card-header a { color: #fff; } .card-primary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-primary.card-outline { border-top: 3px solid #007bff; } .card-primary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-primary.card-outline-tabs > .card-header a.active, .card-primary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-primary > .card-header .btn-tool, .bg-gradient-primary > .card-header .btn-tool, .card-primary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-primary > .card-header .btn-tool:hover, .bg-gradient-primary > .card-header .btn-tool:hover, .card-primary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget .table td, .card.bg-primary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-primary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-secondary:not(.card-outline) > .card-header { background-color: #6c757d; } .card-secondary:not(.card-outline) > .card-header, .card-secondary:not(.card-outline) > .card-header a { color: #fff; } .card-secondary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-secondary.card-outline { border-top: 3px solid #6c757d; } .card-secondary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-secondary.card-outline-tabs > .card-header a.active, .card-secondary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-secondary > .card-header .btn-tool, .bg-gradient-secondary > .card-header .btn-tool, .card-secondary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-secondary > .card-header .btn-tool:hover, .bg-gradient-secondary > .card-header .btn-tool:hover, .card-secondary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-secondary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-secondary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-success:not(.card-outline) > .card-header { background-color: #28a745; } .card-success:not(.card-outline) > .card-header, .card-success:not(.card-outline) > .card-header a { color: #fff; } .card-success:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-success.card-outline { border-top: 3px solid #28a745; } .card-success.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-success.card-outline-tabs > .card-header a.active, .card-success.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-success > .card-header .btn-tool, .bg-gradient-success > .card-header .btn-tool, .card-success:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-success > .card-header .btn-tool:hover, .bg-gradient-success > .card-header .btn-tool:hover, .card-success:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget .table td, .card.bg-success .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.active, .card.bg-success .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-info:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-info:not(.card-outline) > .card-header, .card-info:not(.card-outline) > .card-header a { color: #fff; } .card-info:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-info.card-outline { border-top: 3px solid #17a2b8; } .card-info.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-info.card-outline-tabs > .card-header a.active, .card-info.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-info > .card-header .btn-tool, .bg-gradient-info > .card-header .btn-tool, .card-info:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-info > .card-header .btn-tool:hover, .bg-gradient-info > .card-header .btn-tool:hover, .card-info:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget .table td, .card.bg-info .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.active, .card.bg-info .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-warning:not(.card-outline) > .card-header { background-color: #ffc107; } .card-warning:not(.card-outline) > .card-header, .card-warning:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-warning:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-warning.card-outline { border-top: 3px solid #ffc107; } .card-warning.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-warning.card-outline-tabs > .card-header a.active, .card-warning.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-warning > .card-header .btn-tool, .bg-gradient-warning > .card-header .btn-tool, .card-warning:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-warning > .card-header .btn-tool:hover, .bg-gradient-warning > .card-header .btn-tool:hover, .card-warning:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget .table td, .card.bg-warning .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-warning .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-danger:not(.card-outline) > .card-header { background-color: #dc3545; } .card-danger:not(.card-outline) > .card-header, .card-danger:not(.card-outline) > .card-header a { color: #fff; } .card-danger:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-danger.card-outline { border-top: 3px solid #dc3545; } .card-danger.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-danger.card-outline-tabs > .card-header a.active, .card-danger.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-danger > .card-header .btn-tool, .bg-gradient-danger > .card-header .btn-tool, .card-danger:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-danger > .card-header .btn-tool:hover, .bg-gradient-danger > .card-header .btn-tool:hover, .card-danger:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget .table td, .card.bg-danger .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-danger .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-light:not(.card-outline) > .card-header { background-color: #f8f9fa; } .card-light:not(.card-outline) > .card-header, .card-light:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-light:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-light.card-outline { border-top: 3px solid #f8f9fa; } .card-light.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-light.card-outline-tabs > .card-header a.active, .card-light.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f8f9fa; } .bg-light > .card-header .btn-tool, .bg-gradient-light > .card-header .btn-tool, .card-light:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-light > .card-header .btn-tool:hover, .bg-gradient-light > .card-header .btn-tool:hover, .card-light:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget .table td, .card.bg-light .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e0e5e9; color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.active, .card.bg-light .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-dark:not(.card-outline) > .card-header, .card-dark:not(.card-outline) > .card-header a { color: #fff; } .card-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-dark.card-outline { border-top: 3px solid #343a40; } .card-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-dark.card-outline-tabs > .card-header a.active, .card-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-dark > .card-header .btn-tool, .bg-gradient-dark > .card-header .btn-tool, .card-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-dark > .card-header .btn-tool:hover, .bg-gradient-dark > .card-header .btn-tool:hover, .card-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget .table td, .card.bg-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card-lightblue:not(.card-outline) > .card-header { background-color: #3c8dbc; } .card-lightblue:not(.card-outline) > .card-header, .card-lightblue:not(.card-outline) > .card-header a { color: #fff; } .card-lightblue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lightblue.card-outline { border-top: 3px solid #3c8dbc; } .card-lightblue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lightblue.card-outline-tabs > .card-header a.active, .card-lightblue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3c8dbc; } .bg-lightblue > .card-header .btn-tool, .bg-gradient-lightblue > .card-header .btn-tool, .card-lightblue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-lightblue > .card-header .btn-tool:hover, .bg-gradient-lightblue > .card-header .btn-tool:hover, .card-lightblue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-lightblue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #32769d; color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5fa4cc; color: #fff; } .card-navy:not(.card-outline) > .card-header { background-color: #001f3f; } .card-navy:not(.card-outline) > .card-header, .card-navy:not(.card-outline) > .card-header a { color: #fff; } .card-navy:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-navy.card-outline { border-top: 3px solid #001f3f; } .card-navy.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-navy.card-outline-tabs > .card-header a.active, .card-navy.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #001f3f; } .bg-navy > .card-header .btn-tool, .bg-gradient-navy > .card-header .btn-tool, .card-navy:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-navy > .card-header .btn-tool:hover, .bg-gradient-navy > .card-header .btn-tool:hover, .card-navy:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget .table td, .card.bg-navy .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.second:hover { background-color: #000b16; color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-navy .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active:hover { background-color: #003872; color: #fff; } .card-olive:not(.card-outline) > .card-header { background-color: #3d9970; } .card-olive:not(.card-outline) > .card-header, .card-olive:not(.card-outline) > .card-header a { color: #fff; } .card-olive:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-olive.card-outline { border-top: 3px solid #3d9970; } .card-olive.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-olive.card-outline-tabs > .card-header a.active, .card-olive.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3d9970; } .bg-olive > .card-header .btn-tool, .bg-gradient-olive > .card-header .btn-tool, .card-olive:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-olive > .card-header .btn-tool:hover, .bg-gradient-olive > .card-header .btn-tool:hover, .card-olive:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget .table td, .card.bg-olive .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.second:hover { background-color: #317c5b; color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-olive .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active:hover { background-color: #50b98a; color: #fff; } .card-lime:not(.card-outline) > .card-header { background-color: #01ff70; } .card-lime:not(.card-outline) > .card-header, .card-lime:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-lime:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lime.card-outline { border-top: 3px solid #01ff70; } .card-lime.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lime.card-outline-tabs > .card-header a.active, .card-lime.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #01ff70; } .bg-lime > .card-header .btn-tool, .bg-gradient-lime > .card-header .btn-tool, .card-lime:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-lime > .card-header .btn-tool:hover, .bg-gradient-lime > .card-header .btn-tool:hover, .card-lime:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget .table td, .card.bg-lime .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00d75e; color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-lime .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ff8d; color: #1f2d3d; } .card-fuchsia:not(.card-outline) > .card-header { background-color: #f012be; } .card-fuchsia:not(.card-outline) > .card-header, .card-fuchsia:not(.card-outline) > .card-header a { color: #fff; } .card-fuchsia:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-fuchsia.card-outline { border-top: 3px solid #f012be; } .card-fuchsia.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-fuchsia.card-outline-tabs > .card-header a.active, .card-fuchsia.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f012be; } .bg-fuchsia > .card-header .btn-tool, .bg-gradient-fuchsia > .card-header .btn-tool, .card-fuchsia:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-fuchsia > .card-header .btn-tool:hover, .bg-gradient-fuchsia > .card-header .btn-tool:hover, .card-fuchsia:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-fuchsia .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.second:hover { background-color: #cc0da1; color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f342cb; color: #fff; } .card-maroon:not(.card-outline) > .card-header { background-color: #d81b60; } .card-maroon:not(.card-outline) > .card-header, .card-maroon:not(.card-outline) > .card-header a { color: #fff; } .card-maroon:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-maroon.card-outline { border-top: 3px solid #d81b60; } .card-maroon.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-maroon.card-outline-tabs > .card-header a.active, .card-maroon.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #d81b60; } .bg-maroon > .card-header .btn-tool, .bg-gradient-maroon > .card-header .btn-tool, .card-maroon:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-maroon > .card-header .btn-tool:hover, .bg-gradient-maroon > .card-header .btn-tool:hover, .card-maroon:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-maroon .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.second:hover { background-color: #b41650; color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-maroon .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e73f7c; color: #fff; } .card-blue:not(.card-outline) > .card-header { background-color: #007bff; } .card-blue:not(.card-outline) > .card-header, .card-blue:not(.card-outline) > .card-header a { color: #fff; } .card-blue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-blue.card-outline { border-top: 3px solid #007bff; } .card-blue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-blue.card-outline-tabs > .card-header a.active, .card-blue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-blue > .card-header .btn-tool, .bg-gradient-blue > .card-header .btn-tool, .card-blue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-blue > .card-header .btn-tool:hover, .bg-gradient-blue > .card-header .btn-tool:hover, .card-blue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget .table td, .card.bg-blue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-blue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-indigo:not(.card-outline) > .card-header { background-color: #6610f2; } .card-indigo:not(.card-outline) > .card-header, .card-indigo:not(.card-outline) > .card-header a { color: #fff; } .card-indigo:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-indigo.card-outline { border-top: 3px solid #6610f2; } .card-indigo.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-indigo.card-outline-tabs > .card-header a.active, .card-indigo.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6610f2; } .bg-indigo > .card-header .btn-tool, .bg-gradient-indigo > .card-header .btn-tool, .card-indigo:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-indigo > .card-header .btn-tool:hover, .bg-gradient-indigo > .card-header .btn-tool:hover, .card-indigo:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-indigo .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.second:hover { background-color: #550bce; color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-indigo .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8540f5; color: #fff; } .card-purple:not(.card-outline) > .card-header { background-color: #6f42c1; } .card-purple:not(.card-outline) > .card-header, .card-purple:not(.card-outline) > .card-header a { color: #fff; } .card-purple:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-purple.card-outline { border-top: 3px solid #6f42c1; } .card-purple.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-purple.card-outline-tabs > .card-header a.active, .card-purple.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6f42c1; } .bg-purple > .card-header .btn-tool, .bg-gradient-purple > .card-header .btn-tool, .card-purple:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-purple > .card-header .btn-tool:hover, .bg-gradient-purple > .card-header .btn-tool:hover, .card-purple:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget .table td, .card.bg-purple .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.second:hover { background-color: #5d36a4; color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-purple .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8c68ce; color: #fff; } .card-pink:not(.card-outline) > .card-header { background-color: #e83e8c; } .card-pink:not(.card-outline) > .card-header, .card-pink:not(.card-outline) > .card-header a { color: #fff; } .card-pink:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-pink.card-outline { border-top: 3px solid #e83e8c; } .card-pink.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-pink.card-outline-tabs > .card-header a.active, .card-pink.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e83e8c; } .bg-pink > .card-header .btn-tool, .bg-gradient-pink > .card-header .btn-tool, .card-pink:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-pink > .card-header .btn-tool:hover, .bg-gradient-pink > .card-header .btn-tool:hover, .card-pink:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget .table td, .card.bg-pink .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e21b76; color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-pink .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed6ca7; color: #fff; } .card-red:not(.card-outline) > .card-header { background-color: #dc3545; } .card-red:not(.card-outline) > .card-header, .card-red:not(.card-outline) > .card-header a { color: #fff; } .card-red:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-red.card-outline { border-top: 3px solid #dc3545; } .card-red.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-red.card-outline-tabs > .card-header a.active, .card-red.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-red > .card-header .btn-tool, .bg-gradient-red > .card-header .btn-tool, .card-red:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-red > .card-header .btn-tool:hover, .bg-gradient-red > .card-header .btn-tool:hover, .card-red:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget .table td, .card.bg-red .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.active, .card.bg-red .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-orange:not(.card-outline) > .card-header { background-color: #fd7e14; } .card-orange:not(.card-outline) > .card-header, .card-orange:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-orange:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-orange.card-outline { border-top: 3px solid #fd7e14; } .card-orange.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-orange.card-outline-tabs > .card-header a.active, .card-orange.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fd7e14; } .bg-orange > .card-header .btn-tool, .bg-gradient-orange > .card-header .btn-tool, .card-orange:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-orange > .card-header .btn-tool:hover, .bg-gradient-orange > .card-header .btn-tool:hover, .card-orange:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget .table td, .card.bg-orange .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e66a02; color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-orange .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active:hover { background-color: #fd9a47; color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header { background-color: #ffc107; } .card-yellow:not(.card-outline) > .card-header, .card-yellow:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-yellow.card-outline { border-top: 3px solid #ffc107; } .card-yellow.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-yellow.card-outline-tabs > .card-header a.active, .card-yellow.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-yellow > .card-header .btn-tool, .bg-gradient-yellow > .card-header .btn-tool, .card-yellow:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-yellow > .card-header .btn-tool:hover, .bg-gradient-yellow > .card-header .btn-tool:hover, .card-yellow:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-yellow .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-yellow .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-green:not(.card-outline) > .card-header { background-color: #28a745; } .card-green:not(.card-outline) > .card-header, .card-green:not(.card-outline) > .card-header a { color: #fff; } .card-green:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-green.card-outline { border-top: 3px solid #28a745; } .card-green.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-green.card-outline-tabs > .card-header a.active, .card-green.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-green > .card-header .btn-tool, .bg-gradient-green > .card-header .btn-tool, .card-green:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-green > .card-header .btn-tool:hover, .bg-gradient-green > .card-header .btn-tool:hover, .card-green:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget .table td, .card.bg-green .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.active, .card.bg-green .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-teal:not(.card-outline) > .card-header { background-color: #20c997; } .card-teal:not(.card-outline) > .card-header, .card-teal:not(.card-outline) > .card-header a { color: #fff; } .card-teal:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-teal.card-outline { border-top: 3px solid #20c997; } .card-teal.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-teal.card-outline-tabs > .card-header a.active, .card-teal.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #20c997; } .bg-teal > .card-header .btn-tool, .bg-gradient-teal > .card-header .btn-tool, .card-teal:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-teal > .card-header .btn-tool:hover, .bg-gradient-teal > .card-header .btn-tool:hover, .card-teal:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget .table td, .card.bg-teal .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.second:hover { background-color: #1aa67d; color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-teal .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3ce0af; color: #fff; } .card-cyan:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-cyan:not(.card-outline) > .card-header, .card-cyan:not(.card-outline) > .card-header a { color: #fff; } .card-cyan:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-cyan.card-outline { border-top: 3px solid #17a2b8; } .card-cyan.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-cyan.card-outline-tabs > .card-header a.active, .card-cyan.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-cyan > .card-header .btn-tool, .bg-gradient-cyan > .card-header .btn-tool, .card-cyan:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-cyan > .card-header .btn-tool:hover, .bg-gradient-cyan > .card-header .btn-tool:hover, .card-cyan:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-cyan .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-cyan .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-white:not(.card-outline) > .card-header { background-color: #fff; } .card-white:not(.card-outline) > .card-header, .card-white:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-white:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-white.card-outline { border-top: 3px solid #fff; } .card-white.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-white.card-outline-tabs > .card-header a.active, .card-white.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fff; } .bg-white > .card-header .btn-tool, .bg-gradient-white > .card-header .btn-tool, .card-white:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-white > .card-header .btn-tool:hover, .bg-gradient-white > .card-header .btn-tool:hover, .card-white:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget .table td, .card.bg-white .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.second:hover { background-color: #ebebeb; color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.active, .card.bg-white .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-gray:not(.card-outline) > .card-header { background-color: #6c757d; } .card-gray:not(.card-outline) > .card-header, .card-gray:not(.card-outline) > .card-header a { color: #fff; } .card-gray:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray.card-outline { border-top: 3px solid #6c757d; } .card-gray.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray.card-outline-tabs > .card-header a.active, .card-gray.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-gray > .card-header .btn-tool, .bg-gradient-gray > .card-header .btn-tool, .card-gray:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray > .card-header .btn-tool:hover, .bg-gradient-gray > .card-header .btn-tool:hover, .card-gray:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gray .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gray .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-gray-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-gray-dark:not(.card-outline) > .card-header, .card-gray-dark:not(.card-outline) > .card-header a { color: #fff; } .card-gray-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray-dark.card-outline { border-top: 3px solid #343a40; } .card-gray-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray-dark.card-outline-tabs > .card-header a.active, .card-gray-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-gray-dark > .card-header .btn-tool, .bg-gradient-gray-dark > .card-header .btn-tool, .card-gray-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray-dark > .card-header .btn-tool:hover, .bg-gradient-gray-dark > .card-header .btn-tool:hover, .card-gray-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gray-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); margin-bottom: 1rem; } .card.bg-dark .card-header { border-color: #383f45; } .card.bg-dark, .card.bg-dark .card-body { color: #fff; } .card.maximized-card { height: 100% !important; left: 0; max-height: 100% !important; max-width: 100% !important; position: fixed; top: 0; width: 100% !important; z-index: 1040; } .card.maximized-card.was-collapsed .card-body { display: block !important; } .card.maximized-card .card-body { overflow: auto; } .card.maximized-card [data-card-widgett="collapse"] { display: none; } .card.maximized-card .card-header, .card.maximized-card .card-footer { border-radius: 0 !important; } .card.collapsed-card .card-body, .card.collapsed-card .card-footer { display: none; } .card .nav.flex-column:not(.nav-sidebar) > li { border-bottom: 1px solid rgba(0, 0, 0, 0.125); margin: 0; } .card .nav.flex-column:not(.nav-sidebar) > li:last-of-type { border-bottom: 0; } .card.height-control .card-body { max-height: 300px; overflow: auto; } .card .border-right { border-right: 1px solid rgba(0, 0, 0, 0.125); } .card .border-left { border-left: 1px solid rgba(0, 0, 0, 0.125); } .card.card-tabs:not(.card-outline) > .card-header { border-bottom: 0; } .card.card-tabs:not(.card-outline) > .card-header .nav-item:first-child .nav-link { border-left-color: transparent; } .card.card-tabs.card-outline .nav-item { border-bottom: 0; } .card.card-tabs.card-outline .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-tabs .card-tools { margin: .3rem .5rem; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } .card.card-outline-tabs { border-top: 0; } .card.card-outline-tabs .card-header .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-outline-tabs .card-header a { border-top: 3px solid transparent; } .card.card-outline-tabs .card-header a:hover { border-top: 3px solid #dee2e6; } .card.card-outline-tabs .card-header a.active:hover { margin-top: 0; } .card.card-outline-tabs .card-tools { margin: .5rem .5rem .3rem; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-outline-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } html.maximized-card { overflow: hidden; } .card-header::after, .card-body::after, .card-footer::after { display: block; clear: both; content: ""; } .card-header { background-color: transparent; border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 0.75rem 1.25rem; position: relative; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .collapsed-card .card-header { border-bottom: 0; } .card-header > .card-tools { float: right; margin-right: -0.625rem; } .card-header > .card-tools .input-group, .card-header > .card-tools .nav, .card-header > .card-tools .pagination { margin-bottom: -0.3rem; margin-top: -0.3rem; } .card-header > .card-tools [data-toggle="tooltip"] { position: relative; } .card-title { float: left; font-size: 1.1rem; font-weight: 400; margin: 0; } .card-text { clear: both; } .btn-tool { background-color: transparent; color: #adb5bd; font-size: 0.875rem; margin: -0.75rem 0; padding: .25rem .5rem; } .btn-group.show .btn-tool, .btn-tool:hover { color: #495057; } .show .btn-tool, .btn-tool:focus { box-shadow: none !important; } .text-sm .card-title { font-size: 1rem; } .text-sm .nav-link { padding: 0.4rem 0.8rem; } .card-body > .table { margin-bottom: 0; } .card-body > .table > thead > tr > th, .card-body > .table > thead > tr > td { border-top-width: 0; } .card-body .fc { margin-top: 5px; } .card-body .full-width-chart { margin: -19px; } .card-body.p-0 .full-width-chart { margin: -9px; } .chart-legend { padding-left: 0; list-style: none; margin: 10px 0; } @media (max-width: 576px) { .chart-legend > li { float: left; margin-right: 10px; } } .card-comments { background-color: #f8f9fa; } .card-comments .card-comment { border-bottom: 1px solid #e9ecef; padding: 8px 0; } .card-comments .card-comment::after { display: block; clear: both; content: ""; } .card-comments .card-comment:last-of-type { border-bottom: 0; } .card-comments .card-comment:first-of-type { padding-top: 0; } .card-comments .card-comment img { height: 1.875rem; width: 1.875rem; float: left; } .card-comments .comment-text { color: #78838e; margin-left: 40px; } .card-comments .username { color: #495057; display: block; font-weight: 600; } .card-comments .text-muted { font-size: 12px; font-weight: 400; } .todo-list { list-style: none; margin: 0; overflow: auto; padding: 0; } .todo-list > li { border-radius: 2px; background-color: #f8f9fa; border-left: 2px solid #e9ecef; color: #495057; margin-bottom: 2px; padding: 10px; } .todo-list > li:last-of-type { margin-bottom: 0; } .todo-list > li > input[type="checkbox"] { margin: 0 10px 0 5px; } .todo-list > li .text { display: inline-block; font-weight: 600; margin-left: 5px; } .todo-list > li .badge { font-size: .7rem; margin-left: 10px; } .todo-list > li .tools { color: #dc3545; display: none; float: right; } .todo-list > li .tools > .fa, .todo-list > li .tools > .fas, .todo-list > li .tools > .far, .todo-list > li .tools > .fab, .todo-list > li .tools > .fal, .todo-list > li .tools > .fad, .todo-list > li .tools > .svg-inline--fa, .todo-list > li .tools > .ion { cursor: pointer; margin-right: 5px; } .todo-list > li:hover .tools { display: inline-block; } .todo-list > li.done { color: #697582; } .todo-list > li.done .text { font-weight: 500; text-decoration: line-through; } .todo-list > li.done .badge { background-color: #adb5bd !important; } .todo-list .primary { border-left-color: #007bff; } .todo-list .secondary { border-left-color: #6c757d; } .todo-list .success { border-left-color: #28a745; } .todo-list .info { border-left-color: #17a2b8; } .todo-list .warning { border-left-color: #ffc107; } .todo-list .danger { border-left-color: #dc3545; } .todo-list .light { border-left-color: #f8f9fa; } .todo-list .dark { border-left-color: #343a40; } .todo-list .lightblue { border-left-color: #3c8dbc; } .todo-list .navy { border-left-color: #001f3f; } .todo-list .olive { border-left-color: #3d9970; } .todo-list .lime { border-left-color: #01ff70; } .todo-list .fuchsia { border-left-color: #f012be; } .todo-list .maroon { border-left-color: #d81b60; } .todo-list .blue { border-left-color: #007bff; } .todo-list .indigo { border-left-color: #6610f2; } .todo-list .purple { border-left-color: #6f42c1; } .todo-list .pink { border-left-color: #e83e8c; } .todo-list .red { border-left-color: #dc3545; } .todo-list .orange { border-left-color: #fd7e14; } .todo-list .yellow { border-left-color: #ffc107; } .todo-list .green { border-left-color: #28a745; } .todo-list .teal { border-left-color: #20c997; } .todo-list .cyan { border-left-color: #17a2b8; } .todo-list .white { border-left-color: #fff; } .todo-list .gray { border-left-color: #6c757d; } .todo-list .gray-dark { border-left-color: #343a40; } .todo-list .handle { cursor: move; display: inline-block; margin: 0 5px; } .card-input { max-width: 200px; } .card-default .nav-item:first-child .nav-link { border-left: 0; } .dark-mode .card-primary:not(.card-outline) > .card-header { background-color: #3f6791; } .dark-mode .card-primary:not(.card-outline) > .card-header, .dark-mode .card-primary:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-primary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-primary.card-outline { border-top: 3px solid #3f6791; } .dark-mode .card-primary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-primary.card-outline-tabs > .card-header a.active, .dark-mode .card-primary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3f6791; } .dark-mode .bg-primary > .card-header .btn-tool, .dark-mode .bg-gradient-primary > .card-header .btn-tool, .dark-mode .card-primary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-primary > .card-header .btn-tool:hover, .dark-mode .bg-gradient-primary > .card-header .btn-tool:hover, .dark-mode .card-primary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #335375; color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5080b3; color: #fff; } .dark-mode .card-secondary:not(.card-outline) > .card-header { background-color: #6c757d; } .dark-mode .card-secondary:not(.card-outline) > .card-header, .dark-mode .card-secondary:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-secondary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-secondary.card-outline { border-top: 3px solid #6c757d; } .dark-mode .card-secondary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-secondary.card-outline-tabs > .card-header a.active, .dark-mode .card-secondary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .dark-mode .bg-secondary > .card-header .btn-tool, .dark-mode .bg-gradient-secondary > .card-header .btn-tool, .dark-mode .card-secondary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-secondary > .card-header .btn-tool:hover, .dark-mode .bg-gradient-secondary > .card-header .btn-tool:hover, .dark-mode .card-secondary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .dark-mode .card-success:not(.card-outline) > .card-header { background-color: #00bc8c; } .dark-mode .card-success:not(.card-outline) > .card-header, .dark-mode .card-success:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-success:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-success.card-outline { border-top: 3px solid #00bc8c; } .dark-mode .card-success.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-success.card-outline-tabs > .card-header a.active, .dark-mode .card-success.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #00bc8c; } .dark-mode .bg-success > .card-header .btn-tool, .dark-mode .bg-gradient-success > .card-header .btn-tool, .dark-mode .card-success:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-success > .card-header .btn-tool:hover, .dark-mode .bg-gradient-success > .card-header .btn-tool:hover, .dark-mode .card-success:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00936e; color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00efb2; color: #fff; } .dark-mode .card-info:not(.card-outline) > .card-header { background-color: #3498db; } .dark-mode .card-info:not(.card-outline) > .card-header, .dark-mode .card-info:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-info:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-info.card-outline { border-top: 3px solid #3498db; } .dark-mode .card-info.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-info.card-outline-tabs > .card-header a.active, .dark-mode .card-info.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3498db; } .dark-mode .bg-info > .card-header .btn-tool, .dark-mode .bg-gradient-info > .card-header .btn-tool, .dark-mode .card-info:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-info > .card-header .btn-tool:hover, .dark-mode .bg-gradient-info > .card-header .btn-tool:hover, .dark-mode .card-info:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.second:hover { background-color: #2383c4; color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5faee3; color: #fff; } .dark-mode .card-warning:not(.card-outline) > .card-header { background-color: #f39c12; } .dark-mode .card-warning:not(.card-outline) > .card-header, .dark-mode .card-warning:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-warning:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-warning.card-outline { border-top: 3px solid #f39c12; } .dark-mode .card-warning.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-warning.card-outline-tabs > .card-header a.active, .dark-mode .card-warning.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f39c12; } .dark-mode .bg-warning > .card-header .btn-tool, .dark-mode .bg-gradient-warning > .card-header .btn-tool, .dark-mode .card-warning:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-warning > .card-header .btn-tool:hover, .dark-mode .bg-gradient-warning > .card-header .btn-tool:hover, .dark-mode .card-warning:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.second:hover { background-color: #d2850b; color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f5b043; color: #1f2d3d; } .dark-mode .card-danger:not(.card-outline) > .card-header { background-color: #e74c3c; } .dark-mode .card-danger:not(.card-outline) > .card-header, .dark-mode .card-danger:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-danger:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-danger.card-outline { border-top: 3px solid #e74c3c; } .dark-mode .card-danger.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-danger.card-outline-tabs > .card-header a.active, .dark-mode .card-danger.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e74c3c; } .dark-mode .bg-danger > .card-header .btn-tool, .dark-mode .bg-gradient-danger > .card-header .btn-tool, .dark-mode .card-danger:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-danger > .card-header .btn-tool:hover, .dark-mode .bg-gradient-danger > .card-header .btn-tool:hover, .dark-mode .card-danger:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.second:hover { background-color: #df2e1b; color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed7669; color: #fff; } .dark-mode .card-light:not(.card-outline) > .card-header { background-color: #f8f9fa; } .dark-mode .card-light:not(.card-outline) > .card-header, .dark-mode .card-light:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-light:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-light.card-outline { border-top: 3px solid #f8f9fa; } .dark-mode .card-light.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-light.card-outline-tabs > .card-header a.active, .dark-mode .card-light.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f8f9fa; } .dark-mode .bg-light > .card-header .btn-tool, .dark-mode .bg-gradient-light > .card-header .btn-tool, .dark-mode .card-light:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-light > .card-header .btn-tool:hover, .dark-mode .bg-gradient-light > .card-header .btn-tool:hover, .dark-mode .card-light:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e0e5e9; color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .dark-mode .card-dark:not(.card-outline) > .card-header { background-color: #343a40; } .dark-mode .card-dark:not(.card-outline) > .card-header, .dark-mode .card-dark:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-dark.card-outline { border-top: 3px solid #343a40; } .dark-mode .card-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-dark.card-outline-tabs > .card-header a.active, .dark-mode .card-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .dark-mode .bg-dark > .card-header .btn-tool, .dark-mode .bg-gradient-dark > .card-header .btn-tool, .dark-mode .card-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-dark > .card-header .btn-tool:hover, .dark-mode .bg-gradient-dark > .card-header .btn-tool:hover, .dark-mode .card-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .dark-mode .card-lightblue:not(.card-outline) > .card-header { background-color: #86bad8; } .dark-mode .card-lightblue:not(.card-outline) > .card-header, .dark-mode .card-lightblue:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-lightblue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-lightblue.card-outline { border-top: 3px solid #86bad8; } .dark-mode .card-lightblue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-lightblue.card-outline-tabs > .card-header a.active, .dark-mode .card-lightblue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #86bad8; } .dark-mode .bg-lightblue > .card-header .btn-tool, .dark-mode .bg-gradient-lightblue > .card-header .btn-tool, .dark-mode .card-lightblue:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-lightblue > .card-header .btn-tool:hover, .dark-mode .bg-gradient-lightblue > .card-header .btn-tool:hover, .dark-mode .card-lightblue:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #67a8ce; color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #acd0e5; color: #1f2d3d; } .dark-mode .card-navy:not(.card-outline) > .card-header { background-color: #002c59; } .dark-mode .card-navy:not(.card-outline) > .card-header, .dark-mode .card-navy:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-navy:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-navy.card-outline { border-top: 3px solid #002c59; } .dark-mode .card-navy.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-navy.card-outline-tabs > .card-header a.active, .dark-mode .card-navy.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #002c59; } .dark-mode .bg-navy > .card-header .btn-tool, .dark-mode .bg-gradient-navy > .card-header .btn-tool, .dark-mode .card-navy:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-navy > .card-header .btn-tool:hover, .dark-mode .bg-gradient-navy > .card-header .btn-tool:hover, .dark-mode .card-navy:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.second:hover { background-color: #001730; color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00458c; color: #fff; } .dark-mode .card-olive:not(.card-outline) > .card-header { background-color: #74c8a3; } .dark-mode .card-olive:not(.card-outline) > .card-header, .dark-mode .card-olive:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-olive:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-olive.card-outline { border-top: 3px solid #74c8a3; } .dark-mode .card-olive.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-olive.card-outline-tabs > .card-header a.active, .dark-mode .card-olive.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #74c8a3; } .dark-mode .bg-olive > .card-header .btn-tool, .dark-mode .bg-gradient-olive > .card-header .btn-tool, .dark-mode .card-olive:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-olive > .card-header .btn-tool:hover, .dark-mode .bg-gradient-olive > .card-header .btn-tool:hover, .dark-mode .card-olive:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.second:hover { background-color: #57bc8f; color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active:hover { background-color: #99d6bb; color: #1f2d3d; } .dark-mode .card-lime:not(.card-outline) > .card-header { background-color: #67ffa9; } .dark-mode .card-lime:not(.card-outline) > .card-header, .dark-mode .card-lime:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-lime:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-lime.card-outline { border-top: 3px solid #67ffa9; } .dark-mode .card-lime.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-lime.card-outline-tabs > .card-header a.active, .dark-mode .card-lime.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #67ffa9; } .dark-mode .bg-lime > .card-header .btn-tool, .dark-mode .bg-gradient-lime > .card-header .btn-tool, .dark-mode .card-lime:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-lime > .card-header .btn-tool:hover, .dark-mode .bg-gradient-lime > .card-header .btn-tool:hover, .dark-mode .card-lime:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.second:hover { background-color: #3eff92; color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active:hover { background-color: #9affc6; color: #1f2d3d; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header { background-color: #f672d8; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header, .dark-mode .card-fuchsia:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-fuchsia.card-outline { border-top: 3px solid #f672d8; } .dark-mode .card-fuchsia.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-fuchsia.card-outline-tabs > .card-header a.active, .dark-mode .card-fuchsia.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f672d8; } .dark-mode .bg-fuchsia > .card-header .btn-tool, .dark-mode .bg-gradient-fuchsia > .card-header .btn-tool, .dark-mode .card-fuchsia:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-fuchsia > .card-header .btn-tool:hover, .dark-mode .bg-gradient-fuchsia > .card-header .btn-tool:hover, .dark-mode .card-fuchsia:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.second:hover { background-color: #f44cce; color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f9a2e5; color: #1f2d3d; } .dark-mode .card-maroon:not(.card-outline) > .card-header { background-color: #ed6c9b; } .dark-mode .card-maroon:not(.card-outline) > .card-header, .dark-mode .card-maroon:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-maroon:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-maroon.card-outline { border-top: 3px solid #ed6c9b; } .dark-mode .card-maroon.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-maroon.card-outline-tabs > .card-header a.active, .dark-mode .card-maroon.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ed6c9b; } .dark-mode .bg-maroon > .card-header .btn-tool, .dark-mode .bg-gradient-maroon > .card-header .btn-tool, .dark-mode .card-maroon:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-maroon > .card-header .btn-tool:hover, .dark-mode .bg-gradient-maroon > .card-header .btn-tool:hover, .dark-mode .card-maroon:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e84883; color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f29aba; color: #1f2d3d; } .dark-mode .card-blue:not(.card-outline) > .card-header { background-color: #3f6791; } .dark-mode .card-blue:not(.card-outline) > .card-header, .dark-mode .card-blue:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-blue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-blue.card-outline { border-top: 3px solid #3f6791; } .dark-mode .card-blue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-blue.card-outline-tabs > .card-header a.active, .dark-mode .card-blue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3f6791; } .dark-mode .bg-blue > .card-header .btn-tool, .dark-mode .bg-gradient-blue > .card-header .btn-tool, .dark-mode .card-blue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-blue > .card-header .btn-tool:hover, .dark-mode .bg-gradient-blue > .card-header .btn-tool:hover, .dark-mode .card-blue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #335375; color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5080b3; color: #fff; } .dark-mode .card-indigo:not(.card-outline) > .card-header { background-color: #6610f2; } .dark-mode .card-indigo:not(.card-outline) > .card-header, .dark-mode .card-indigo:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-indigo:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-indigo.card-outline { border-top: 3px solid #6610f2; } .dark-mode .card-indigo.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-indigo.card-outline-tabs > .card-header a.active, .dark-mode .card-indigo.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6610f2; } .dark-mode .bg-indigo > .card-header .btn-tool, .dark-mode .bg-gradient-indigo > .card-header .btn-tool, .dark-mode .card-indigo:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-indigo > .card-header .btn-tool:hover, .dark-mode .bg-gradient-indigo > .card-header .btn-tool:hover, .dark-mode .card-indigo:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.second:hover { background-color: #550bce; color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8540f5; color: #fff; } .dark-mode .card-purple:not(.card-outline) > .card-header { background-color: #6f42c1; } .dark-mode .card-purple:not(.card-outline) > .card-header, .dark-mode .card-purple:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-purple:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-purple.card-outline { border-top: 3px solid #6f42c1; } .dark-mode .card-purple.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-purple.card-outline-tabs > .card-header a.active, .dark-mode .card-purple.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6f42c1; } .dark-mode .bg-purple > .card-header .btn-tool, .dark-mode .bg-gradient-purple > .card-header .btn-tool, .dark-mode .card-purple:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-purple > .card-header .btn-tool:hover, .dark-mode .bg-gradient-purple > .card-header .btn-tool:hover, .dark-mode .card-purple:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.second:hover { background-color: #5d36a4; color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8c68ce; color: #fff; } .dark-mode .card-pink:not(.card-outline) > .card-header { background-color: #e83e8c; } .dark-mode .card-pink:not(.card-outline) > .card-header, .dark-mode .card-pink:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-pink:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-pink.card-outline { border-top: 3px solid #e83e8c; } .dark-mode .card-pink.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-pink.card-outline-tabs > .card-header a.active, .dark-mode .card-pink.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e83e8c; } .dark-mode .bg-pink > .card-header .btn-tool, .dark-mode .bg-gradient-pink > .card-header .btn-tool, .dark-mode .card-pink:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-pink > .card-header .btn-tool:hover, .dark-mode .bg-gradient-pink > .card-header .btn-tool:hover, .dark-mode .card-pink:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e21b76; color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed6ca7; color: #fff; } .dark-mode .card-red:not(.card-outline) > .card-header { background-color: #e74c3c; } .dark-mode .card-red:not(.card-outline) > .card-header, .dark-mode .card-red:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-red:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-red.card-outline { border-top: 3px solid #e74c3c; } .dark-mode .card-red.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-red.card-outline-tabs > .card-header a.active, .dark-mode .card-red.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e74c3c; } .dark-mode .bg-red > .card-header .btn-tool, .dark-mode .bg-gradient-red > .card-header .btn-tool, .dark-mode .card-red:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-red > .card-header .btn-tool:hover, .dark-mode .bg-gradient-red > .card-header .btn-tool:hover, .dark-mode .card-red:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.second:hover { background-color: #df2e1b; color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed7669; color: #fff; } .dark-mode .card-orange:not(.card-outline) > .card-header { background-color: #fd7e14; } .dark-mode .card-orange:not(.card-outline) > .card-header, .dark-mode .card-orange:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-orange:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-orange.card-outline { border-top: 3px solid #fd7e14; } .dark-mode .card-orange.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-orange.card-outline-tabs > .card-header a.active, .dark-mode .card-orange.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fd7e14; } .dark-mode .bg-orange > .card-header .btn-tool, .dark-mode .bg-gradient-orange > .card-header .btn-tool, .dark-mode .card-orange:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-orange > .card-header .btn-tool:hover, .dark-mode .bg-gradient-orange > .card-header .btn-tool:hover, .dark-mode .card-orange:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e66a02; color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active:hover { background-color: #fd9a47; color: #1f2d3d; } .dark-mode .card-yellow:not(.card-outline) > .card-header { background-color: #f39c12; } .dark-mode .card-yellow:not(.card-outline) > .card-header, .dark-mode .card-yellow:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-yellow:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-yellow.card-outline { border-top: 3px solid #f39c12; } .dark-mode .card-yellow.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-yellow.card-outline-tabs > .card-header a.active, .dark-mode .card-yellow.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f39c12; } .dark-mode .bg-yellow > .card-header .btn-tool, .dark-mode .bg-gradient-yellow > .card-header .btn-tool, .dark-mode .card-yellow:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-yellow > .card-header .btn-tool:hover, .dark-mode .bg-gradient-yellow > .card-header .btn-tool:hover, .dark-mode .card-yellow:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.second:hover { background-color: #d2850b; color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f5b043; color: #1f2d3d; } .dark-mode .card-green:not(.card-outline) > .card-header { background-color: #00bc8c; } .dark-mode .card-green:not(.card-outline) > .card-header, .dark-mode .card-green:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-green:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-green.card-outline { border-top: 3px solid #00bc8c; } .dark-mode .card-green.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-green.card-outline-tabs > .card-header a.active, .dark-mode .card-green.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #00bc8c; } .dark-mode .bg-green > .card-header .btn-tool, .dark-mode .bg-gradient-green > .card-header .btn-tool, .dark-mode .card-green:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-green > .card-header .btn-tool:hover, .dark-mode .bg-gradient-green > .card-header .btn-tool:hover, .dark-mode .card-green:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00936e; color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00efb2; color: #fff; } .dark-mode .card-teal:not(.card-outline) > .card-header { background-color: #20c997; } .dark-mode .card-teal:not(.card-outline) > .card-header, .dark-mode .card-teal:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-teal:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-teal.card-outline { border-top: 3px solid #20c997; } .dark-mode .card-teal.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-teal.card-outline-tabs > .card-header a.active, .dark-mode .card-teal.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #20c997; } .dark-mode .bg-teal > .card-header .btn-tool, .dark-mode .bg-gradient-teal > .card-header .btn-tool, .dark-mode .card-teal:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-teal > .card-header .btn-tool:hover, .dark-mode .bg-gradient-teal > .card-header .btn-tool:hover, .dark-mode .card-teal:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.second:hover { background-color: #1aa67d; color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3ce0af; color: #fff; } .dark-mode .card-cyan:not(.card-outline) > .card-header { background-color: #3498db; } .dark-mode .card-cyan:not(.card-outline) > .card-header, .dark-mode .card-cyan:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-cyan:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-cyan.card-outline { border-top: 3px solid #3498db; } .dark-mode .card-cyan.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-cyan.card-outline-tabs > .card-header a.active, .dark-mode .card-cyan.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3498db; } .dark-mode .bg-cyan > .card-header .btn-tool, .dark-mode .bg-gradient-cyan > .card-header .btn-tool, .dark-mode .card-cyan:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-cyan > .card-header .btn-tool:hover, .dark-mode .bg-gradient-cyan > .card-header .btn-tool:hover, .dark-mode .card-cyan:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.second:hover { background-color: #2383c4; color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5faee3; color: #fff; } .dark-mode .card-white:not(.card-outline) > .card-header { background-color: #fff; } .dark-mode .card-white:not(.card-outline) > .card-header, .dark-mode .card-white:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-white:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-white.card-outline { border-top: 3px solid #fff; } .dark-mode .card-white.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-white.card-outline-tabs > .card-header a.active, .dark-mode .card-white.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fff; } .dark-mode .bg-white > .card-header .btn-tool, .dark-mode .bg-gradient-white > .card-header .btn-tool, .dark-mode .card-white:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-white > .card-header .btn-tool:hover, .dark-mode .bg-gradient-white > .card-header .btn-tool:hover, .dark-mode .card-white:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.second:hover { background-color: #ebebeb; color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .dark-mode .card-gray:not(.card-outline) > .card-header { background-color: #6c757d; } .dark-mode .card-gray:not(.card-outline) > .card-header, .dark-mode .card-gray:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-gray:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-gray.card-outline { border-top: 3px solid #6c757d; } .dark-mode .card-gray.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-gray.card-outline-tabs > .card-header a.active, .dark-mode .card-gray.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .dark-mode .bg-gray > .card-header .btn-tool, .dark-mode .bg-gradient-gray > .card-header .btn-tool, .dark-mode .card-gray:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-gray > .card-header .btn-tool:hover, .dark-mode .bg-gradient-gray > .card-header .btn-tool:hover, .dark-mode .card-gray:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header { background-color: #343a40; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header, .dark-mode .card-gray-dark:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-gray-dark.card-outline { border-top: 3px solid #343a40; } .dark-mode .card-gray-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-gray-dark.card-outline-tabs > .card-header a.active, .dark-mode .card-gray-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .dark-mode .bg-gray-dark > .card-header .btn-tool, .dark-mode .bg-gradient-gray-dark > .card-header .btn-tool, .dark-mode .card-gray-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-gray-dark > .card-header .btn-tool:hover, .dark-mode .bg-gradient-gray-dark > .card-header .btn-tool:hover, .dark-mode .card-gray-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .dark-mode .card { background-color: #343a40; color: #fff; } .dark-mode .card .card { background-color: #3f474e; color: #fff; } .dark-mode .card .nav.flex-column > li { border-bottom-color: #6c757d; } .dark-mode .card .card-footer { background-color: rgba(0, 0, 0, 0.1); } .dark-mode .card.card-outline-tabs { border-top: 0; } .dark-mode .card.card-outline-tabs .card-header a:hover { border-top-color: #6c757d; border-bottom-color: transparent; } .dark-mode .card:not(.card-outline) > .card-header a.active { color: #fff; } .dark-mode .card-comments { background-color: #373d44; } .dark-mode .card-comments .username { color: #ced4da; } .dark-mode .card-comments .card-comment { border-bottom-color: #454d55; } .dark-mode .todo-list > li { background-color: #3f474e; border-color: #454d55; color: #fff; } .dark-mode .todo-list .primary { border-left-color: #3f6791; } .dark-mode .todo-list .secondary { border-left-color: #6c757d; } .dark-mode .todo-list .success { border-left-color: #00bc8c; } .dark-mode .todo-list .info { border-left-color: #3498db; } .dark-mode .todo-list .warning { border-left-color: #f39c12; } .dark-mode .todo-list .danger { border-left-color: #e74c3c; } .dark-mode .todo-list .light { border-left-color: #f8f9fa; } .dark-mode .todo-list .dark { border-left-color: #343a40; } .dark-mode .todo-list .lightblue { border-left-color: #86bad8; } .dark-mode .todo-list .navy { border-left-color: #002c59; } .dark-mode .todo-list .olive { border-left-color: #74c8a3; } .dark-mode .todo-list .lime { border-left-color: #67ffa9; } .dark-mode .todo-list .fuchsia { border-left-color: #f672d8; } .dark-mode .todo-list .maroon { border-left-color: #ed6c9b; } .dark-mode .todo-list .blue { border-left-color: #3f6791; } .dark-mode .todo-list .indigo { border-left-color: #6610f2; } .dark-mode .todo-list .purple { border-left-color: #6f42c1; } .dark-mode .todo-list .pink { border-left-color: #e83e8c; } .dark-mode .todo-list .red { border-left-color: #e74c3c; } .dark-mode .todo-list .orange { border-left-color: #fd7e14; } .dark-mode .todo-list .yellow { border-left-color: #f39c12; } .dark-mode .todo-list .green { border-left-color: #00bc8c; } .dark-mode .todo-list .teal { border-left-color: #20c997; } .dark-mode .todo-list .cyan { border-left-color: #3498db; } .dark-mode .todo-list .white { border-left-color: #fff; } .dark-mode .todo-list .gray { border-left-color: #6c757d; } .dark-mode .todo-list .gray-dark { border-left-color: #343a40; } .modal-dialog .overlay { display: -ms-flexbox; display: flex; position: absolute; left: 0; top: 0; bottom: 0; right: 0; margin: -1px; z-index: 1052; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; background-color: rgba(0, 0, 0, 0.7); color: #666f76; border-radius: 0.3rem; } .modal-content.bg-warning .modal-header, .modal-content.bg-warning .modal-footer { border-color: #343a40; } .modal-content.bg-primary .close, .modal-content.bg-primary .mailbox-attachment-close, .modal-content.bg-secondary .close, .modal-content.bg-secondary .mailbox-attachment-close, .modal-content.bg-info .close, .modal-content.bg-info .mailbox-attachment-close, .modal-content.bg-danger .close, .modal-content.bg-danger .mailbox-attachment-close, .modal-content.bg-success .close, .modal-content.bg-success .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .modal-header, .dark-mode .modal-footer { border-color: #6c757d; } .dark-mode .modal-content { background-color: #343a40; } .dark-mode .modal-content.bg-warning .modal-header, .dark-mode .modal-content.bg-warning .modal-footer { border-color: #6c757d; } .dark-mode .modal-content.bg-warning .close, .dark-mode .modal-content.bg-warning .mailbox-attachment-close { color: #343a40 !important; text-shadow: 0 1px 0 #495057 !important; } .dark-mode .modal-content.bg-primary .modal-header, .dark-mode .modal-content.bg-primary .modal-footer, .dark-mode .modal-content.bg-secondary .modal-header, .dark-mode .modal-content.bg-secondary .modal-footer, .dark-mode .modal-content.bg-info .modal-header, .dark-mode .modal-content.bg-info .modal-footer, .dark-mode .modal-content.bg-danger .modal-header, .dark-mode .modal-content.bg-danger .modal-footer, .dark-mode .modal-content.bg-success .modal-header, .dark-mode .modal-content.bg-success .modal-footer { border-color: #fff; } .toasts-top-right { position: absolute; right: 0; top: 0; z-index: 1040; } .toasts-top-right.fixed { position: fixed; } .toasts-top-left { left: 0; position: absolute; top: 0; z-index: 1040; } .toasts-top-left.fixed { position: fixed; } .toasts-bottom-right { bottom: 0; position: absolute; right: 0; z-index: 1040; } .toasts-bottom-right.fixed { position: fixed; } .toasts-bottom-left { bottom: 0; left: 0; position: absolute; z-index: 1040; } .toasts-bottom-left.fixed { position: fixed; } .dark-mode .toast { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .dark-mode .toast .toast-header { background-color: rgba(52, 58, 64, 0.7); color: #f8f9fa; } .dark-mode .toast.bg-primary { background-color: rgba(63, 103, 145, 0.9) !important; } .dark-mode .toast.bg-primary .close, .dark-mode .toast.bg-primary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-primary .toast-header { background-color: rgba(63, 103, 145, 0.85); color: #fff; } .dark-mode .toast.bg-secondary { background-color: rgba(108, 117, 125, 0.9) !important; } .dark-mode .toast.bg-secondary .close, .dark-mode .toast.bg-secondary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-secondary .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .dark-mode .toast.bg-success { background-color: rgba(0, 188, 140, 0.9) !important; } .dark-mode .toast.bg-success .close, .dark-mode .toast.bg-success .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-success .toast-header { background-color: rgba(0, 188, 140, 0.85); color: #fff; } .dark-mode .toast.bg-info { background-color: rgba(52, 152, 219, 0.9) !important; } .dark-mode .toast.bg-info .close, .dark-mode .toast.bg-info .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-info .toast-header { background-color: rgba(52, 152, 219, 0.85); color: #fff; } .dark-mode .toast.bg-warning { background-color: rgba(243, 156, 18, 0.9) !important; } .dark-mode .toast.bg-warning .toast-header { background-color: rgba(243, 156, 18, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-danger { background-color: rgba(231, 76, 60, 0.9) !important; } .dark-mode .toast.bg-danger .close, .dark-mode .toast.bg-danger .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-danger .toast-header { background-color: rgba(231, 76, 60, 0.85); color: #fff; } .dark-mode .toast.bg-light { background-color: rgba(248, 249, 250, 0.9) !important; } .dark-mode .toast.bg-light .toast-header { background-color: rgba(248, 249, 250, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .dark-mode .toast.bg-dark .close, .dark-mode .toast.bg-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .dark-mode .toast.bg-lightblue { background-color: rgba(134, 186, 216, 0.9) !important; } .dark-mode .toast.bg-lightblue .toast-header { background-color: rgba(134, 186, 216, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-navy { background-color: rgba(0, 44, 89, 0.9) !important; } .dark-mode .toast.bg-navy .close, .dark-mode .toast.bg-navy .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-navy .toast-header { background-color: rgba(0, 44, 89, 0.85); color: #fff; } .dark-mode .toast.bg-olive { background-color: rgba(116, 200, 163, 0.9) !important; } .dark-mode .toast.bg-olive .toast-header { background-color: rgba(116, 200, 163, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-lime { background-color: rgba(103, 255, 169, 0.9) !important; } .dark-mode .toast.bg-lime .toast-header { background-color: rgba(103, 255, 169, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-fuchsia { background-color: rgba(246, 114, 216, 0.9) !important; } .dark-mode .toast.bg-fuchsia .toast-header { background-color: rgba(246, 114, 216, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-maroon { background-color: rgba(237, 108, 155, 0.9) !important; } .dark-mode .toast.bg-maroon .toast-header { background-color: rgba(237, 108, 155, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-blue { background-color: rgba(63, 103, 145, 0.9) !important; } .dark-mode .toast.bg-blue .close, .dark-mode .toast.bg-blue .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-blue .toast-header { background-color: rgba(63, 103, 145, 0.85); color: #fff; } .dark-mode .toast.bg-indigo { background-color: rgba(102, 16, 242, 0.9) !important; } .dark-mode .toast.bg-indigo .close, .dark-mode .toast.bg-indigo .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-indigo .toast-header { background-color: rgba(102, 16, 242, 0.85); color: #fff; } .dark-mode .toast.bg-purple { background-color: rgba(111, 66, 193, 0.9) !important; } .dark-mode .toast.bg-purple .close, .dark-mode .toast.bg-purple .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-purple .toast-header { background-color: rgba(111, 66, 193, 0.85); color: #fff; } .dark-mode .toast.bg-pink { background-color: rgba(232, 62, 140, 0.9) !important; } .dark-mode .toast.bg-pink .close, .dark-mode .toast.bg-pink .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-pink .toast-header { background-color: rgba(232, 62, 140, 0.85); color: #fff; } .dark-mode .toast.bg-red { background-color: rgba(231, 76, 60, 0.9) !important; } .dark-mode .toast.bg-red .close, .dark-mode .toast.bg-red .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-red .toast-header { background-color: rgba(231, 76, 60, 0.85); color: #fff; } .dark-mode .toast.bg-orange { background-color: rgba(253, 126, 20, 0.9) !important; } .dark-mode .toast.bg-orange .toast-header { background-color: rgba(253, 126, 20, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-yellow { background-color: rgba(243, 156, 18, 0.9) !important; } .dark-mode .toast.bg-yellow .toast-header { background-color: rgba(243, 156, 18, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-green { background-color: rgba(0, 188, 140, 0.9) !important; } .dark-mode .toast.bg-green .close, .dark-mode .toast.bg-green .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-green .toast-header { background-color: rgba(0, 188, 140, 0.85); color: #fff; } .dark-mode .toast.bg-teal { background-color: rgba(32, 201, 151, 0.9) !important; } .dark-mode .toast.bg-teal .close, .dark-mode .toast.bg-teal .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-teal .toast-header { background-color: rgba(32, 201, 151, 0.85); color: #fff; } .dark-mode .toast.bg-cyan { background-color: rgba(52, 152, 219, 0.9) !important; } .dark-mode .toast.bg-cyan .close, .dark-mode .toast.bg-cyan .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-cyan .toast-header { background-color: rgba(52, 152, 219, 0.85); color: #fff; } .dark-mode .toast.bg-white { background-color: rgba(255, 255, 255, 0.9) !important; } .dark-mode .toast.bg-white .toast-header { background-color: rgba(255, 255, 255, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-gray { background-color: rgba(108, 117, 125, 0.9) !important; } .dark-mode .toast.bg-gray .close, .dark-mode .toast.bg-gray .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-gray .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .dark-mode .toast.bg-gray-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .dark-mode .toast.bg-gray-dark .close, .dark-mode .toast.bg-gray-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-gray-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .toast.bg-primary { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-primary .close, .toast.bg-primary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-primary .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-secondary { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-secondary .close, .toast.bg-secondary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-secondary .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-success { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-success .close, .toast.bg-success .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-success .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-info { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-info .close, .toast.bg-info .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-info .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-warning { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-warning .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-danger { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-danger .close, .toast.bg-danger .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-danger .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-light { background-color: rgba(248, 249, 250, 0.9) !important; } .toast.bg-light .toast-header { background-color: rgba(248, 249, 250, 0.85); color: #1f2d3d; } .toast.bg-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-dark .close, .toast.bg-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .toast.bg-lightblue { background-color: rgba(60, 141, 188, 0.9) !important; } .toast.bg-lightblue .close, .toast.bg-lightblue .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-lightblue .toast-header { background-color: rgba(60, 141, 188, 0.85); color: #fff; } .toast.bg-navy { background-color: rgba(0, 31, 63, 0.9) !important; } .toast.bg-navy .close, .toast.bg-navy .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-navy .toast-header { background-color: rgba(0, 31, 63, 0.85); color: #fff; } .toast.bg-olive { background-color: rgba(61, 153, 112, 0.9) !important; } .toast.bg-olive .close, .toast.bg-olive .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-olive .toast-header { background-color: rgba(61, 153, 112, 0.85); color: #fff; } .toast.bg-lime { background-color: rgba(1, 255, 112, 0.9) !important; } .toast.bg-lime .toast-header { background-color: rgba(1, 255, 112, 0.85); color: #1f2d3d; } .toast.bg-fuchsia { background-color: rgba(240, 18, 190, 0.9) !important; } .toast.bg-fuchsia .close, .toast.bg-fuchsia .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-fuchsia .toast-header { background-color: rgba(240, 18, 190, 0.85); color: #fff; } .toast.bg-maroon { background-color: rgba(216, 27, 96, 0.9) !important; } .toast.bg-maroon .close, .toast.bg-maroon .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-maroon .toast-header { background-color: rgba(216, 27, 96, 0.85); color: #fff; } .toast.bg-blue { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-blue .close, .toast.bg-blue .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-blue .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-indigo { background-color: rgba(102, 16, 242, 0.9) !important; } .toast.bg-indigo .close, .toast.bg-indigo .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-indigo .toast-header { background-color: rgba(102, 16, 242, 0.85); color: #fff; } .toast.bg-purple { background-color: rgba(111, 66, 193, 0.9) !important; } .toast.bg-purple .close, .toast.bg-purple .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-purple .toast-header { background-color: rgba(111, 66, 193, 0.85); color: #fff; } .toast.bg-pink { background-color: rgba(232, 62, 140, 0.9) !important; } .toast.bg-pink .close, .toast.bg-pink .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-pink .toast-header { background-color: rgba(232, 62, 140, 0.85); color: #fff; } .toast.bg-red { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-red .close, .toast.bg-red .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-red .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-orange { background-color: rgba(253, 126, 20, 0.9) !important; } .toast.bg-orange .toast-header { background-color: rgba(253, 126, 20, 0.85); color: #1f2d3d; } .toast.bg-yellow { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-yellow .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-green { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-green .close, .toast.bg-green .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-green .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-teal { background-color: rgba(32, 201, 151, 0.9) !important; } .toast.bg-teal .close, .toast.bg-teal .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-teal .toast-header { background-color: rgba(32, 201, 151, 0.85); color: #fff; } .toast.bg-cyan { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-cyan .close, .toast.bg-cyan .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-cyan .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-white { background-color: rgba(255, 255, 255, 0.9) !important; } .toast.bg-white .toast-header { background-color: rgba(255, 255, 255, 0.85); color: #1f2d3d; } .toast.bg-gray { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-gray .close, .toast.bg-gray .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-gray-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-gray-dark .close, .toast.bg-gray-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .btn.disabled, .btn:disabled { cursor: not-allowed; } .btn.btn-flat { border-radius: 0; border-width: 1px; box-shadow: none; } .btn.btn-file { overflow: hidden; position: relative; } .btn.btn-file > input[type="file"] { background-color: #fff; cursor: inherit; display: block; font-size: 100px; min-height: 100%; min-width: 100%; opacity: 0; outline: none; position: absolute; right: 0; text-align: right; top: 0; } .text-sm .btn { font-size: 0.875rem !important; } .btn-default { background-color: #f8f9fa; border-color: #ddd; color: #444; } .btn-default:hover, .btn-default:active, .btn-default.hover { background-color: #e9ecef; color: #2b2b2b; } .btn-default.disabled, .btn-default:disabled { color: #444; background-color: #f8f9fa; } .btn-outline-light { color: #bdc6d0; border-color: #bdc6d0; } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #bdc6d0; border-color: #bdc6d0; } .btn-app { border-radius: 3px; background-color: #f8f9fa; border: 1px solid #ddd; color: #6c757d; font-size: 12px; height: 60px; margin: 0 0 10px 10px; min-width: 80px; padding: 15px 5px; position: relative; text-align: center; } .btn-app > .fa, .btn-app > .fas, .btn-app > .far, .btn-app > .fab, .btn-app > .fal, .btn-app > .fad, .btn-app > .svg-inline--fa, .btn-app > .ion { display: block; font-size: 20px; } .btn-app > .svg-inline--fa { margin: 0 auto; } .btn-app:hover { background-color: #f8f9fa; border-color: #aaaaaa; color: #444; } .btn-app:active, .btn-app:focus { box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-app > .badge { font-size: 10px; font-weight: 400; position: absolute; right: -10px; top: -3px; } .btn-xs { padding: 0.125rem 0.25rem; font-size: 0.75rem; line-height: 1.5; border-radius: 0.15rem; } .dark-mode .btn-default, .dark-mode .btn-app { background-color: #3a4047; color: #fff; border-color: #6c757d; } .dark-mode .btn-default:hover, .dark-mode .btn-default:focus, .dark-mode .btn-app:hover, .dark-mode .btn-app:focus { background-color: #3f474e; color: #dee2e6; border-color: #727b84; } .dark-mode .btn-light { background-color: #454d55; color: #fff; border-color: #6c757d; } .dark-mode .btn-light:hover, .dark-mode .btn-light:focus { background-color: #4b545c; color: #dee2e6; border-color: #78828a; } .dark-mode .btn-primary { color: #fff; background-color: #3f6791; border-color: #3f6791; box-shadow: none; } .dark-mode .btn-primary:hover { color: #fff; background-color: #335476; border-color: #304e6d; } .dark-mode .btn-primary:focus, .dark-mode .btn-primary.focus { color: #fff; background-color: #335476; border-color: #304e6d; box-shadow: 0 0 0 0 rgba(92, 126, 162, 0.5); } .dark-mode .btn-primary.disabled, .dark-mode .btn-primary:disabled { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-primary:not(:disabled):not(.disabled):active, .dark-mode .btn-primary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-primary.dropdown-toggle { color: #fff; background-color: #304e6d; border-color: #2c4765; } .dark-mode .btn-primary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(92, 126, 162, 0.5); } .dark-mode .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; box-shadow: none; } .dark-mode .btn-secondary:hover { color: #fff; background-color: #5a6268; border-color: #545b62; } .dark-mode .btn-secondary:focus, .dark-mode .btn-secondary.focus { color: #fff; background-color: #5a6268; border-color: #545b62; box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .dark-mode .btn-secondary.disabled, .dark-mode .btn-secondary:disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-secondary:not(:disabled):not(.disabled):active, .dark-mode .btn-secondary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-secondary.dropdown-toggle { color: #fff; background-color: #545b62; border-color: #4e555b; } .dark-mode .btn-secondary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .dark-mode .btn-success { color: #fff; background-color: #00bc8c; border-color: #00bc8c; box-shadow: none; } .dark-mode .btn-success:hover { color: #fff; background-color: #009670; border-color: #008966; } .dark-mode .btn-success:focus, .dark-mode .btn-success.focus { color: #fff; background-color: #009670; border-color: #008966; box-shadow: 0 0 0 0 rgba(38, 198, 157, 0.5); } .dark-mode .btn-success.disabled, .dark-mode .btn-success:disabled { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-success:not(:disabled):not(.disabled):active, .dark-mode .btn-success:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-success.dropdown-toggle { color: #fff; background-color: #008966; border-color: #007c5d; } .dark-mode .btn-success:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-success:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(38, 198, 157, 0.5); } .dark-mode .btn-info { color: #fff; background-color: #3498db; border-color: #3498db; box-shadow: none; } .dark-mode .btn-info:hover { color: #fff; background-color: #2384c6; border-color: #217dbb; } .dark-mode .btn-info:focus, .dark-mode .btn-info.focus { color: #fff; background-color: #2384c6; border-color: #217dbb; box-shadow: 0 0 0 0 rgba(82, 167, 224, 0.5); } .dark-mode .btn-info.disabled, .dark-mode .btn-info:disabled { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-info:not(:disabled):not(.disabled):active, .dark-mode .btn-info:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-info.dropdown-toggle { color: #fff; background-color: #217dbb; border-color: #1f76b0; } .dark-mode .btn-info:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-info:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(82, 167, 224, 0.5); } .dark-mode .btn-warning { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; box-shadow: none; } .dark-mode .btn-warning:hover { color: #fff; background-color: #d4860b; border-color: #c87f0a; } .dark-mode .btn-warning:focus, .dark-mode .btn-warning.focus { color: #fff; background-color: #d4860b; border-color: #c87f0a; box-shadow: 0 0 0 0 rgba(211, 139, 24, 0.5); } .dark-mode .btn-warning.disabled, .dark-mode .btn-warning:disabled { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-warning:not(:disabled):not(.disabled):active, .dark-mode .btn-warning:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-warning.dropdown-toggle { color: #fff; background-color: #c87f0a; border-color: #bc770a; } .dark-mode .btn-warning:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(211, 139, 24, 0.5); } .dark-mode .btn-danger { color: #fff; background-color: #e74c3c; border-color: #e74c3c; box-shadow: none; } .dark-mode .btn-danger:hover { color: #fff; background-color: #e12e1c; border-color: #d62c1a; } .dark-mode .btn-danger:focus, .dark-mode .btn-danger.focus { color: #fff; background-color: #e12e1c; border-color: #d62c1a; box-shadow: 0 0 0 0 rgba(235, 103, 89, 0.5); } .dark-mode .btn-danger.disabled, .dark-mode .btn-danger:disabled { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-danger:not(:disabled):not(.disabled):active, .dark-mode .btn-danger:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-danger.dropdown-toggle { color: #fff; background-color: #d62c1a; border-color: #ca2a19; } .dark-mode .btn-danger:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(235, 103, 89, 0.5); } .dark-mode .btn-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: none; } .dark-mode .btn-light:hover { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; } .dark-mode .btn-light:focus, .dark-mode .btn-light.focus { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .dark-mode .btn-light.disabled, .dark-mode .btn-light:disabled { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-light:not(:disabled):not(.disabled):active, .dark-mode .btn-light:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-light.dropdown-toggle { color: #1f2d3d; background-color: #dae0e5; border-color: #d3d9df; } .dark-mode .btn-light:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-light:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .dark-mode .btn-dark { color: #fff; background-color: #292d32; border-color: #4b545c; box-shadow: none; } .dark-mode .btn-dark:hover { color: #fff; background-color: #171a1d; border-color: #343a40; } .dark-mode .btn-dark:focus, .dark-mode .btn-dark.focus { color: #fff; background-color: #171a1d; border-color: #343a40; box-shadow: 0 0 0 0 rgba(102, 109, 117, 0.5); } .dark-mode .btn-dark.disabled, .dark-mode .btn-dark:disabled { color: #fff; background-color: #292d32; border-color: #4b545c; } .dark-mode .btn-dark:not(:disabled):not(.disabled):active, .dark-mode .btn-dark:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-dark.dropdown-toggle { color: #fff; background-color: #121416; border-color: #2e3439; } .dark-mode .btn-dark:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(102, 109, 117, 0.5); } .dark-mode .btn-outline-primary { color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:hover { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:focus, .dark-mode .btn-outline-primary.focus { box-shadow: 0 0 0 0 rgba(63, 103, 145, 0.5); } .dark-mode .btn-outline-primary.disabled, .dark-mode .btn-outline-primary:disabled { color: #3f6791; background-color: transparent; } .dark-mode .btn-outline-primary:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(63, 103, 145, 0.5); } .dark-mode .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:focus, .dark-mode .btn-outline-secondary.focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .dark-mode .btn-outline-secondary.disabled, .dark-mode .btn-outline-secondary:disabled { color: #6c757d; background-color: transparent; } .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .dark-mode .btn-outline-success { color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:hover { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:focus, .dark-mode .btn-outline-success.focus { box-shadow: 0 0 0 0 rgba(0, 188, 140, 0.5); } .dark-mode .btn-outline-success.disabled, .dark-mode .btn-outline-success:disabled { color: #00bc8c; background-color: transparent; } .dark-mode .btn-outline-success:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-success:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-success.dropdown-toggle { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(0, 188, 140, 0.5); } .dark-mode .btn-outline-info { color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:hover { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:focus, .dark-mode .btn-outline-info.focus { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.5); } .dark-mode .btn-outline-info.disabled, .dark-mode .btn-outline-info:disabled { color: #3498db; background-color: transparent; } .dark-mode .btn-outline-info:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-info:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-info.dropdown-toggle { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.5); } .dark-mode .btn-outline-warning { color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:hover { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:focus, .dark-mode .btn-outline-warning.focus { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0.5); } .dark-mode .btn-outline-warning.disabled, .dark-mode .btn-outline-warning:disabled { color: #f39c12; background-color: transparent; } .dark-mode .btn-outline-warning:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-warning.dropdown-toggle { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0.5); } .dark-mode .btn-outline-danger { color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:hover { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:focus, .dark-mode .btn-outline-danger.focus { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); } .dark-mode .btn-outline-danger.disabled, .dark-mode .btn-outline-danger:disabled { color: #e74c3c; background-color: transparent; } .dark-mode .btn-outline-danger:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); } .dark-mode .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:hover { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:focus, .dark-mode .btn-outline-light.focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .dark-mode .btn-outline-light.disabled, .dark-mode .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .dark-mode .btn-outline-light:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-light:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-light.dropdown-toggle { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .dark-mode .btn-outline-dark { color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:hover { color: #fff; background-color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:focus, .dark-mode .btn-outline-dark.focus { box-shadow: 0 0 0 0 rgba(6, 7, 8, 0.5); } .dark-mode .btn-outline-dark.disabled, .dark-mode .btn-outline-dark:disabled { color: #060708; background-color: transparent; } .dark-mode .btn-outline-dark:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(6, 7, 8, 0.5); } .callout { border-radius: 0.25rem; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); background-color: #fff; border-left: 5px solid #e9ecef; margin-bottom: 1rem; padding: 1rem; } .callout a { color: #495057; text-decoration: underline; } .callout a:hover { color: #e9ecef; } .callout p:last-child { margin-bottom: 0; } .callout.callout-danger { border-left-color: #bd2130; } .callout.callout-warning { border-left-color: #d39e00; } .callout.callout-info { border-left-color: #117a8b; } .callout.callout-success { border-left-color: #1e7e34; } .dark-mode .callout { background-color: #3f474e; } .dark-mode .callout.callout-danger { border-left-color: #ed7669; } .dark-mode .callout.callout-warning { border-left-color: #f5b043; } .dark-mode .callout.callout-info { border-left-color: #5faee3; } .dark-mode .callout.callout-success { border-left-color: #00efb2; } .alert .icon { margin-right: 10px; } .alert .close, .alert .mailbox-attachment-close { color: #000; opacity: .2; } .alert .close:hover, .alert .mailbox-attachment-close:hover { opacity: .5; } .alert a { color: #fff; text-decoration: underline; } .alert-primary { color: #fff; background-color: #007bff; border-color: #006fe6; } .alert-default-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-default-primary hr { border-top-color: #9fcdff; } .alert-default-primary .alert-link { color: #002752; } .alert-secondary { color: #fff; background-color: #6c757d; border-color: #60686f; } .alert-default-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-default-secondary hr { border-top-color: #c8cbcf; } .alert-default-secondary .alert-link { color: #202326; } .alert-success { color: #fff; background-color: #28a745; border-color: #23923d; } .alert-default-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-default-success hr { border-top-color: #b1dfbb; } .alert-default-success .alert-link { color: #0b2e13; } .alert-info { color: #fff; background-color: #17a2b8; border-color: #148ea1; } .alert-default-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-default-info hr { border-top-color: #abdde5; } .alert-default-info .alert-link { color: #062c33; } .alert-warning { color: #1f2d3d; background-color: #ffc107; border-color: #edb100; } .alert-default-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-default-warning hr { border-top-color: #ffe8a1; } .alert-default-warning .alert-link { color: #533f03; } .alert-danger { color: #fff; background-color: #dc3545; border-color: #d32535; } .alert-default-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-default-danger hr { border-top-color: #f1b0b7; } .alert-default-danger .alert-link { color: #491217; } .alert-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #e9ecef; } .alert-default-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-default-light hr { border-top-color: #ececf6; } .alert-default-light .alert-link { color: #686868; } .alert-dark { color: #fff; background-color: #343a40; border-color: #292d32; } .alert-default-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-default-dark hr { border-top-color: #b9bbbe; } .alert-default-dark .alert-link { color: #040505; } .dark-mode .alert-primary { color: #fff; background-color: #3f6791; border-color: #375a7f; } .dark-mode .alert-default-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .dark-mode .alert-default-primary hr { border-top-color: #9fcdff; } .dark-mode .alert-default-primary .alert-link { color: #002752; } .dark-mode .alert-secondary { color: #fff; background-color: #6c757d; border-color: #60686f; } .dark-mode .alert-default-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .dark-mode .alert-default-secondary hr { border-top-color: #c8cbcf; } .dark-mode .alert-default-secondary .alert-link { color: #202326; } .dark-mode .alert-success { color: #fff; background-color: #00bc8c; border-color: #00a379; } .dark-mode .alert-default-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .dark-mode .alert-default-success hr { border-top-color: #b1dfbb; } .dark-mode .alert-default-success .alert-link { color: #0b2e13; } .dark-mode .alert-info { color: #fff; background-color: #3498db; border-color: #258cd1; } .dark-mode .alert-default-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .dark-mode .alert-default-info hr { border-top-color: #abdde5; } .dark-mode .alert-default-info .alert-link { color: #062c33; } .dark-mode .alert-warning { color: #1f2d3d; background-color: #f39c12; border-color: #e08e0b; } .dark-mode .alert-default-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .dark-mode .alert-default-warning hr { border-top-color: #ffe8a1; } .dark-mode .alert-default-warning .alert-link { color: #533f03; } .dark-mode .alert-danger { color: #fff; background-color: #e74c3c; border-color: #e43725; } .dark-mode .alert-default-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .dark-mode .alert-default-danger hr { border-top-color: #f1b0b7; } .dark-mode .alert-default-danger .alert-link { color: #491217; } .dark-mode .alert-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #e9ecef; } .dark-mode .alert-default-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .dark-mode .alert-default-light hr { border-top-color: #ececf6; } .dark-mode .alert-default-light .alert-link { color: #686868; } .dark-mode .alert-dark { color: #fff; background-color: #343a40; border-color: #292d32; } .dark-mode .alert-default-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .dark-mode .alert-default-dark hr { border-top-color: #b9bbbe; } .dark-mode .alert-default-dark .alert-link { color: #040505; } .table:not(.table-dark) { color: inherit; } .table.table-head-fixed thead tr:nth-child(1) th { background-color: #fff; border-bottom: 0; box-shadow: inset 0 1px 0 #dee2e6, inset 0 -1px 0 #dee2e6; position: -webkit-sticky; position: sticky; top: 0; z-index: 10; } .table.table-head-fixed.table-dark thead tr:nth-child(1) th { background-color: #212529; box-shadow: inset 0 1px 0 #383f45, inset 0 -1px 0 #383f45; } .table.no-border, .table.no-border td, .table.no-border th { border: 0; } .table.text-center, .table.text-center td, .table.text-center th { text-align: center; } .table.table-valign-middle thead > tr > th, .table.table-valign-middle thead > tr > td, .table.table-valign-middle tbody > tr > th, .table.table-valign-middle tbody > tr > td { vertical-align: middle; } .card-body.p-0 .table thead > tr > th:first-of-type, .card-body.p-0 .table thead > tr > td:first-of-type, .card-body.p-0 .table tfoot > tr > th:first-of-type, .card-body.p-0 .table tfoot > tr > td:first-of-type, .card-body.p-0 .table tbody > tr > th:first-of-type, .card-body.p-0 .table tbody > tr > td:first-of-type { padding-left: 1.5rem; } .card-body.p-0 .table thead > tr > th:last-of-type, .card-body.p-0 .table thead > tr > td:last-of-type, .card-body.p-0 .table tfoot > tr > th:last-of-type, .card-body.p-0 .table tfoot > tr > td:last-of-type, .card-body.p-0 .table tbody > tr > th:last-of-type, .card-body.p-0 .table tbody > tr > td:last-of-type { padding-right: 1.5rem; } .table-hover tbody tr.expandable-body:hover { background-color: inherit !important; } [data-widget="expandable-table"] { cursor: pointer; } [data-widget="expandable-table"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } [aria-expanded="true"] { cursor: pointer; } [aria-expanded="true"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .expandable-body > td { padding: 0 !important; width: 100%; } .expandable-body > td > div, .expandable-body > td > p { padding: 0.75rem; } .expandable-body .table { width: calc(100% - 0.75rem); margin: 0 0 0 0.75rem; } .expandable-body .table tr:first-child td, .expandable-body .table tr:first-child th { border-top: none; } .dark-mode .table-bordered, .dark-mode .table-bordered td, .dark-mode .table-bordered th { border-color: #6c757d; } .dark-mode .table-hover tbody tr:hover { color: #dee2e6; background-color: #3a4047; border-color: #6c757d; } .dark-mode .table thead th { border-bottom-color: #6c757d; } .dark-mode .table th, .dark-mode .table td { border-top-color: #6c757d; } .dark-mode .table.table-head-fixed thead tr:nth-child(1) th { background-color: #3f474e; } .carousel-control-prev .carousel-control-custom-icon { margin-left: -20px; } .carousel-control-next .carousel-control-custom-icon { margin-right: 20px; } .carousel-control-custom-icon > .fa, .carousel-control-custom-icon > .fas, .carousel-control-custom-icon > .far, .carousel-control-custom-icon > .fab, .carousel-control-custom-icon > .fal, .carousel-control-custom-icon > .fad, .carousel-control-custom-icon > .svg-inline--fa, .carousel-control-custom-icon > .ion { display: inline-block; font-size: 40px; margin-top: -20px; position: absolute; top: 50%; z-index: 5; } .close, .mailbox-attachment-close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover, .mailbox-attachment-close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .mailbox-attachment-close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus, .mailbox-attachment-close:not(:disabled):not(.disabled):focus { opacity: .75; } .close:focus, .mailbox-attachment-close:focus { outline: none; } button.close, button.mailbox-attachment-close { padding: 0; background-color: transparent; border: 0; } a.close.disabled, a.disabled.mailbox-attachment-close { pointer-events: none; } .small-box { border-radius: 0.25rem; box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); display: block; margin-bottom: 20px; position: relative; } .small-box > .inner { padding: 10px; } .small-box > .small-box-footer { background-color: rgba(0, 0, 0, 0.1); color: rgba(255, 255, 255, 0.8); display: block; padding: 3px 0; position: relative; text-align: center; text-decoration: none; z-index: 10; } .small-box > .small-box-footer:hover { background-color: rgba(0, 0, 0, 0.15); color: #fff; } .small-box h3 { font-size: 2.2rem; font-weight: 700; margin: 0 0 10px; padding: 0; white-space: nowrap; } @media (min-width: 992px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 1.6rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 1.6rem; } } @media (min-width: 1200px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 2.2rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 2.2rem; } } .small-box p { font-size: 1rem; } .small-box p > small { color: #f8f9fa; display: block; font-size: .9rem; margin-top: 5px; } .small-box h3, .small-box p { z-index: 5; } .small-box .icon { color: rgba(0, 0, 0, 0.15); z-index: 0; } .small-box .icon > i { font-size: 90px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box .icon > i.fa, .small-box .icon > i.fas, .small-box .icon > i.far, .small-box .icon > i.fab, .small-box .icon > i.fal, .small-box .icon > i.fad, .small-box .icon > i.ion { font-size: 70px; top: 20px; } .small-box .icon svg { font-size: 70px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box:hover { text-decoration: none; } .small-box:hover .icon > i, .small-box:hover .icon > i.fa, .small-box:hover .icon > i.fas, .small-box:hover .icon > i.far, .small-box:hover .icon > i.fab, .small-box:hover .icon > i.fal, .small-box:hover .icon > i.fad, .small-box:hover .icon > i.ion { -webkit-transform: scale(1.1); transform: scale(1.1); } .small-box:hover .icon > svg { -webkit-transform: scale(1.1); transform: scale(1.1); } @media (max-width: 767.98px) { .small-box { text-align: center; } .small-box .icon { display: none; } .small-box p { font-size: 12px; } } .info-box { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; display: -ms-flexbox; display: flex; margin-bottom: 1rem; min-height: 80px; padding: .5rem; position: relative; width: 100%; } .info-box .progress { background-color: rgba(0, 0, 0, 0.125); height: 2px; margin: 5px 0; } .info-box .progress .progress-bar { background-color: #fff; } .info-box .info-box-icon { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; display: -ms-flexbox; display: flex; font-size: 1.875rem; -ms-flex-pack: center; justify-content: center; text-align: center; width: 70px; } .info-box .info-box-icon > img { max-width: 100%; } .info-box .info-box-content { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; line-height: 1.8; -ms-flex: 1; flex: 1; padding: 0 10px; overflow: hidden; } .info-box .info-box-number { display: block; margin-top: .25rem; font-weight: 700; } .info-box .progress-description, .info-box .info-box-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .info-box .info-box .bg-primary, .info-box .info-box .bg-gradient-primary { color: #fff; } .info-box .info-box .bg-primary .progress-bar, .info-box .info-box .bg-gradient-primary .progress-bar { background-color: #fff; } .info-box .info-box .bg-secondary, .info-box .info-box .bg-gradient-secondary { color: #fff; } .info-box .info-box .bg-secondary .progress-bar, .info-box .info-box .bg-gradient-secondary .progress-bar { background-color: #fff; } .info-box .info-box .bg-success, .info-box .info-box .bg-gradient-success { color: #fff; } .info-box .info-box .bg-success .progress-bar, .info-box .info-box .bg-gradient-success .progress-bar { background-color: #fff; } .info-box .info-box .bg-info, .info-box .info-box .bg-gradient-info { color: #fff; } .info-box .info-box .bg-info .progress-bar, .info-box .info-box .bg-gradient-info .progress-bar { background-color: #fff; } .info-box .info-box .bg-warning, .info-box .info-box .bg-gradient-warning { color: #1f2d3d; } .info-box .info-box .bg-warning .progress-bar, .info-box .info-box .bg-gradient-warning .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-danger, .info-box .info-box .bg-gradient-danger { color: #fff; } .info-box .info-box .bg-danger .progress-bar, .info-box .info-box .bg-gradient-danger .progress-bar { background-color: #fff; } .info-box .info-box .bg-light, .info-box .info-box .bg-gradient-light { color: #1f2d3d; } .info-box .info-box .bg-light .progress-bar, .info-box .info-box .bg-gradient-light .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-dark, .info-box .info-box .bg-gradient-dark { color: #fff; } .info-box .info-box .bg-dark .progress-bar, .info-box .info-box .bg-gradient-dark .progress-bar { background-color: #fff; } .info-box .info-box-more { display: block; } .info-box .progress-description { margin: 0; } @media (min-width: 768px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { display: none; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { display: none; } } @media (min-width: 992px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 0.75rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 0.75rem; display: block; } } @media (min-width: 1200px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 1rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 1rem; display: block; } } .dark-mode .info-box { background-color: #343a40; color: #fff; } .dark-mode .info-box .info-box .bg-primary, .dark-mode .info-box .info-box .bg-gradient-primary { color: #fff; } .dark-mode .info-box .info-box .bg-primary .progress-bar, .dark-mode .info-box .info-box .bg-gradient-primary .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-secondary, .dark-mode .info-box .info-box .bg-gradient-secondary { color: #fff; } .dark-mode .info-box .info-box .bg-secondary .progress-bar, .dark-mode .info-box .info-box .bg-gradient-secondary .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-success, .dark-mode .info-box .info-box .bg-gradient-success { color: #fff; } .dark-mode .info-box .info-box .bg-success .progress-bar, .dark-mode .info-box .info-box .bg-gradient-success .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-info, .dark-mode .info-box .info-box .bg-gradient-info { color: #fff; } .dark-mode .info-box .info-box .bg-info .progress-bar, .dark-mode .info-box .info-box .bg-gradient-info .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-warning, .dark-mode .info-box .info-box .bg-gradient-warning { color: #1f2d3d; } .dark-mode .info-box .info-box .bg-warning .progress-bar, .dark-mode .info-box .info-box .bg-gradient-warning .progress-bar { background-color: #1f2d3d; } .dark-mode .info-box .info-box .bg-danger, .dark-mode .info-box .info-box .bg-gradient-danger { color: #fff; } .dark-mode .info-box .info-box .bg-danger .progress-bar, .dark-mode .info-box .info-box .bg-gradient-danger .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-light, .dark-mode .info-box .info-box .bg-gradient-light { color: #1f2d3d; } .dark-mode .info-box .info-box .bg-light .progress-bar, .dark-mode .info-box .info-box .bg-gradient-light .progress-bar { background-color: #1f2d3d; } .dark-mode .info-box .info-box .bg-dark, .dark-mode .info-box .info-box .bg-gradient-dark { color: #fff; } .dark-mode .info-box .info-box .bg-dark .progress-bar, .dark-mode .info-box .info-box .bg-gradient-dark .progress-bar { background-color: #fff; } .timeline { margin: 0 0 45px; padding: 0; position: relative; } .timeline::before { border-radius: 0.25rem; background-color: #dee2e6; bottom: 0; content: ""; left: 31px; margin: 0; position: absolute; top: 0; width: 4px; } .timeline > div { margin-bottom: 15px; margin-right: 10px; position: relative; } .timeline > div::before, .timeline > div::after { content: ""; display: table; } .timeline > div > .timeline-item { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; color: #495057; margin-left: 60px; margin-right: 15px; margin-top: 0; padding: 0; position: relative; } .timeline > div > .timeline-item > .time { color: #999; float: right; font-size: 12px; padding: 10px; } .timeline > div > .timeline-item > .timeline-header { border-bottom: 1px solid rgba(0, 0, 0, 0.125); color: #495057; font-size: 16px; line-height: 1.1; margin: 0; padding: 10px; } .timeline > div > .timeline-item > .timeline-header > a { font-weight: 600; } .timeline > div > .timeline-item > .timeline-body, .timeline > div > .timeline-item > .timeline-footer { padding: 10px; } .timeline > div > .timeline-item > .timeline-body > img { margin: 10px; } .timeline > div > .timeline-item > .timeline-body > dl, .timeline > div > .timeline-item > .timeline-body ol, .timeline > div > .timeline-item > .timeline-body ul { margin: 0; } .timeline > div > .timeline-item > .timeline-footer > a { color: #fff; } .timeline > div > .fa, .timeline > div > .fas, .timeline > div > .far, .timeline > div > .fab, .timeline > div > .fal, .timeline > div > .fad, .timeline > div > .svg-inline--fa, .timeline > div > .ion { background-color: #adb5bd; border-radius: 50%; font-size: 16px; height: 30px; left: 18px; line-height: 30px; position: absolute; text-align: center; top: 0; width: 30px; } .timeline > div > .svg-inline--fa { padding: 7px; } .timeline > .time-label > span { border-radius: 4px; background-color: #fff; display: inline-block; font-weight: 600; padding: 5px; } .timeline-inverse > div > .timeline-item { box-shadow: none; background-color: #f8f9fa; border: 1px solid #dee2e6; } .timeline-inverse > div > .timeline-item > .timeline-header { border-bottom-color: #dee2e6; } .dark-mode .timeline::before { background-color: #6c757d; } .dark-mode .timeline > div > .timeline-item { background-color: #343a40; color: #fff; border-color: #6c757d; } .dark-mode .timeline > div > .timeline-item > .timeline-header { color: #ced4da; border-color: #6c757d; } .dark-mode .timeline > div > .timeline-item > .time { color: #ced4da; } .products-list { list-style: none; margin: 0; padding: 0; } .products-list > .item { border-radius: 0.25rem; background-color: #fff; padding: 10px 0; } .products-list > .item::after { display: block; clear: both; content: ""; } .products-list .product-img { float: left; } .products-list .product-img img { height: 50px; width: 50px; } .products-list .product-info { margin-left: 60px; } .products-list .product-title { font-weight: 600; } .products-list .product-description { color: #6c757d; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .product-list-in-card > .item { border-radius: 0; border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .product-list-in-card > .item:last-of-type { border-bottom-width: 0; } .dark-mode .products-list > .item { background-color: #343a40; color: #fff; border-bottom-color: #6c757d; } .dark-mode .product-description { color: #ced4da; } .direct-chat .card-body { overflow-x: hidden; padding: 0; position: relative; } .direct-chat.chat-pane-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat.timestamp-light .direct-chat-timestamp { color: #30465f; } .direct-chat.timestamp-dark .direct-chat-timestamp { color: #cccccc; } .direct-chat-messages { -webkit-transform: translate(0, 0); transform: translate(0, 0); height: 250px; overflow: auto; padding: 10px; } .direct-chat-msg, .direct-chat-text { display: block; } .direct-chat-msg { margin-bottom: 10px; } .direct-chat-msg::after { display: block; clear: both; content: ""; } .direct-chat-messages, .direct-chat-contacts { transition: -webkit-transform .5s ease-in-out; transition: transform .5s ease-in-out; transition: transform .5s ease-in-out, -webkit-transform .5s ease-in-out; } .direct-chat-text { border-radius: 0.3rem; background-color: #d2d6de; border: 1px solid #d2d6de; color: #444; margin: 5px 0 0 50px; padding: 5px 10px; position: relative; } .direct-chat-text::after, .direct-chat-text::before { border: solid transparent; border-right-color: #d2d6de; content: " "; height: 0; pointer-events: none; position: absolute; right: 100%; top: 15px; width: 0; } .direct-chat-text::after { border-width: 5px; margin-top: -5px; } .direct-chat-text::before { border-width: 6px; margin-top: -6px; } .right .direct-chat-text { margin-left: 0; margin-right: 50px; } .right .direct-chat-text::after, .right .direct-chat-text::before { border-left-color: #d2d6de; border-right-color: transparent; left: 100%; right: auto; } .direct-chat-img { border-radius: 50%; float: left; height: 40px; width: 40px; } .right .direct-chat-img { float: right; } .direct-chat-infos { display: block; font-size: 0.875rem; margin-bottom: 2px; } .direct-chat-name { font-weight: 600; } .direct-chat-timestamp { color: #697582; } .direct-chat-contacts-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat-contacts { -webkit-transform: translate(101%, 0); transform: translate(101%, 0); background-color: #343a40; bottom: 0; color: #fff; height: 250px; overflow: auto; position: absolute; top: 0; width: 100%; } .direct-chat-contacts-light { background-color: #f8f9fa; } .direct-chat-contacts-light .contacts-list-name { color: #495057; } .direct-chat-contacts-light .contacts-list-date { color: #6c757d; } .direct-chat-contacts-light .contacts-list-msg { color: #545b62; } .contacts-list { padding-left: 0; list-style: none; } .contacts-list > li { border-bottom: 1px solid rgba(0, 0, 0, 0.2); margin: 0; padding: 10px; } .contacts-list > li::after { display: block; clear: both; content: ""; } .contacts-list > li:last-of-type { border-bottom: 0; } .contacts-list-img { border-radius: 50%; float: left; width: 40px; } .contacts-list-info { color: #fff; margin-left: 45px; } .contacts-list-name, .contacts-list-status { display: block; } .contacts-list-name { font-weight: 600; } .contacts-list-status { font-size: 0.875rem; } .contacts-list-date { color: #ced4da; font-weight: 400; } .contacts-list-msg { color: #b1bbc4; } .direct-chat-primary .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-primary .right > .direct-chat-text::after, .direct-chat-primary .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-secondary .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-secondary .right > .direct-chat-text::after, .direct-chat-secondary .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-success .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-success .right > .direct-chat-text::after, .direct-chat-success .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-info .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-info .right > .direct-chat-text::after, .direct-chat-info .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-warning .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-warning .right > .direct-chat-text::after, .direct-chat-warning .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-danger .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-danger .right > .direct-chat-text::after, .direct-chat-danger .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-light .right > .direct-chat-text { background-color: #f8f9fa; border-color: #f8f9fa; color: #1f2d3d; } .direct-chat-light .right > .direct-chat-text::after, .direct-chat-light .right > .direct-chat-text::before { border-left-color: #f8f9fa; } .direct-chat-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-dark .right > .direct-chat-text::after, .direct-chat-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .direct-chat-lightblue .right > .direct-chat-text { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .direct-chat-lightblue .right > .direct-chat-text::after, .direct-chat-lightblue .right > .direct-chat-text::before { border-left-color: #3c8dbc; } .direct-chat-navy .right > .direct-chat-text { background-color: #001f3f; border-color: #001f3f; color: #fff; } .direct-chat-navy .right > .direct-chat-text::after, .direct-chat-navy .right > .direct-chat-text::before { border-left-color: #001f3f; } .direct-chat-olive .right > .direct-chat-text { background-color: #3d9970; border-color: #3d9970; color: #fff; } .direct-chat-olive .right > .direct-chat-text::after, .direct-chat-olive .right > .direct-chat-text::before { border-left-color: #3d9970; } .direct-chat-lime .right > .direct-chat-text { background-color: #01ff70; border-color: #01ff70; color: #1f2d3d; } .direct-chat-lime .right > .direct-chat-text::after, .direct-chat-lime .right > .direct-chat-text::before { border-left-color: #01ff70; } .direct-chat-fuchsia .right > .direct-chat-text { background-color: #f012be; border-color: #f012be; color: #fff; } .direct-chat-fuchsia .right > .direct-chat-text::after, .direct-chat-fuchsia .right > .direct-chat-text::before { border-left-color: #f012be; } .direct-chat-maroon .right > .direct-chat-text { background-color: #d81b60; border-color: #d81b60; color: #fff; } .direct-chat-maroon .right > .direct-chat-text::after, .direct-chat-maroon .right > .direct-chat-text::before { border-left-color: #d81b60; } .direct-chat-blue .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-blue .right > .direct-chat-text::after, .direct-chat-blue .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-indigo .right > .direct-chat-text { background-color: #6610f2; border-color: #6610f2; color: #fff; } .direct-chat-indigo .right > .direct-chat-text::after, .direct-chat-indigo .right > .direct-chat-text::before { border-left-color: #6610f2; } .direct-chat-purple .right > .direct-chat-text { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .direct-chat-purple .right > .direct-chat-text::after, .direct-chat-purple .right > .direct-chat-text::before { border-left-color: #6f42c1; } .direct-chat-pink .right > .direct-chat-text { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .direct-chat-pink .right > .direct-chat-text::after, .direct-chat-pink .right > .direct-chat-text::before { border-left-color: #e83e8c; } .direct-chat-red .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-red .right > .direct-chat-text::after, .direct-chat-red .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-orange .right > .direct-chat-text { background-color: #fd7e14; border-color: #fd7e14; color: #1f2d3d; } .direct-chat-orange .right > .direct-chat-text::after, .direct-chat-orange .right > .direct-chat-text::before { border-left-color: #fd7e14; } .direct-chat-yellow .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-yellow .right > .direct-chat-text::after, .direct-chat-yellow .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-green .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-green .right > .direct-chat-text::after, .direct-chat-green .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-teal .right > .direct-chat-text { background-color: #20c997; border-color: #20c997; color: #fff; } .direct-chat-teal .right > .direct-chat-text::after, .direct-chat-teal .right > .direct-chat-text::before { border-left-color: #20c997; } .direct-chat-cyan .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-cyan .right > .direct-chat-text::after, .direct-chat-cyan .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-white .right > .direct-chat-text { background-color: #fff; border-color: #fff; color: #1f2d3d; } .direct-chat-white .right > .direct-chat-text::after, .direct-chat-white .right > .direct-chat-text::before { border-left-color: #fff; } .direct-chat-gray .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-gray .right > .direct-chat-text::after, .direct-chat-gray .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-gray-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-gray-dark .right > .direct-chat-text::after, .direct-chat-gray-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .dark-mode .direct-chat-text { background-color: #454d55; border-color: #4b545c; color: #fff; } .dark-mode .direct-chat-text::after, .dark-mode .direct-chat-text::before { border-right-color: #4b545c; } .dark-mode .direct-chat-timestamp { color: #adb5bd; } .dark-mode .right > .direct-chat-text::after, .dark-mode .right > .direct-chat-text::before { border-right-color: transparent; } .dark-mode .direct-chat-primary .right > .direct-chat-text { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .direct-chat-primary .right > .direct-chat-text::after, .dark-mode .direct-chat-primary .right > .direct-chat-text::before { border-left-color: #3f6791; } .dark-mode .direct-chat-secondary .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .direct-chat-secondary .right > .direct-chat-text::after, .dark-mode .direct-chat-secondary .right > .direct-chat-text::before { border-left-color: #6c757d; } .dark-mode .direct-chat-success .right > .direct-chat-text { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .direct-chat-success .right > .direct-chat-text::after, .dark-mode .direct-chat-success .right > .direct-chat-text::before { border-left-color: #00bc8c; } .dark-mode .direct-chat-info .right > .direct-chat-text { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .direct-chat-info .right > .direct-chat-text::after, .dark-mode .direct-chat-info .right > .direct-chat-text::before { border-left-color: #3498db; } .dark-mode .direct-chat-warning .right > .direct-chat-text { background-color: #f39c12; border-color: #f39c12; color: #1f2d3d; } .dark-mode .direct-chat-warning .right > .direct-chat-text::after, .dark-mode .direct-chat-warning .right > .direct-chat-text::before { border-left-color: #f39c12; } .dark-mode .direct-chat-danger .right > .direct-chat-text { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .direct-chat-danger .right > .direct-chat-text::after, .dark-mode .direct-chat-danger .right > .direct-chat-text::before { border-left-color: #e74c3c; } .dark-mode .direct-chat-light .right > .direct-chat-text { background-color: #f8f9fa; border-color: #f8f9fa; color: #1f2d3d; } .dark-mode .direct-chat-light .right > .direct-chat-text::after, .dark-mode .direct-chat-light .right > .direct-chat-text::before { border-left-color: #f8f9fa; } .dark-mode .direct-chat-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .direct-chat-dark .right > .direct-chat-text::after, .dark-mode .direct-chat-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .dark-mode .direct-chat-lightblue .right > .direct-chat-text { background-color: #86bad8; border-color: #86bad8; color: #1f2d3d; } .dark-mode .direct-chat-lightblue .right > .direct-chat-text::after, .dark-mode .direct-chat-lightblue .right > .direct-chat-text::before { border-left-color: #86bad8; } .dark-mode .direct-chat-navy .right > .direct-chat-text { background-color: #002c59; border-color: #002c59; color: #fff; } .dark-mode .direct-chat-navy .right > .direct-chat-text::after, .dark-mode .direct-chat-navy .right > .direct-chat-text::before { border-left-color: #002c59; } .dark-mode .direct-chat-olive .right > .direct-chat-text { background-color: #74c8a3; border-color: #74c8a3; color: #1f2d3d; } .dark-mode .direct-chat-olive .right > .direct-chat-text::after, .dark-mode .direct-chat-olive .right > .direct-chat-text::before { border-left-color: #74c8a3; } .dark-mode .direct-chat-lime .right > .direct-chat-text { background-color: #67ffa9; border-color: #67ffa9; color: #1f2d3d; } .dark-mode .direct-chat-lime .right > .direct-chat-text::after, .dark-mode .direct-chat-lime .right > .direct-chat-text::before { border-left-color: #67ffa9; } .dark-mode .direct-chat-fuchsia .right > .direct-chat-text { background-color: #f672d8; border-color: #f672d8; color: #1f2d3d; } .dark-mode .direct-chat-fuchsia .right > .direct-chat-text::after, .dark-mode .direct-chat-fuchsia .right > .direct-chat-text::before { border-left-color: #f672d8; } .dark-mode .direct-chat-maroon .right > .direct-chat-text { background-color: #ed6c9b; border-color: #ed6c9b; color: #1f2d3d; } .dark-mode .direct-chat-maroon .right > .direct-chat-text::after, .dark-mode .direct-chat-maroon .right > .direct-chat-text::before { border-left-color: #ed6c9b; } .dark-mode .direct-chat-blue .right > .direct-chat-text { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .direct-chat-blue .right > .direct-chat-text::after, .dark-mode .direct-chat-blue .right > .direct-chat-text::before { border-left-color: #3f6791; } .dark-mode .direct-chat-indigo .right > .direct-chat-text { background-color: #6610f2; border-color: #6610f2; color: #fff; } .dark-mode .direct-chat-indigo .right > .direct-chat-text::after, .dark-mode .direct-chat-indigo .right > .direct-chat-text::before { border-left-color: #6610f2; } .dark-mode .direct-chat-purple .right > .direct-chat-text { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .dark-mode .direct-chat-purple .right > .direct-chat-text::after, .dark-mode .direct-chat-purple .right > .direct-chat-text::before { border-left-color: #6f42c1; } .dark-mode .direct-chat-pink .right > .direct-chat-text { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .dark-mode .direct-chat-pink .right > .direct-chat-text::after, .dark-mode .direct-chat-pink .right > .direct-chat-text::before { border-left-color: #e83e8c; } .dark-mode .direct-chat-red .right > .direct-chat-text { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .direct-chat-red .right > .direct-chat-text::after, .dark-mode .direct-chat-red .right > .direct-chat-text::before { border-left-color: #e74c3c; } .dark-mode .direct-chat-orange .right > .direct-chat-text { background-color: #fd7e14; border-color: #fd7e14; color: #1f2d3d; } .dark-mode .direct-chat-orange .right > .direct-chat-text::after, .dark-mode .direct-chat-orange .right > .direct-chat-text::before { border-left-color: #fd7e14; } .dark-mode .direct-chat-yellow .right > .direct-chat-text { background-color: #f39c12; border-color: #f39c12; color: #1f2d3d; } .dark-mode .direct-chat-yellow .right > .direct-chat-text::after, .dark-mode .direct-chat-yellow .right > .direct-chat-text::before { border-left-color: #f39c12; } .dark-mode .direct-chat-green .right > .direct-chat-text { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .direct-chat-green .right > .direct-chat-text::after, .dark-mode .direct-chat-green .right > .direct-chat-text::before { border-left-color: #00bc8c; } .dark-mode .direct-chat-teal .right > .direct-chat-text { background-color: #20c997; border-color: #20c997; color: #fff; } .dark-mode .direct-chat-teal .right > .direct-chat-text::after, .dark-mode .direct-chat-teal .right > .direct-chat-text::before { border-left-color: #20c997; } .dark-mode .direct-chat-cyan .right > .direct-chat-text { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .direct-chat-cyan .right > .direct-chat-text::after, .dark-mode .direct-chat-cyan .right > .direct-chat-text::before { border-left-color: #3498db; } .dark-mode .direct-chat-white .right > .direct-chat-text { background-color: #fff; border-color: #fff; color: #1f2d3d; } .dark-mode .direct-chat-white .right > .direct-chat-text::after, .dark-mode .direct-chat-white .right > .direct-chat-text::before { border-left-color: #fff; } .dark-mode .direct-chat-gray .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .direct-chat-gray .right > .direct-chat-text::after, .dark-mode .direct-chat-gray .right > .direct-chat-text::before { border-left-color: #6c757d; } .dark-mode .direct-chat-gray-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .direct-chat-gray-dark .right > .direct-chat-text::after, .dark-mode .direct-chat-gray-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .users-list { padding-left: 0; list-style: none; } .users-list > li { float: left; padding: 10px; text-align: center; width: 25%; } .users-list > li img { border-radius: 50%; height: auto; max-width: 100%; } .users-list > li > a:hover, .users-list > li > a:hover .users-list-name { color: #999; } .users-list-name, .users-list-date { display: block; } .users-list-name { color: #495057; font-size: 0.875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .users-list-date { color: #748290; font-size: 12px; } .dark-mode .users-list-name { color: #ced4da; } .dark-mode .users-list-date { color: #adb5bd; } .card-widget { border: 0; position: relative; } .widget-user .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; height: 135px; padding: 1rem; text-align: center; } .widget-user .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 0; margin-top: 0; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); } .widget-user .widget-user-desc { margin-top: 0; } .widget-user .widget-user-image { left: 50%; margin-left: -45px; position: absolute; top: 80px; } .widget-user .widget-user-image > img { border: 3px solid #fff; height: auto; width: 90px; } .widget-user .card-footer { padding-top: 50px; } .widget-user-2 .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; padding: 1rem; } .widget-user-2 .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 5px; margin-top: 5px; } .widget-user-2 .widget-user-desc { margin-top: 0; } .widget-user-2 .widget-user-username, .widget-user-2 .widget-user-desc { margin-left: 75px; } .widget-user-2 .widget-user-image > img { float: left; height: auto; width: 65px; } .mailbox-messages > .table { margin: 0; } .mailbox-controls { padding: 5px; } .mailbox-controls.with-border { border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .mailbox-read-info { border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 10px; } .mailbox-read-info h3 { font-size: 20px; margin: 0; } .mailbox-read-info h5 { margin: 0; padding: 5px 0 0; } .mailbox-read-time { color: #999; font-size: 13px; } .mailbox-read-message { padding: 10px; } .mailbox-attachments { padding-left: 0; list-style: none; } .mailbox-attachments li { border: 1px solid #eee; float: left; margin-bottom: 10px; margin-right: 10px; width: 200px; } .mailbox-attachment-name { color: #666; font-weight: 700; } .mailbox-attachment-icon, .mailbox-attachment-info, .mailbox-attachment-size { display: block; } .mailbox-attachment-info { background-color: #f8f9fa; padding: 10px; } .mailbox-attachment-size { color: #999; font-size: 12px; } .mailbox-attachment-size > span { display: inline-block; padding-top: .75rem; } .mailbox-attachment-icon { color: #666; font-size: 65px; max-height: 132.5px; padding: 20px 10px; text-align: center; } .mailbox-attachment-icon.has-img { padding: 0; } .mailbox-attachment-icon.has-img > img { height: auto; max-width: 100%; } .lockscreen { background-color: #e9ecef; } .lockscreen .lockscreen-name { font-weight: 600; text-align: center; } .lockscreen-logo { font-size: 35px; font-weight: 300; margin-bottom: 25px; text-align: center; } .lockscreen-logo a { color: #495057; } .lockscreen-wrapper { margin: 0 auto; margin-top: 10%; max-width: 400px; } .lockscreen-item { border-radius: 4px; background-color: #fff; margin: 10px auto 30px; padding: 0; position: relative; width: 290px; } .lockscreen-image { border-radius: 50%; background-color: #fff; left: -10px; padding: 5px; position: absolute; top: -25px; z-index: 10; } .lockscreen-image > img { border-radius: 50%; height: 70px; width: 70px; } .lockscreen-credentials { margin-left: 70px; } .lockscreen-credentials .form-control { border: 0; } .lockscreen-credentials .btn { background-color: #fff; border: 0; padding: 0 10px; } .lockscreen-footer { margin-top: 10px; } .dark-mode .lockscreen-item { background-color: #343a40; } .dark-mode .lockscreen-logo a { color: #fff; } .dark-mode .lockscreen-credentials .btn { background-color: #343a40; } .dark-mode .lockscreen-image { background-color: #6c757d; } .login-logo, .register-logo { font-size: 2.1rem; font-weight: 300; margin-bottom: .9rem; text-align: center; } .login-logo a, .register-logo a { color: #495057; } .login-page, .register-page { -ms-flex-align: center; align-items: center; background-color: #e9ecef; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; height: 100vh; -ms-flex-pack: center; justify-content: center; } .login-box, .register-box { width: 360px; } @media (max-width: 576px) { .login-box, .register-box { margin-top: .5rem; width: 90%; } } .login-box .card, .register-box .card { margin-bottom: 0; } .login-card-body, .register-card-body { background-color: #fff; border-top: 0; color: #666; padding: 20px; } .login-card-body .input-group .form-control, .register-card-body .input-group .form-control { border-right: 0; } .login-card-body .input-group .form-control:focus, .register-card-body .input-group .form-control:focus { box-shadow: none; } .login-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text { border-color: #80bdff; } .login-card-body .input-group .form-control.is-valid:focus, .register-card-body .input-group .form-control.is-valid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text { border-color: #28a745; } .login-card-body .input-group .form-control.is-invalid:focus, .register-card-body .input-group .form-control.is-invalid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text { border-color: #dc3545; } .login-card-body .input-group .input-group-text, .register-card-body .input-group .input-group-text { background-color: transparent; border-bottom-right-radius: 0.25rem; border-left: 0; border-top-right-radius: 0.25rem; color: #777; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .login-box-msg, .register-box-msg { margin: 0; padding: 0 20px 20px; text-align: center; } .social-auth-links { margin: 10px 0; } .dark-mode .login-card-body, .dark-mode .register-card-body { background-color: #343a40; border-color: #6c757d; color: #fff; } .dark-mode .login-logo a, .dark-mode .register-logo a { color: #fff; } .error-page { margin: 20px auto 0; width: 600px; } @media (max-width: 767.98px) { .error-page { width: 100%; } } .error-page > .headline { float: left; font-size: 100px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .headline { float: none; text-align: center; } } .error-page > .error-content { display: block; margin-left: 190px; } @media (max-width: 767.98px) { .error-page > .error-content { margin-left: 0; } } .error-page > .error-content > h3 { font-size: 25px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .error-content > h3 { text-align: center; } } .invoice { background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); position: relative; } .invoice-title { margin-top: 0; } .dark-mode .invoice { background-color: #343a40; } .profile-user-img { border: 3px solid #adb5bd; margin: 0 auto; padding: 3px; width: 100px; } .profile-username { font-size: 21px; margin-top: 5px; } .post { border-bottom: 1px solid #adb5bd; color: #666; margin-bottom: 15px; padding-bottom: 15px; } .post:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; } .post .user-block { margin-bottom: 15px; width: 100%; } .post .row { width: 100%; } .dark-mode .post { color: #fff; border-color: #6c757d; } .product-image { max-width: 100%; height: auto; width: 100%; } .product-image-thumbs { -ms-flex-align: stretch; align-items: stretch; display: -ms-flexbox; display: flex; margin-top: 2rem; } .product-image-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); border-radius: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; display: -ms-flexbox; display: flex; margin-right: 1rem; max-width: 7rem; padding: 0.5rem; } .product-image-thumb img { max-width: 100%; height: auto; -ms-flex-item-align: center; align-self: center; } .product-image-thumb:hover { opacity: .5; } .product-share a { margin-right: .5rem; } .projects td { vertical-align: middle; } .projects .list-inline { margin-bottom: 0; } .projects img.table-avatar, .projects .table-avatar img { border-radius: 50%; display: inline; width: 2.5rem; } .projects .project-state { text-align: center; } body.iframe-mode .main-sidebar { display: none; } body.iframe-mode .content-wrapper { margin-left: 0 !important; margin-top: 0 !important; padding-bottom: 0 !important; } body.iframe-mode .main-header, body.iframe-mode .main-footer { display: none; } body.iframe-mode-fullscreen { overflow: hidden; } body.iframe-mode-fullscreen.layout-navbar-fixed .wrapper .content-wrapper { margin-top: 0 !important; } .content-wrapper { height: 100%; } .content-wrapper.iframe-mode .btn-iframe-close { color: #dc3545; position: absolute; line-height: 1; right: .125rem; top: .125rem; z-index: 10; visibility: hidden; } .content-wrapper.iframe-mode .btn-iframe-close:hover, .content-wrapper.iframe-mode .btn-iframe-close:focus { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .navbar-nav { overflow-y: auto; width: 100%; } .content-wrapper.iframe-mode .navbar-nav .nav-link { white-space: nowrap; } .content-wrapper.iframe-mode .navbar-nav .nav-item { position: relative; } .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .tab-content { position: relative; } .content-wrapper.iframe-mode .tab-pane + .tab-empty { display: none; } .content-wrapper.iframe-mode .tab-empty { width: 100%; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; } .content-wrapper.iframe-mode .tab-loading { position: absolute; top: 0; left: 0; width: 100%; display: none; background-color: #f4f6f9; } .content-wrapper.iframe-mode .tab-loading > div { display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; width: 100%; height: 100%; } .content-wrapper.iframe-mode iframe { border: 0; width: 100%; height: 100%; margin-bottom: -8px; } .content-wrapper.iframe-mode iframe .content-wrapper { padding-bottom: 0 !important; } body.iframe-mode-fullscreen .content-wrapper.iframe-mode { position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin-left: 0 !important; height: 100%; min-height: 100%; z-index: 1048; } .permanent-btn-iframe-close .btn-iframe-close { -webkit-animation: none !important; animation: none !important; visibility: visible !important; opacity: 1; } .dark-mode .content-wrapper.iframe-mode .tab-loading { background-color: #343a40; } .content-wrapper.kanban { height: 1px; } .content-wrapper.kanban .content { height: 100%; overflow-x: auto; overflow-y: hidden; } .content-wrapper.kanban .content .container, .content-wrapper.kanban .content .container-fluid, .content-wrapper.kanban .content .container-sm, .content-wrapper.kanban .content .container-md, .content-wrapper.kanban .content .container-lg, .content-wrapper.kanban .content .container-xl { width: -webkit-max-content; width: -moz-max-content; width: max-content; display: -ms-flexbox; display: flex; -ms-flex-align: stretch; align-items: stretch; } .content-wrapper.kanban .content-header + .content { height: calc(100% - ((2 * 15px) + (1.8rem * 1.2))); } .content-wrapper.kanban .card .card-body { padding: .5rem; } .content-wrapper.kanban .card.card-row { width: 340px; display: inline-block; margin: 0 .5rem; } .content-wrapper.kanban .card.card-row:first-child { margin-left: 0; } .content-wrapper.kanban .card.card-row .card-body { height: calc(100% - (12px + (1.8rem * 1.2) + .5rem)); overflow-y: auto; } .content-wrapper.kanban .card.card-row .card:last-child { margin-bottom: 0; border-bottom-width: 1px; } .content-wrapper.kanban .card.card-row .card .card-header { padding: .5rem .75rem; } .content-wrapper.kanban .card.card-row .card .card-body { padding: .75rem; } .content-wrapper.kanban .btn-tool.btn-link { text-decoration: underline; padding-left: 0; padding-right: 0; } .fc-button { background: #f8f9fa; background-image: none; border-bottom-color: #ddd; border-color: #ddd; color: #495057; } .fc-button:hover, .fc-button:active, .fc-button.hover { background-color: #e9e9e9; } .fc-header-title h2 { color: #666; font-size: 15px; line-height: 1.6em; margin-left: 10px; } .fc-header-right { padding-right: 10px; } .fc-header-left { padding-left: 10px; } .fc-widget-header { background: #fafafa; } .fc-grid { border: 0; width: 100%; } .fc-widget-header:first-of-type, .fc-widget-content:first-of-type { border-left: 0; border-right: 0; } .fc-widget-header:last-of-type, .fc-widget-content:last-of-type { border-right: 0; } .fc-toolbar, .fc-toolbar.fc-header-toolbar { margin: 0; padding: 1rem; } @media (max-width: 575.98px) { .fc-toolbar { -ms-flex-direction: column; flex-direction: column; } .fc-toolbar .fc-left { -ms-flex-order: 1; order: 1; margin-bottom: .5rem; } .fc-toolbar .fc-center { -ms-flex-order: 0; order: 0; margin-bottom: .375rem; } .fc-toolbar .fc-right { -ms-flex-order: 2; order: 2; } } .fc-day-number { font-size: 20px; font-weight: 300; padding-right: 10px; } .fc-color-picker { list-style: none; margin: 0; padding: 0; } .fc-color-picker > li { float: left; font-size: 30px; line-height: 30px; margin-right: 5px; } .fc-color-picker > li .fa, .fc-color-picker > li .fas, .fc-color-picker > li .far, .fc-color-picker > li .fab, .fc-color-picker > li .fal, .fc-color-picker > li .fad, .fc-color-picker > li .svg-inline--fa, .fc-color-picker > li .ion { transition: -webkit-transform linear .3s; transition: transform linear .3s; transition: transform linear .3s, -webkit-transform linear .3s; } .fc-color-picker > li .fa:hover, .fc-color-picker > li .fas:hover, .fc-color-picker > li .far:hover, .fc-color-picker > li .fab:hover, .fc-color-picker > li .fal:hover, .fc-color-picker > li .fad:hover, .fc-color-picker > li .svg-inline--fa:hover, .fc-color-picker > li .ion:hover { -webkit-transform: rotate(30deg); transform: rotate(30deg); } #add-new-event { transition: all linear .3s; } .external-event { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; cursor: move; font-weight: 700; margin-bottom: 4px; padding: 5px 10px; } .external-event:hover { box-shadow: inset 0 0 90px rgba(0, 0, 0, 0.2); } .select2-container--default .select2-selection--single { border: 1px solid #ced4da; padding: 0.46875rem 0.75rem; height: calc(2.25rem + 2px); } .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-dropdown { border: 1px solid #ced4da; } .select2-container--default .select2-results__option { padding: 6px 12px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .select2-container--default .select2-selection--single .select2-selection__rendered { padding-left: 0; height: auto; margin-top: -3px; } .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__rendered { padding-right: 6px; padding-left: 20px; } .select2-container--default .select2-selection--single .select2-selection__arrow { height: 31px; right: 6px; } .select2-container--default .select2-selection--single .select2-selection__arrow b { margin-top: 0; } .select2-container--default .select2-dropdown .select2-search__field, .select2-container--default .select2-search--inline .select2-search__field { border: 1px solid #ced4da; } .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-search--inline .select2-search__field:focus { outline: none; border: 1px solid #80bdff; } .select2-container--default .select2-dropdown.select2-dropdown--below { border-top: 0; } .select2-container--default .select2-dropdown.select2-dropdown--above { border-bottom: 0; } .select2-container--default .select2-results__option[aria-disabled='true'] { color: #6c757d; } .select2-container--default .select2-results__option[aria-selected='true'] { background-color: #dee2e6; } .select2-container--default .select2-results__option[aria-selected='true'], .select2-container--default .select2-results__option[aria-selected='true']:hover { color: #1f2d3d; } .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-selection--multiple { border: 1px solid #ced4da; min-height: calc(2.25rem + 2px); } .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.375rem 0.375rem; margin-bottom: -0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { width: 100%; margin-left: 0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline .select2-search__field { width: 100% !important; } .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { border: 0; margin-top: 6px; } .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; padding: 0 10px; margin-top: .31rem; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); float: right; margin-left: 5px; margin-right: -2px; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .text-sm .select2-container--default .select2-selection--multiple .select2-search.select2-search--inline .select2-search__field, .select2-container--default .select2-selection--multiple.text-sm .select2-search.select2-search--inline .select2-search__field { margin-top: 8px; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__choice, .select2-container--default .select2-selection--multiple.text-sm .select2-selection__choice { margin-top: .4rem; } .select2-container--default.select2-container--focus .select2-selection--single, .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-container--default.select2-container--focus .select2-search__field { border: 0; } .select2-container--default .select2-selection--single .select2-selection__rendered li { padding-right: 10px; } .input-group-prepend ~ .select2-container--default .select2-selection { border-bottom-left-radius: 0; border-top-left-radius: 0; } .input-group > .select2-container--default:not(:last-child) .select2-selection { border-bottom-right-radius: 0; border-top-right-radius: 0; } .select2-container--bootstrap4.select2-container--focus .select2-selection { box-shadow: none; } select.form-control-sm ~ .select2-container--default { font-size: 75%; } .text-sm .select2-container--default .select2-selection--single, select.form-control-sm ~ .select2-container--default .select2-selection--single { height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--single .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__rendered { margin-top: -.4rem; } .text-sm .select2-container--default .select2-selection--single .select2-selection__arrow, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__arrow { top: -.12rem; } .text-sm .select2-container--default .select2-selection--multiple, select.form-control-sm ~ .select2-container--default .select2-selection--multiple { min-height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.25rem 0.25rem; margin-top: -0.1rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { margin-left: 0.25rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { margin-top: 6px; } .maximized-card .select2-dropdown { z-index: 9999; } .select2-primary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-primary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-primary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-search--inline .select2-search__field:focus, .select2-primary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-primary .select2-results__option--highlighted, .select2-primary .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected]:hover, .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple:focus, .select2-primary .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-primary.select2-container--focus .select2-selection--multiple, .select2-primary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-secondary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-secondary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-secondary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-search--inline .select2-search__field:focus, .select2-secondary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-secondary .select2-results__option--highlighted, .select2-secondary .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected]:hover, .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple:focus, .select2-secondary .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-secondary.select2-container--focus .select2-selection--multiple, .select2-secondary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-success + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-success + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-success.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-search--inline .select2-search__field:focus, .select2-success .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-success .select2-results__option--highlighted, .select2-success .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected]:hover, .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple:focus, .select2-success .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-success.select2-container--focus .select2-selection--multiple, .select2-success .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-info + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-info + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-info.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-search--inline .select2-search__field:focus, .select2-info .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-info .select2-results__option--highlighted, .select2-info .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected]:hover, .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple:focus, .select2-info .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-info.select2-container--focus .select2-selection--multiple, .select2-info .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-warning + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-warning + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-warning.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-search--inline .select2-search__field:focus, .select2-warning .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-warning .select2-results__option--highlighted, .select2-warning .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected]:hover, .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple:focus, .select2-warning .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-warning.select2-container--focus .select2-selection--multiple, .select2-warning .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-danger + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-danger + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-danger.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-search--inline .select2-search__field:focus, .select2-danger .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-danger .select2-results__option--highlighted, .select2-danger .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected]:hover, .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple:focus, .select2-danger .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-danger.select2-container--focus .select2-selection--multiple, .select2-danger .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-light + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-light + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-light.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-search--inline .select2-search__field:focus, .select2-light .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-light .select2-results__option--highlighted, .select2-light .select2-container--default .select2-results__option--highlighted { background-color: #f8f9fa; color: #1f2d3d; } .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected]:hover, .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eff1f4; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple:focus, .select2-light .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f8f9fa; border-color: #e9ecef; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-light.select2-container--focus .select2-selection--multiple, .select2-light .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-search--inline .select2-search__field:focus, .select2-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-dark .select2-results__option--highlighted, .select2-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple:focus, .select2-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-dark.select2-container--focus .select2-selection--multiple, .select2-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .select2-lightblue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #99c5de; } .select2-lightblue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #99c5de; } .select2-container--default .select2-lightblue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-search--inline .select2-search__field:focus, .select2-lightblue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #99c5de; } .select2-container--default .select2-lightblue .select2-results__option--highlighted, .select2-lightblue .select2-container--default .select2-results__option--highlighted { background-color: #3c8dbc; color: #fff; } .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected]:hover, .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3884b0; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple:focus, .select2-lightblue .select2-container--default .select2-selection--multiple:focus { border-color: #99c5de; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3c8dbc; border-color: #367fa9; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-lightblue.select2-container--focus .select2-selection--multiple, .select2-lightblue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #99c5de; } .select2-navy + .select2-container--default.select2-container--open .select2-selection--single { border-color: #005ebf; } .select2-navy + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #005ebf; } .select2-container--default .select2-navy.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-search--inline .select2-search__field:focus, .select2-navy .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #005ebf; } .select2-container--default .select2-navy .select2-results__option--highlighted, .select2-navy .select2-container--default .select2-results__option--highlighted { background-color: #001f3f; color: #fff; } .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected]:hover, .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #001730; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple:focus, .select2-navy .select2-container--default .select2-selection--multiple:focus { border-color: #005ebf; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #001f3f; border-color: #001226; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-navy.select2-container--focus .select2-selection--multiple, .select2-navy .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #005ebf; } .select2-olive + .select2-container--default.select2-container--open .select2-selection--single { border-color: #87cfaf; } .select2-olive + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #87cfaf; } .select2-container--default .select2-olive.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-search--inline .select2-search__field:focus, .select2-olive .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #87cfaf; } .select2-container--default .select2-olive .select2-results__option--highlighted, .select2-olive .select2-container--default .select2-results__option--highlighted { background-color: #3d9970; color: #fff; } .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected]:hover, .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #398e68; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple:focus, .select2-olive .select2-container--default .select2-selection--multiple:focus { border-color: #87cfaf; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3d9970; border-color: #368763; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-olive.select2-container--focus .select2-selection--multiple, .select2-olive .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #87cfaf; } .select2-lime + .select2-container--default.select2-container--open .select2-selection--single { border-color: #81ffb8; } .select2-lime + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #81ffb8; } .select2-container--default .select2-lime.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-search--inline .select2-search__field:focus, .select2-lime .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #81ffb8; } .select2-container--default .select2-lime .select2-results__option--highlighted, .select2-lime .select2-container--default .select2-results__option--highlighted { background-color: #01ff70; color: #1f2d3d; } .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected]:hover, .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00f169; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple:focus, .select2-lime .select2-container--default .select2-selection--multiple:focus { border-color: #81ffb8; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #01ff70; border-color: #00e765; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-lime.select2-container--focus .select2-selection--multiple, .select2-lime .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #81ffb8; } .select2-fuchsia + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f88adf; } .select2-fuchsia + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f88adf; } .select2-container--default .select2-fuchsia.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-search--inline .select2-search__field:focus, .select2-fuchsia .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f88adf; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted, .select2-fuchsia .select2-container--default .select2-results__option--highlighted { background-color: #f012be; color: #fff; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected]:hover, .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e40eb4; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple:focus, .select2-fuchsia .select2-container--default .select2-selection--multiple:focus { border-color: #f88adf; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f012be; border-color: #db0ead; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-fuchsia.select2-container--focus .select2-selection--multiple, .select2-fuchsia .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f88adf; } .select2-maroon + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f083ab; } .select2-maroon + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f083ab; } .select2-container--default .select2-maroon.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-search--inline .select2-search__field:focus, .select2-maroon .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f083ab; } .select2-container--default .select2-maroon .select2-results__option--highlighted, .select2-maroon .select2-container--default .select2-results__option--highlighted { background-color: #d81b60; color: #fff; } .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected]:hover, .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ca195a; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple:focus, .select2-maroon .select2-container--default .select2-selection--multiple:focus { border-color: #f083ab; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #d81b60; border-color: #c11856; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-maroon.select2-container--focus .select2-selection--multiple, .select2-maroon .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f083ab; } .select2-blue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-blue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-blue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-search--inline .select2-search__field:focus, .select2-blue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-blue .select2-results__option--highlighted, .select2-blue .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected]:hover, .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple:focus, .select2-blue .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-blue.select2-container--focus .select2-selection--multiple, .select2-blue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-indigo + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b389f9; } .select2-indigo + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b389f9; } .select2-container--default .select2-indigo.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-search--inline .select2-search__field:focus, .select2-indigo .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b389f9; } .select2-container--default .select2-indigo .select2-results__option--highlighted, .select2-indigo .select2-container--default .select2-results__option--highlighted { background-color: #6610f2; color: #fff; } .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected]:hover, .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #5f0de6; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple:focus, .select2-indigo .select2-container--default .select2-selection--multiple:focus { border-color: #b389f9; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6610f2; border-color: #5b0cdd; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-indigo.select2-container--focus .select2-selection--multiple, .select2-indigo .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b389f9; } .select2-purple + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b8a2e0; } .select2-purple + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b8a2e0; } .select2-container--default .select2-purple.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-search--inline .select2-search__field:focus, .select2-purple .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b8a2e0; } .select2-container--default .select2-purple .select2-results__option--highlighted, .select2-purple .select2-container--default .select2-results__option--highlighted { background-color: #6f42c1; color: #fff; } .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected]:hover, .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #683cb8; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple:focus, .select2-purple .select2-container--default .select2-selection--multiple:focus { border-color: #b8a2e0; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6f42c1; border-color: #643ab0; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-purple.select2-container--focus .select2-selection--multiple, .select2-purple .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b8a2e0; } .select2-pink + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f6b0d0; } .select2-pink + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f6b0d0; } .select2-container--default .select2-pink.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-search--inline .select2-search__field:focus, .select2-pink .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f6b0d0; } .select2-container--default .select2-pink .select2-results__option--highlighted, .select2-pink .select2-container--default .select2-results__option--highlighted { background-color: #e83e8c; color: #fff; } .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected]:hover, .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e63084; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple:focus, .select2-pink .select2-container--default .select2-selection--multiple:focus { border-color: #f6b0d0; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e83e8c; border-color: #e5277e; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-pink.select2-container--focus .select2-selection--multiple, .select2-pink .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f6b0d0; } .select2-red + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-red + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-red.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-search--inline .select2-search__field:focus, .select2-red .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-red .select2-results__option--highlighted, .select2-red .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected]:hover, .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple:focus, .select2-red .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-red.select2-container--focus .select2-selection--multiple, .select2-red .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-orange + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fec392; } .select2-orange + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fec392; } .select2-container--default .select2-orange.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-search--inline .select2-search__field:focus, .select2-orange .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fec392; } .select2-container--default .select2-orange .select2-results__option--highlighted, .select2-orange .select2-container--default .select2-results__option--highlighted { background-color: #fd7e14; color: #1f2d3d; } .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected]:hover, .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #fd7605; color: #fff; } .select2-container--default .select2-orange .select2-selection--multiple:focus, .select2-orange .select2-container--default .select2-selection--multiple:focus { border-color: #fec392; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fd7e14; border-color: #f57102; color: #1f2d3d; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-orange.select2-container--focus .select2-selection--multiple, .select2-orange .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fec392; } .select2-yellow + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-yellow + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-yellow.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-search--inline .select2-search__field:focus, .select2-yellow .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-yellow .select2-results__option--highlighted, .select2-yellow .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected]:hover, .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple:focus, .select2-yellow .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-yellow.select2-container--focus .select2-selection--multiple, .select2-yellow .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-green + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-green + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-green.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-search--inline .select2-search__field:focus, .select2-green .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-green .select2-results__option--highlighted, .select2-green .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected]:hover, .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple:focus, .select2-green .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-green.select2-container--focus .select2-selection--multiple, .select2-green .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-teal + .select2-container--default.select2-container--open .select2-selection--single { border-color: #7eeaca; } .select2-teal + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #7eeaca; } .select2-container--default .select2-teal.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-search--inline .select2-search__field:focus, .select2-teal .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #7eeaca; } .select2-container--default .select2-teal .select2-results__option--highlighted, .select2-teal .select2-container--default .select2-results__option--highlighted { background-color: #20c997; color: #fff; } .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected]:hover, .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1ebc8d; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple:focus, .select2-teal .select2-container--default .select2-selection--multiple:focus { border-color: #7eeaca; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #20c997; border-color: #1cb386; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-teal.select2-container--focus .select2-selection--multiple, .select2-teal .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #7eeaca; } .select2-cyan + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-cyan + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-cyan.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-search--inline .select2-search__field:focus, .select2-cyan .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-cyan .select2-results__option--highlighted, .select2-cyan .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected]:hover, .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple:focus, .select2-cyan .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-cyan.select2-container--focus .select2-selection--multiple, .select2-cyan .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-white + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-white + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-white.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-search--inline .select2-search__field:focus, .select2-white .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-white .select2-results__option--highlighted, .select2-white .select2-container--default .select2-results__option--highlighted { background-color: #fff; color: #1f2d3d; } .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected]:hover, .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7f7f7; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple:focus, .select2-white .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border-color: #f2f2f2; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-white.select2-container--focus .select2-selection--multiple, .select2-white .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-gray + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-gray + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-gray.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-search--inline .select2-search__field:focus, .select2-gray .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-gray .select2-results__option--highlighted, .select2-gray .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected]:hover, .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple:focus, .select2-gray .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray.select2-container--focus .select2-selection--multiple, .select2-gray .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-gray-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-gray-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-gray-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-search--inline .select2-search__field:focus, .select2-gray-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted, .select2-gray-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple:focus, .select2-gray-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray-dark.select2-container--focus .select2-selection--multiple, .select2-gray-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .dark-mode .select2-selection { background-color: #343a40; border-color: #6c757d; } .dark-mode .select2-container--disabled .select2-selection--single { background-color: #454d55; } .dark-mode .select2-selection--single { background-color: #343a40; border-color: #6c757d; } .dark-mode .select2-selection--single .select2-selection__rendered { color: #fff; } .dark-mode .select2-dropdown .select2-search__field, .dark-mode .select2-search--inline .select2-search__field { background-color: #343a40; border-color: #6c757d; color: white; } .dark-mode .select2-dropdown { background-color: #343a40; border-color: #6c757d; color: white; } .dark-mode .select2-results__option[aria-selected="true"] { background-color: #3f474e !important; color: #dee2e6; } .dark-mode .select2-container .select2-search--inline .select2-search__field { background-color: transparent; color: #fff; } .dark-mode .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { color: #fff; } .dark-mode .select2-primary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #85a7ca; } .dark-mode .select2-primary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-primary.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-primary .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-primary .select2-search--inline .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #85a7ca; } .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted, .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted { background-color: #3f6791; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3a5f86; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple:focus, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple:focus { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3f6791; border-color: #375a7f; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-primary.select2-container--focus .select2-selection--multiple, .dark-mode .select2-primary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #85a7ca; } .dark-mode .select2-secondary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .dark-mode .select2-secondary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-secondary.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-secondary .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-secondary .select2-search--inline .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted, .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple:focus, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-secondary.select2-container--focus .select2-selection--multiple, .dark-mode .select2-secondary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .dark-mode .select2-success + .select2-container--default.select2-container--open .select2-selection--single { border-color: #3dffcd; } .dark-mode .select2-success + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-success.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-success .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-success .select2-search--inline .select2-search__field:focus, .dark-mode .select2-success .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-success .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-success .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #3dffcd; } .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted, .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted { background-color: #00bc8c; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00ad81; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple:focus, .dark-mode .select2-success .select2-container--default .select2-selection--multiple:focus { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #00bc8c; border-color: #00a379; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-success.select2-container--focus .select2-selection--multiple, .dark-mode .select2-success .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #3dffcd; } .dark-mode .select2-info + .select2-container--default.select2-container--open .select2-selection--single { border-color: #a0cfee; } .dark-mode .select2-info + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-info.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-info .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-info .select2-search--inline .select2-search__field:focus, .dark-mode .select2-info .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-info .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-info .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #a0cfee; } .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted, .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted { background-color: #3498db; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2791d9; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple:focus, .dark-mode .select2-info .select2-container--default .select2-selection--multiple:focus { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3498db; border-color: #258cd1; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-info.select2-container--focus .select2-selection--multiple, .dark-mode .select2-info .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #a0cfee; } .dark-mode .select2-warning + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f9cf8b; } .dark-mode .select2-warning + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-warning.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-warning .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-warning .select2-search--inline .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f9cf8b; } .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted, .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted { background-color: #f39c12; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ea940c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple:focus, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple:focus { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f39c12; border-color: #e08e0b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning.select2-container--focus .select2-selection--multiple, .dark-mode .select2-warning .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f9cf8b; } .dark-mode .select2-danger + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f5b4ae; } .dark-mode .select2-danger + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-danger.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-danger .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-danger .select2-search--inline .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f5b4ae; } .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted, .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted { background-color: #e74c3c; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e53f2e; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple:focus, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple:focus { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e74c3c; border-color: #e43725; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-danger.select2-container--focus .select2-selection--multiple, .dark-mode .select2-danger .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f5b4ae; } .dark-mode .select2-light + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .dark-mode .select2-light + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .dark-mode .select2-light.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-light .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-light .select2-search--inline .select2-search__field:focus, .dark-mode .select2-light .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-light .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-light .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted, .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted { background-color: #f8f9fa; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eff1f4; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple:focus, .dark-mode .select2-light .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f8f9fa; border-color: #e9ecef; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-light.select2-container--focus .select2-selection--multiple, .dark-mode .select2-light .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .dark-mode .select2-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .dark-mode .select2-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-dark .select2-search--inline .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted, .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple:focus, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-dark.select2-container--focus .select2-selection--multiple, .dark-mode .select2-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .dark-mode .select2-lightblue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #e6f1f7; } .dark-mode .select2-lightblue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lightblue .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lightblue .select2-search--inline .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted, .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted { background-color: #86bad8; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #7ab3d5; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple:focus, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple:focus { border-color: #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #86bad8; border-color: #72afd2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue.select2-container--focus .select2-selection--multiple, .dark-mode .select2-lightblue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #e6f1f7; } .dark-mode .select2-navy + .select2-container--default.select2-container--open .select2-selection--single { border-color: #006ad8; } .dark-mode .select2-navy + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #006ad8; } .select2-container--default .dark-mode .select2-navy.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-navy .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-navy .select2-search--inline .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #006ad8; } .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted, .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted { background-color: #002c59; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #002449; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple:focus, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple:focus { border-color: #006ad8; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #002c59; border-color: #001f3f; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-navy.select2-container--focus .select2-selection--multiple, .dark-mode .select2-navy .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #006ad8; } .dark-mode .select2-olive + .select2-container--default.select2-container--open .select2-selection--single { border-color: #cfecdf; } .dark-mode .select2-olive + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #cfecdf; } .select2-container--default .dark-mode .select2-olive.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-olive .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-olive .select2-search--inline .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #cfecdf; } .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted, .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted { background-color: #74c8a3; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #69c39b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple:focus, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple:focus { border-color: #cfecdf; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #74c8a3; border-color: #62c096; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive.select2-container--focus .select2-selection--multiple, .dark-mode .select2-olive .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #cfecdf; } .dark-mode .select2-lime + .select2-container--default.select2-container--open .select2-selection--single { border-color: #e7fff1; } .dark-mode .select2-lime + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #e7fff1; } .select2-container--default .dark-mode .select2-lime.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lime .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lime .select2-search--inline .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #e7fff1; } .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted, .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted { background-color: #67ffa9; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #58ffa1; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple:focus, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple:focus { border-color: #e7fff1; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #67ffa9; border-color: #4eff9b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime.select2-container--focus .select2-selection--multiple, .dark-mode .select2-lime .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #e7fff1; } .dark-mode .select2-fuchsia + .select2-container--default.select2-container--open .select2-selection--single { border-color: #feeaf9; } .dark-mode .select2-fuchsia + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-fuchsia .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-fuchsia .select2-search--inline .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted, .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted { background-color: #f672d8; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f564d4; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple:focus { border-color: #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f672d8; border-color: #f55ad2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia.select2-container--focus .select2-selection--multiple, .dark-mode .select2-fuchsia .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #feeaf9; } .dark-mode .select2-maroon + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fbdee8; } .dark-mode .select2-maroon + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fbdee8; } .select2-container--default .dark-mode .select2-maroon.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-maroon .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-maroon .select2-search--inline .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fbdee8; } .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted, .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted { background-color: #ed6c9b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eb5f92; color: #fff; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple:focus, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple:focus { border-color: #fbdee8; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ed6c9b; border-color: #ea568c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon.select2-container--focus .select2-selection--multiple, .dark-mode .select2-maroon .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fbdee8; } .dark-mode .select2-blue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #85a7ca; } .dark-mode .select2-blue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-blue.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-blue .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-blue .select2-search--inline .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #85a7ca; } .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted, .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted { background-color: #3f6791; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3a5f86; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple:focus, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple:focus { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3f6791; border-color: #375a7f; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-blue.select2-container--focus .select2-selection--multiple, .dark-mode .select2-blue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #85a7ca; } .dark-mode .select2-indigo + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b389f9; } .dark-mode .select2-indigo + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b389f9; } .select2-container--default .dark-mode .select2-indigo.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-indigo .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-indigo .select2-search--inline .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b389f9; } .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted, .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted { background-color: #6610f2; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #5f0de6; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple:focus, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple:focus { border-color: #b389f9; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6610f2; border-color: #5b0cdd; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-indigo.select2-container--focus .select2-selection--multiple, .dark-mode .select2-indigo .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b389f9; } .dark-mode .select2-purple + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b8a2e0; } .dark-mode .select2-purple + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b8a2e0; } .select2-container--default .dark-mode .select2-purple.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-purple .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-purple .select2-search--inline .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b8a2e0; } .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted, .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted { background-color: #6f42c1; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #683cb8; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple:focus, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple:focus { border-color: #b8a2e0; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6f42c1; border-color: #643ab0; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-purple.select2-container--focus .select2-selection--multiple, .dark-mode .select2-purple .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b8a2e0; } .dark-mode .select2-pink + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f6b0d0; } .dark-mode .select2-pink + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f6b0d0; } .select2-container--default .dark-mode .select2-pink.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-pink .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-pink .select2-search--inline .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f6b0d0; } .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted, .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted { background-color: #e83e8c; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e63084; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple:focus, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple:focus { border-color: #f6b0d0; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e83e8c; border-color: #e5277e; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-pink.select2-container--focus .select2-selection--multiple, .dark-mode .select2-pink .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f6b0d0; } .dark-mode .select2-red + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f5b4ae; } .dark-mode .select2-red + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-red.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-red .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-red .select2-search--inline .select2-search__field:focus, .dark-mode .select2-red .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-red .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-red .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f5b4ae; } .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted, .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted { background-color: #e74c3c; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e53f2e; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple:focus, .dark-mode .select2-red .select2-container--default .select2-selection--multiple:focus { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e74c3c; border-color: #e43725; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-red.select2-container--focus .select2-selection--multiple, .dark-mode .select2-red .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f5b4ae; } .dark-mode .select2-orange + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fec392; } .dark-mode .select2-orange + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fec392; } .select2-container--default .dark-mode .select2-orange.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-orange .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-orange .select2-search--inline .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fec392; } .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted, .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted { background-color: #fd7e14; color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #fd7605; color: #fff; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple:focus, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple:focus { border-color: #fec392; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fd7e14; border-color: #f57102; color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange.select2-container--focus .select2-selection--multiple, .dark-mode .select2-orange .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fec392; } .dark-mode .select2-yellow + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f9cf8b; } .dark-mode .select2-yellow + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-yellow.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-yellow .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-yellow .select2-search--inline .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f9cf8b; } .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted, .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted { background-color: #f39c12; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ea940c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple:focus, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple:focus { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f39c12; border-color: #e08e0b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow.select2-container--focus .select2-selection--multiple, .dark-mode .select2-yellow .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f9cf8b; } .dark-mode .select2-green + .select2-container--default.select2-container--open .select2-selection--single { border-color: #3dffcd; } .dark-mode .select2-green + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-green.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-green .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-green .select2-search--inline .select2-search__field:focus, .dark-mode .select2-green .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-green .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-green .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #3dffcd; } .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted, .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted { background-color: #00bc8c; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00ad81; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple:focus, .dark-mode .select2-green .select2-container--default .select2-selection--multiple:focus { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #00bc8c; border-color: #00a379; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-green.select2-container--focus .select2-selection--multiple, .dark-mode .select2-green .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #3dffcd; } .dark-mode .select2-teal + .select2-container--default.select2-container--open .select2-selection--single { border-color: #7eeaca; } .dark-mode .select2-teal + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #7eeaca; } .select2-container--default .dark-mode .select2-teal.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-teal .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-teal .select2-search--inline .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #7eeaca; } .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted, .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted { background-color: #20c997; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1ebc8d; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple:focus, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple:focus { border-color: #7eeaca; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #20c997; border-color: #1cb386; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-teal.select2-container--focus .select2-selection--multiple, .dark-mode .select2-teal .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #7eeaca; } .dark-mode .select2-cyan + .select2-container--default.select2-container--open .select2-selection--single { border-color: #a0cfee; } .dark-mode .select2-cyan + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-cyan.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-cyan .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-cyan .select2-search--inline .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #a0cfee; } .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted, .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted { background-color: #3498db; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2791d9; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple:focus, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple:focus { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3498db; border-color: #258cd1; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-cyan.select2-container--focus .select2-selection--multiple, .dark-mode .select2-cyan .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #a0cfee; } .dark-mode .select2-white + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .dark-mode .select2-white + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .dark-mode .select2-white.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-white .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-white .select2-search--inline .select2-search__field:focus, .dark-mode .select2-white .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-white .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-white .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted, .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted { background-color: #fff; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7f7f7; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple:focus, .dark-mode .select2-white .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border-color: #f2f2f2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-white.select2-container--focus .select2-selection--multiple, .dark-mode .select2-white .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .dark-mode .select2-gray + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .dark-mode .select2-gray + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-gray.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray .select2-search--inline .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted, .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple:focus, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-gray.select2-container--focus .select2-selection--multiple, .dark-mode .select2-gray .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .dark-mode .select2-gray-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .dark-mode .select2-gray-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray-dark .select2-search--inline .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted, .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-gray-dark.select2-container--focus .select2-selection--multiple, .dark-mode .select2-gray-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .slider .tooltip.in { opacity: 0.9; } .slider.slider-vertical { height: 100%; } .slider.slider-horizontal { width: 100%; } .slider-primary .slider .slider-selection { background: #007bff; } .slider-secondary .slider .slider-selection { background: #6c757d; } .slider-success .slider .slider-selection { background: #28a745; } .slider-info .slider .slider-selection { background: #17a2b8; } .slider-warning .slider .slider-selection { background: #ffc107; } .slider-danger .slider .slider-selection { background: #dc3545; } .slider-light .slider .slider-selection { background: #f8f9fa; } .slider-dark .slider .slider-selection { background: #343a40; } .slider-lightblue .slider .slider-selection { background: #3c8dbc; } .slider-navy .slider .slider-selection { background: #001f3f; } .slider-olive .slider .slider-selection { background: #3d9970; } .slider-lime .slider .slider-selection { background: #01ff70; } .slider-fuchsia .slider .slider-selection { background: #f012be; } .slider-maroon .slider .slider-selection { background: #d81b60; } .slider-blue .slider .slider-selection { background: #007bff; } .slider-indigo .slider .slider-selection { background: #6610f2; } .slider-purple .slider .slider-selection { background: #6f42c1; } .slider-pink .slider .slider-selection { background: #e83e8c; } .slider-red .slider .slider-selection { background: #dc3545; } .slider-orange .slider .slider-selection { background: #fd7e14; } .slider-yellow .slider .slider-selection { background: #ffc107; } .slider-green .slider .slider-selection { background: #28a745; } .slider-teal .slider .slider-selection { background: #20c997; } .slider-cyan .slider .slider-selection { background: #17a2b8; } .slider-white .slider .slider-selection { background: #fff; } .slider-gray .slider .slider-selection { background: #6c757d; } .slider-gray-dark .slider .slider-selection { background: #343a40; } .dark-mode .slider-track { background-color: #4b545c; background-image: none; } .dark-mode .slider-primary .slider .slider-selection { background: #3f6791; } .dark-mode .slider-secondary .slider .slider-selection { background: #6c757d; } .dark-mode .slider-success .slider .slider-selection { background: #00bc8c; } .dark-mode .slider-info .slider .slider-selection { background: #3498db; } .dark-mode .slider-warning .slider .slider-selection { background: #f39c12; } .dark-mode .slider-danger .slider .slider-selection { background: #e74c3c; } .dark-mode .slider-light .slider .slider-selection { background: #f8f9fa; } .dark-mode .slider-dark .slider .slider-selection { background: #343a40; } .dark-mode .slider-lightblue .slider .slider-selection { background: #86bad8; } .dark-mode .slider-navy .slider .slider-selection { background: #002c59; } .dark-mode .slider-olive .slider .slider-selection { background: #74c8a3; } .dark-mode .slider-lime .slider .slider-selection { background: #67ffa9; } .dark-mode .slider-fuchsia .slider .slider-selection { background: #f672d8; } .dark-mode .slider-maroon .slider .slider-selection { background: #ed6c9b; } .dark-mode .slider-blue .slider .slider-selection { background: #3f6791; } .dark-mode .slider-indigo .slider .slider-selection { background: #6610f2; } .dark-mode .slider-purple .slider .slider-selection { background: #6f42c1; } .dark-mode .slider-pink .slider .slider-selection { background: #e83e8c; } .dark-mode .slider-red .slider .slider-selection { background: #e74c3c; } .dark-mode .slider-orange .slider .slider-selection { background: #fd7e14; } .dark-mode .slider-yellow .slider .slider-selection { background: #f39c12; } .dark-mode .slider-green .slider .slider-selection { background: #00bc8c; } .dark-mode .slider-teal .slider .slider-selection { background: #20c997; } .dark-mode .slider-cyan .slider .slider-selection { background: #3498db; } .dark-mode .slider-white .slider .slider-selection { background: #fff; } .dark-mode .slider-gray .slider .slider-selection { background: #6c757d; } .dark-mode .slider-gray-dark .slider .slider-selection { background: #343a40; } .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:checked + label::before, .icheck-primary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:checked + label::before, .icheck-secondary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-success > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:checked + label::before, .icheck-success > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-info > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:checked + label::before, .icheck-info > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:checked + label::before, .icheck-warning > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:checked + label::before, .icheck-danger > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-light > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:checked + label::before, .icheck-light > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f8f9fa; border-color: #f8f9fa; } .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:checked + label::before, .icheck-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:checked + label::before, .icheck-lightblue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3c8dbc; border-color: #3c8dbc; } .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:checked + label::before, .icheck-navy > input:first-child:checked + input[type="hidden"] + label::before { background-color: #001f3f; border-color: #001f3f; } .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:checked + label::before, .icheck-olive > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3d9970; border-color: #3d9970; } .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:checked + label::before, .icheck-lime > input:first-child:checked + input[type="hidden"] + label::before { background-color: #01ff70; border-color: #01ff70; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:checked + label::before, .icheck-fuchsia > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f012be; border-color: #f012be; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:checked + label::before, .icheck-maroon > input:first-child:checked + input[type="hidden"] + label::before { background-color: #d81b60; border-color: #d81b60; } .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:checked + label::before, .icheck-blue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:checked + label::before, .icheck-indigo > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6610f2; border-color: #6610f2; } .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:checked + label::before, .icheck-purple > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6f42c1; border-color: #6f42c1; } .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:checked + label::before, .icheck-pink > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e83e8c; border-color: #e83e8c; } .icheck-red > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:checked + label::before, .icheck-red > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:checked + label::before, .icheck-orange > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fd7e14; border-color: #fd7e14; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:checked + label::before, .icheck-yellow > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-green > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:checked + label::before, .icheck-green > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:checked + label::before, .icheck-teal > input:first-child:checked + input[type="hidden"] + label::before { background-color: #20c997; border-color: #20c997; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:checked + label::before, .icheck-cyan > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-white > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:checked + label::before, .icheck-white > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fff; border-color: #fff; } .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:checked + label::before, .icheck-gray > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:checked + label::before, .icheck-gray-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .dark-mode [class*="icheck-"] > input:first-child:not(:checked) + input[type="hidden"] + label::before, .dark-mode [class*="icheck-"] > input:first-child:not(:checked) + label::before { border-color: #6c757d; } .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-primary > input:first-child:checked + label::before, .dark-mode .icheck-primary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3f6791; border-color: #3f6791; } .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-secondary > input:first-child:checked + label::before, .dark-mode .icheck-secondary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-success > input:first-child:checked + label::before, .dark-mode .icheck-success > input:first-child:checked + input[type="hidden"] + label::before { background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-info > input:first-child:checked + label::before, .dark-mode .icheck-info > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3498db; border-color: #3498db; } .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-warning > input:first-child:checked + label::before, .dark-mode .icheck-warning > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f39c12; border-color: #f39c12; } .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-danger > input:first-child:checked + label::before, .dark-mode .icheck-danger > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f8f9fa; } .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f8f9fa; } .dark-mode .icheck-light > input:first-child:checked + label::before, .dark-mode .icheck-light > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-dark > input:first-child:checked + label::before, .dark-mode .icheck-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #86bad8; } .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #86bad8; } .dark-mode .icheck-lightblue > input:first-child:checked + label::before, .dark-mode .icheck-lightblue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #86bad8; border-color: #86bad8; } .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #002c59; } .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #002c59; } .dark-mode .icheck-navy > input:first-child:checked + label::before, .dark-mode .icheck-navy > input:first-child:checked + input[type="hidden"] + label::before { background-color: #002c59; border-color: #002c59; } .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #74c8a3; } .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #74c8a3; } .dark-mode .icheck-olive > input:first-child:checked + label::before, .dark-mode .icheck-olive > input:first-child:checked + input[type="hidden"] + label::before { background-color: #74c8a3; border-color: #74c8a3; } .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #67ffa9; } .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #67ffa9; } .dark-mode .icheck-lime > input:first-child:checked + label::before, .dark-mode .icheck-lime > input:first-child:checked + input[type="hidden"] + label::before { background-color: #67ffa9; border-color: #67ffa9; } .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f672d8; } .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f672d8; } .dark-mode .icheck-fuchsia > input:first-child:checked + label::before, .dark-mode .icheck-fuchsia > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f672d8; border-color: #f672d8; } .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ed6c9b; } .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ed6c9b; } .dark-mode .icheck-maroon > input:first-child:checked + label::before, .dark-mode .icheck-maroon > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ed6c9b; border-color: #ed6c9b; } .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-blue > input:first-child:checked + label::before, .dark-mode .icheck-blue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3f6791; border-color: #3f6791; } .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6610f2; } .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6610f2; } .dark-mode .icheck-indigo > input:first-child:checked + label::before, .dark-mode .icheck-indigo > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6610f2; border-color: #6610f2; } .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6f42c1; } .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6f42c1; } .dark-mode .icheck-purple > input:first-child:checked + label::before, .dark-mode .icheck-purple > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6f42c1; border-color: #6f42c1; } .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e83e8c; } .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e83e8c; } .dark-mode .icheck-pink > input:first-child:checked + label::before, .dark-mode .icheck-pink > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e83e8c; border-color: #e83e8c; } .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-red > input:first-child:checked + label::before, .dark-mode .icheck-red > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fd7e14; } .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fd7e14; } .dark-mode .icheck-orange > input:first-child:checked + label::before, .dark-mode .icheck-orange > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fd7e14; border-color: #fd7e14; } .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-yellow > input:first-child:checked + label::before, .dark-mode .icheck-yellow > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f39c12; border-color: #f39c12; } .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-green > input:first-child:checked + label::before, .dark-mode .icheck-green > input:first-child:checked + input[type="hidden"] + label::before { background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #20c997; } .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #20c997; } .dark-mode .icheck-teal > input:first-child:checked + label::before, .dark-mode .icheck-teal > input:first-child:checked + input[type="hidden"] + label::before { background-color: #20c997; border-color: #20c997; } .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-cyan > input:first-child:checked + label::before, .dark-mode .icheck-cyan > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3498db; border-color: #3498db; } .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fff; } .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fff; } .dark-mode .icheck-white > input:first-child:checked + label::before, .dark-mode .icheck-white > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fff; border-color: #fff; } .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-gray > input:first-child:checked + label::before, .dark-mode .icheck-gray > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-gray-dark > input:first-child:checked + label::before, .dark-mode .icheck-gray-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .mapael .map { position: relative; } .mapael .mapTooltip { font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; border-radius: 0.25rem; font-size: 0.875rem; background-color: #000; color: #fff; display: block; max-width: 200px; padding: 0.25rem 0.5rem; position: absolute; text-align: center; word-wrap: break-word; z-index: 1070; } .mapael .myLegend { background-color: #f8f9fa; border: 1px solid #adb5bd; padding: 10px; width: 600px; } .mapael .zoomButton { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; cursor: pointer; font-weight: 700; height: 16px; left: 10px; line-height: 14px; padding-left: 1px; position: absolute; text-align: center; top: 0; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; width: 16px; } .mapael .zoomButton:hover, .mapael .zoomButton:active, .mapael .zoomButton.hover { background-color: #e9ecef; color: #2b2b2b; } .mapael .zoomReset { line-height: 12px; top: 10px; } .mapael .zoomIn { top: 30px; } .mapael .zoomOut { top: 50px; } .jqvmap-zoomin, .jqvmap-zoomout { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; height: 15px; width: 15px; padding: 1px 2px; } .jqvmap-zoomin:hover, .jqvmap-zoomin:active, .jqvmap-zoomin.hover, .jqvmap-zoomout:hover, .jqvmap-zoomout:active, .jqvmap-zoomout.hover { background-color: #e9ecef; color: #2b2b2b; } .swal2-icon.swal2-info { border-color: ligthen(#17a2b8, 20%); color: #17a2b8; } .swal2-icon.swal2-warning { border-color: ligthen(#ffc107, 20%); color: #ffc107; } .swal2-icon.swal2-error { border-color: ligthen(#dc3545, 20%); color: #dc3545; } .swal2-icon.swal2-question { border-color: ligthen(#6c757d, 20%); color: #6c757d; } .swal2-icon.swal2-success { border-color: ligthen(#28a745, 20%); color: #28a745; } .swal2-icon.swal2-success .swal2-success-ring { border-color: ligthen(#28a745, 20%); } .swal2-icon.swal2-success [class^='swal2-success-line'] { background-color: #28a745; } .dark-mode .swal2-popup { background-color: #343a40; color: #e9ecef; } .dark-mode .swal2-popup .swal2-content, .dark-mode .swal2-popup .swal2-title { color: #e9ecef; } #toast-container .toast { background-color: #007bff; } #toast-container .toast-success { background-color: #28a745; } #toast-container .toast-error { background-color: #dc3545; } #toast-container .toast-info { background-color: #17a2b8; } #toast-container .toast-warning { background-color: #ffc107; } .toast-bottom-full-width .toast, .toast-top-full-width .toast { max-width: inherit; } .pace { z-index: 1048; } .pace .pace-progress { z-index: 1049; } .pace .pace-activity { z-index: 1050; } .pace-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace { background: #fff; } .pace-barber-shop-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-primary .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-primary .pace .pace-activity { background: #007bff; } .pace-center-atom-primary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-primary .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-primary .pace-activity { border-color: #007bff; } .pace-center-atom-primary .pace-activity::after, .pace-center-atom-primary .pace-activity::before { border-color: #007bff; } .pace-center-circle-primary .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-primary .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-primary .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-primary .pace { background: #fff; border-color: #007bff; } .pace-center-simple-primary .pace .pace-progress { background: #007bff; } .pace-material-primary .pace { color: #007bff; } .pace-corner-indicator-primary .pace .pace-activity { background: #007bff; } .pace-corner-indicator-primary .pace .pace-activity::after, .pace-corner-indicator-primary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-primary .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-primary .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-primary .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-primary .pace .pace-progress { background: #007bff; } .pace-flash-primary .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-primary .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-primary .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-primary .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-primary .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-primary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-primary .pace-progress { color: #007bff; } .pace-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace { background: #fff; } .pace-barber-shop-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-secondary .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-secondary .pace .pace-activity { background: #6c757d; } .pace-center-atom-secondary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-secondary .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-secondary .pace-activity { border-color: #6c757d; } .pace-center-atom-secondary .pace-activity::after, .pace-center-atom-secondary .pace-activity::before { border-color: #6c757d; } .pace-center-circle-secondary .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-secondary .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-secondary .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-secondary .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-secondary .pace .pace-progress { background: #6c757d; } .pace-material-secondary .pace { color: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity::after, .pace-corner-indicator-secondary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-secondary .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-secondary .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-secondary .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-secondary .pace .pace-progress { background: #6c757d; } .pace-flash-secondary .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-secondary .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-secondary .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-secondary .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-secondary .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-secondary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-secondary .pace-progress { color: #6c757d; } .pace-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace { background: #fff; } .pace-barber-shop-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-success .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-success .pace .pace-activity { background: #28a745; } .pace-center-atom-success .pace-progress { height: 100px; width: 80px; } .pace-center-atom-success .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-success .pace-activity { border-color: #28a745; } .pace-center-atom-success .pace-activity::after, .pace-center-atom-success .pace-activity::before { border-color: #28a745; } .pace-center-circle-success .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-success .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-success .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-success .pace { background: #fff; border-color: #28a745; } .pace-center-simple-success .pace .pace-progress { background: #28a745; } .pace-material-success .pace { color: #28a745; } .pace-corner-indicator-success .pace .pace-activity { background: #28a745; } .pace-corner-indicator-success .pace .pace-activity::after, .pace-corner-indicator-success .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-success .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-success .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-success .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-success .pace .pace-progress { background: #28a745; } .pace-flash-success .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-success .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-success .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-success .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-success .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-success .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-success .pace-progress { color: #28a745; } .pace-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace { background: #fff; } .pace-barber-shop-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-info .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-info .pace .pace-activity { background: #17a2b8; } .pace-center-atom-info .pace-progress { height: 100px; width: 80px; } .pace-center-atom-info .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-info .pace-activity { border-color: #17a2b8; } .pace-center-atom-info .pace-activity::after, .pace-center-atom-info .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-info .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-info .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-info .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-info .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-info .pace .pace-progress { background: #17a2b8; } .pace-material-info .pace { color: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity::after, .pace-corner-indicator-info .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-info .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-info .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-info .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-info .pace .pace-progress { background: #17a2b8; } .pace-flash-info .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-info .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-info .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-info .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-info .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-info .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-info .pace-progress { color: #17a2b8; } .pace-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace { background: #1f2d3d; } .pace-barber-shop-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-warning .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-warning .pace .pace-activity { background: #ffc107; } .pace-center-atom-warning .pace-progress { height: 100px; width: 80px; } .pace-center-atom-warning .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-warning .pace-activity { border-color: #ffc107; } .pace-center-atom-warning .pace-activity::after, .pace-center-atom-warning .pace-activity::before { border-color: #ffc107; } .pace-center-circle-warning .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-warning .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-warning .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-warning .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-warning .pace .pace-progress { background: #ffc107; } .pace-material-warning .pace { color: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity::after, .pace-corner-indicator-warning .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-warning .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-warning .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-warning .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-warning .pace .pace-progress { background: #ffc107; } .pace-flash-warning .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-warning .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-warning .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-warning .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-warning .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-warning .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-warning .pace-progress { color: #ffc107; } .pace-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace { background: #fff; } .pace-barber-shop-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-danger .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-danger .pace .pace-activity { background: #dc3545; } .pace-center-atom-danger .pace-progress { height: 100px; width: 80px; } .pace-center-atom-danger .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-danger .pace-activity { border-color: #dc3545; } .pace-center-atom-danger .pace-activity::after, .pace-center-atom-danger .pace-activity::before { border-color: #dc3545; } .pace-center-circle-danger .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-danger .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-danger .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-danger .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-danger .pace .pace-progress { background: #dc3545; } .pace-material-danger .pace { color: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity::after, .pace-corner-indicator-danger .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-danger .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-danger .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-danger .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-danger .pace .pace-progress { background: #dc3545; } .pace-flash-danger .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-danger .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-danger .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-danger .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-danger .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-danger .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-danger .pace-progress { color: #dc3545; } .pace-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace { background: #1f2d3d; } .pace-barber-shop-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-light .pace .pace-progress::after { color: rgba(248, 249, 250, 0.2); } .pace-bounce-light .pace .pace-activity { background: #f8f9fa; } .pace-center-atom-light .pace-progress { height: 100px; width: 80px; } .pace-center-atom-light .pace-progress::before { background: #f8f9fa; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-light .pace-activity { border-color: #f8f9fa; } .pace-center-atom-light .pace-activity::after, .pace-center-atom-light .pace-activity::before { border-color: #f8f9fa; } .pace-center-circle-light .pace .pace-progress { background: rgba(248, 249, 250, 0.8); color: #1f2d3d; } .pace-center-radar-light .pace .pace-activity { border-color: #f8f9fa transparent transparent; } .pace-center-radar-light .pace .pace-activity::before { border-color: #f8f9fa transparent transparent; } .pace-center-simple-light .pace { background: #1f2d3d; border-color: #f8f9fa; } .pace-center-simple-light .pace .pace-progress { background: #f8f9fa; } .pace-material-light .pace { color: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity { background: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity::after, .pace-corner-indicator-light .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-light .pace .pace-activity::before { border-right-color: rgba(248, 249, 250, 0.2); border-left-color: rgba(248, 249, 250, 0.2); } .pace-corner-indicator-light .pace .pace-activity::after { border-top-color: rgba(248, 249, 250, 0.2); border-bottom-color: rgba(248, 249, 250, 0.2); } .pace-fill-left-light .pace .pace-progress { background-color: rgba(248, 249, 250, 0.2); } .pace-flash-light .pace .pace-progress { background: #f8f9fa; } .pace-flash-light .pace .pace-progress-inner { box-shadow: 0 0 10px #f8f9fa, 0 0 5px #f8f9fa; } .pace-flash-light .pace .pace-activity { border-top-color: #f8f9fa; border-left-color: #f8f9fa; } .pace-loading-bar-light .pace .pace-progress { background: #f8f9fa; color: #f8f9fa; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-light .pace .pace-activity { box-shadow: inset 0 0 0 2px #f8f9fa, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-light .pace .pace-progress { background-color: #f8f9fa; box-shadow: inset -1px 0 #f8f9fa, inset 0 -1px #f8f9fa, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-light .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-light .pace-progress { color: #f8f9fa; } .pace-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace { background: #fff; } .pace-barber-shop-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-dark .pace-activity { border-color: #343a40; } .pace-center-atom-dark .pace-activity::after, .pace-center-atom-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-dark .pace .pace-progress { background: #343a40; } .pace-material-dark .pace { color: #343a40; } .pace-corner-indicator-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-dark .pace .pace-activity::after, .pace-corner-indicator-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-dark .pace .pace-progress { background: #343a40; } .pace-flash-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-dark .pace-progress { color: #343a40; } .pace-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace { background: #fff; } .pace-barber-shop-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lightblue .pace .pace-progress::after { color: rgba(60, 141, 188, 0.2); } .pace-bounce-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-center-atom-lightblue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lightblue .pace-progress::before { background: #3c8dbc; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lightblue .pace-activity { border-color: #3c8dbc; } .pace-center-atom-lightblue .pace-activity::after, .pace-center-atom-lightblue .pace-activity::before { border-color: #3c8dbc; } .pace-center-circle-lightblue .pace .pace-progress { background: rgba(60, 141, 188, 0.8); color: #fff; } .pace-center-radar-lightblue .pace .pace-activity { border-color: #3c8dbc transparent transparent; } .pace-center-radar-lightblue .pace .pace-activity::before { border-color: #3c8dbc transparent transparent; } .pace-center-simple-lightblue .pace { background: #fff; border-color: #3c8dbc; } .pace-center-simple-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-material-lightblue .pace { color: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity::after, .pace-corner-indicator-lightblue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-lightblue .pace .pace-activity::before { border-right-color: rgba(60, 141, 188, 0.2); border-left-color: rgba(60, 141, 188, 0.2); } .pace-corner-indicator-lightblue .pace .pace-activity::after { border-top-color: rgba(60, 141, 188, 0.2); border-bottom-color: rgba(60, 141, 188, 0.2); } .pace-fill-left-lightblue .pace .pace-progress { background-color: rgba(60, 141, 188, 0.2); } .pace-flash-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-flash-lightblue .pace .pace-progress-inner { box-shadow: 0 0 10px #3c8dbc, 0 0 5px #3c8dbc; } .pace-flash-lightblue .pace .pace-activity { border-top-color: #3c8dbc; border-left-color: #3c8dbc; } .pace-loading-bar-lightblue .pace .pace-progress { background: #3c8dbc; color: #3c8dbc; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-lightblue .pace .pace-activity { box-shadow: inset 0 0 0 2px #3c8dbc, inset 0 0 0 7px #fff; } .pace-mac-osx-lightblue .pace .pace-progress { background-color: #3c8dbc; box-shadow: inset -1px 0 #3c8dbc, inset 0 -1px #3c8dbc, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-lightblue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-lightblue .pace-progress { color: #3c8dbc; } .pace-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace { background: #fff; } .pace-barber-shop-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-navy .pace .pace-progress::after { color: rgba(0, 31, 63, 0.2); } .pace-bounce-navy .pace .pace-activity { background: #001f3f; } .pace-center-atom-navy .pace-progress { height: 100px; width: 80px; } .pace-center-atom-navy .pace-progress::before { background: #001f3f; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-navy .pace-activity { border-color: #001f3f; } .pace-center-atom-navy .pace-activity::after, .pace-center-atom-navy .pace-activity::before { border-color: #001f3f; } .pace-center-circle-navy .pace .pace-progress { background: rgba(0, 31, 63, 0.8); color: #fff; } .pace-center-radar-navy .pace .pace-activity { border-color: #001f3f transparent transparent; } .pace-center-radar-navy .pace .pace-activity::before { border-color: #001f3f transparent transparent; } .pace-center-simple-navy .pace { background: #fff; border-color: #001f3f; } .pace-center-simple-navy .pace .pace-progress { background: #001f3f; } .pace-material-navy .pace { color: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity { background: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity::after, .pace-corner-indicator-navy .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-navy .pace .pace-activity::before { border-right-color: rgba(0, 31, 63, 0.2); border-left-color: rgba(0, 31, 63, 0.2); } .pace-corner-indicator-navy .pace .pace-activity::after { border-top-color: rgba(0, 31, 63, 0.2); border-bottom-color: rgba(0, 31, 63, 0.2); } .pace-fill-left-navy .pace .pace-progress { background-color: rgba(0, 31, 63, 0.2); } .pace-flash-navy .pace .pace-progress { background: #001f3f; } .pace-flash-navy .pace .pace-progress-inner { box-shadow: 0 0 10px #001f3f, 0 0 5px #001f3f; } .pace-flash-navy .pace .pace-activity { border-top-color: #001f3f; border-left-color: #001f3f; } .pace-loading-bar-navy .pace .pace-progress { background: #001f3f; color: #001f3f; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-navy .pace .pace-activity { box-shadow: inset 0 0 0 2px #001f3f, inset 0 0 0 7px #fff; } .pace-mac-osx-navy .pace .pace-progress { background-color: #001f3f; box-shadow: inset -1px 0 #001f3f, inset 0 -1px #001f3f, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-navy .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-navy .pace-progress { color: #001f3f; } .pace-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace { background: #fff; } .pace-barber-shop-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-olive .pace .pace-progress::after { color: rgba(61, 153, 112, 0.2); } .pace-bounce-olive .pace .pace-activity { background: #3d9970; } .pace-center-atom-olive .pace-progress { height: 100px; width: 80px; } .pace-center-atom-olive .pace-progress::before { background: #3d9970; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-olive .pace-activity { border-color: #3d9970; } .pace-center-atom-olive .pace-activity::after, .pace-center-atom-olive .pace-activity::before { border-color: #3d9970; } .pace-center-circle-olive .pace .pace-progress { background: rgba(61, 153, 112, 0.8); color: #fff; } .pace-center-radar-olive .pace .pace-activity { border-color: #3d9970 transparent transparent; } .pace-center-radar-olive .pace .pace-activity::before { border-color: #3d9970 transparent transparent; } .pace-center-simple-olive .pace { background: #fff; border-color: #3d9970; } .pace-center-simple-olive .pace .pace-progress { background: #3d9970; } .pace-material-olive .pace { color: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity { background: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity::after, .pace-corner-indicator-olive .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-olive .pace .pace-activity::before { border-right-color: rgba(61, 153, 112, 0.2); border-left-color: rgba(61, 153, 112, 0.2); } .pace-corner-indicator-olive .pace .pace-activity::after { border-top-color: rgba(61, 153, 112, 0.2); border-bottom-color: rgba(61, 153, 112, 0.2); } .pace-fill-left-olive .pace .pace-progress { background-color: rgba(61, 153, 112, 0.2); } .pace-flash-olive .pace .pace-progress { background: #3d9970; } .pace-flash-olive .pace .pace-progress-inner { box-shadow: 0 0 10px #3d9970, 0 0 5px #3d9970; } .pace-flash-olive .pace .pace-activity { border-top-color: #3d9970; border-left-color: #3d9970; } .pace-loading-bar-olive .pace .pace-progress { background: #3d9970; color: #3d9970; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-olive .pace .pace-activity { box-shadow: inset 0 0 0 2px #3d9970, inset 0 0 0 7px #fff; } .pace-mac-osx-olive .pace .pace-progress { background-color: #3d9970; box-shadow: inset -1px 0 #3d9970, inset 0 -1px #3d9970, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-olive .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-olive .pace-progress { color: #3d9970; } .pace-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace { background: #1f2d3d; } .pace-barber-shop-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lime .pace .pace-progress::after { color: rgba(1, 255, 112, 0.2); } .pace-bounce-lime .pace .pace-activity { background: #01ff70; } .pace-center-atom-lime .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lime .pace-progress::before { background: #01ff70; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lime .pace-activity { border-color: #01ff70; } .pace-center-atom-lime .pace-activity::after, .pace-center-atom-lime .pace-activity::before { border-color: #01ff70; } .pace-center-circle-lime .pace .pace-progress { background: rgba(1, 255, 112, 0.8); color: #1f2d3d; } .pace-center-radar-lime .pace .pace-activity { border-color: #01ff70 transparent transparent; } .pace-center-radar-lime .pace .pace-activity::before { border-color: #01ff70 transparent transparent; } .pace-center-simple-lime .pace { background: #1f2d3d; border-color: #01ff70; } .pace-center-simple-lime .pace .pace-progress { background: #01ff70; } .pace-material-lime .pace { color: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity { background: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity::after, .pace-corner-indicator-lime .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-lime .pace .pace-activity::before { border-right-color: rgba(1, 255, 112, 0.2); border-left-color: rgba(1, 255, 112, 0.2); } .pace-corner-indicator-lime .pace .pace-activity::after { border-top-color: rgba(1, 255, 112, 0.2); border-bottom-color: rgba(1, 255, 112, 0.2); } .pace-fill-left-lime .pace .pace-progress { background-color: rgba(1, 255, 112, 0.2); } .pace-flash-lime .pace .pace-progress { background: #01ff70; } .pace-flash-lime .pace .pace-progress-inner { box-shadow: 0 0 10px #01ff70, 0 0 5px #01ff70; } .pace-flash-lime .pace .pace-activity { border-top-color: #01ff70; border-left-color: #01ff70; } .pace-loading-bar-lime .pace .pace-progress { background: #01ff70; color: #01ff70; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-lime .pace .pace-activity { box-shadow: inset 0 0 0 2px #01ff70, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-lime .pace .pace-progress { background-color: #01ff70; box-shadow: inset -1px 0 #01ff70, inset 0 -1px #01ff70, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-lime .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-lime .pace-progress { color: #01ff70; } .pace-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace { background: #fff; } .pace-barber-shop-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-fuchsia .pace .pace-progress::after { color: rgba(240, 18, 190, 0.2); } .pace-bounce-fuchsia .pace .pace-activity { background: #f012be; } .pace-center-atom-fuchsia .pace-progress { height: 100px; width: 80px; } .pace-center-atom-fuchsia .pace-progress::before { background: #f012be; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-fuchsia .pace-activity { border-color: #f012be; } .pace-center-atom-fuchsia .pace-activity::after, .pace-center-atom-fuchsia .pace-activity::before { border-color: #f012be; } .pace-center-circle-fuchsia .pace .pace-progress { background: rgba(240, 18, 190, 0.8); color: #fff; } .pace-center-radar-fuchsia .pace .pace-activity { border-color: #f012be transparent transparent; } .pace-center-radar-fuchsia .pace .pace-activity::before { border-color: #f012be transparent transparent; } .pace-center-simple-fuchsia .pace { background: #fff; border-color: #f012be; } .pace-center-simple-fuchsia .pace .pace-progress { background: #f012be; } .pace-material-fuchsia .pace { color: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity { background: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity::after, .pace-corner-indicator-fuchsia .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-fuchsia .pace .pace-activity::before { border-right-color: rgba(240, 18, 190, 0.2); border-left-color: rgba(240, 18, 190, 0.2); } .pace-corner-indicator-fuchsia .pace .pace-activity::after { border-top-color: rgba(240, 18, 190, 0.2); border-bottom-color: rgba(240, 18, 190, 0.2); } .pace-fill-left-fuchsia .pace .pace-progress { background-color: rgba(240, 18, 190, 0.2); } .pace-flash-fuchsia .pace .pace-progress { background: #f012be; } .pace-flash-fuchsia .pace .pace-progress-inner { box-shadow: 0 0 10px #f012be, 0 0 5px #f012be; } .pace-flash-fuchsia .pace .pace-activity { border-top-color: #f012be; border-left-color: #f012be; } .pace-loading-bar-fuchsia .pace .pace-progress { background: #f012be; color: #f012be; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-fuchsia .pace .pace-activity { box-shadow: inset 0 0 0 2px #f012be, inset 0 0 0 7px #fff; } .pace-mac-osx-fuchsia .pace .pace-progress { background-color: #f012be; box-shadow: inset -1px 0 #f012be, inset 0 -1px #f012be, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-fuchsia .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-fuchsia .pace-progress { color: #f012be; } .pace-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace { background: #fff; } .pace-barber-shop-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-maroon .pace .pace-progress::after { color: rgba(216, 27, 96, 0.2); } .pace-bounce-maroon .pace .pace-activity { background: #d81b60; } .pace-center-atom-maroon .pace-progress { height: 100px; width: 80px; } .pace-center-atom-maroon .pace-progress::before { background: #d81b60; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-maroon .pace-activity { border-color: #d81b60; } .pace-center-atom-maroon .pace-activity::after, .pace-center-atom-maroon .pace-activity::before { border-color: #d81b60; } .pace-center-circle-maroon .pace .pace-progress { background: rgba(216, 27, 96, 0.8); color: #fff; } .pace-center-radar-maroon .pace .pace-activity { border-color: #d81b60 transparent transparent; } .pace-center-radar-maroon .pace .pace-activity::before { border-color: #d81b60 transparent transparent; } .pace-center-simple-maroon .pace { background: #fff; border-color: #d81b60; } .pace-center-simple-maroon .pace .pace-progress { background: #d81b60; } .pace-material-maroon .pace { color: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity { background: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity::after, .pace-corner-indicator-maroon .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-maroon .pace .pace-activity::before { border-right-color: rgba(216, 27, 96, 0.2); border-left-color: rgba(216, 27, 96, 0.2); } .pace-corner-indicator-maroon .pace .pace-activity::after { border-top-color: rgba(216, 27, 96, 0.2); border-bottom-color: rgba(216, 27, 96, 0.2); } .pace-fill-left-maroon .pace .pace-progress { background-color: rgba(216, 27, 96, 0.2); } .pace-flash-maroon .pace .pace-progress { background: #d81b60; } .pace-flash-maroon .pace .pace-progress-inner { box-shadow: 0 0 10px #d81b60, 0 0 5px #d81b60; } .pace-flash-maroon .pace .pace-activity { border-top-color: #d81b60; border-left-color: #d81b60; } .pace-loading-bar-maroon .pace .pace-progress { background: #d81b60; color: #d81b60; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-maroon .pace .pace-activity { box-shadow: inset 0 0 0 2px #d81b60, inset 0 0 0 7px #fff; } .pace-mac-osx-maroon .pace .pace-progress { background-color: #d81b60; box-shadow: inset -1px 0 #d81b60, inset 0 -1px #d81b60, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-maroon .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-maroon .pace-progress { color: #d81b60; } .pace-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace { background: #fff; } .pace-barber-shop-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-blue .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-blue .pace .pace-activity { background: #007bff; } .pace-center-atom-blue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-blue .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-blue .pace-activity { border-color: #007bff; } .pace-center-atom-blue .pace-activity::after, .pace-center-atom-blue .pace-activity::before { border-color: #007bff; } .pace-center-circle-blue .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-blue .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-blue .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-blue .pace { background: #fff; border-color: #007bff; } .pace-center-simple-blue .pace .pace-progress { background: #007bff; } .pace-material-blue .pace { color: #007bff; } .pace-corner-indicator-blue .pace .pace-activity { background: #007bff; } .pace-corner-indicator-blue .pace .pace-activity::after, .pace-corner-indicator-blue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-blue .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-blue .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-blue .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-blue .pace .pace-progress { background: #007bff; } .pace-flash-blue .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-blue .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-blue .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-blue .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-blue .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-blue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-blue .pace-progress { color: #007bff; } .pace-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace { background: #fff; } .pace-barber-shop-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-indigo .pace .pace-progress::after { color: rgba(102, 16, 242, 0.2); } .pace-bounce-indigo .pace .pace-activity { background: #6610f2; } .pace-center-atom-indigo .pace-progress { height: 100px; width: 80px; } .pace-center-atom-indigo .pace-progress::before { background: #6610f2; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-indigo .pace-activity { border-color: #6610f2; } .pace-center-atom-indigo .pace-activity::after, .pace-center-atom-indigo .pace-activity::before { border-color: #6610f2; } .pace-center-circle-indigo .pace .pace-progress { background: rgba(102, 16, 242, 0.8); color: #fff; } .pace-center-radar-indigo .pace .pace-activity { border-color: #6610f2 transparent transparent; } .pace-center-radar-indigo .pace .pace-activity::before { border-color: #6610f2 transparent transparent; } .pace-center-simple-indigo .pace { background: #fff; border-color: #6610f2; } .pace-center-simple-indigo .pace .pace-progress { background: #6610f2; } .pace-material-indigo .pace { color: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity { background: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity::after, .pace-corner-indicator-indigo .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-indigo .pace .pace-activity::before { border-right-color: rgba(102, 16, 242, 0.2); border-left-color: rgba(102, 16, 242, 0.2); } .pace-corner-indicator-indigo .pace .pace-activity::after { border-top-color: rgba(102, 16, 242, 0.2); border-bottom-color: rgba(102, 16, 242, 0.2); } .pace-fill-left-indigo .pace .pace-progress { background-color: rgba(102, 16, 242, 0.2); } .pace-flash-indigo .pace .pace-progress { background: #6610f2; } .pace-flash-indigo .pace .pace-progress-inner { box-shadow: 0 0 10px #6610f2, 0 0 5px #6610f2; } .pace-flash-indigo .pace .pace-activity { border-top-color: #6610f2; border-left-color: #6610f2; } .pace-loading-bar-indigo .pace .pace-progress { background: #6610f2; color: #6610f2; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-indigo .pace .pace-activity { box-shadow: inset 0 0 0 2px #6610f2, inset 0 0 0 7px #fff; } .pace-mac-osx-indigo .pace .pace-progress { background-color: #6610f2; box-shadow: inset -1px 0 #6610f2, inset 0 -1px #6610f2, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-indigo .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-indigo .pace-progress { color: #6610f2; } .pace-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace { background: #fff; } .pace-barber-shop-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-purple .pace .pace-progress::after { color: rgba(111, 66, 193, 0.2); } .pace-bounce-purple .pace .pace-activity { background: #6f42c1; } .pace-center-atom-purple .pace-progress { height: 100px; width: 80px; } .pace-center-atom-purple .pace-progress::before { background: #6f42c1; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-purple .pace-activity { border-color: #6f42c1; } .pace-center-atom-purple .pace-activity::after, .pace-center-atom-purple .pace-activity::before { border-color: #6f42c1; } .pace-center-circle-purple .pace .pace-progress { background: rgba(111, 66, 193, 0.8); color: #fff; } .pace-center-radar-purple .pace .pace-activity { border-color: #6f42c1 transparent transparent; } .pace-center-radar-purple .pace .pace-activity::before { border-color: #6f42c1 transparent transparent; } .pace-center-simple-purple .pace { background: #fff; border-color: #6f42c1; } .pace-center-simple-purple .pace .pace-progress { background: #6f42c1; } .pace-material-purple .pace { color: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity { background: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity::after, .pace-corner-indicator-purple .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-purple .pace .pace-activity::before { border-right-color: rgba(111, 66, 193, 0.2); border-left-color: rgba(111, 66, 193, 0.2); } .pace-corner-indicator-purple .pace .pace-activity::after { border-top-color: rgba(111, 66, 193, 0.2); border-bottom-color: rgba(111, 66, 193, 0.2); } .pace-fill-left-purple .pace .pace-progress { background-color: rgba(111, 66, 193, 0.2); } .pace-flash-purple .pace .pace-progress { background: #6f42c1; } .pace-flash-purple .pace .pace-progress-inner { box-shadow: 0 0 10px #6f42c1, 0 0 5px #6f42c1; } .pace-flash-purple .pace .pace-activity { border-top-color: #6f42c1; border-left-color: #6f42c1; } .pace-loading-bar-purple .pace .pace-progress { background: #6f42c1; color: #6f42c1; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-purple .pace .pace-activity { box-shadow: inset 0 0 0 2px #6f42c1, inset 0 0 0 7px #fff; } .pace-mac-osx-purple .pace .pace-progress { background-color: #6f42c1; box-shadow: inset -1px 0 #6f42c1, inset 0 -1px #6f42c1, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-purple .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-purple .pace-progress { color: #6f42c1; } .pace-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace { background: #fff; } .pace-barber-shop-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-pink .pace .pace-progress::after { color: rgba(232, 62, 140, 0.2); } .pace-bounce-pink .pace .pace-activity { background: #e83e8c; } .pace-center-atom-pink .pace-progress { height: 100px; width: 80px; } .pace-center-atom-pink .pace-progress::before { background: #e83e8c; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-pink .pace-activity { border-color: #e83e8c; } .pace-center-atom-pink .pace-activity::after, .pace-center-atom-pink .pace-activity::before { border-color: #e83e8c; } .pace-center-circle-pink .pace .pace-progress { background: rgba(232, 62, 140, 0.8); color: #fff; } .pace-center-radar-pink .pace .pace-activity { border-color: #e83e8c transparent transparent; } .pace-center-radar-pink .pace .pace-activity::before { border-color: #e83e8c transparent transparent; } .pace-center-simple-pink .pace { background: #fff; border-color: #e83e8c; } .pace-center-simple-pink .pace .pace-progress { background: #e83e8c; } .pace-material-pink .pace { color: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity { background: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity::after, .pace-corner-indicator-pink .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-pink .pace .pace-activity::before { border-right-color: rgba(232, 62, 140, 0.2); border-left-color: rgba(232, 62, 140, 0.2); } .pace-corner-indicator-pink .pace .pace-activity::after { border-top-color: rgba(232, 62, 140, 0.2); border-bottom-color: rgba(232, 62, 140, 0.2); } .pace-fill-left-pink .pace .pace-progress { background-color: rgba(232, 62, 140, 0.2); } .pace-flash-pink .pace .pace-progress { background: #e83e8c; } .pace-flash-pink .pace .pace-progress-inner { box-shadow: 0 0 10px #e83e8c, 0 0 5px #e83e8c; } .pace-flash-pink .pace .pace-activity { border-top-color: #e83e8c; border-left-color: #e83e8c; } .pace-loading-bar-pink .pace .pace-progress { background: #e83e8c; color: #e83e8c; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-pink .pace .pace-activity { box-shadow: inset 0 0 0 2px #e83e8c, inset 0 0 0 7px #fff; } .pace-mac-osx-pink .pace .pace-progress { background-color: #e83e8c; box-shadow: inset -1px 0 #e83e8c, inset 0 -1px #e83e8c, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-pink .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-pink .pace-progress { color: #e83e8c; } .pace-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace { background: #fff; } .pace-barber-shop-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-red .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-red .pace .pace-activity { background: #dc3545; } .pace-center-atom-red .pace-progress { height: 100px; width: 80px; } .pace-center-atom-red .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-red .pace-activity { border-color: #dc3545; } .pace-center-atom-red .pace-activity::after, .pace-center-atom-red .pace-activity::before { border-color: #dc3545; } .pace-center-circle-red .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-red .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-red .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-red .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-red .pace .pace-progress { background: #dc3545; } .pace-material-red .pace { color: #dc3545; } .pace-corner-indicator-red .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-red .pace .pace-activity::after, .pace-corner-indicator-red .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-red .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-red .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-red .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-red .pace .pace-progress { background: #dc3545; } .pace-flash-red .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-red .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-red .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-red .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-red .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-red .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-red .pace-progress { color: #dc3545; } .pace-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace { background: #1f2d3d; } .pace-barber-shop-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-orange .pace .pace-progress::after { color: rgba(253, 126, 20, 0.2); } .pace-bounce-orange .pace .pace-activity { background: #fd7e14; } .pace-center-atom-orange .pace-progress { height: 100px; width: 80px; } .pace-center-atom-orange .pace-progress::before { background: #fd7e14; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-orange .pace-activity { border-color: #fd7e14; } .pace-center-atom-orange .pace-activity::after, .pace-center-atom-orange .pace-activity::before { border-color: #fd7e14; } .pace-center-circle-orange .pace .pace-progress { background: rgba(253, 126, 20, 0.8); color: #1f2d3d; } .pace-center-radar-orange .pace .pace-activity { border-color: #fd7e14 transparent transparent; } .pace-center-radar-orange .pace .pace-activity::before { border-color: #fd7e14 transparent transparent; } .pace-center-simple-orange .pace { background: #1f2d3d; border-color: #fd7e14; } .pace-center-simple-orange .pace .pace-progress { background: #fd7e14; } .pace-material-orange .pace { color: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity { background: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity::after, .pace-corner-indicator-orange .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-orange .pace .pace-activity::before { border-right-color: rgba(253, 126, 20, 0.2); border-left-color: rgba(253, 126, 20, 0.2); } .pace-corner-indicator-orange .pace .pace-activity::after { border-top-color: rgba(253, 126, 20, 0.2); border-bottom-color: rgba(253, 126, 20, 0.2); } .pace-fill-left-orange .pace .pace-progress { background-color: rgba(253, 126, 20, 0.2); } .pace-flash-orange .pace .pace-progress { background: #fd7e14; } .pace-flash-orange .pace .pace-progress-inner { box-shadow: 0 0 10px #fd7e14, 0 0 5px #fd7e14; } .pace-flash-orange .pace .pace-activity { border-top-color: #fd7e14; border-left-color: #fd7e14; } .pace-loading-bar-orange .pace .pace-progress { background: #fd7e14; color: #fd7e14; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-orange .pace .pace-activity { box-shadow: inset 0 0 0 2px #fd7e14, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-orange .pace .pace-progress { background-color: #fd7e14; box-shadow: inset -1px 0 #fd7e14, inset 0 -1px #fd7e14, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-orange .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-orange .pace-progress { color: #fd7e14; } .pace-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace { background: #1f2d3d; } .pace-barber-shop-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-yellow .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-yellow .pace .pace-activity { background: #ffc107; } .pace-center-atom-yellow .pace-progress { height: 100px; width: 80px; } .pace-center-atom-yellow .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-yellow .pace-activity { border-color: #ffc107; } .pace-center-atom-yellow .pace-activity::after, .pace-center-atom-yellow .pace-activity::before { border-color: #ffc107; } .pace-center-circle-yellow .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-yellow .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-yellow .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-yellow .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-yellow .pace .pace-progress { background: #ffc107; } .pace-material-yellow .pace { color: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity::after, .pace-corner-indicator-yellow .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-yellow .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-yellow .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-yellow .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-yellow .pace .pace-progress { background: #ffc107; } .pace-flash-yellow .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-yellow .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-yellow .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-yellow .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-yellow .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-yellow .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-yellow .pace-progress { color: #ffc107; } .pace-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace { background: #fff; } .pace-barber-shop-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-green .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-green .pace .pace-activity { background: #28a745; } .pace-center-atom-green .pace-progress { height: 100px; width: 80px; } .pace-center-atom-green .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-green .pace-activity { border-color: #28a745; } .pace-center-atom-green .pace-activity::after, .pace-center-atom-green .pace-activity::before { border-color: #28a745; } .pace-center-circle-green .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-green .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-green .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-green .pace { background: #fff; border-color: #28a745; } .pace-center-simple-green .pace .pace-progress { background: #28a745; } .pace-material-green .pace { color: #28a745; } .pace-corner-indicator-green .pace .pace-activity { background: #28a745; } .pace-corner-indicator-green .pace .pace-activity::after, .pace-corner-indicator-green .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-green .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-green .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-green .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-green .pace .pace-progress { background: #28a745; } .pace-flash-green .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-green .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-green .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-green .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-green .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-green .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-green .pace-progress { color: #28a745; } .pace-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace { background: #fff; } .pace-barber-shop-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-teal .pace .pace-progress::after { color: rgba(32, 201, 151, 0.2); } .pace-bounce-teal .pace .pace-activity { background: #20c997; } .pace-center-atom-teal .pace-progress { height: 100px; width: 80px; } .pace-center-atom-teal .pace-progress::before { background: #20c997; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-teal .pace-activity { border-color: #20c997; } .pace-center-atom-teal .pace-activity::after, .pace-center-atom-teal .pace-activity::before { border-color: #20c997; } .pace-center-circle-teal .pace .pace-progress { background: rgba(32, 201, 151, 0.8); color: #fff; } .pace-center-radar-teal .pace .pace-activity { border-color: #20c997 transparent transparent; } .pace-center-radar-teal .pace .pace-activity::before { border-color: #20c997 transparent transparent; } .pace-center-simple-teal .pace { background: #fff; border-color: #20c997; } .pace-center-simple-teal .pace .pace-progress { background: #20c997; } .pace-material-teal .pace { color: #20c997; } .pace-corner-indicator-teal .pace .pace-activity { background: #20c997; } .pace-corner-indicator-teal .pace .pace-activity::after, .pace-corner-indicator-teal .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-teal .pace .pace-activity::before { border-right-color: rgba(32, 201, 151, 0.2); border-left-color: rgba(32, 201, 151, 0.2); } .pace-corner-indicator-teal .pace .pace-activity::after { border-top-color: rgba(32, 201, 151, 0.2); border-bottom-color: rgba(32, 201, 151, 0.2); } .pace-fill-left-teal .pace .pace-progress { background-color: rgba(32, 201, 151, 0.2); } .pace-flash-teal .pace .pace-progress { background: #20c997; } .pace-flash-teal .pace .pace-progress-inner { box-shadow: 0 0 10px #20c997, 0 0 5px #20c997; } .pace-flash-teal .pace .pace-activity { border-top-color: #20c997; border-left-color: #20c997; } .pace-loading-bar-teal .pace .pace-progress { background: #20c997; color: #20c997; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-teal .pace .pace-activity { box-shadow: inset 0 0 0 2px #20c997, inset 0 0 0 7px #fff; } .pace-mac-osx-teal .pace .pace-progress { background-color: #20c997; box-shadow: inset -1px 0 #20c997, inset 0 -1px #20c997, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-teal .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-teal .pace-progress { color: #20c997; } .pace-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace { background: #fff; } .pace-barber-shop-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-cyan .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-cyan .pace .pace-activity { background: #17a2b8; } .pace-center-atom-cyan .pace-progress { height: 100px; width: 80px; } .pace-center-atom-cyan .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-cyan .pace-activity { border-color: #17a2b8; } .pace-center-atom-cyan .pace-activity::after, .pace-center-atom-cyan .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-cyan .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-cyan .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-cyan .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-cyan .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-cyan .pace .pace-progress { background: #17a2b8; } .pace-material-cyan .pace { color: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity::after, .pace-corner-indicator-cyan .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-cyan .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-cyan .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-cyan .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-cyan .pace .pace-progress { background: #17a2b8; } .pace-flash-cyan .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-cyan .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-cyan .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-cyan .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-cyan .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-cyan .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-cyan .pace-progress { color: #17a2b8; } .pace-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace { background: #1f2d3d; } .pace-barber-shop-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-white .pace .pace-progress::after { color: rgba(255, 255, 255, 0.2); } .pace-bounce-white .pace .pace-activity { background: #fff; } .pace-center-atom-white .pace-progress { height: 100px; width: 80px; } .pace-center-atom-white .pace-progress::before { background: #fff; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-white .pace-activity { border-color: #fff; } .pace-center-atom-white .pace-activity::after, .pace-center-atom-white .pace-activity::before { border-color: #fff; } .pace-center-circle-white .pace .pace-progress { background: rgba(255, 255, 255, 0.8); color: #1f2d3d; } .pace-center-radar-white .pace .pace-activity { border-color: #fff transparent transparent; } .pace-center-radar-white .pace .pace-activity::before { border-color: #fff transparent transparent; } .pace-center-simple-white .pace { background: #1f2d3d; border-color: #fff; } .pace-center-simple-white .pace .pace-progress { background: #fff; } .pace-material-white .pace { color: #fff; } .pace-corner-indicator-white .pace .pace-activity { background: #fff; } .pace-corner-indicator-white .pace .pace-activity::after, .pace-corner-indicator-white .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-white .pace .pace-activity::before { border-right-color: rgba(255, 255, 255, 0.2); border-left-color: rgba(255, 255, 255, 0.2); } .pace-corner-indicator-white .pace .pace-activity::after { border-top-color: rgba(255, 255, 255, 0.2); border-bottom-color: rgba(255, 255, 255, 0.2); } .pace-fill-left-white .pace .pace-progress { background-color: rgba(255, 255, 255, 0.2); } .pace-flash-white .pace .pace-progress { background: #fff; } .pace-flash-white .pace .pace-progress-inner { box-shadow: 0 0 10px #fff, 0 0 5px #fff; } .pace-flash-white .pace .pace-activity { border-top-color: #fff; border-left-color: #fff; } .pace-loading-bar-white .pace .pace-progress { background: #fff; color: #fff; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-white .pace .pace-activity { box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-white .pace .pace-progress { background-color: #fff; box-shadow: inset -1px 0 #fff, inset 0 -1px #fff, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-white .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-white .pace-progress { color: #fff; } .pace-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace { background: #fff; } .pace-barber-shop-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-gray .pace .pace-activity { background: #6c757d; } .pace-center-atom-gray .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray .pace-activity { border-color: #6c757d; } .pace-center-atom-gray .pace-activity::after, .pace-center-atom-gray .pace-activity::before { border-color: #6c757d; } .pace-center-circle-gray .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-gray .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-gray .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-gray .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-gray .pace .pace-progress { background: #6c757d; } .pace-material-gray .pace { color: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity::after, .pace-corner-indicator-gray .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-gray .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-gray .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-gray .pace .pace-progress { background: #6c757d; } .pace-flash-gray .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-gray .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-gray .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-gray .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray .pace-progress { color: #6c757d; } .pace-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace { background: #fff; } .pace-barber-shop-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-gray-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-gray-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray-dark .pace-activity { border-color: #343a40; } .pace-center-atom-gray-dark .pace-activity::after, .pace-center-atom-gray-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-gray-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-gray-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-gray-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-gray-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-gray-dark .pace .pace-progress { background: #343a40; } .pace-material-gray-dark .pace { color: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity::after, .pace-corner-indicator-gray-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-gray-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-gray-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-gray-dark .pace .pace-progress { background: #343a40; } .pace-flash-gray-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-gray-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-gray-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-gray-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray-dark .pace-progress { color: #343a40; } /** * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. * * @version v3.4 (MODDED) * @homepage https://bttstrp.github.io/bootstrap-switch * @author Mattia Larentis (http://larentis.eu) * @license MIT */ .bootstrap-switch { border: 1px solid #ced4da; border-radius: 0.25rem; cursor: pointer; direction: ltr; display: inline-block; line-height: .5rem; overflow: hidden; position: relative; text-align: left; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; vertical-align: middle; z-index: 0; } .bootstrap-switch .bootstrap-switch-container { border-radius: 0.25rem; display: inline-block; top: 0; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .bootstrap-switch:focus-within { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off, .bootstrap-switch .bootstrap-switch-label { box-sizing: border-box; cursor: pointer; display: table-cell; font-size: 1rem; font-weight: 500; line-height: 1.2rem; padding: .25rem .5rem; vertical-align: middle; } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off { text-align: center; z-index: 1; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default { background: #e9ecef; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-secondary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-secondary { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-light, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-light { background: #f8f9fa; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lightblue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lightblue { background: #3c8dbc; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-navy, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-navy { background: #001f3f; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-olive, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-olive { background: #3d9970; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lime, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lime { background: #01ff70; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-fuchsia, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-fuchsia { background: #f012be; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-maroon, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-maroon { background: #d81b60; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-indigo, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-indigo { background: #6610f2; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-purple, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-purple { background: #6f42c1; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-pink, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-pink { background: #e83e8c; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange { background: #fd7e14; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-yellow, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-yellow { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-teal, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-teal { background: #20c997; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-cyan, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-cyan { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-white, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-white { background: #fff; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .bootstrap-switch .bootstrap-switch-handle-off { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch input[type='radio'], .bootstrap-switch input[type='checkbox'] { filter: alpha(opacity=0); left: 0; margin: 0; opacity: 0; position: absolute; top: 0; visibility: hidden; z-index: -1; } .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .1rem .3rem; } .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .2rem .4rem; } .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label { font-size: 1.25rem; line-height: 1.3333333rem; padding: .3rem .5rem; } .bootstrap-switch.bootstrap-switch-disabled, .bootstrap-switch.bootstrap-switch-readonly, .bootstrap-switch.bootstrap-switch-indeterminate { cursor: default; } .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label { cursor: default; filter: alpha(opacity=50); opacity: .5; } .bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container { transition: margin-left .5s; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on { border-radius: 0 0.1rem 0.1rem 0; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off { border-radius: 0.1rem 0 0 0.1rem; } .bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .dark-mode .bootstrap-switch { border-color: #6c757d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default, .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default { background-color: #3a4047; color: #fff; border-color: #454d55; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { background: #3f6791; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-secondary, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-secondary { background: #6c757d; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { background: #00bc8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { background: #3498db; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { background: #f39c12; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { background: #e74c3c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-light, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-light { background: #f8f9fa; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-dark, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-dark { background: #343a40; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lightblue, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lightblue { background: #86bad8; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-navy, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-navy { background: #002c59; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-olive, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-olive { background: #74c8a3; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lime, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lime { background: #67ffa9; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-fuchsia, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-fuchsia { background: #f672d8; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-maroon, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-maroon { background: #ed6c9b; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue { background: #3f6791; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-indigo, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-indigo { background: #6610f2; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-purple, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-purple { background: #6f42c1; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-pink, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-pink { background: #e83e8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red { background: #e74c3c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange { background: #fd7e14; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-yellow, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-yellow { background: #f39c12; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green { background: #00bc8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-teal, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-teal { background: #20c997; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-cyan, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-cyan { background: #3498db; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-white, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-white { background: #fff; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray { background: #6c757d; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray-dark, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray-dark { background: #343a40; color: #fff; } .dark-mode .daterangepicker { background-color: #3f474e; border: inherit; } .dark-mode .daterangepicker::before, .dark-mode .daterangepicker::after { border-bottom-color: #3f474e; } .dark-mode .daterangepicker td.available:hover, .dark-mode .daterangepicker th.available:hover { background-color: #3f474e; } .dark-mode .daterangepicker td.in-range { background-color: #4b545c; color: #fff; } .dark-mode .daterangepicker td.off, .dark-mode .daterangepicker td.off.in-range, .dark-mode .daterangepicker td.off.start-date, .dark-mode .daterangepicker td.off.end-date { background-color: #292d32; color: #fff; } .dark-mode .daterangepicker .ranges li:hover { background-color: #343a40; } .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar { border-color: #4b545c; } .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar.left, .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar.right { border-color: #4b545c; padding-top: 0; } .dark-mode .daterangepicker .drp-buttons { border-color: #4b545c; } .dark-mode .daterangepicker .calendar-table { background-color: #343a40; border-color: #4b545c; } .dark-mode .daterangepicker .calendar-table th, .dark-mode .daterangepicker .calendar-table td { color: #fff; } .dark-mode .daterangepicker .calendar-table .next span, .dark-mode .daterangepicker .calendar-table .prev span { border-color: #fff; } .dark-mode .daterangepicker select.hourselect, .dark-mode .daterangepicker select.minuteselect, .dark-mode .daterangepicker select.secondselect, .dark-mode .daterangepicker select.ampmselect { background-color: #343a40; border-color: #4b545c; } .jqstooltip { height: auto !important; padding: 5px !important; width: auto !important; } .connectedSortable { min-height: 100px; } .ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .sort-highlight { background: #f8f9fa; border: 1px dashed #dee2e6; margin-bottom: 10px; } .chart { overflow: hidden; position: relative; } .dark-mode .irs--flat .irs-line { background-color: #4b545c; } .dark-mode .jsgrid-edit-row > .jsgrid-cell, .dark-mode .jsgrid-filter-row > .jsgrid-cell, .dark-mode .jsgrid-grid-body, .dark-mode .jsgrid-grid-header, .dark-mode .jsgrid-header-row > .jsgrid-header-cell, .dark-mode .jsgrid-insert-row > .jsgrid-cell, .dark-mode .jsgrid-row > .jsgrid-cell, .dark-mode .jsgrid-alt-row > .jsgrid-cell { border-color: #6c757d; } .dark-mode .jsgrid-header-row > .jsgrid-header-cell, .dark-mode .jsgrid-row > .jsgrid-cell { background-color: #343a40; } .dark-mode .jsgrid-alt-row > .jsgrid-cell { background-color: #3a4047; } .dark-mode .jsgrid-selected-row > .jsgrid-cell { background-color: #3f474e; } .border-transparent { border-color: transparent !important; } .description-block { display: block; margin: 10px 0; text-align: center; } .description-block.margin-bottom { margin-bottom: 25px; } .description-block > .description-header { font-size: 16px; font-weight: 600; margin: 0; padding: 0; } .description-block > .description-text { text-transform: uppercase; } .description-block .description-icon { font-size: 16px; } .list-group-unbordered > .list-group-item { border-left: 0; border-radius: 0; border-right: 0; padding-left: 0; padding-right: 0; } .list-header { color: #6c757d; font-size: 15px; font-weight: 700; padding: 10px 4px; } .list-seperator { background-color: rgba(0, 0, 0, 0.125); height: 1px; margin: 15px 0 9px; } .list-link > a { color: #6c757d; padding: 4px; } .list-link > a:hover { color: #212529; } .user-block { float: left; } .user-block img { float: left; height: 40px; width: 40px; } .user-block .username, .user-block .description, .user-block .comment { display: block; margin-left: 50px; } .user-block .username { font-size: 16px; font-weight: 600; margin-top: -1px; } .user-block .description { color: #6c757d; font-size: 13px; margin-top: -3px; } .user-block.user-block-sm img { width: 1.875rem; height: 1.875rem; } .user-block.user-block-sm .username, .user-block.user-block-sm .description, .user-block.user-block-sm .comment { margin-left: 40px; } .user-block.user-block-sm .username { font-size: 14px; } .img-sm, .img-md, .img-lg { float: left; } .img-sm { height: 1.875rem; width: 1.875rem; } .img-sm + .img-push { margin-left: 2.5rem; } .img-md { width: 3.75rem; height: 3.75rem; } .img-md + .img-push { margin-left: 4.375rem; } .img-lg { width: 6.25rem; height: 6.25rem; } .img-lg + .img-push { margin-left: 6.875rem; } .img-bordered { border: 3px solid #adb5bd; padding: 3px; } .img-bordered-sm { border: 2px solid #adb5bd; padding: 2px; } .img-rounded { border-radius: 0.25rem; } .img-circle { border-radius: 50%; } .img-size-64, .img-size-50, .img-size-32 { height: auto; } .img-size-64 { width: 64px; } .img-size-50 { width: 50px; } .img-size-32 { width: 32px; } .size-32, .size-40, .size-50 { display: block; text-align: center; } .size-32 { height: 32px; line-height: 32px; width: 32px; } .size-40 { height: 40px; line-height: 40px; width: 40px; } .size-50 { height: 50px; line-height: 50px; width: 50px; } .attachment-block { background-color: #f8f9fa; border: 1px solid rgba(0, 0, 0, 0.125); margin-bottom: 10px; padding: 5px; } .attachment-block .attachment-img { float: left; height: auto; max-height: 100px; max-width: 100px; } .attachment-block .attachment-pushed { margin-left: 110px; } .attachment-block .attachment-heading { margin: 0; } .attachment-block .attachment-text { color: #495057; } .card > .overlay, .card > .loading-img, .overlay-wrapper > .overlay, .overlay-wrapper > .loading-img, .info-box > .overlay, .info-box > .loading-img, .small-box > .overlay, .small-box > .loading-img { height: 100%; left: 0; position: absolute; top: 0; width: 100%; } .card .overlay, .overlay-wrapper .overlay, .info-box .overlay, .small-box .overlay { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; background-color: rgba(255, 255, 255, 0.7); display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; z-index: 50; } .card .overlay > .fa, .card .overlay > .fas, .card .overlay > .far, .card .overlay > .fab, .card .overlay > .fal, .card .overlay > .fad, .card .overlay > .svg-inline--fa, .card .overlay > .ion, .overlay-wrapper .overlay > .fa, .overlay-wrapper .overlay > .fas, .overlay-wrapper .overlay > .far, .overlay-wrapper .overlay > .fab, .overlay-wrapper .overlay > .fal, .overlay-wrapper .overlay > .fad, .overlay-wrapper .overlay > .svg-inline--fa, .overlay-wrapper .overlay > .ion, .info-box .overlay > .fa, .info-box .overlay > .fas, .info-box .overlay > .far, .info-box .overlay > .fab, .info-box .overlay > .fal, .info-box .overlay > .fad, .info-box .overlay > .svg-inline--fa, .info-box .overlay > .ion, .small-box .overlay > .fa, .small-box .overlay > .fas, .small-box .overlay > .far, .small-box .overlay > .fab, .small-box .overlay > .fal, .small-box .overlay > .fad, .small-box .overlay > .svg-inline--fa, .small-box .overlay > .ion { color: #343a40; } .card .overlay.dark, .overlay-wrapper .overlay.dark, .info-box .overlay.dark, .small-box .overlay.dark { background-color: rgba(0, 0, 0, 0.5); } .card .overlay.dark > .fa, .card .overlay.dark > .fas, .card .overlay.dark > .far, .card .overlay.dark > .fab, .card .overlay.dark > .fal, .card .overlay.dark > .fad, .card .overlay.dark > .svg-inline--fa, .card .overlay.dark > .ion, .overlay-wrapper .overlay.dark > .fa, .overlay-wrapper .overlay.dark > .fas, .overlay-wrapper .overlay.dark > .far, .overlay-wrapper .overlay.dark > .fab, .overlay-wrapper .overlay.dark > .fal, .overlay-wrapper .overlay.dark > .fad, .overlay-wrapper .overlay.dark > .svg-inline--fa, .overlay-wrapper .overlay.dark > .ion, .info-box .overlay.dark > .fa, .info-box .overlay.dark > .fas, .info-box .overlay.dark > .far, .info-box .overlay.dark > .fab, .info-box .overlay.dark > .fal, .info-box .overlay.dark > .fad, .info-box .overlay.dark > .svg-inline--fa, .info-box .overlay.dark > .ion, .small-box .overlay.dark > .fa, .small-box .overlay.dark > .fas, .small-box .overlay.dark > .far, .small-box .overlay.dark > .fab, .small-box .overlay.dark > .fal, .small-box .overlay.dark > .fad, .small-box .overlay.dark > .svg-inline--fa, .small-box .overlay.dark > .ion { color: #ced4da; } .tab-pane > .overlay-wrapper { position: relative; } .tab-pane > .overlay-wrapper > .overlay { border-top-left-radius: 0; border-top-right-radius: 0; -ms-flex-direction: column; flex-direction: column; margin-top: -1.25rem; margin-left: -1.25rem; height: calc(100% + 2 * 1.25rem); width: calc(100% + 2 * 1.25rem); } .tab-pane > .overlay-wrapper > .overlay.dark { color: #fff; } .ribbon-wrapper { height: 70px; overflow: hidden; position: absolute; right: -2px; top: -2px; width: 70px; z-index: 10; } .ribbon-wrapper.ribbon-lg { height: 120px; width: 120px; } .ribbon-wrapper.ribbon-lg .ribbon { right: 0; top: 26px; width: 160px; } .ribbon-wrapper.ribbon-xl { height: 180px; width: 180px; } .ribbon-wrapper.ribbon-xl .ribbon { right: 4px; top: 47px; width: 240px; } .ribbon-wrapper .ribbon { box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); font-size: 0.8rem; line-height: 100%; padding: 0.375rem 0; position: relative; right: -2px; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); text-transform: uppercase; top: 10px; -webkit-transform: rotate(45deg); transform: rotate(45deg); width: 90px; } .ribbon-wrapper .ribbon::before, .ribbon-wrapper .ribbon::after { border-left: 3px solid transparent; border-right: 3px solid transparent; border-top: 3px solid #9e9e9e; bottom: -3px; content: ""; position: absolute; } .ribbon-wrapper .ribbon::before { left: 0; } .ribbon-wrapper .ribbon::after { right: 0; } .back-to-top { bottom: 1.25rem; position: fixed; right: 1.25rem; z-index: 1032; } .back-to-top:focus { box-shadow: none; } pre { padding: .75rem; } blockquote { background-color: #fff; border-left: 0.7rem solid #007bff; margin: 1.5em .7rem; padding: .5em .7rem; } .box blockquote { background-color: #e9ecef; } blockquote p:last-child { margin-bottom: 0; } blockquote h1, blockquote h2, blockquote h3, blockquote h4, blockquote h5, blockquote h6 { color: #007bff; font-size: 1.25rem; font-weight: 600; } blockquote.quote-primary { border-color: #007bff; } blockquote.quote-primary h1, blockquote.quote-primary h2, blockquote.quote-primary h3, blockquote.quote-primary h4, blockquote.quote-primary h5, blockquote.quote-primary h6 { color: #007bff; } blockquote.quote-secondary { border-color: #6c757d; } blockquote.quote-secondary h1, blockquote.quote-secondary h2, blockquote.quote-secondary h3, blockquote.quote-secondary h4, blockquote.quote-secondary h5, blockquote.quote-secondary h6 { color: #6c757d; } blockquote.quote-success { border-color: #28a745; } blockquote.quote-success h1, blockquote.quote-success h2, blockquote.quote-success h3, blockquote.quote-success h4, blockquote.quote-success h5, blockquote.quote-success h6 { color: #28a745; } blockquote.quote-info { border-color: #17a2b8; } blockquote.quote-info h1, blockquote.quote-info h2, blockquote.quote-info h3, blockquote.quote-info h4, blockquote.quote-info h5, blockquote.quote-info h6 { color: #17a2b8; } blockquote.quote-warning { border-color: #ffc107; } blockquote.quote-warning h1, blockquote.quote-warning h2, blockquote.quote-warning h3, blockquote.quote-warning h4, blockquote.quote-warning h5, blockquote.quote-warning h6 { color: #ffc107; } blockquote.quote-danger { border-color: #dc3545; } blockquote.quote-danger h1, blockquote.quote-danger h2, blockquote.quote-danger h3, blockquote.quote-danger h4, blockquote.quote-danger h5, blockquote.quote-danger h6 { color: #dc3545; } blockquote.quote-light { border-color: #f8f9fa; } blockquote.quote-light h1, blockquote.quote-light h2, blockquote.quote-light h3, blockquote.quote-light h4, blockquote.quote-light h5, blockquote.quote-light h6 { color: #f8f9fa; } blockquote.quote-dark { border-color: #343a40; } blockquote.quote-dark h1, blockquote.quote-dark h2, blockquote.quote-dark h3, blockquote.quote-dark h4, blockquote.quote-dark h5, blockquote.quote-dark h6 { color: #343a40; } blockquote.quote-lightblue { border-color: #3c8dbc; } blockquote.quote-lightblue h1, blockquote.quote-lightblue h2, blockquote.quote-lightblue h3, blockquote.quote-lightblue h4, blockquote.quote-lightblue h5, blockquote.quote-lightblue h6 { color: #3c8dbc; } blockquote.quote-navy { border-color: #001f3f; } blockquote.quote-navy h1, blockquote.quote-navy h2, blockquote.quote-navy h3, blockquote.quote-navy h4, blockquote.quote-navy h5, blockquote.quote-navy h6 { color: #001f3f; } blockquote.quote-olive { border-color: #3d9970; } blockquote.quote-olive h1, blockquote.quote-olive h2, blockquote.quote-olive h3, blockquote.quote-olive h4, blockquote.quote-olive h5, blockquote.quote-olive h6 { color: #3d9970; } blockquote.quote-lime { border-color: #01ff70; } blockquote.quote-lime h1, blockquote.quote-lime h2, blockquote.quote-lime h3, blockquote.quote-lime h4, blockquote.quote-lime h5, blockquote.quote-lime h6 { color: #01ff70; } blockquote.quote-fuchsia { border-color: #f012be; } blockquote.quote-fuchsia h1, blockquote.quote-fuchsia h2, blockquote.quote-fuchsia h3, blockquote.quote-fuchsia h4, blockquote.quote-fuchsia h5, blockquote.quote-fuchsia h6 { color: #f012be; } blockquote.quote-maroon { border-color: #d81b60; } blockquote.quote-maroon h1, blockquote.quote-maroon h2, blockquote.quote-maroon h3, blockquote.quote-maroon h4, blockquote.quote-maroon h5, blockquote.quote-maroon h6 { color: #d81b60; } blockquote.quote-blue { border-color: #007bff; } blockquote.quote-blue h1, blockquote.quote-blue h2, blockquote.quote-blue h3, blockquote.quote-blue h4, blockquote.quote-blue h5, blockquote.quote-blue h6 { color: #007bff; } blockquote.quote-indigo { border-color: #6610f2; } blockquote.quote-indigo h1, blockquote.quote-indigo h2, blockquote.quote-indigo h3, blockquote.quote-indigo h4, blockquote.quote-indigo h5, blockquote.quote-indigo h6 { color: #6610f2; } blockquote.quote-purple { border-color: #6f42c1; } blockquote.quote-purple h1, blockquote.quote-purple h2, blockquote.quote-purple h3, blockquote.quote-purple h4, blockquote.quote-purple h5, blockquote.quote-purple h6 { color: #6f42c1; } blockquote.quote-pink { border-color: #e83e8c; } blockquote.quote-pink h1, blockquote.quote-pink h2, blockquote.quote-pink h3, blockquote.quote-pink h4, blockquote.quote-pink h5, blockquote.quote-pink h6 { color: #e83e8c; } blockquote.quote-red { border-color: #dc3545; } blockquote.quote-red h1, blockquote.quote-red h2, blockquote.quote-red h3, blockquote.quote-red h4, blockquote.quote-red h5, blockquote.quote-red h6 { color: #dc3545; } blockquote.quote-orange { border-color: #fd7e14; } blockquote.quote-orange h1, blockquote.quote-orange h2, blockquote.quote-orange h3, blockquote.quote-orange h4, blockquote.quote-orange h5, blockquote.quote-orange h6 { color: #fd7e14; } blockquote.quote-yellow { border-color: #ffc107; } blockquote.quote-yellow h1, blockquote.quote-yellow h2, blockquote.quote-yellow h3, blockquote.quote-yellow h4, blockquote.quote-yellow h5, blockquote.quote-yellow h6 { color: #ffc107; } blockquote.quote-green { border-color: #28a745; } blockquote.quote-green h1, blockquote.quote-green h2, blockquote.quote-green h3, blockquote.quote-green h4, blockquote.quote-green h5, blockquote.quote-green h6 { color: #28a745; } blockquote.quote-teal { border-color: #20c997; } blockquote.quote-teal h1, blockquote.quote-teal h2, blockquote.quote-teal h3, blockquote.quote-teal h4, blockquote.quote-teal h5, blockquote.quote-teal h6 { color: #20c997; } blockquote.quote-cyan { border-color: #17a2b8; } blockquote.quote-cyan h1, blockquote.quote-cyan h2, blockquote.quote-cyan h3, blockquote.quote-cyan h4, blockquote.quote-cyan h5, blockquote.quote-cyan h6 { color: #17a2b8; } blockquote.quote-white { border-color: #fff; } blockquote.quote-white h1, blockquote.quote-white h2, blockquote.quote-white h3, blockquote.quote-white h4, blockquote.quote-white h5, blockquote.quote-white h6 { color: #fff; } blockquote.quote-gray { border-color: #6c757d; } blockquote.quote-gray h1, blockquote.quote-gray h2, blockquote.quote-gray h3, blockquote.quote-gray h4, blockquote.quote-gray h5, blockquote.quote-gray h6 { color: #6c757d; } blockquote.quote-gray-dark { border-color: #343a40; } blockquote.quote-gray-dark h1, blockquote.quote-gray-dark h2, blockquote.quote-gray-dark h3, blockquote.quote-gray-dark h4, blockquote.quote-gray-dark h5, blockquote.quote-gray-dark h6 { color: #343a40; } .tab-custom-content { border-top: 1px solid #dee2e6; margin-top: .5rem; padding-top: .5rem; } .nav + .tab-custom-content { border-top: none; border-bottom: 1px solid #dee2e6; margin-top: 0; margin-bottom: .5rem; padding-bottom: .5rem; } .badge-btn { border-radius: 0.15rem; font-size: 0.75rem; font-weight: 400; padding: 0.25rem 0.5rem; } .badge-btn.badge-pill { padding: .375rem .6rem; } .dark-mode a:not(.btn):hover { color: #3395ff; } .dark-mode .attachment-block { background-color: #3d444b; } .dark-mode .attachment-block .attachment-text { color: #ced4da; } .dark-mode blockquote { background-color: #3f474e; } .dark-mode blockquote.quote-primary { border-color: #007bff; } .dark-mode blockquote.quote-primary h1, .dark-mode blockquote.quote-primary h2, .dark-mode blockquote.quote-primary h3, .dark-mode blockquote.quote-primary h4, .dark-mode blockquote.quote-primary h5, .dark-mode blockquote.quote-primary h6 { color: #007bff; } .dark-mode blockquote.quote-secondary { border-color: #6c757d; } .dark-mode blockquote.quote-secondary h1, .dark-mode blockquote.quote-secondary h2, .dark-mode blockquote.quote-secondary h3, .dark-mode blockquote.quote-secondary h4, .dark-mode blockquote.quote-secondary h5, .dark-mode blockquote.quote-secondary h6 { color: #6c757d; } .dark-mode blockquote.quote-success { border-color: #28a745; } .dark-mode blockquote.quote-success h1, .dark-mode blockquote.quote-success h2, .dark-mode blockquote.quote-success h3, .dark-mode blockquote.quote-success h4, .dark-mode blockquote.quote-success h5, .dark-mode blockquote.quote-success h6 { color: #28a745; } .dark-mode blockquote.quote-info { border-color: #17a2b8; } .dark-mode blockquote.quote-info h1, .dark-mode blockquote.quote-info h2, .dark-mode blockquote.quote-info h3, .dark-mode blockquote.quote-info h4, .dark-mode blockquote.quote-info h5, .dark-mode blockquote.quote-info h6 { color: #17a2b8; } .dark-mode blockquote.quote-warning { border-color: #ffc107; } .dark-mode blockquote.quote-warning h1, .dark-mode blockquote.quote-warning h2, .dark-mode blockquote.quote-warning h3, .dark-mode blockquote.quote-warning h4, .dark-mode blockquote.quote-warning h5, .dark-mode blockquote.quote-warning h6 { color: #ffc107; } .dark-mode blockquote.quote-danger { border-color: #dc3545; } .dark-mode blockquote.quote-danger h1, .dark-mode blockquote.quote-danger h2, .dark-mode blockquote.quote-danger h3, .dark-mode blockquote.quote-danger h4, .dark-mode blockquote.quote-danger h5, .dark-mode blockquote.quote-danger h6 { color: #dc3545; } .dark-mode blockquote.quote-light { border-color: #f8f9fa; } .dark-mode blockquote.quote-light h1, .dark-mode blockquote.quote-light h2, .dark-mode blockquote.quote-light h3, .dark-mode blockquote.quote-light h4, .dark-mode blockquote.quote-light h5, .dark-mode blockquote.quote-light h6 { color: #f8f9fa; } .dark-mode blockquote.quote-dark { border-color: #343a40; } .dark-mode blockquote.quote-dark h1, .dark-mode blockquote.quote-dark h2, .dark-mode blockquote.quote-dark h3, .dark-mode blockquote.quote-dark h4, .dark-mode blockquote.quote-dark h5, .dark-mode blockquote.quote-dark h6 { color: #343a40; } .dark-mode blockquote.quote-lightblue { border-color: #3c8dbc; } .dark-mode blockquote.quote-lightblue h1, .dark-mode blockquote.quote-lightblue h2, .dark-mode blockquote.quote-lightblue h3, .dark-mode blockquote.quote-lightblue h4, .dark-mode blockquote.quote-lightblue h5, .dark-mode blockquote.quote-lightblue h6 { color: #3c8dbc; } .dark-mode blockquote.quote-navy { border-color: #001f3f; } .dark-mode blockquote.quote-navy h1, .dark-mode blockquote.quote-navy h2, .dark-mode blockquote.quote-navy h3, .dark-mode blockquote.quote-navy h4, .dark-mode blockquote.quote-navy h5, .dark-mode blockquote.quote-navy h6 { color: #001f3f; } .dark-mode blockquote.quote-olive { border-color: #3d9970; } .dark-mode blockquote.quote-olive h1, .dark-mode blockquote.quote-olive h2, .dark-mode blockquote.quote-olive h3, .dark-mode blockquote.quote-olive h4, .dark-mode blockquote.quote-olive h5, .dark-mode blockquote.quote-olive h6 { color: #3d9970; } .dark-mode blockquote.quote-lime { border-color: #01ff70; } .dark-mode blockquote.quote-lime h1, .dark-mode blockquote.quote-lime h2, .dark-mode blockquote.quote-lime h3, .dark-mode blockquote.quote-lime h4, .dark-mode blockquote.quote-lime h5, .dark-mode blockquote.quote-lime h6 { color: #01ff70; } .dark-mode blockquote.quote-fuchsia { border-color: #f012be; } .dark-mode blockquote.quote-fuchsia h1, .dark-mode blockquote.quote-fuchsia h2, .dark-mode blockquote.quote-fuchsia h3, .dark-mode blockquote.quote-fuchsia h4, .dark-mode blockquote.quote-fuchsia h5, .dark-mode blockquote.quote-fuchsia h6 { color: #f012be; } .dark-mode blockquote.quote-maroon { border-color: #d81b60; } .dark-mode blockquote.quote-maroon h1, .dark-mode blockquote.quote-maroon h2, .dark-mode blockquote.quote-maroon h3, .dark-mode blockquote.quote-maroon h4, .dark-mode blockquote.quote-maroon h5, .dark-mode blockquote.quote-maroon h6 { color: #d81b60; } .dark-mode blockquote.quote-blue { border-color: #007bff; } .dark-mode blockquote.quote-blue h1, .dark-mode blockquote.quote-blue h2, .dark-mode blockquote.quote-blue h3, .dark-mode blockquote.quote-blue h4, .dark-mode blockquote.quote-blue h5, .dark-mode blockquote.quote-blue h6 { color: #007bff; } .dark-mode blockquote.quote-indigo { border-color: #6610f2; } .dark-mode blockquote.quote-indigo h1, .dark-mode blockquote.quote-indigo h2, .dark-mode blockquote.quote-indigo h3, .dark-mode blockquote.quote-indigo h4, .dark-mode blockquote.quote-indigo h5, .dark-mode blockquote.quote-indigo h6 { color: #6610f2; } .dark-mode blockquote.quote-purple { border-color: #6f42c1; } .dark-mode blockquote.quote-purple h1, .dark-mode blockquote.quote-purple h2, .dark-mode blockquote.quote-purple h3, .dark-mode blockquote.quote-purple h4, .dark-mode blockquote.quote-purple h5, .dark-mode blockquote.quote-purple h6 { color: #6f42c1; } .dark-mode blockquote.quote-pink { border-color: #e83e8c; } .dark-mode blockquote.quote-pink h1, .dark-mode blockquote.quote-pink h2, .dark-mode blockquote.quote-pink h3, .dark-mode blockquote.quote-pink h4, .dark-mode blockquote.quote-pink h5, .dark-mode blockquote.quote-pink h6 { color: #e83e8c; } .dark-mode blockquote.quote-red { border-color: #dc3545; } .dark-mode blockquote.quote-red h1, .dark-mode blockquote.quote-red h2, .dark-mode blockquote.quote-red h3, .dark-mode blockquote.quote-red h4, .dark-mode blockquote.quote-red h5, .dark-mode blockquote.quote-red h6 { color: #dc3545; } .dark-mode blockquote.quote-orange { border-color: #fd7e14; } .dark-mode blockquote.quote-orange h1, .dark-mode blockquote.quote-orange h2, .dark-mode blockquote.quote-orange h3, .dark-mode blockquote.quote-orange h4, .dark-mode blockquote.quote-orange h5, .dark-mode blockquote.quote-orange h6 { color: #fd7e14; } .dark-mode blockquote.quote-yellow { border-color: #ffc107; } .dark-mode blockquote.quote-yellow h1, .dark-mode blockquote.quote-yellow h2, .dark-mode blockquote.quote-yellow h3, .dark-mode blockquote.quote-yellow h4, .dark-mode blockquote.quote-yellow h5, .dark-mode blockquote.quote-yellow h6 { color: #ffc107; } .dark-mode blockquote.quote-green { border-color: #28a745; } .dark-mode blockquote.quote-green h1, .dark-mode blockquote.quote-green h2, .dark-mode blockquote.quote-green h3, .dark-mode blockquote.quote-green h4, .dark-mode blockquote.quote-green h5, .dark-mode blockquote.quote-green h6 { color: #28a745; } .dark-mode blockquote.quote-teal { border-color: #20c997; } .dark-mode blockquote.quote-teal h1, .dark-mode blockquote.quote-teal h2, .dark-mode blockquote.quote-teal h3, .dark-mode blockquote.quote-teal h4, .dark-mode blockquote.quote-teal h5, .dark-mode blockquote.quote-teal h6 { color: #20c997; } .dark-mode blockquote.quote-cyan { border-color: #17a2b8; } .dark-mode blockquote.quote-cyan h1, .dark-mode blockquote.quote-cyan h2, .dark-mode blockquote.quote-cyan h3, .dark-mode blockquote.quote-cyan h4, .dark-mode blockquote.quote-cyan h5, .dark-mode blockquote.quote-cyan h6 { color: #17a2b8; } .dark-mode blockquote.quote-white { border-color: #fff; } .dark-mode blockquote.quote-white h1, .dark-mode blockquote.quote-white h2, .dark-mode blockquote.quote-white h3, .dark-mode blockquote.quote-white h4, .dark-mode blockquote.quote-white h5, .dark-mode blockquote.quote-white h6 { color: #fff; } .dark-mode blockquote.quote-gray { border-color: #6c757d; } .dark-mode blockquote.quote-gray h1, .dark-mode blockquote.quote-gray h2, .dark-mode blockquote.quote-gray h3, .dark-mode blockquote.quote-gray h4, .dark-mode blockquote.quote-gray h5, .dark-mode blockquote.quote-gray h6 { color: #6c757d; } .dark-mode blockquote.quote-gray-dark { border-color: #343a40; } .dark-mode blockquote.quote-gray-dark h1, .dark-mode blockquote.quote-gray-dark h2, .dark-mode blockquote.quote-gray-dark h3, .dark-mode blockquote.quote-gray-dark h4, .dark-mode blockquote.quote-gray-dark h5, .dark-mode blockquote.quote-gray-dark h6 { color: #343a40; } .dark-mode .close, .dark-mode .mailbox-attachment-close, .dark-mode .mailbox-attachment-close { color: #adb5bd; text-shadow: 0 1px 0 #495057; } .dark-mode .tab-custom-content { border-color: #6c757d; } .dark-mode .list-group-item { background-color: #343a40; border-color: #6c757d; } @media print { .no-print, .main-sidebar, .main-header, .content-header { display: none !important; } .content-wrapper, .main-footer { -webkit-transform: translate(0, 0); transform: translate(0, 0); margin-left: 0 !important; min-height: 0 !important; } .layout-fixed .content-wrapper { padding-top: 0 !important; } .invoice { border: 0; margin: 0; padding: 0; width: 100%; } .invoice-col { float: left; width: 33.3333333%; } .table-responsive { overflow: auto; } .table-responsive > .table tr th, .table-responsive > .table tr td { white-space: normal !important; } } .text-bold, .text-bold.table td, .text-bold.table th { font-weight: 700; } .text-xs { font-size: 0.75rem !important; } .text-sm { font-size: 0.875rem !important; } .text-md { font-size: 1rem !important; } .text-lg { font-size: 1.25rem !important; } .text-xl { font-size: 2rem !important; } .text-lightblue { color: #3c8dbc !important; } .text-navy { color: #001f3f !important; } .text-olive { color: #3d9970 !important; } .text-lime { color: #01ff70 !important; } .text-fuchsia { color: #f012be !important; } .text-maroon { color: #d81b60 !important; } .text-blue { color: #007bff !important; } .text-indigo { color: #6610f2 !important; } .text-purple { color: #6f42c1 !important; } .text-pink { color: #e83e8c !important; } .text-red { color: #dc3545 !important; } .text-orange { color: #fd7e14 !important; } .text-yellow { color: #ffc107 !important; } .text-green { color: #28a745 !important; } .text-teal { color: #20c997 !important; } .text-cyan { color: #17a2b8 !important; } .text-white { color: #fff !important; } .text-gray { color: #6c757d !important; } .text-gray-dark { color: #343a40 !important; } .dark-mode .text-muted { color: #adb5bd !important; } .dark-mode .text-lightblue { color: #86bad8 !important; } .dark-mode .text-navy { color: #002c59 !important; } .dark-mode .text-olive { color: #74c8a3 !important; } .dark-mode .text-lime { color: #67ffa9 !important; } .dark-mode .text-fuchsia { color: #f672d8 !important; } .dark-mode .text-maroon { color: #ed6c9b !important; } .dark-mode .text-blue { color: #3f6791 !important; } .dark-mode .text-indigo { color: #6610f2 !important; } .dark-mode .text-purple { color: #6f42c1 !important; } .dark-mode .text-pink { color: #e83e8c !important; } .dark-mode .text-red { color: #e74c3c !important; } .dark-mode .text-orange { color: #fd7e14 !important; } .dark-mode .text-yellow { color: #f39c12 !important; } .dark-mode .text-green { color: #00bc8c !important; } .dark-mode .text-teal { color: #20c997 !important; } .dark-mode .text-cyan { color: #3498db !important; } .dark-mode .text-white { color: #fff !important; } .dark-mode .text-gray { color: #6c757d !important; } .dark-mode .text-gray-dark { color: #343a40 !important; } .elevation-0 { box-shadow: none !important; } .elevation-1 { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important; } .elevation-2 { box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-3 { box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-4 { box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22) !important; } .elevation-5 { box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22) !important; } .bg-primary { background-color: #007bff !important; } .bg-primary, .bg-primary > a { color: #fff !important; } .bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .bg-primary.btn:not(:disabled):not(.disabled):active, .bg-primary.btn:not(:disabled):not(.disabled).active, .bg-primary.btn:active, .bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-secondary { background-color: #6c757d !important; } .bg-secondary, .bg-secondary > a { color: #fff !important; } .bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .bg-secondary.btn:not(:disabled):not(.disabled):active, .bg-secondary.btn:not(:disabled):not(.disabled).active, .bg-secondary.btn:active, .bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-success { background-color: #28a745 !important; } .bg-success, .bg-success > a { color: #fff !important; } .bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-success.btn:not(:disabled):not(.disabled):active, .bg-success.btn:not(:disabled):not(.disabled).active, .bg-success.btn:active, .bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-info { background-color: #17a2b8 !important; } .bg-info, .bg-info > a { color: #fff !important; } .bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .bg-info.btn:not(:disabled):not(.disabled):active, .bg-info.btn:not(:disabled):not(.disabled).active, .bg-info.btn:active, .bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-warning { background-color: #ffc107 !important; } .bg-warning, .bg-warning > a { color: #1f2d3d !important; } .bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .bg-warning.btn:not(:disabled):not(.disabled):active, .bg-warning.btn:not(:disabled):not(.disabled).active, .bg-warning.btn:active, .bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-danger { background-color: #dc3545 !important; } .bg-danger, .bg-danger > a { color: #fff !important; } .bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .bg-danger.btn:not(:disabled):not(.disabled):active, .bg-danger.btn:not(:disabled):not(.disabled).active, .bg-danger.btn:active, .bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-light { background-color: #f8f9fa !important; } .bg-light, .bg-light > a { color: #1f2d3d !important; } .bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .bg-light.btn:not(:disabled):not(.disabled):active, .bg-light.btn:not(:disabled):not(.disabled).active, .bg-light.btn:active, .bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .bg-dark { background-color: #343a40 !important; } .bg-dark, .bg-dark > a { color: #fff !important; } .bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-dark.btn:not(:disabled):not(.disabled):active, .bg-dark.btn:not(:disabled):not(.disabled).active, .bg-dark.btn:active, .bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .bg-lightblue { background-color: #3c8dbc !important; } .bg-lightblue, .bg-lightblue > a { color: #fff !important; } .bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .bg-lightblue.btn:not(:disabled):not(.disabled):active, .bg-lightblue.btn:not(:disabled):not(.disabled).active, .bg-lightblue.btn:active, .bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .bg-navy { background-color: #001f3f !important; } .bg-navy, .bg-navy > a { color: #fff !important; } .bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .bg-navy.btn:not(:disabled):not(.disabled):active, .bg-navy.btn:not(:disabled):not(.disabled).active, .bg-navy.btn:active, .bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .bg-olive { background-color: #3d9970 !important; } .bg-olive, .bg-olive > a { color: #fff !important; } .bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .bg-olive.btn:not(:disabled):not(.disabled):active, .bg-olive.btn:not(:disabled):not(.disabled).active, .bg-olive.btn:active, .bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .bg-lime { background-color: #01ff70 !important; } .bg-lime, .bg-lime > a { color: #1f2d3d !important; } .bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .bg-lime.btn:not(:disabled):not(.disabled):active, .bg-lime.btn:not(:disabled):not(.disabled).active, .bg-lime.btn:active, .bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .bg-fuchsia { background-color: #f012be !important; } .bg-fuchsia, .bg-fuchsia > a { color: #fff !important; } .bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .bg-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-fuchsia.btn:active, .bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .bg-maroon { background-color: #d81b60 !important; } .bg-maroon, .bg-maroon > a { color: #fff !important; } .bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .bg-maroon.btn:not(:disabled):not(.disabled):active, .bg-maroon.btn:not(:disabled):not(.disabled).active, .bg-maroon.btn:active, .bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .bg-blue { background-color: #007bff !important; } .bg-blue, .bg-blue > a { color: #fff !important; } .bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .bg-blue.btn:not(:disabled):not(.disabled):active, .bg-blue.btn:not(:disabled):not(.disabled).active, .bg-blue.btn:active, .bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-indigo { background-color: #6610f2 !important; } .bg-indigo, .bg-indigo > a { color: #fff !important; } .bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .bg-indigo.btn:not(:disabled):not(.disabled):active, .bg-indigo.btn:not(:disabled):not(.disabled).active, .bg-indigo.btn:active, .bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .bg-purple { background-color: #6f42c1 !important; } .bg-purple, .bg-purple > a { color: #fff !important; } .bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .bg-purple.btn:not(:disabled):not(.disabled):active, .bg-purple.btn:not(:disabled):not(.disabled).active, .bg-purple.btn:active, .bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .bg-pink { background-color: #e83e8c !important; } .bg-pink, .bg-pink > a { color: #fff !important; } .bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .bg-pink.btn:not(:disabled):not(.disabled):active, .bg-pink.btn:not(:disabled):not(.disabled).active, .bg-pink.btn:active, .bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .bg-red { background-color: #dc3545 !important; } .bg-red, .bg-red > a { color: #fff !important; } .bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .bg-red.btn:not(:disabled):not(.disabled):active, .bg-red.btn:not(:disabled):not(.disabled).active, .bg-red.btn:active, .bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-orange { background-color: #fd7e14 !important; } .bg-orange, .bg-orange > a { color: #1f2d3d !important; } .bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .bg-orange.btn:not(:disabled):not(.disabled):active, .bg-orange.btn:not(:disabled):not(.disabled).active, .bg-orange.btn:active, .bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .bg-yellow { background-color: #ffc107 !important; } .bg-yellow, .bg-yellow > a { color: #1f2d3d !important; } .bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .bg-yellow.btn:not(:disabled):not(.disabled):active, .bg-yellow.btn:not(:disabled):not(.disabled).active, .bg-yellow.btn:active, .bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-green { background-color: #28a745 !important; } .bg-green, .bg-green > a { color: #fff !important; } .bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-green.btn:not(:disabled):not(.disabled):active, .bg-green.btn:not(:disabled):not(.disabled).active, .bg-green.btn:active, .bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-teal { background-color: #20c997 !important; } .bg-teal, .bg-teal > a { color: #fff !important; } .bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .bg-teal.btn:not(:disabled):not(.disabled):active, .bg-teal.btn:not(:disabled):not(.disabled).active, .bg-teal.btn:active, .bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .bg-cyan { background-color: #17a2b8 !important; } .bg-cyan, .bg-cyan > a { color: #fff !important; } .bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .bg-cyan.btn:not(:disabled):not(.disabled):active, .bg-cyan.btn:not(:disabled):not(.disabled).active, .bg-cyan.btn:active, .bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-white { background-color: #fff !important; } .bg-white, .bg-white > a { color: #1f2d3d !important; } .bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .bg-white.btn:not(:disabled):not(.disabled):active, .bg-white.btn:not(:disabled):not(.disabled).active, .bg-white.btn:active, .bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gray { background-color: #6c757d !important; } .bg-gray, .bg-gray > a { color: #fff !important; } .bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .bg-gray.btn:not(:disabled):not(.disabled):active, .bg-gray.btn:not(:disabled):not(.disabled).active, .bg-gray.btn:active, .bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-gray-dark { background-color: #343a40 !important; } .bg-gray-dark, .bg-gray-dark > a { color: #fff !important; } .bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gray-dark.btn:active, .bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } @media print { .table td.bg-primary, .table th.bg-primary { background-color: #007bff !important; } .table td.bg-primary, .table td.bg-primary > a, .table th.bg-primary, .table th.bg-primary > a { color: #fff !important; } .table td.bg-primary.btn:hover, .table th.bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-primary.btn:not(:disabled):not(.disabled):active, .table td.bg-primary.btn:not(:disabled):not(.disabled).active, .table td.bg-primary.btn:active, .table td.bg-primary.btn.active, .table th.bg-primary.btn:not(:disabled):not(.disabled):active, .table th.bg-primary.btn:not(:disabled):not(.disabled).active, .table th.bg-primary.btn:active, .table th.bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-secondary, .table th.bg-secondary { background-color: #6c757d !important; } .table td.bg-secondary, .table td.bg-secondary > a, .table th.bg-secondary, .table th.bg-secondary > a { color: #fff !important; } .table td.bg-secondary.btn:hover, .table th.bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-secondary.btn:not(:disabled):not(.disabled):active, .table td.bg-secondary.btn:not(:disabled):not(.disabled).active, .table td.bg-secondary.btn:active, .table td.bg-secondary.btn.active, .table th.bg-secondary.btn:not(:disabled):not(.disabled):active, .table th.bg-secondary.btn:not(:disabled):not(.disabled).active, .table th.bg-secondary.btn:active, .table th.bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-success, .table th.bg-success { background-color: #28a745 !important; } .table td.bg-success, .table td.bg-success > a, .table th.bg-success, .table th.bg-success > a { color: #fff !important; } .table td.bg-success.btn:hover, .table th.bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-success.btn:not(:disabled):not(.disabled):active, .table td.bg-success.btn:not(:disabled):not(.disabled).active, .table td.bg-success.btn:active, .table td.bg-success.btn.active, .table th.bg-success.btn:not(:disabled):not(.disabled):active, .table th.bg-success.btn:not(:disabled):not(.disabled).active, .table th.bg-success.btn:active, .table th.bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-info, .table th.bg-info { background-color: #17a2b8 !important; } .table td.bg-info, .table td.bg-info > a, .table th.bg-info, .table th.bg-info > a { color: #fff !important; } .table td.bg-info.btn:hover, .table th.bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-info.btn:not(:disabled):not(.disabled):active, .table td.bg-info.btn:not(:disabled):not(.disabled).active, .table td.bg-info.btn:active, .table td.bg-info.btn.active, .table th.bg-info.btn:not(:disabled):not(.disabled):active, .table th.bg-info.btn:not(:disabled):not(.disabled).active, .table th.bg-info.btn:active, .table th.bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-warning, .table th.bg-warning { background-color: #ffc107 !important; } .table td.bg-warning, .table td.bg-warning > a, .table th.bg-warning, .table th.bg-warning > a { color: #1f2d3d !important; } .table td.bg-warning.btn:hover, .table th.bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-warning.btn:not(:disabled):not(.disabled):active, .table td.bg-warning.btn:not(:disabled):not(.disabled).active, .table td.bg-warning.btn:active, .table td.bg-warning.btn.active, .table th.bg-warning.btn:not(:disabled):not(.disabled):active, .table th.bg-warning.btn:not(:disabled):not(.disabled).active, .table th.bg-warning.btn:active, .table th.bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-danger, .table th.bg-danger { background-color: #dc3545 !important; } .table td.bg-danger, .table td.bg-danger > a, .table th.bg-danger, .table th.bg-danger > a { color: #fff !important; } .table td.bg-danger.btn:hover, .table th.bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-danger.btn:not(:disabled):not(.disabled):active, .table td.bg-danger.btn:not(:disabled):not(.disabled).active, .table td.bg-danger.btn:active, .table td.bg-danger.btn.active, .table th.bg-danger.btn:not(:disabled):not(.disabled):active, .table th.bg-danger.btn:not(:disabled):not(.disabled).active, .table th.bg-danger.btn:active, .table th.bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-light, .table th.bg-light { background-color: #f8f9fa !important; } .table td.bg-light, .table td.bg-light > a, .table th.bg-light, .table th.bg-light > a { color: #1f2d3d !important; } .table td.bg-light.btn:hover, .table th.bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .table td.bg-light.btn:not(:disabled):not(.disabled):active, .table td.bg-light.btn:not(:disabled):not(.disabled).active, .table td.bg-light.btn:active, .table td.bg-light.btn.active, .table th.bg-light.btn:not(:disabled):not(.disabled):active, .table th.bg-light.btn:not(:disabled):not(.disabled).active, .table th.bg-light.btn:active, .table th.bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .table td.bg-dark, .table th.bg-dark { background-color: #343a40 !important; } .table td.bg-dark, .table td.bg-dark > a, .table th.bg-dark, .table th.bg-dark > a { color: #fff !important; } .table td.bg-dark.btn:hover, .table th.bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-dark.btn:active, .table td.bg-dark.btn.active, .table th.bg-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-dark.btn:active, .table th.bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .table td.bg-lightblue, .table th.bg-lightblue { background-color: #3c8dbc !important; } .table td.bg-lightblue, .table td.bg-lightblue > a, .table th.bg-lightblue, .table th.bg-lightblue > a { color: #fff !important; } .table td.bg-lightblue.btn:hover, .table th.bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .table td.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table td.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table td.bg-lightblue.btn:active, .table td.bg-lightblue.btn.active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table th.bg-lightblue.btn:active, .table th.bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .table td.bg-navy, .table th.bg-navy { background-color: #001f3f !important; } .table td.bg-navy, .table td.bg-navy > a, .table th.bg-navy, .table th.bg-navy > a { color: #fff !important; } .table td.bg-navy.btn:hover, .table th.bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .table td.bg-navy.btn:not(:disabled):not(.disabled):active, .table td.bg-navy.btn:not(:disabled):not(.disabled).active, .table td.bg-navy.btn:active, .table td.bg-navy.btn.active, .table th.bg-navy.btn:not(:disabled):not(.disabled):active, .table th.bg-navy.btn:not(:disabled):not(.disabled).active, .table th.bg-navy.btn:active, .table th.bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .table td.bg-olive, .table th.bg-olive { background-color: #3d9970 !important; } .table td.bg-olive, .table td.bg-olive > a, .table th.bg-olive, .table th.bg-olive > a { color: #fff !important; } .table td.bg-olive.btn:hover, .table th.bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .table td.bg-olive.btn:not(:disabled):not(.disabled):active, .table td.bg-olive.btn:not(:disabled):not(.disabled).active, .table td.bg-olive.btn:active, .table td.bg-olive.btn.active, .table th.bg-olive.btn:not(:disabled):not(.disabled):active, .table th.bg-olive.btn:not(:disabled):not(.disabled).active, .table th.bg-olive.btn:active, .table th.bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .table td.bg-lime, .table th.bg-lime { background-color: #01ff70 !important; } .table td.bg-lime, .table td.bg-lime > a, .table th.bg-lime, .table th.bg-lime > a { color: #1f2d3d !important; } .table td.bg-lime.btn:hover, .table th.bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .table td.bg-lime.btn:not(:disabled):not(.disabled):active, .table td.bg-lime.btn:not(:disabled):not(.disabled).active, .table td.bg-lime.btn:active, .table td.bg-lime.btn.active, .table th.bg-lime.btn:not(:disabled):not(.disabled):active, .table th.bg-lime.btn:not(:disabled):not(.disabled).active, .table th.bg-lime.btn:active, .table th.bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .table td.bg-fuchsia, .table th.bg-fuchsia { background-color: #f012be !important; } .table td.bg-fuchsia, .table td.bg-fuchsia > a, .table th.bg-fuchsia, .table th.bg-fuchsia > a { color: #fff !important; } .table td.bg-fuchsia.btn:hover, .table th.bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .table td.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table td.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table td.bg-fuchsia.btn:active, .table td.bg-fuchsia.btn.active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table th.bg-fuchsia.btn:active, .table th.bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .table td.bg-maroon, .table th.bg-maroon { background-color: #d81b60 !important; } .table td.bg-maroon, .table td.bg-maroon > a, .table th.bg-maroon, .table th.bg-maroon > a { color: #fff !important; } .table td.bg-maroon.btn:hover, .table th.bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .table td.bg-maroon.btn:not(:disabled):not(.disabled):active, .table td.bg-maroon.btn:not(:disabled):not(.disabled).active, .table td.bg-maroon.btn:active, .table td.bg-maroon.btn.active, .table th.bg-maroon.btn:not(:disabled):not(.disabled):active, .table th.bg-maroon.btn:not(:disabled):not(.disabled).active, .table th.bg-maroon.btn:active, .table th.bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .table td.bg-blue, .table th.bg-blue { background-color: #007bff !important; } .table td.bg-blue, .table td.bg-blue > a, .table th.bg-blue, .table th.bg-blue > a { color: #fff !important; } .table td.bg-blue.btn:hover, .table th.bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-blue.btn:not(:disabled):not(.disabled):active, .table td.bg-blue.btn:not(:disabled):not(.disabled).active, .table td.bg-blue.btn:active, .table td.bg-blue.btn.active, .table th.bg-blue.btn:not(:disabled):not(.disabled):active, .table th.bg-blue.btn:not(:disabled):not(.disabled).active, .table th.bg-blue.btn:active, .table th.bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-indigo, .table th.bg-indigo { background-color: #6610f2 !important; } .table td.bg-indigo, .table td.bg-indigo > a, .table th.bg-indigo, .table th.bg-indigo > a { color: #fff !important; } .table td.bg-indigo.btn:hover, .table th.bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .table td.bg-indigo.btn:not(:disabled):not(.disabled):active, .table td.bg-indigo.btn:not(:disabled):not(.disabled).active, .table td.bg-indigo.btn:active, .table td.bg-indigo.btn.active, .table th.bg-indigo.btn:not(:disabled):not(.disabled):active, .table th.bg-indigo.btn:not(:disabled):not(.disabled).active, .table th.bg-indigo.btn:active, .table th.bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .table td.bg-purple, .table th.bg-purple { background-color: #6f42c1 !important; } .table td.bg-purple, .table td.bg-purple > a, .table th.bg-purple, .table th.bg-purple > a { color: #fff !important; } .table td.bg-purple.btn:hover, .table th.bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .table td.bg-purple.btn:not(:disabled):not(.disabled):active, .table td.bg-purple.btn:not(:disabled):not(.disabled).active, .table td.bg-purple.btn:active, .table td.bg-purple.btn.active, .table th.bg-purple.btn:not(:disabled):not(.disabled):active, .table th.bg-purple.btn:not(:disabled):not(.disabled).active, .table th.bg-purple.btn:active, .table th.bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .table td.bg-pink, .table th.bg-pink { background-color: #e83e8c !important; } .table td.bg-pink, .table td.bg-pink > a, .table th.bg-pink, .table th.bg-pink > a { color: #fff !important; } .table td.bg-pink.btn:hover, .table th.bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .table td.bg-pink.btn:not(:disabled):not(.disabled):active, .table td.bg-pink.btn:not(:disabled):not(.disabled).active, .table td.bg-pink.btn:active, .table td.bg-pink.btn.active, .table th.bg-pink.btn:not(:disabled):not(.disabled):active, .table th.bg-pink.btn:not(:disabled):not(.disabled).active, .table th.bg-pink.btn:active, .table th.bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .table td.bg-red, .table th.bg-red { background-color: #dc3545 !important; } .table td.bg-red, .table td.bg-red > a, .table th.bg-red, .table th.bg-red > a { color: #fff !important; } .table td.bg-red.btn:hover, .table th.bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-red.btn:not(:disabled):not(.disabled):active, .table td.bg-red.btn:not(:disabled):not(.disabled).active, .table td.bg-red.btn:active, .table td.bg-red.btn.active, .table th.bg-red.btn:not(:disabled):not(.disabled):active, .table th.bg-red.btn:not(:disabled):not(.disabled).active, .table th.bg-red.btn:active, .table th.bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-orange, .table th.bg-orange { background-color: #fd7e14 !important; } .table td.bg-orange, .table td.bg-orange > a, .table th.bg-orange, .table th.bg-orange > a { color: #1f2d3d !important; } .table td.bg-orange.btn:hover, .table th.bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .table td.bg-orange.btn:not(:disabled):not(.disabled):active, .table td.bg-orange.btn:not(:disabled):not(.disabled).active, .table td.bg-orange.btn:active, .table td.bg-orange.btn.active, .table th.bg-orange.btn:not(:disabled):not(.disabled):active, .table th.bg-orange.btn:not(:disabled):not(.disabled).active, .table th.bg-orange.btn:active, .table th.bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .table td.bg-yellow, .table th.bg-yellow { background-color: #ffc107 !important; } .table td.bg-yellow, .table td.bg-yellow > a, .table th.bg-yellow, .table th.bg-yellow > a { color: #1f2d3d !important; } .table td.bg-yellow.btn:hover, .table th.bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-yellow.btn:not(:disabled):not(.disabled):active, .table td.bg-yellow.btn:not(:disabled):not(.disabled).active, .table td.bg-yellow.btn:active, .table td.bg-yellow.btn.active, .table th.bg-yellow.btn:not(:disabled):not(.disabled):active, .table th.bg-yellow.btn:not(:disabled):not(.disabled).active, .table th.bg-yellow.btn:active, .table th.bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-green, .table th.bg-green { background-color: #28a745 !important; } .table td.bg-green, .table td.bg-green > a, .table th.bg-green, .table th.bg-green > a { color: #fff !important; } .table td.bg-green.btn:hover, .table th.bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-green.btn:not(:disabled):not(.disabled):active, .table td.bg-green.btn:not(:disabled):not(.disabled).active, .table td.bg-green.btn:active, .table td.bg-green.btn.active, .table th.bg-green.btn:not(:disabled):not(.disabled):active, .table th.bg-green.btn:not(:disabled):not(.disabled).active, .table th.bg-green.btn:active, .table th.bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-teal, .table th.bg-teal { background-color: #20c997 !important; } .table td.bg-teal, .table td.bg-teal > a, .table th.bg-teal, .table th.bg-teal > a { color: #fff !important; } .table td.bg-teal.btn:hover, .table th.bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .table td.bg-teal.btn:not(:disabled):not(.disabled):active, .table td.bg-teal.btn:not(:disabled):not(.disabled).active, .table td.bg-teal.btn:active, .table td.bg-teal.btn.active, .table th.bg-teal.btn:not(:disabled):not(.disabled):active, .table th.bg-teal.btn:not(:disabled):not(.disabled).active, .table th.bg-teal.btn:active, .table th.bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .table td.bg-cyan, .table th.bg-cyan { background-color: #17a2b8 !important; } .table td.bg-cyan, .table td.bg-cyan > a, .table th.bg-cyan, .table th.bg-cyan > a { color: #fff !important; } .table td.bg-cyan.btn:hover, .table th.bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-cyan.btn:not(:disabled):not(.disabled):active, .table td.bg-cyan.btn:not(:disabled):not(.disabled).active, .table td.bg-cyan.btn:active, .table td.bg-cyan.btn.active, .table th.bg-cyan.btn:not(:disabled):not(.disabled):active, .table th.bg-cyan.btn:not(:disabled):not(.disabled).active, .table th.bg-cyan.btn:active, .table th.bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-white, .table th.bg-white { background-color: #fff !important; } .table td.bg-white, .table td.bg-white > a, .table th.bg-white, .table th.bg-white > a { color: #1f2d3d !important; } .table td.bg-white.btn:hover, .table th.bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .table td.bg-white.btn:not(:disabled):not(.disabled):active, .table td.bg-white.btn:not(:disabled):not(.disabled).active, .table td.bg-white.btn:active, .table td.bg-white.btn.active, .table th.bg-white.btn:not(:disabled):not(.disabled):active, .table th.bg-white.btn:not(:disabled):not(.disabled).active, .table th.bg-white.btn:active, .table th.bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .table td.bg-gray, .table th.bg-gray { background-color: #6c757d !important; } .table td.bg-gray, .table td.bg-gray > a, .table th.bg-gray, .table th.bg-gray > a { color: #fff !important; } .table td.bg-gray.btn:hover, .table th.bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-gray.btn:not(:disabled):not(.disabled):active, .table td.bg-gray.btn:not(:disabled):not(.disabled).active, .table td.bg-gray.btn:active, .table td.bg-gray.btn.active, .table th.bg-gray.btn:not(:disabled):not(.disabled):active, .table th.bg-gray.btn:not(:disabled):not(.disabled).active, .table th.bg-gray.btn:active, .table th.bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-gray-dark, .table th.bg-gray-dark { background-color: #343a40 !important; } .table td.bg-gray-dark, .table td.bg-gray-dark > a, .table th.bg-gray-dark, .table th.bg-gray-dark > a { color: #fff !important; } .table td.bg-gray-dark.btn:hover, .table th.bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-gray-dark.btn:active, .table td.bg-gray-dark.btn.active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-gray-dark.btn:active, .table th.bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } } .bg-gray { background-color: #adb5bd; color: #1f2d3d; } .bg-gray-light { background-color: #f2f4f5; color: #1f2d3d !important; } .bg-black { background-color: #000; color: #fff !important; } .bg-white { background-color: #fff; color: #1f2d3d !important; } .bg-gradient-primary { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-primary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-primary.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .bg-gradient-primary.btn:active, .bg-gradient-primary.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-primary.btn:disabled, .bg-gradient-primary.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-secondary { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-secondary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-secondary.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .bg-gradient-secondary.btn:active, .bg-gradient-secondary.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-secondary.btn:disabled, .bg-gradient-secondary.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-success { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-success.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-success.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .bg-gradient-success.btn:active, .bg-gradient-success.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-success.btn:disabled, .bg-gradient-success.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-info { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-info.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-info.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .bg-gradient-info.btn:active, .bg-gradient-info.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-info.btn:disabled, .bg-gradient-info.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-warning { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-warning.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-warning.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .bg-gradient-warning.btn:active, .bg-gradient-warning.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-warning.btn:disabled, .bg-gradient-warning.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-danger { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-danger.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-danger.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .bg-gradient-danger.btn:active, .bg-gradient-danger.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-danger.btn:disabled, .bg-gradient-danger.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-light { background: #f8f9fa linear-gradient(180deg, #f9fafb, #f8f9fa) repeat-x !important; color: #1f2d3d; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-light.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-light.btn:hover { background: #f8f9fa linear-gradient(180deg, #e6eaed, #e2e6ea) repeat-x !important; border-color: #dae0e5; color: #121a24; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .bg-gradient-light.btn:active, .bg-gradient-light.btn.active { background: #f8f9fa linear-gradient(180deg, #e0e4e9, #dae0e5) repeat-x !important; border-color: #d3d9df; color: #1f2d3d; } .bg-gradient-light.btn:disabled, .bg-gradient-light.btn.disabled { background-image: none !important; border-color: #f8f9fa; color: #1f2d3d; } .bg-gradient-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-dark.btn:active, .bg-gradient-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-dark.btn:disabled, .bg-gradient-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .bg-gradient-lightblue { background: #3c8dbc linear-gradient(180deg, #599ec6, #3c8dbc) repeat-x !important; color: #fff; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lightblue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lightblue.btn:hover { background: #3c8dbc linear-gradient(180deg, #518cad, #33779f) repeat-x !important; border-color: #307095; color: #ececec; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .bg-gradient-lightblue.btn:active, .bg-gradient-lightblue.btn.active { background: #3c8dbc linear-gradient(180deg, #4f85a5, #307095) repeat-x !important; border-color: #2d698c; color: #fff; } .bg-gradient-lightblue.btn:disabled, .bg-gradient-lightblue.btn.disabled { background-image: none !important; border-color: #3c8dbc; color: #fff; } .bg-gradient-navy { background: #001f3f linear-gradient(180deg, #26415c, #001f3f) repeat-x !important; color: #fff; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-navy.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-navy.btn:hover { background: #001f3f linear-gradient(180deg, #26313b, #000c19) repeat-x !important; border-color: #00060c; color: #ececec; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .bg-gradient-navy.btn:active, .bg-gradient-navy.btn.active { background: #001f3f linear-gradient(180deg, #262b30, #00060c) repeat-x !important; border-color: black; color: #fff; } .bg-gradient-navy.btn:disabled, .bg-gradient-navy.btn.disabled { background-image: none !important; border-color: #001f3f; color: #fff; } .bg-gradient-olive { background: #3d9970 linear-gradient(180deg, #5aa885, #3d9970) repeat-x !important; color: #fff; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-olive.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-olive.btn:hover { background: #3d9970 linear-gradient(180deg, #519174, #327e5c) repeat-x !important; border-color: #2e7555; color: #ececec; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .bg-gradient-olive.btn:active, .bg-gradient-olive.btn.active { background: #3d9970 linear-gradient(180deg, #4e896f, #2e7555) repeat-x !important; border-color: #2b6b4f; color: #fff; } .bg-gradient-olive.btn:disabled, .bg-gradient-olive.btn.disabled { background-image: none !important; border-color: #3d9970; color: #fff; } .bg-gradient-lime { background: #01ff70 linear-gradient(180deg, #27ff85, #01ff70) repeat-x !important; color: #1f2d3d; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lime.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lime.btn:hover { background: #01ff70 linear-gradient(180deg, #26df77, #00da5f) repeat-x !important; border-color: #00cd5a; color: #121a24; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .bg-gradient-lime.btn:active, .bg-gradient-lime.btn.active { background: #01ff70 linear-gradient(180deg, #26d572, #00cd5a) repeat-x !important; border-color: #00c054; color: #fff; } .bg-gradient-lime.btn:disabled, .bg-gradient-lime.btn.disabled { background-image: none !important; border-color: #01ff70; color: #1f2d3d; } .bg-gradient-fuchsia { background: #f012be linear-gradient(180deg, #f236c8, #f012be) repeat-x !important; color: #fff; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-fuchsia.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-fuchsia.btn:hover { background: #f012be linear-gradient(180deg, #d631b1, #cf0da3) repeat-x !important; border-color: #c30c9a; color: #ececec; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-gradient-fuchsia.btn:active, .bg-gradient-fuchsia.btn.active { background: #f012be linear-gradient(180deg, #cc31a9, #c30c9a) repeat-x !important; border-color: #b70c90; color: #fff; } .bg-gradient-fuchsia.btn:disabled, .bg-gradient-fuchsia.btn.disabled { background-image: none !important; border-color: #f012be; color: #fff; } .bg-gradient-maroon { background: #d81b60 linear-gradient(180deg, #de3d78, #d81b60) repeat-x !important; color: #fff; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-maroon.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-maroon.btn:hover { background: #d81b60 linear-gradient(180deg, #c13a6b, #b61751) repeat-x !important; border-color: #ab154c; color: #ececec; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .bg-gradient-maroon.btn:active, .bg-gradient-maroon.btn.active { background: #d81b60 linear-gradient(180deg, #b73867, #ab154c) repeat-x !important; border-color: #9f1447; color: #fff; } .bg-gradient-maroon.btn:disabled, .bg-gradient-maroon.btn.disabled { background-image: none !important; border-color: #d81b60; color: #fff; } .bg-gradient-blue { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-blue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-blue.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .bg-gradient-blue.btn:active, .bg-gradient-blue.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-blue.btn:disabled, .bg-gradient-blue.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-indigo { background: #6610f2 linear-gradient(180deg, #7d34f4, #6610f2) repeat-x !important; color: #fff; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-indigo.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-indigo.btn:hover { background: #6610f2 linear-gradient(180deg, #7030d7, #560bd0) repeat-x !important; border-color: #510bc4; color: #ececec; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .bg-gradient-indigo.btn:active, .bg-gradient-indigo.btn.active { background: #6610f2 linear-gradient(180deg, #6b2fcd, #510bc4) repeat-x !important; border-color: #4c0ab8; color: #fff; } .bg-gradient-indigo.btn:disabled, .bg-gradient-indigo.btn.disabled { background-image: none !important; border-color: #6610f2; color: #fff; } .bg-gradient-purple { background: #6f42c1 linear-gradient(180deg, #855eca, #6f42c1) repeat-x !important; color: #fff; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-purple.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-purple.btn:hover { background: #6f42c1 linear-gradient(180deg, #7655b4, #5e37a6) repeat-x !important; border-color: #59339d; color: #ececec; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .bg-gradient-purple.btn:active, .bg-gradient-purple.btn.active { background: #6f42c1 linear-gradient(180deg, #7252ab, #59339d) repeat-x !important; border-color: #533093; color: #fff; } .bg-gradient-purple.btn:disabled, .bg-gradient-purple.btn.disabled { background-image: none !important; border-color: #6f42c1; color: #fff; } .bg-gradient-pink { background: #e83e8c linear-gradient(180deg, #eb5b9d, #e83e8c) repeat-x !important; color: #fff; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-pink.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-pink.btn:hover { background: #e83e8c linear-gradient(180deg, #e83e8c, #e41c78) repeat-x !important; border-color: #d91a72; color: #ececec; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .bg-gradient-pink.btn:active, .bg-gradient-pink.btn.active { background: #e83e8c linear-gradient(180deg, #df3c87, #d91a72) repeat-x !important; border-color: #ce196c; color: #fff; } .bg-gradient-pink.btn:disabled, .bg-gradient-pink.btn.disabled { background-image: none !important; border-color: #e83e8c; color: #fff; } .bg-gradient-red { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-red.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-red.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .bg-gradient-red.btn:active, .bg-gradient-red.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-red.btn:disabled, .bg-gradient-red.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-orange { background: #fd7e14 linear-gradient(180deg, #fd9137, #fd7e14) repeat-x !important; color: #1f2d3d; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-orange.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-orange.btn:hover { background: #fd7e14 linear-gradient(180deg, #ec8128, #e96b02) repeat-x !important; border-color: #dc6502; color: #121a24; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .bg-gradient-orange.btn:active, .bg-gradient-orange.btn.active { background: #fd7e14 linear-gradient(180deg, #e17c28, #dc6502) repeat-x !important; border-color: #cf5f02; color: #fff; } .bg-gradient-orange.btn:disabled, .bg-gradient-orange.btn.disabled { background-image: none !important; border-color: #fd7e14; color: #1f2d3d; } .bg-gradient-yellow { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-yellow.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-yellow.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .bg-gradient-yellow.btn:active, .bg-gradient-yellow.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-yellow.btn:disabled, .bg-gradient-yellow.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-green { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-green.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-green.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .bg-gradient-green.btn:active, .bg-gradient-green.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-green.btn:disabled, .bg-gradient-green.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-teal { background: #20c997 linear-gradient(180deg, #41d1a7, #20c997) repeat-x !important; color: #fff; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-teal.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-teal.btn:hover { background: #20c997 linear-gradient(180deg, #3db592, #1ba87e) repeat-x !important; border-color: #199d76; color: #ececec; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .bg-gradient-teal.btn:active, .bg-gradient-teal.btn.active { background: #20c997 linear-gradient(180deg, #3bac8b, #199d76) repeat-x !important; border-color: #17926e; color: #fff; } .bg-gradient-teal.btn:disabled, .bg-gradient-teal.btn.disabled { background-image: none !important; border-color: #20c997; color: #fff; } .bg-gradient-cyan { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-cyan.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-cyan.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .bg-gradient-cyan.btn:active, .bg-gradient-cyan.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-cyan.btn:disabled, .bg-gradient-cyan.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-white { background: #fff linear-gradient(180deg, white, #fff) repeat-x !important; color: #1f2d3d; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-white.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-white.btn:hover { background: #fff linear-gradient(180deg, #efefef, #ececec) repeat-x !important; border-color: #e6e6e6; color: #121a24; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .bg-gradient-white.btn:active, .bg-gradient-white.btn.active { background: #fff linear-gradient(180deg, #e9e9e9, #e6e6e6) repeat-x !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gradient-white.btn:disabled, .bg-gradient-white.btn.disabled { background-image: none !important; border-color: #fff; color: #1f2d3d; } .bg-gradient-gray { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray.btn:active, .bg-gradient-gray.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-gray.btn:disabled, .bg-gradient-gray.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-gray-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray-dark.btn:active, .bg-gradient-gray-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-gray-dark.btn:disabled, .bg-gradient-gray-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } [class^="bg-"].disabled { opacity: .65; } a.text-muted:hover { color: #007bff !important; } .link-muted { color: #5d6974; } .link-muted:hover, .link-muted:focus { color: #464f58; } .link-black { color: #6c757d; } .link-black:hover, .link-black:focus { color: #e6e8ea; } .accent-primary .btn-link, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-primary .nav-tabs .nav-link { color: #007bff; } .accent-primary .btn-link:hover, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-primary .nav-tabs .nav-link:hover { color: #0056b3; } .accent-primary .dropdown-item:active, .accent-primary .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-primary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-primary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-primary .custom-select:focus, .accent-primary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-primary .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-primary .page-item .page-link { color: #007bff; } .accent-primary .page-item.active a, .accent-primary .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-primary .page-item.disabled a, .accent-primary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-primary .page-item .page-link:hover, .dark-mode.accent-primary .page-item .page-link:focus { color: #1a88ff; } .accent-secondary .btn-link, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-secondary .nav-tabs .nav-link { color: #6c757d; } .accent-secondary .btn-link:hover, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-secondary .nav-tabs .nav-link:hover { color: #494f54; } .accent-secondary .dropdown-item:active, .accent-secondary .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-secondary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-secondary .custom-select:focus, .accent-secondary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-secondary .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-secondary .page-item .page-link { color: #6c757d; } .accent-secondary .page-item.active a, .accent-secondary .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-secondary .page-item.disabled a, .accent-secondary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-secondary .page-item .page-link:hover, .dark-mode.accent-secondary .page-item .page-link:focus { color: #78828a; } .accent-success .btn-link, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-success .nav-tabs .nav-link { color: #28a745; } .accent-success .btn-link:hover, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-success .nav-tabs .nav-link:hover { color: #19692c; } .accent-success .dropdown-item:active, .accent-success .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-success .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-success .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-success .custom-select:focus, .accent-success .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-success .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-success .page-item .page-link { color: #28a745; } .accent-success .page-item.active a, .accent-success .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-success .page-item.disabled a, .accent-success .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-success .page-item .page-link:hover, .dark-mode.accent-success .page-item .page-link:focus { color: #2dbc4e; } .accent-info .btn-link, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-info .nav-tabs .nav-link { color: #17a2b8; } .accent-info .btn-link:hover, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-info .nav-tabs .nav-link:hover { color: #0f6674; } .accent-info .dropdown-item:active, .accent-info .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-info .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-info .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-info .custom-select:focus, .accent-info .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-info .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-info .page-item .page-link { color: #17a2b8; } .accent-info .page-item.active a, .accent-info .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-info .page-item.disabled a, .accent-info .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-info .page-item .page-link:hover, .dark-mode.accent-info .page-item .page-link:focus { color: #1ab6cf; } .accent-warning .btn-link, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-warning .nav-tabs .nav-link { color: #ffc107; } .accent-warning .btn-link:hover, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-warning .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-warning .dropdown-item:active, .accent-warning .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-warning .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-warning .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-warning .custom-select:focus, .accent-warning .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-warning .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-warning .page-item .page-link { color: #ffc107; } .accent-warning .page-item.active a, .accent-warning .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-warning .page-item.disabled a, .accent-warning .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-warning .page-item .page-link:hover, .dark-mode.accent-warning .page-item .page-link:focus { color: #ffc721; } .accent-danger .btn-link, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-danger .nav-tabs .nav-link { color: #dc3545; } .accent-danger .btn-link:hover, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-danger .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-danger .dropdown-item:active, .accent-danger .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-danger .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-danger .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-danger .custom-select:focus, .accent-danger .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-danger .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-danger .page-item .page-link { color: #dc3545; } .accent-danger .page-item.active a, .accent-danger .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-danger .page-item.disabled a, .accent-danger .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-danger .page-item .page-link:hover, .dark-mode.accent-danger .page-item .page-link:focus { color: #e04b59; } .accent-light .btn-link, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-light .nav-tabs .nav-link { color: #f8f9fa; } .accent-light .btn-link:hover, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-light .nav-tabs .nav-link:hover { color: #cbd3da; } .accent-light .dropdown-item:active, .accent-light .dropdown-item.active { background-color: #f8f9fa; color: #1f2d3d; } .accent-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .accent-light .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-light .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-light .custom-select:focus, .accent-light .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-light .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-light .page-item .page-link { color: #f8f9fa; } .accent-light .page-item.active a, .accent-light .page-item.active .page-link { background-color: #f8f9fa; border-color: #f8f9fa; color: #fff; } .accent-light .page-item.disabled a, .accent-light .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-light .page-item .page-link:hover, .dark-mode.accent-light .page-item .page-link:focus { color: white; } .accent-dark .btn-link, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-dark .nav-tabs .nav-link { color: #343a40; } .accent-dark .btn-link:hover, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-dark .dropdown-item:active, .accent-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-dark .custom-select:focus, .accent-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-dark .page-item .page-link { color: #343a40; } .accent-dark .page-item.active a, .accent-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-dark .page-item.disabled a, .accent-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-dark .page-item .page-link:hover, .dark-mode.accent-dark .page-item .page-link:focus { color: #3f474e; } .accent-lightblue .btn-link, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lightblue .nav-tabs .nav-link { color: #3c8dbc; } .accent-lightblue .btn-link:hover, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lightblue .nav-tabs .nav-link:hover { color: #296282; } .accent-lightblue .dropdown-item:active, .accent-lightblue .dropdown-item.active { background-color: #3c8dbc; color: #fff; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lightblue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lightblue .custom-select:focus, .accent-lightblue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lightblue .custom-file-input:focus ~ .custom-file-label { border-color: #99c5de; } .accent-lightblue .page-item .page-link { color: #3c8dbc; } .accent-lightblue .page-item.active a, .accent-lightblue .page-item.active .page-link { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .accent-lightblue .page-item.disabled a, .accent-lightblue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-lightblue .page-item .page-link:hover, .dark-mode.accent-lightblue .page-item .page-link:focus { color: #4c99c6; } .accent-navy .btn-link, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-navy .nav-tabs .nav-link { color: #001f3f; } .accent-navy .btn-link:hover, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-navy .nav-tabs .nav-link:hover { color: black; } .accent-navy .dropdown-item:active, .accent-navy .dropdown-item.active { background-color: #001f3f; color: #fff; } .accent-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .accent-navy .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-navy .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-navy .custom-select:focus, .accent-navy .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-navy .custom-file-input:focus ~ .custom-file-label { border-color: #005ebf; } .accent-navy .page-item .page-link { color: #001f3f; } .accent-navy .page-item.active a, .accent-navy .page-item.active .page-link { background-color: #001f3f; border-color: #001f3f; color: #fff; } .accent-navy .page-item.disabled a, .accent-navy .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-navy .page-item .page-link:hover, .dark-mode.accent-navy .page-item .page-link:focus { color: #002c59; } .accent-olive .btn-link, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-olive .nav-tabs .nav-link { color: #3d9970; } .accent-olive .btn-link:hover, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-olive .nav-tabs .nav-link:hover { color: #276248; } .accent-olive .dropdown-item:active, .accent-olive .dropdown-item.active { background-color: #3d9970; color: #fff; } .accent-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .accent-olive .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-olive .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-olive .custom-select:focus, .accent-olive .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-olive .custom-file-input:focus ~ .custom-file-label { border-color: #87cfaf; } .accent-olive .page-item .page-link { color: #3d9970; } .accent-olive .page-item.active a, .accent-olive .page-item.active .page-link { background-color: #3d9970; border-color: #3d9970; color: #fff; } .accent-olive .page-item.disabled a, .accent-olive .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-olive .page-item .page-link:hover, .dark-mode.accent-olive .page-item .page-link:focus { color: #44ab7d; } .accent-lime .btn-link, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lime .nav-tabs .nav-link { color: #01ff70; } .accent-lime .btn-link:hover, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lime .nav-tabs .nav-link:hover { color: #00b44e; } .accent-lime .dropdown-item:active, .accent-lime .dropdown-item.active { background-color: #01ff70; color: #1f2d3d; } .accent-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .accent-lime .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lime .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lime .custom-select:focus, .accent-lime .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lime .custom-file-input:focus ~ .custom-file-label { border-color: #81ffb8; } .accent-lime .page-item .page-link { color: #01ff70; } .accent-lime .page-item.active a, .accent-lime .page-item.active .page-link { background-color: #01ff70; border-color: #01ff70; color: #fff; } .accent-lime .page-item.disabled a, .accent-lime .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-lime .page-item .page-link:hover, .dark-mode.accent-lime .page-item .page-link:focus { color: #1bff7e; } .accent-fuchsia .btn-link, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-fuchsia .nav-tabs .nav-link { color: #f012be; } .accent-fuchsia .btn-link:hover, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-fuchsia .nav-tabs .nav-link:hover { color: #ab0b87; } .accent-fuchsia .dropdown-item:active, .accent-fuchsia .dropdown-item.active { background-color: #f012be; color: #fff; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-fuchsia .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-fuchsia .custom-select:focus, .accent-fuchsia .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-fuchsia .custom-file-input:focus ~ .custom-file-label { border-color: #f88adf; } .accent-fuchsia .page-item .page-link { color: #f012be; } .accent-fuchsia .page-item.active a, .accent-fuchsia .page-item.active .page-link { background-color: #f012be; border-color: #f012be; color: #fff; } .accent-fuchsia .page-item.disabled a, .accent-fuchsia .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-fuchsia .page-item .page-link:hover, .dark-mode.accent-fuchsia .page-item .page-link:focus { color: #f22ac5; } .accent-maroon .btn-link, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-maroon .nav-tabs .nav-link { color: #d81b60; } .accent-maroon .btn-link:hover, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-maroon .nav-tabs .nav-link:hover { color: #941342; } .accent-maroon .dropdown-item:active, .accent-maroon .dropdown-item.active { background-color: #d81b60; color: #fff; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-maroon .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-maroon .custom-select:focus, .accent-maroon .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-maroon .custom-file-input:focus ~ .custom-file-label { border-color: #f083ab; } .accent-maroon .page-item .page-link { color: #d81b60; } .accent-maroon .page-item.active a, .accent-maroon .page-item.active .page-link { background-color: #d81b60; border-color: #d81b60; color: #fff; } .accent-maroon .page-item.disabled a, .accent-maroon .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-maroon .page-item .page-link:hover, .dark-mode.accent-maroon .page-item .page-link:focus { color: #e4286d; } .accent-blue .btn-link, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-blue .nav-tabs .nav-link { color: #007bff; } .accent-blue .btn-link:hover, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-blue .nav-tabs .nav-link:hover { color: #0056b3; } .accent-blue .dropdown-item:active, .accent-blue .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-blue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-blue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-blue .custom-select:focus, .accent-blue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-blue .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-blue .page-item .page-link { color: #007bff; } .accent-blue .page-item.active a, .accent-blue .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-blue .page-item.disabled a, .accent-blue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-blue .page-item .page-link:hover, .dark-mode.accent-blue .page-item .page-link:focus { color: #1a88ff; } .accent-indigo .btn-link, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-indigo .nav-tabs .nav-link { color: #6610f2; } .accent-indigo .btn-link:hover, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-indigo .nav-tabs .nav-link:hover { color: #4709ac; } .accent-indigo .dropdown-item:active, .accent-indigo .dropdown-item.active { background-color: #6610f2; color: #fff; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-indigo .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-indigo .custom-select:focus, .accent-indigo .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-indigo .custom-file-input:focus ~ .custom-file-label { border-color: #b389f9; } .accent-indigo .page-item .page-link { color: #6610f2; } .accent-indigo .page-item.active a, .accent-indigo .page-item.active .page-link { background-color: #6610f2; border-color: #6610f2; color: #fff; } .accent-indigo .page-item.disabled a, .accent-indigo .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-indigo .page-item .page-link:hover, .dark-mode.accent-indigo .page-item .page-link:focus { color: #7528f3; } .accent-purple .btn-link, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-purple .nav-tabs .nav-link { color: #6f42c1; } .accent-purple .btn-link:hover, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-purple .nav-tabs .nav-link:hover { color: #4e2d89; } .accent-purple .dropdown-item:active, .accent-purple .dropdown-item.active { background-color: #6f42c1; color: #fff; } .accent-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .accent-purple .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-purple .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-purple .custom-select:focus, .accent-purple .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-purple .custom-file-input:focus ~ .custom-file-label { border-color: #b8a2e0; } .accent-purple .page-item .page-link { color: #6f42c1; } .accent-purple .page-item.active a, .accent-purple .page-item.active .page-link { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .accent-purple .page-item.disabled a, .accent-purple .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-purple .page-item .page-link:hover, .dark-mode.accent-purple .page-item .page-link:focus { color: #7e55c7; } .accent-pink .btn-link, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-pink .nav-tabs .nav-link { color: #e83e8c; } .accent-pink .btn-link:hover, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-pink .nav-tabs .nav-link:hover { color: #c21766; } .accent-pink .dropdown-item:active, .accent-pink .dropdown-item.active { background-color: #e83e8c; color: #fff; } .accent-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .accent-pink .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-pink .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-pink .custom-select:focus, .accent-pink .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-pink .custom-file-input:focus ~ .custom-file-label { border-color: #f6b0d0; } .accent-pink .page-item .page-link { color: #e83e8c; } .accent-pink .page-item.active a, .accent-pink .page-item.active .page-link { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .accent-pink .page-item.disabled a, .accent-pink .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-pink .page-item .page-link:hover, .dark-mode.accent-pink .page-item .page-link:focus { color: #eb559a; } .accent-red .btn-link, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-red .nav-tabs .nav-link { color: #dc3545; } .accent-red .btn-link:hover, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-red .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-red .dropdown-item:active, .accent-red .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-red .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-red .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-red .custom-select:focus, .accent-red .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-red .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-red .page-item .page-link { color: #dc3545; } .accent-red .page-item.active a, .accent-red .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-red .page-item.disabled a, .accent-red .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-red .page-item .page-link:hover, .dark-mode.accent-red .page-item .page-link:focus { color: #e04b59; } .accent-orange .btn-link, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-orange .nav-tabs .nav-link { color: #fd7e14; } .accent-orange .btn-link:hover, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-orange .nav-tabs .nav-link:hover { color: #c35a02; } .accent-orange .dropdown-item:active, .accent-orange .dropdown-item.active { background-color: #fd7e14; color: #1f2d3d; } .accent-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .accent-orange .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-orange .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-orange .custom-select:focus, .accent-orange .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-orange .custom-file-input:focus ~ .custom-file-label { border-color: #fec392; } .accent-orange .page-item .page-link { color: #fd7e14; } .accent-orange .page-item.active a, .accent-orange .page-item.active .page-link { background-color: #fd7e14; border-color: #fd7e14; color: #fff; } .accent-orange .page-item.disabled a, .accent-orange .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-orange .page-item .page-link:hover, .dark-mode.accent-orange .page-item .page-link:focus { color: #fd8c2d; } .accent-yellow .btn-link, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-yellow .nav-tabs .nav-link { color: #ffc107; } .accent-yellow .btn-link:hover, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-yellow .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-yellow .dropdown-item:active, .accent-yellow .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-yellow .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-yellow .custom-select:focus, .accent-yellow .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-yellow .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-yellow .page-item .page-link { color: #ffc107; } .accent-yellow .page-item.active a, .accent-yellow .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-yellow .page-item.disabled a, .accent-yellow .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-yellow .page-item .page-link:hover, .dark-mode.accent-yellow .page-item .page-link:focus { color: #ffc721; } .accent-green .btn-link, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-green .nav-tabs .nav-link { color: #28a745; } .accent-green .btn-link:hover, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-green .nav-tabs .nav-link:hover { color: #19692c; } .accent-green .dropdown-item:active, .accent-green .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-green .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-green .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-green .custom-select:focus, .accent-green .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-green .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-green .page-item .page-link { color: #28a745; } .accent-green .page-item.active a, .accent-green .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-green .page-item.disabled a, .accent-green .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-green .page-item .page-link:hover, .dark-mode.accent-green .page-item .page-link:focus { color: #2dbc4e; } .accent-teal .btn-link, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-teal .nav-tabs .nav-link { color: #20c997; } .accent-teal .btn-link:hover, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-teal .nav-tabs .nav-link:hover { color: #158765; } .accent-teal .dropdown-item:active, .accent-teal .dropdown-item.active { background-color: #20c997; color: #fff; } .accent-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .accent-teal .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-teal .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-teal .custom-select:focus, .accent-teal .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-teal .custom-file-input:focus ~ .custom-file-label { border-color: #7eeaca; } .accent-teal .page-item .page-link { color: #20c997; } .accent-teal .page-item.active a, .accent-teal .page-item.active .page-link { background-color: #20c997; border-color: #20c997; color: #fff; } .accent-teal .page-item.disabled a, .accent-teal .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-teal .page-item .page-link:hover, .dark-mode.accent-teal .page-item .page-link:focus { color: #26dca6; } .accent-cyan .btn-link, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-cyan .nav-tabs .nav-link { color: #17a2b8; } .accent-cyan .btn-link:hover, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-cyan .nav-tabs .nav-link:hover { color: #0f6674; } .accent-cyan .dropdown-item:active, .accent-cyan .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-cyan .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-cyan .custom-select:focus, .accent-cyan .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-cyan .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-cyan .page-item .page-link { color: #17a2b8; } .accent-cyan .page-item.active a, .accent-cyan .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-cyan .page-item.disabled a, .accent-cyan .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-cyan .page-item .page-link:hover, .dark-mode.accent-cyan .page-item .page-link:focus { color: #1ab6cf; } .accent-white .btn-link, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-white .nav-tabs .nav-link { color: #fff; } .accent-white .btn-link:hover, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-white .nav-tabs .nav-link:hover { color: #d9d9d9; } .accent-white .dropdown-item:active, .accent-white .dropdown-item.active { background-color: #fff; color: #1f2d3d; } .accent-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .accent-white .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-white .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-white .custom-select:focus, .accent-white .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-white .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-white .page-item .page-link { color: #fff; } .accent-white .page-item.active a, .accent-white .page-item.active .page-link { background-color: #fff; border-color: #fff; color: #fff; } .accent-white .page-item.disabled a, .accent-white .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-white .page-item .page-link:hover, .dark-mode.accent-white .page-item .page-link:focus { color: white; } .accent-gray .btn-link, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray .nav-tabs .nav-link { color: #6c757d; } .accent-gray .btn-link:hover, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray .nav-tabs .nav-link:hover { color: #494f54; } .accent-gray .dropdown-item:active, .accent-gray .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-gray .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray .custom-select:focus, .accent-gray .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-gray .page-item .page-link { color: #6c757d; } .accent-gray .page-item.active a, .accent-gray .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-gray .page-item.disabled a, .accent-gray .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-gray .page-item .page-link:hover, .dark-mode.accent-gray .page-item .page-link:focus { color: #78828a; } .accent-gray-dark .btn-link, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray-dark .nav-tabs .nav-link { color: #343a40; } .accent-gray-dark .btn-link:hover, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-gray-dark .dropdown-item:active, .accent-gray-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray-dark .custom-select:focus, .accent-gray-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-gray-dark .page-item .page-link { color: #343a40; } .accent-gray-dark .page-item.active a, .accent-gray-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-gray-dark .page-item.disabled a, .accent-gray-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-gray-dark .page-item .page-link:hover, .dark-mode.accent-gray-dark .page-item .page-link:focus { color: #3f474e; } [class*="accent-"] a.btn-primary { color: #fff; } [class*="accent-"] a.btn-secondary { color: #fff; } [class*="accent-"] a.btn-success { color: #fff; } [class*="accent-"] a.btn-info { color: #fff; } [class*="accent-"] a.btn-warning { color: #1f2d3d; } [class*="accent-"] a.btn-danger { color: #fff; } [class*="accent-"] a.btn-light { color: #1f2d3d; } [class*="accent-"] a.btn-dark { color: #fff; } .dark-mode .bg-light { background-color: #454d55 !important; color: #fff !important; } .dark-mode .text-black, .dark-mode .text-dark, .dark-mode .link-black, .dark-mode .link-dark { color: #ced4da !important; } .dark-mode.bg-primary { background-color: #3f6791 !important; } .dark-mode.bg-primary, .dark-mode.bg-primary > a { color: #fff !important; } .dark-mode.bg-primary.btn:hover { border-color: #304e6d; color: #ececec; } .dark-mode.bg-primary.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-primary.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-primary.btn:active, .dark-mode.bg-primary.btn.active { background-color: #304e6d !important; border-color: #2c4765; color: #fff; } .dark-mode.bg-secondary { background-color: #6c757d !important; } .dark-mode.bg-secondary, .dark-mode.bg-secondary > a { color: #fff !important; } .dark-mode.bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .dark-mode.bg-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-secondary.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-secondary.btn:active, .dark-mode.bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .dark-mode.bg-success { background-color: #00bc8c !important; } .dark-mode.bg-success, .dark-mode.bg-success > a { color: #fff !important; } .dark-mode.bg-success.btn:hover { border-color: #008966; color: #ececec; } .dark-mode.bg-success.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-success.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-success.btn:active, .dark-mode.bg-success.btn.active { background-color: #008966 !important; border-color: #007c5d; color: #fff; } .dark-mode.bg-info { background-color: #3498db !important; } .dark-mode.bg-info, .dark-mode.bg-info > a { color: #fff !important; } .dark-mode.bg-info.btn:hover { border-color: #217dbb; color: #ececec; } .dark-mode.bg-info.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-info.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-info.btn:active, .dark-mode.bg-info.btn.active { background-color: #217dbb !important; border-color: #1f76b0; color: #fff; } .dark-mode.bg-warning { background-color: #f39c12 !important; } .dark-mode.bg-warning, .dark-mode.bg-warning > a { color: #1f2d3d !important; } .dark-mode.bg-warning.btn:hover { border-color: #c87f0a; color: #121a24; } .dark-mode.bg-warning.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-warning.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-warning.btn:active, .dark-mode.bg-warning.btn.active { background-color: #c87f0a !important; border-color: #bc770a; color: #fff; } .dark-mode.bg-danger { background-color: #e74c3c !important; } .dark-mode.bg-danger, .dark-mode.bg-danger > a { color: #fff !important; } .dark-mode.bg-danger.btn:hover { border-color: #d62c1a; color: #ececec; } .dark-mode.bg-danger.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-danger.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-danger.btn:active, .dark-mode.bg-danger.btn.active { background-color: #d62c1a !important; border-color: #ca2a19; color: #fff; } .dark-mode.bg-light { background-color: #f8f9fa !important; } .dark-mode.bg-light, .dark-mode.bg-light > a { color: #1f2d3d !important; } .dark-mode.bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .dark-mode.bg-light.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-light.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-light.btn:active, .dark-mode.bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .dark-mode.bg-dark { background-color: #343a40 !important; } .dark-mode.bg-dark, .dark-mode.bg-dark > a { color: #fff !important; } .dark-mode.bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .dark-mode.bg-dark.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-dark.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-dark.btn:active, .dark-mode.bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .dark-mode.bg-lightblue { background-color: #86bad8 !important; } .dark-mode.bg-lightblue, .dark-mode.bg-lightblue > a { color: #1f2d3d !important; } .dark-mode.bg-lightblue.btn:hover { border-color: #5fa4cc; color: #121a24; } .dark-mode.bg-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-lightblue.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-lightblue.btn:active, .dark-mode.bg-lightblue.btn.active { background-color: #5fa4cc !important; border-color: #559ec9; color: #fff; } .dark-mode.bg-navy { background-color: #002c59 !important; } .dark-mode.bg-navy, .dark-mode.bg-navy > a { color: #fff !important; } .dark-mode.bg-navy.btn:hover { border-color: #001226; color: #ececec; } .dark-mode.bg-navy.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-navy.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-navy.btn:active, .dark-mode.bg-navy.btn.active { background-color: #001226 !important; border-color: #000c19; color: #fff; } .dark-mode.bg-olive { background-color: #74c8a3 !important; } .dark-mode.bg-olive, .dark-mode.bg-olive > a { color: #1f2d3d !important; } .dark-mode.bg-olive.btn:hover { border-color: #50b98a; color: #121a24; } .dark-mode.bg-olive.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-olive.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-olive.btn:active, .dark-mode.bg-olive.btn.active { background-color: #50b98a !important; border-color: #48b484; color: #fff; } .dark-mode.bg-lime { background-color: #67ffa9 !important; } .dark-mode.bg-lime, .dark-mode.bg-lime > a { color: #1f2d3d !important; } .dark-mode.bg-lime.btn:hover { border-color: #34ff8d; color: #121a24; } .dark-mode.bg-lime.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-lime.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-lime.btn:active, .dark-mode.bg-lime.btn.active { background-color: #34ff8d !important; border-color: #27ff86; color: #1f2d3d; } .dark-mode.bg-fuchsia { background-color: #f672d8 !important; } .dark-mode.bg-fuchsia, .dark-mode.bg-fuchsia > a { color: #1f2d3d !important; } .dark-mode.bg-fuchsia.btn:hover { border-color: #f342cb; color: #121a24; } .dark-mode.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-fuchsia.btn:active, .dark-mode.bg-fuchsia.btn.active { background-color: #f342cb !important; border-color: #f236c8; color: #fff; } .dark-mode.bg-maroon { background-color: #ed6c9b !important; } .dark-mode.bg-maroon, .dark-mode.bg-maroon > a { color: #1f2d3d !important; } .dark-mode.bg-maroon.btn:hover { border-color: #e73f7c; color: #121a24; } .dark-mode.bg-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-maroon.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-maroon.btn:active, .dark-mode.bg-maroon.btn.active { background-color: #e73f7c !important; border-color: #e63475; color: #fff; } .dark-mode.bg-blue { background-color: #3f6791 !important; } .dark-mode.bg-blue, .dark-mode.bg-blue > a { color: #fff !important; } .dark-mode.bg-blue.btn:hover { border-color: #304e6d; color: #ececec; } .dark-mode.bg-blue.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-blue.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-blue.btn:active, .dark-mode.bg-blue.btn.active { background-color: #304e6d !important; border-color: #2c4765; color: #fff; } .dark-mode.bg-indigo { background-color: #6610f2 !important; } .dark-mode.bg-indigo, .dark-mode.bg-indigo > a { color: #fff !important; } .dark-mode.bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .dark-mode.bg-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-indigo.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-indigo.btn:active, .dark-mode.bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .dark-mode.bg-purple { background-color: #6f42c1 !important; } .dark-mode.bg-purple, .dark-mode.bg-purple > a { color: #fff !important; } .dark-mode.bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .dark-mode.bg-purple.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-purple.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-purple.btn:active, .dark-mode.bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .dark-mode.bg-pink { background-color: #e83e8c !important; } .dark-mode.bg-pink, .dark-mode.bg-pink > a { color: #fff !important; } .dark-mode.bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .dark-mode.bg-pink.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-pink.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-pink.btn:active, .dark-mode.bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .dark-mode.bg-red { background-color: #e74c3c !important; } .dark-mode.bg-red, .dark-mode.bg-red > a { color: #fff !important; } .dark-mode.bg-red.btn:hover { border-color: #d62c1a; color: #ececec; } .dark-mode.bg-red.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-red.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-red.btn:active, .dark-mode.bg-red.btn.active { background-color: #d62c1a !important; border-color: #ca2a19; color: #fff; } .dark-mode.bg-orange { background-color: #fd7e14 !important; } .dark-mode.bg-orange, .dark-mode.bg-orange > a { color: #1f2d3d !important; } .dark-mode.bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .dark-mode.bg-orange.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-orange.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-orange.btn:active, .dark-mode.bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .dark-mode.bg-yellow { background-color: #f39c12 !important; } .dark-mode.bg-yellow, .dark-mode.bg-yellow > a { color: #1f2d3d !important; } .dark-mode.bg-yellow.btn:hover { border-color: #c87f0a; color: #121a24; } .dark-mode.bg-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-yellow.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-yellow.btn:active, .dark-mode.bg-yellow.btn.active { background-color: #c87f0a !important; border-color: #bc770a; color: #fff; } .dark-mode.bg-green { background-color: #00bc8c !important; } .dark-mode.bg-green, .dark-mode.bg-green > a { color: #fff !important; } .dark-mode.bg-green.btn:hover { border-color: #008966; color: #ececec; } .dark-mode.bg-green.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-green.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-green.btn:active, .dark-mode.bg-green.btn.active { background-color: #008966 !important; border-color: #007c5d; color: #fff; } .dark-mode.bg-teal { background-color: #20c997 !important; } .dark-mode.bg-teal, .dark-mode.bg-teal > a { color: #fff !important; } .dark-mode.bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .dark-mode.bg-teal.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-teal.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-teal.btn:active, .dark-mode.bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .dark-mode.bg-cyan { background-color: #3498db !important; } .dark-mode.bg-cyan, .dark-mode.bg-cyan > a { color: #fff !important; } .dark-mode.bg-cyan.btn:hover { border-color: #217dbb; color: #ececec; } .dark-mode.bg-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-cyan.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-cyan.btn:active, .dark-mode.bg-cyan.btn.active { background-color: #217dbb !important; border-color: #1f76b0; color: #fff; } .dark-mode.bg-white { background-color: #fff !important; } .dark-mode.bg-white, .dark-mode.bg-white > a { color: #1f2d3d !important; } .dark-mode.bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .dark-mode.bg-white.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-white.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-white.btn:active, .dark-mode.bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .dark-mode.bg-gray { background-color: #6c757d !important; } .dark-mode.bg-gray, .dark-mode.bg-gray > a { color: #fff !important; } .dark-mode.bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .dark-mode.bg-gray.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-gray.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-gray.btn:active, .dark-mode.bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .dark-mode.bg-gray-dark { background-color: #343a40 !important; } .dark-mode.bg-gray-dark, .dark-mode.bg-gray-dark > a { color: #fff !important; } .dark-mode.bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .dark-mode.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-gray-dark.btn:active, .dark-mode.bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-primary { background: #3f6791 linear-gradient(180deg, #5c7ea2, #3f6791) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-primary.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-primary.btn:hover { background: #3f6791 linear-gradient(180deg, #526e8b, #335476) repeat-x !important; border-color: #304e6d; color: #ececec; } .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-primary.btn:active, .dark-mode .bg-gradient-primary.btn.active { background: #3f6791 linear-gradient(180deg, #4f6883, #304e6d) repeat-x !important; border-color: #2c4765; color: #fff; } .dark-mode .bg-gradient-primary.btn:disabled, .dark-mode .bg-gradient-primary.btn.disabled { background-image: none !important; border-color: #3f6791; color: #fff; } .dark-mode .bg-gradient-secondary { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-secondary.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-secondary.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-secondary.btn:active, .dark-mode .bg-gradient-secondary.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .dark-mode .bg-gradient-secondary.btn:disabled, .dark-mode .bg-gradient-secondary.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .dark-mode .bg-gradient-success { background: #00bc8c linear-gradient(180deg, #26c69d, #00bc8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-success.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-success.btn:hover { background: #00bc8c linear-gradient(180deg, #26a685, #009670) repeat-x !important; border-color: #008966; color: #ececec; } .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-success.btn:active, .dark-mode .bg-gradient-success.btn.active { background: #00bc8c linear-gradient(180deg, #269b7d, #008966) repeat-x !important; border-color: #007c5d; color: #fff; } .dark-mode .bg-gradient-success.btn:disabled, .dark-mode .bg-gradient-success.btn.disabled { background-image: none !important; border-color: #00bc8c; color: #fff; } .dark-mode .bg-gradient-info { background: #3498db linear-gradient(180deg, #52a7e0, #3498db) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-info.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-info.btn:hover { background: #3498db linear-gradient(180deg, #4497ce, #2384c6) repeat-x !important; border-color: #217dbb; color: #ececec; } .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-info.btn:active, .dark-mode .bg-gradient-info.btn.active { background: #3498db linear-gradient(180deg, #4291c5, #217dbb) repeat-x !important; border-color: #1f76b0; color: #fff; } .dark-mode .bg-gradient-info.btn:disabled, .dark-mode .bg-gradient-info.btn.disabled { background-image: none !important; border-color: #3498db; color: #fff; } .dark-mode .bg-gradient-warning { background: #f39c12 linear-gradient(180deg, #f5ab36, #f39c12) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-warning.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-warning.btn:hover { background: #f39c12 linear-gradient(180deg, #da982f, #d4860b) repeat-x !important; border-color: #c87f0a; color: #121a24; } .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-warning.btn:active, .dark-mode .bg-gradient-warning.btn.active { background: #f39c12 linear-gradient(180deg, #d0922f, #c87f0a) repeat-x !important; border-color: #bc770a; color: #fff; } .dark-mode .bg-gradient-warning.btn:disabled, .dark-mode .bg-gradient-warning.btn.disabled { background-image: none !important; border-color: #f39c12; color: #1f2d3d; } .dark-mode .bg-gradient-danger { background: #e74c3c linear-gradient(180deg, #eb6759, #e74c3c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-danger.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-danger.btn:hover { background: #e74c3c linear-gradient(180deg, #e64d3e, #e12e1c) repeat-x !important; border-color: #d62c1a; color: #ececec; } .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-danger.btn:active, .dark-mode .bg-gradient-danger.btn.active { background: #e74c3c linear-gradient(180deg, #dc4c3d, #d62c1a) repeat-x !important; border-color: #ca2a19; color: #fff; } .dark-mode .bg-gradient-danger.btn:disabled, .dark-mode .bg-gradient-danger.btn.disabled { background-image: none !important; border-color: #e74c3c; color: #fff; } .dark-mode .bg-gradient-light { background: #f8f9fa linear-gradient(180deg, #f9fafb, #f8f9fa) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-light.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-light.btn:hover { background: #f8f9fa linear-gradient(180deg, #e6eaed, #e2e6ea) repeat-x !important; border-color: #dae0e5; color: #121a24; } .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-light.btn:active, .dark-mode .bg-gradient-light.btn.active { background: #f8f9fa linear-gradient(180deg, #e0e4e9, #dae0e5) repeat-x !important; border-color: #d3d9df; color: #1f2d3d; } .dark-mode .bg-gradient-light.btn:disabled, .dark-mode .bg-gradient-light.btn.disabled { background-image: none !important; border-color: #f8f9fa; color: #1f2d3d; } .dark-mode .bg-gradient-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-dark.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-dark.btn:active, .dark-mode .bg-gradient-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-dark.btn:disabled, .dark-mode .bg-gradient-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .dark-mode .bg-gradient-lightblue { background: #86bad8 linear-gradient(180deg, #98c4de, #86bad8) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-lightblue.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-lightblue.btn:hover { background: #86bad8 linear-gradient(180deg, #7fb6d6, #69a9cf) repeat-x !important; border-color: #5fa4cc; color: #121a24; } .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-lightblue.btn:active, .dark-mode .bg-gradient-lightblue.btn.active { background: #86bad8 linear-gradient(180deg, #77b2d4, #5fa4cc) repeat-x !important; border-color: #559ec9; color: #fff; } .dark-mode .bg-gradient-lightblue.btn:disabled, .dark-mode .bg-gradient-lightblue.btn.disabled { background-image: none !important; border-color: #86bad8; color: #1f2d3d; } .dark-mode .bg-gradient-navy { background: #002c59 linear-gradient(180deg, #264b71, #002c59) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-navy.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-navy.btn:hover { background: #002c59 linear-gradient(180deg, #263b51, #001932) repeat-x !important; border-color: #001226; color: #ececec; } .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-navy.btn:active, .dark-mode .bg-gradient-navy.btn.active { background: #002c59 linear-gradient(180deg, #263646, #001226) repeat-x !important; border-color: #000c19; color: #fff; } .dark-mode .bg-gradient-navy.btn:disabled, .dark-mode .bg-gradient-navy.btn.disabled { background-image: none !important; border-color: #002c59; color: #fff; } .dark-mode .bg-gradient-olive { background: #74c8a3 linear-gradient(180deg, #89d0b0, #74c8a3) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-olive.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-olive.btn:hover { background: #74c8a3 linear-gradient(180deg, #72c7a1, #59bd90) repeat-x !important; border-color: #50b98a; color: #121a24; } .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-olive.btn:active, .dark-mode .bg-gradient-olive.btn.active { background: #74c8a3 linear-gradient(180deg, #6ac49c, #50b98a) repeat-x !important; border-color: #48b484; color: #fff; } .dark-mode .bg-gradient-olive.btn:disabled, .dark-mode .bg-gradient-olive.btn.disabled { background-image: none !important; border-color: #74c8a3; color: #1f2d3d; } .dark-mode .bg-gradient-lime { background: #67ffa9 linear-gradient(180deg, #7effb6, #67ffa9) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-lime.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-lime.btn:hover { background: #67ffa9 linear-gradient(180deg, #5dffa4, #41ff94) repeat-x !important; border-color: #34ff8d; color: #121a24; } .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-lime.btn:active, .dark-mode .bg-gradient-lime.btn.active { background: #67ffa9 linear-gradient(180deg, #52ff9e, #34ff8d) repeat-x !important; border-color: #27ff86; color: #1f2d3d; } .dark-mode .bg-gradient-lime.btn:disabled, .dark-mode .bg-gradient-lime.btn.disabled { background-image: none !important; border-color: #67ffa9; color: #1f2d3d; } .dark-mode .bg-gradient-fuchsia { background: #f672d8 linear-gradient(180deg, #f787de, #f672d8) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-fuchsia.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-fuchsia.btn:hover { background: #f672d8 linear-gradient(180deg, #f569d6, #f44ece) repeat-x !important; border-color: #f342cb; color: #121a24; } .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-fuchsia.btn:active, .dark-mode .bg-gradient-fuchsia.btn.active { background: #f672d8 linear-gradient(180deg, #f55ed3, #f342cb) repeat-x !important; border-color: #f236c8; color: #fff; } .dark-mode .bg-gradient-fuchsia.btn:disabled, .dark-mode .bg-gradient-fuchsia.btn.disabled { background-image: none !important; border-color: #f672d8; color: #1f2d3d; } .dark-mode .bg-gradient-maroon { background: #ed6c9b linear-gradient(180deg, #ef82aa, #ed6c9b) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-maroon.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-maroon.btn:hover { background: #ed6c9b linear-gradient(180deg, #ec6596, #e84a84) repeat-x !important; border-color: #e73f7c; color: #121a24; } .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-maroon.btn:active, .dark-mode .bg-gradient-maroon.btn.active { background: #ed6c9b linear-gradient(180deg, #eb5c90, #e73f7c) repeat-x !important; border-color: #e63475; color: #fff; } .dark-mode .bg-gradient-maroon.btn:disabled, .dark-mode .bg-gradient-maroon.btn.disabled { background-image: none !important; border-color: #ed6c9b; color: #1f2d3d; } .dark-mode .bg-gradient-blue { background: #3f6791 linear-gradient(180deg, #5c7ea2, #3f6791) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-blue.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-blue.btn:hover { background: #3f6791 linear-gradient(180deg, #526e8b, #335476) repeat-x !important; border-color: #304e6d; color: #ececec; } .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-blue.btn:active, .dark-mode .bg-gradient-blue.btn.active { background: #3f6791 linear-gradient(180deg, #4f6883, #304e6d) repeat-x !important; border-color: #2c4765; color: #fff; } .dark-mode .bg-gradient-blue.btn:disabled, .dark-mode .bg-gradient-blue.btn.disabled { background-image: none !important; border-color: #3f6791; color: #fff; } .dark-mode .bg-gradient-indigo { background: #6610f2 linear-gradient(180deg, #7d34f4, #6610f2) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-indigo.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-indigo.btn:hover { background: #6610f2 linear-gradient(180deg, #7030d7, #560bd0) repeat-x !important; border-color: #510bc4; color: #ececec; } .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-indigo.btn:active, .dark-mode .bg-gradient-indigo.btn.active { background: #6610f2 linear-gradient(180deg, #6b2fcd, #510bc4) repeat-x !important; border-color: #4c0ab8; color: #fff; } .dark-mode .bg-gradient-indigo.btn:disabled, .dark-mode .bg-gradient-indigo.btn.disabled { background-image: none !important; border-color: #6610f2; color: #fff; } .dark-mode .bg-gradient-purple { background: #6f42c1 linear-gradient(180deg, #855eca, #6f42c1) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-purple.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-purple.btn:hover { background: #6f42c1 linear-gradient(180deg, #7655b4, #5e37a6) repeat-x !important; border-color: #59339d; color: #ececec; } .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-purple.btn:active, .dark-mode .bg-gradient-purple.btn.active { background: #6f42c1 linear-gradient(180deg, #7252ab, #59339d) repeat-x !important; border-color: #533093; color: #fff; } .dark-mode .bg-gradient-purple.btn:disabled, .dark-mode .bg-gradient-purple.btn.disabled { background-image: none !important; border-color: #6f42c1; color: #fff; } .dark-mode .bg-gradient-pink { background: #e83e8c linear-gradient(180deg, #eb5b9d, #e83e8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-pink.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-pink.btn:hover { background: #e83e8c linear-gradient(180deg, #e83e8c, #e41c78) repeat-x !important; border-color: #d91a72; color: #ececec; } .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-pink.btn:active, .dark-mode .bg-gradient-pink.btn.active { background: #e83e8c linear-gradient(180deg, #df3c87, #d91a72) repeat-x !important; border-color: #ce196c; color: #fff; } .dark-mode .bg-gradient-pink.btn:disabled, .dark-mode .bg-gradient-pink.btn.disabled { background-image: none !important; border-color: #e83e8c; color: #fff; } .dark-mode .bg-gradient-red { background: #e74c3c linear-gradient(180deg, #eb6759, #e74c3c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-red.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-red.btn:hover { background: #e74c3c linear-gradient(180deg, #e64d3e, #e12e1c) repeat-x !important; border-color: #d62c1a; color: #ececec; } .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-red.btn:active, .dark-mode .bg-gradient-red.btn.active { background: #e74c3c linear-gradient(180deg, #dc4c3d, #d62c1a) repeat-x !important; border-color: #ca2a19; color: #fff; } .dark-mode .bg-gradient-red.btn:disabled, .dark-mode .bg-gradient-red.btn.disabled { background-image: none !important; border-color: #e74c3c; color: #fff; } .dark-mode .bg-gradient-orange { background: #fd7e14 linear-gradient(180deg, #fd9137, #fd7e14) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-orange.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-orange.btn:hover { background: #fd7e14 linear-gradient(180deg, #ec8128, #e96b02) repeat-x !important; border-color: #dc6502; color: #121a24; } .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-orange.btn:active, .dark-mode .bg-gradient-orange.btn.active { background: #fd7e14 linear-gradient(180deg, #e17c28, #dc6502) repeat-x !important; border-color: #cf5f02; color: #fff; } .dark-mode .bg-gradient-orange.btn:disabled, .dark-mode .bg-gradient-orange.btn.disabled { background-image: none !important; border-color: #fd7e14; color: #1f2d3d; } .dark-mode .bg-gradient-yellow { background: #f39c12 linear-gradient(180deg, #f5ab36, #f39c12) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-yellow.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-yellow.btn:hover { background: #f39c12 linear-gradient(180deg, #da982f, #d4860b) repeat-x !important; border-color: #c87f0a; color: #121a24; } .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-yellow.btn:active, .dark-mode .bg-gradient-yellow.btn.active { background: #f39c12 linear-gradient(180deg, #d0922f, #c87f0a) repeat-x !important; border-color: #bc770a; color: #fff; } .dark-mode .bg-gradient-yellow.btn:disabled, .dark-mode .bg-gradient-yellow.btn.disabled { background-image: none !important; border-color: #f39c12; color: #1f2d3d; } .dark-mode .bg-gradient-green { background: #00bc8c linear-gradient(180deg, #26c69d, #00bc8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-green.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-green.btn:hover { background: #00bc8c linear-gradient(180deg, #26a685, #009670) repeat-x !important; border-color: #008966; color: #ececec; } .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-green.btn:active, .dark-mode .bg-gradient-green.btn.active { background: #00bc8c linear-gradient(180deg, #269b7d, #008966) repeat-x !important; border-color: #007c5d; color: #fff; } .dark-mode .bg-gradient-green.btn:disabled, .dark-mode .bg-gradient-green.btn.disabled { background-image: none !important; border-color: #00bc8c; color: #fff; } .dark-mode .bg-gradient-teal { background: #20c997 linear-gradient(180deg, #41d1a7, #20c997) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-teal.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-teal.btn:hover { background: #20c997 linear-gradient(180deg, #3db592, #1ba87e) repeat-x !important; border-color: #199d76; color: #ececec; } .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-teal.btn:active, .dark-mode .bg-gradient-teal.btn.active { background: #20c997 linear-gradient(180deg, #3bac8b, #199d76) repeat-x !important; border-color: #17926e; color: #fff; } .dark-mode .bg-gradient-teal.btn:disabled, .dark-mode .bg-gradient-teal.btn.disabled { background-image: none !important; border-color: #20c997; color: #fff; } .dark-mode .bg-gradient-cyan { background: #3498db linear-gradient(180deg, #52a7e0, #3498db) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-cyan.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-cyan.btn:hover { background: #3498db linear-gradient(180deg, #4497ce, #2384c6) repeat-x !important; border-color: #217dbb; color: #ececec; } .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-cyan.btn:active, .dark-mode .bg-gradient-cyan.btn.active { background: #3498db linear-gradient(180deg, #4291c5, #217dbb) repeat-x !important; border-color: #1f76b0; color: #fff; } .dark-mode .bg-gradient-cyan.btn:disabled, .dark-mode .bg-gradient-cyan.btn.disabled { background-image: none !important; border-color: #3498db; color: #fff; } .dark-mode .bg-gradient-white { background: #fff linear-gradient(180deg, white, #fff) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-white.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-white.btn:hover { background: #fff linear-gradient(180deg, #efefef, #ececec) repeat-x !important; border-color: #e6e6e6; color: #121a24; } .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-white.btn:active, .dark-mode .bg-gradient-white.btn.active { background: #fff linear-gradient(180deg, #e9e9e9, #e6e6e6) repeat-x !important; border-color: #dfdfdf; color: #1f2d3d; } .dark-mode .bg-gradient-white.btn:disabled, .dark-mode .bg-gradient-white.btn.disabled { background-image: none !important; border-color: #fff; color: #1f2d3d; } .dark-mode .bg-gradient-gray { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-gray.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-gray.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-gray.btn:active, .dark-mode .bg-gradient-gray.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .dark-mode .bg-gradient-gray.btn:disabled, .dark-mode .bg-gradient-gray.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .dark-mode .bg-gradient-gray-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-gray-dark.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-gray-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-gray-dark.btn:active, .dark-mode .bg-gradient-gray-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-gray-dark.btn:disabled, .dark-mode .bg-gradient-gray-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .dark-mode .accent-primary .btn-link, .dark-mode .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-primary .nav-tabs .nav-link { color: #3f6791; } .dark-mode .accent-primary .btn-link:hover, .dark-mode .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-primary .nav-tabs .nav-link:hover { color: #28415c; } .dark-mode .accent-primary .dropdown-item:active, .dark-mode .accent-primary .dropdown-item.active { background-color: #3f6791; color: #fff; } .dark-mode .accent-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .accent-primary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-primary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-primary .custom-select:focus, .dark-mode .accent-primary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-primary .custom-file-input:focus ~ .custom-file-label { border-color: #85a7ca; } .dark-mode .accent-primary .page-item .page-link { color: #3f6791; } .dark-mode .accent-primary .page-item.active a, .dark-mode .accent-primary .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .accent-primary .page-item.disabled a, .dark-mode .accent-primary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-primary .page-item .page-link:hover, .dark-mode .dark-mode.accent-primary .page-item .page-link:focus { color: #4774a3; } .dark-mode .accent-secondary .btn-link, .dark-mode .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-secondary .nav-tabs .nav-link { color: #6c757d; } .dark-mode .accent-secondary .btn-link:hover, .dark-mode .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-secondary .nav-tabs .nav-link:hover { color: #494f54; } .dark-mode .accent-secondary .dropdown-item:active, .dark-mode .accent-secondary .dropdown-item.active { background-color: #6c757d; color: #fff; } .dark-mode .accent-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .accent-secondary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-secondary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-secondary .custom-select:focus, .dark-mode .accent-secondary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-secondary .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .dark-mode .accent-secondary .page-item .page-link { color: #6c757d; } .dark-mode .accent-secondary .page-item.active a, .dark-mode .accent-secondary .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .accent-secondary .page-item.disabled a, .dark-mode .accent-secondary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-secondary .page-item .page-link:hover, .dark-mode .dark-mode.accent-secondary .page-item .page-link:focus { color: #78828a; } .dark-mode .accent-success .btn-link, .dark-mode .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-success .nav-tabs .nav-link { color: #00bc8c; } .dark-mode .accent-success .btn-link:hover, .dark-mode .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-success .nav-tabs .nav-link:hover { color: #007053; } .dark-mode .accent-success .dropdown-item:active, .dark-mode .accent-success .dropdown-item.active { background-color: #00bc8c; color: #fff; } .dark-mode .accent-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .accent-success .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-success .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-success .custom-select:focus, .dark-mode .accent-success .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-success .custom-file-input:focus ~ .custom-file-label { border-color: #3dffcd; } .dark-mode .accent-success .page-item .page-link { color: #00bc8c; } .dark-mode .accent-success .page-item.active a, .dark-mode .accent-success .page-item.active .page-link { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .accent-success .page-item.disabled a, .dark-mode .accent-success .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-success .page-item .page-link:hover, .dark-mode .dark-mode.accent-success .page-item .page-link:focus { color: #00d69f; } .dark-mode .accent-info .btn-link, .dark-mode .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-info .nav-tabs .nav-link { color: #3498db; } .dark-mode .accent-info .btn-link:hover, .dark-mode .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-info .nav-tabs .nav-link:hover { color: #1d6fa5; } .dark-mode .accent-info .dropdown-item:active, .dark-mode .accent-info .dropdown-item.active { background-color: #3498db; color: #fff; } .dark-mode .accent-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .accent-info .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-info .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-info .custom-select:focus, .dark-mode .accent-info .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-info .custom-file-input:focus ~ .custom-file-label { border-color: #a0cfee; } .dark-mode .accent-info .page-item .page-link { color: #3498db; } .dark-mode .accent-info .page-item.active a, .dark-mode .accent-info .page-item.active .page-link { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .accent-info .page-item.disabled a, .dark-mode .accent-info .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-info .page-item .page-link:hover, .dark-mode .dark-mode.accent-info .page-item .page-link:focus { color: #4aa3df; } .dark-mode .accent-warning .btn-link, .dark-mode .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-warning .nav-tabs .nav-link { color: #f39c12; } .dark-mode .accent-warning .btn-link:hover, .dark-mode .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-warning .nav-tabs .nav-link:hover { color: #b06f09; } .dark-mode .accent-warning .dropdown-item:active, .dark-mode .accent-warning .dropdown-item.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .accent-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .accent-warning .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-warning .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-warning .custom-select:focus, .dark-mode .accent-warning .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-warning .custom-file-input:focus ~ .custom-file-label { border-color: #f9cf8b; } .dark-mode .accent-warning .page-item .page-link { color: #f39c12; } .dark-mode .accent-warning .page-item.active a, .dark-mode .accent-warning .page-item.active .page-link { background-color: #f39c12; border-color: #f39c12; color: #fff; } .dark-mode .accent-warning .page-item.disabled a, .dark-mode .accent-warning .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-warning .page-item .page-link:hover, .dark-mode .dark-mode.accent-warning .page-item .page-link:focus { color: #f4a62a; } .dark-mode .accent-danger .btn-link, .dark-mode .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-danger .nav-tabs .nav-link { color: #e74c3c; } .dark-mode .accent-danger .btn-link:hover, .dark-mode .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-danger .nav-tabs .nav-link:hover { color: #bf2718; } .dark-mode .accent-danger .dropdown-item:active, .dark-mode .accent-danger .dropdown-item.active { background-color: #e74c3c; color: #fff; } .dark-mode .accent-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .accent-danger .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-danger .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-danger .custom-select:focus, .dark-mode .accent-danger .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-danger .custom-file-input:focus ~ .custom-file-label { border-color: #f5b4ae; } .dark-mode .accent-danger .page-item .page-link { color: #e74c3c; } .dark-mode .accent-danger .page-item.active a, .dark-mode .accent-danger .page-item.active .page-link { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .accent-danger .page-item.disabled a, .dark-mode .accent-danger .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-danger .page-item .page-link:hover, .dark-mode .dark-mode.accent-danger .page-item .page-link:focus { color: #ea6153; } .dark-mode .accent-light .btn-link, .dark-mode .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-light .nav-tabs .nav-link { color: #f8f9fa; } .dark-mode .accent-light .btn-link:hover, .dark-mode .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-light .nav-tabs .nav-link:hover { color: #cbd3da; } .dark-mode .accent-light .dropdown-item:active, .dark-mode .accent-light .dropdown-item.active { background-color: #f8f9fa; color: #1f2d3d; } .dark-mode .accent-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .accent-light .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-light .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-light .custom-select:focus, .dark-mode .accent-light .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-light .custom-file-input:focus ~ .custom-file-label { border-color: white; } .dark-mode .accent-light .page-item .page-link { color: #f8f9fa; } .dark-mode .accent-light .page-item.active a, .dark-mode .accent-light .page-item.active .page-link { background-color: #f8f9fa; border-color: #f8f9fa; color: #fff; } .dark-mode .accent-light .page-item.disabled a, .dark-mode .accent-light .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-light .page-item .page-link:hover, .dark-mode .dark-mode.accent-light .page-item .page-link:focus { color: white; } .dark-mode .accent-dark .btn-link, .dark-mode .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-dark .nav-tabs .nav-link { color: #343a40; } .dark-mode .accent-dark .btn-link:hover, .dark-mode .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-dark .nav-tabs .nav-link:hover { color: #121416; } .dark-mode .accent-dark .dropdown-item:active, .dark-mode .accent-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .dark-mode .accent-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .accent-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-dark .custom-select:focus, .dark-mode .accent-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .dark-mode .accent-dark .page-item .page-link { color: #343a40; } .dark-mode .accent-dark .page-item.active a, .dark-mode .accent-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .accent-dark .page-item.disabled a, .dark-mode .accent-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-dark .page-item .page-link:hover, .dark-mode .dark-mode.accent-dark .page-item .page-link:focus { color: #3f474e; } .dark-mode [class*="accent-"] a.btn-primary { color: #fff; } .dark-mode [class*="accent-"] a.btn-secondary { color: #fff; } .dark-mode [class*="accent-"] a.btn-success { color: #fff; } .dark-mode [class*="accent-"] a.btn-info { color: #fff; } .dark-mode [class*="accent-"] a.btn-warning { color: #1f2d3d; } .dark-mode [class*="accent-"] a.btn-danger { color: #fff; } .dark-mode [class*="accent-"] a.btn-light { color: #1f2d3d; } .dark-mode [class*="accent-"] a.btn-dark { color: #fff; } .dark-mode .accent-lightblue .btn-link, .dark-mode .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-lightblue .nav-tabs .nav-link { color: #86bad8; } .dark-mode .accent-lightblue .btn-link:hover, .dark-mode .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-lightblue .nav-tabs .nav-link:hover { color: #4c99c6; } .dark-mode .accent-lightblue .dropdown-item:active, .dark-mode .accent-lightblue .dropdown-item.active { background-color: #86bad8; color: #1f2d3d; } .dark-mode .accent-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .accent-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-lightblue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-lightblue .custom-select:focus, .dark-mode .accent-lightblue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-lightblue .custom-file-input:focus ~ .custom-file-label { border-color: #e6f1f7; } .dark-mode .accent-lightblue .page-item .page-link { color: #86bad8; } .dark-mode .accent-lightblue .page-item.active a, .dark-mode .accent-lightblue .page-item.active .page-link { background-color: #86bad8; border-color: #86bad8; color: #fff; } .dark-mode .accent-lightblue .page-item.disabled a, .dark-mode .accent-lightblue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-lightblue .page-item .page-link:hover, .dark-mode .dark-mode.accent-lightblue .page-item .page-link:focus { color: #99c5de; } .dark-mode .accent-navy .btn-link, .dark-mode .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-navy .nav-tabs .nav-link { color: #002c59; } .dark-mode .accent-navy .btn-link:hover, .dark-mode .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-navy .nav-tabs .nav-link:hover { color: #00060c; } .dark-mode .accent-navy .dropdown-item:active, .dark-mode .accent-navy .dropdown-item.active { background-color: #002c59; color: #fff; } .dark-mode .accent-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .accent-navy .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-navy .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-navy .custom-select:focus, .dark-mode .accent-navy .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-navy .custom-file-input:focus ~ .custom-file-label { border-color: #006ad8; } .dark-mode .accent-navy .page-item .page-link { color: #002c59; } .dark-mode .accent-navy .page-item.active a, .dark-mode .accent-navy .page-item.active .page-link { background-color: #002c59; border-color: #002c59; color: #fff; } .dark-mode .accent-navy .page-item.disabled a, .dark-mode .accent-navy .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-navy .page-item .page-link:hover, .dark-mode .dark-mode.accent-navy .page-item .page-link:focus { color: #003872; } .dark-mode .accent-olive .btn-link, .dark-mode .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-olive .nav-tabs .nav-link { color: #74c8a3; } .dark-mode .accent-olive .btn-link:hover, .dark-mode .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-olive .nav-tabs .nav-link:hover { color: #44ab7d; } .dark-mode .accent-olive .dropdown-item:active, .dark-mode .accent-olive .dropdown-item.active { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .accent-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .accent-olive .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-olive .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-olive .custom-select:focus, .dark-mode .accent-olive .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-olive .custom-file-input:focus ~ .custom-file-label { border-color: #cfecdf; } .dark-mode .accent-olive .page-item .page-link { color: #74c8a3; } .dark-mode .accent-olive .page-item.active a, .dark-mode .accent-olive .page-item.active .page-link { background-color: #74c8a3; border-color: #74c8a3; color: #fff; } .dark-mode .accent-olive .page-item.disabled a, .dark-mode .accent-olive .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-olive .page-item .page-link:hover, .dark-mode .dark-mode.accent-olive .page-item .page-link:focus { color: #87cfaf; } .dark-mode .accent-lime .btn-link, .dark-mode .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-lime .nav-tabs .nav-link { color: #67ffa9; } .dark-mode .accent-lime .btn-link:hover, .dark-mode .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-lime .nav-tabs .nav-link:hover { color: #1bff7e; } .dark-mode .accent-lime .dropdown-item:active, .dark-mode .accent-lime .dropdown-item.active { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .accent-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .accent-lime .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-lime .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-lime .custom-select:focus, .dark-mode .accent-lime .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-lime .custom-file-input:focus ~ .custom-file-label { border-color: #e7fff1; } .dark-mode .accent-lime .page-item .page-link { color: #67ffa9; } .dark-mode .accent-lime .page-item.active a, .dark-mode .accent-lime .page-item.active .page-link { background-color: #67ffa9; border-color: #67ffa9; color: #fff; } .dark-mode .accent-lime .page-item.disabled a, .dark-mode .accent-lime .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-lime .page-item .page-link:hover, .dark-mode .dark-mode.accent-lime .page-item .page-link:focus { color: #81ffb8; } .dark-mode .accent-fuchsia .btn-link, .dark-mode .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-fuchsia .nav-tabs .nav-link { color: #f672d8; } .dark-mode .accent-fuchsia .btn-link:hover, .dark-mode .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-fuchsia .nav-tabs .nav-link:hover { color: #f22ac5; } .dark-mode .accent-fuchsia .dropdown-item:active, .dark-mode .accent-fuchsia .dropdown-item.active { background-color: #f672d8; color: #1f2d3d; } .dark-mode .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-fuchsia .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-fuchsia .custom-select:focus, .dark-mode .accent-fuchsia .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-fuchsia .custom-file-input:focus ~ .custom-file-label { border-color: #feeaf9; } .dark-mode .accent-fuchsia .page-item .page-link { color: #f672d8; } .dark-mode .accent-fuchsia .page-item.active a, .dark-mode .accent-fuchsia .page-item.active .page-link { background-color: #f672d8; border-color: #f672d8; color: #fff; } .dark-mode .accent-fuchsia .page-item.disabled a, .dark-mode .accent-fuchsia .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-fuchsia .page-item .page-link:hover, .dark-mode .dark-mode.accent-fuchsia .page-item .page-link:focus { color: #f88adf; } .dark-mode .accent-maroon .btn-link, .dark-mode .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-maroon .nav-tabs .nav-link { color: #ed6c9b; } .dark-mode .accent-maroon .btn-link:hover, .dark-mode .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-maroon .nav-tabs .nav-link:hover { color: #e4286d; } .dark-mode .accent-maroon .dropdown-item:active, .dark-mode .accent-maroon .dropdown-item.active { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .accent-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .accent-maroon .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-maroon .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-maroon .custom-select:focus, .dark-mode .accent-maroon .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-maroon .custom-file-input:focus ~ .custom-file-label { border-color: #fbdee8; } .dark-mode .accent-maroon .page-item .page-link { color: #ed6c9b; } .dark-mode .accent-maroon .page-item.active a, .dark-mode .accent-maroon .page-item.active .page-link { background-color: #ed6c9b; border-color: #ed6c9b; color: #fff; } .dark-mode .accent-maroon .page-item.disabled a, .dark-mode .accent-maroon .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-maroon .page-item .page-link:hover, .dark-mode .dark-mode.accent-maroon .page-item .page-link:focus { color: #f083ab; } .dark-mode .accent-blue .btn-link, .dark-mode .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-blue .nav-tabs .nav-link { color: #3f6791; } .dark-mode .accent-blue .btn-link:hover, .dark-mode .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-blue .nav-tabs .nav-link:hover { color: #28415c; } .dark-mode .accent-blue .dropdown-item:active, .dark-mode .accent-blue .dropdown-item.active { background-color: #3f6791; color: #fff; } .dark-mode .accent-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .accent-blue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-blue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-blue .custom-select:focus, .dark-mode .accent-blue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-blue .custom-file-input:focus ~ .custom-file-label { border-color: #85a7ca; } .dark-mode .accent-blue .page-item .page-link { color: #3f6791; } .dark-mode .accent-blue .page-item.active a, .dark-mode .accent-blue .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .accent-blue .page-item.disabled a, .dark-mode .accent-blue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-blue .page-item .page-link:hover, .dark-mode .dark-mode.accent-blue .page-item .page-link:focus { color: #4774a3; } .dark-mode .accent-indigo .btn-link, .dark-mode .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-indigo .nav-tabs .nav-link { color: #6610f2; } .dark-mode .accent-indigo .btn-link:hover, .dark-mode .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-indigo .nav-tabs .nav-link:hover { color: #4709ac; } .dark-mode .accent-indigo .dropdown-item:active, .dark-mode .accent-indigo .dropdown-item.active { background-color: #6610f2; color: #fff; } .dark-mode .accent-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .accent-indigo .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-indigo .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-indigo .custom-select:focus, .dark-mode .accent-indigo .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-indigo .custom-file-input:focus ~ .custom-file-label { border-color: #b389f9; } .dark-mode .accent-indigo .page-item .page-link { color: #6610f2; } .dark-mode .accent-indigo .page-item.active a, .dark-mode .accent-indigo .page-item.active .page-link { background-color: #6610f2; border-color: #6610f2; color: #fff; } .dark-mode .accent-indigo .page-item.disabled a, .dark-mode .accent-indigo .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-indigo .page-item .page-link:hover, .dark-mode .dark-mode.accent-indigo .page-item .page-link:focus { color: #7528f3; } .dark-mode .accent-purple .btn-link, .dark-mode .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-purple .nav-tabs .nav-link { color: #6f42c1; } .dark-mode .accent-purple .btn-link:hover, .dark-mode .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-purple .nav-tabs .nav-link:hover { color: #4e2d89; } .dark-mode .accent-purple .dropdown-item:active, .dark-mode .accent-purple .dropdown-item.active { background-color: #6f42c1; color: #fff; } .dark-mode .accent-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .accent-purple .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-purple .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-purple .custom-select:focus, .dark-mode .accent-purple .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-purple .custom-file-input:focus ~ .custom-file-label { border-color: #b8a2e0; } .dark-mode .accent-purple .page-item .page-link { color: #6f42c1; } .dark-mode .accent-purple .page-item.active a, .dark-mode .accent-purple .page-item.active .page-link { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .dark-mode .accent-purple .page-item.disabled a, .dark-mode .accent-purple .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-purple .page-item .page-link:hover, .dark-mode .dark-mode.accent-purple .page-item .page-link:focus { color: #7e55c7; } .dark-mode .accent-pink .btn-link, .dark-mode .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-pink .nav-tabs .nav-link { color: #e83e8c; } .dark-mode .accent-pink .btn-link:hover, .dark-mode .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-pink .nav-tabs .nav-link:hover { color: #c21766; } .dark-mode .accent-pink .dropdown-item:active, .dark-mode .accent-pink .dropdown-item.active { background-color: #e83e8c; color: #fff; } .dark-mode .accent-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .accent-pink .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-pink .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-pink .custom-select:focus, .dark-mode .accent-pink .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-pink .custom-file-input:focus ~ .custom-file-label { border-color: #f6b0d0; } .dark-mode .accent-pink .page-item .page-link { color: #e83e8c; } .dark-mode .accent-pink .page-item.active a, .dark-mode .accent-pink .page-item.active .page-link { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .dark-mode .accent-pink .page-item.disabled a, .dark-mode .accent-pink .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-pink .page-item .page-link:hover, .dark-mode .dark-mode.accent-pink .page-item .page-link:focus { color: #eb559a; } .dark-mode .accent-red .btn-link, .dark-mode .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-red .nav-tabs .nav-link { color: #e74c3c; } .dark-mode .accent-red .btn-link:hover, .dark-mode .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-red .nav-tabs .nav-link:hover { color: #bf2718; } .dark-mode .accent-red .dropdown-item:active, .dark-mode .accent-red .dropdown-item.active { background-color: #e74c3c; color: #fff; } .dark-mode .accent-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .accent-red .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-red .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-red .custom-select:focus, .dark-mode .accent-red .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-red .custom-file-input:focus ~ .custom-file-label { border-color: #f5b4ae; } .dark-mode .accent-red .page-item .page-link { color: #e74c3c; } .dark-mode .accent-red .page-item.active a, .dark-mode .accent-red .page-item.active .page-link { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .accent-red .page-item.disabled a, .dark-mode .accent-red .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-red .page-item .page-link:hover, .dark-mode .dark-mode.accent-red .page-item .page-link:focus { color: #ea6153; } .dark-mode .accent-orange .btn-link, .dark-mode .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-orange .nav-tabs .nav-link { color: #fd7e14; } .dark-mode .accent-orange .btn-link:hover, .dark-mode .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-orange .nav-tabs .nav-link:hover { color: #c35a02; } .dark-mode .accent-orange .dropdown-item:active, .dark-mode .accent-orange .dropdown-item.active { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .accent-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .accent-orange .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-orange .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-orange .custom-select:focus, .dark-mode .accent-orange .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-orange .custom-file-input:focus ~ .custom-file-label { border-color: #fec392; } .dark-mode .accent-orange .page-item .page-link { color: #fd7e14; } .dark-mode .accent-orange .page-item.active a, .dark-mode .accent-orange .page-item.active .page-link { background-color: #fd7e14; border-color: #fd7e14; color: #fff; } .dark-mode .accent-orange .page-item.disabled a, .dark-mode .accent-orange .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-orange .page-item .page-link:hover, .dark-mode .dark-mode.accent-orange .page-item .page-link:focus { color: #fd8c2d; } .dark-mode .accent-yellow .btn-link, .dark-mode .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-yellow .nav-tabs .nav-link { color: #f39c12; } .dark-mode .accent-yellow .btn-link:hover, .dark-mode .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-yellow .nav-tabs .nav-link:hover { color: #b06f09; } .dark-mode .accent-yellow .dropdown-item:active, .dark-mode .accent-yellow .dropdown-item.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .accent-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .accent-yellow .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-yellow .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-yellow .custom-select:focus, .dark-mode .accent-yellow .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-yellow .custom-file-input:focus ~ .custom-file-label { border-color: #f9cf8b; } .dark-mode .accent-yellow .page-item .page-link { color: #f39c12; } .dark-mode .accent-yellow .page-item.active a, .dark-mode .accent-yellow .page-item.active .page-link { background-color: #f39c12; border-color: #f39c12; color: #fff; } .dark-mode .accent-yellow .page-item.disabled a, .dark-mode .accent-yellow .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-yellow .page-item .page-link:hover, .dark-mode .dark-mode.accent-yellow .page-item .page-link:focus { color: #f4a62a; } .dark-mode .accent-green .btn-link, .dark-mode .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-green .nav-tabs .nav-link { color: #00bc8c; } .dark-mode .accent-green .btn-link:hover, .dark-mode .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-green .nav-tabs .nav-link:hover { color: #007053; } .dark-mode .accent-green .dropdown-item:active, .dark-mode .accent-green .dropdown-item.active { background-color: #00bc8c; color: #fff; } .dark-mode .accent-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .accent-green .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-green .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-green .custom-select:focus, .dark-mode .accent-green .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-green .custom-file-input:focus ~ .custom-file-label { border-color: #3dffcd; } .dark-mode .accent-green .page-item .page-link { color: #00bc8c; } .dark-mode .accent-green .page-item.active a, .dark-mode .accent-green .page-item.active .page-link { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .accent-green .page-item.disabled a, .dark-mode .accent-green .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-green .page-item .page-link:hover, .dark-mode .dark-mode.accent-green .page-item .page-link:focus { color: #00d69f; } .dark-mode .accent-teal .btn-link, .dark-mode .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-teal .nav-tabs .nav-link { color: #20c997; } .dark-mode .accent-teal .btn-link:hover, .dark-mode .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-teal .nav-tabs .nav-link:hover { color: #158765; } .dark-mode .accent-teal .dropdown-item:active, .dark-mode .accent-teal .dropdown-item.active { background-color: #20c997; color: #fff; } .dark-mode .accent-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .accent-teal .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-teal .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-teal .custom-select:focus, .dark-mode .accent-teal .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-teal .custom-file-input:focus ~ .custom-file-label { border-color: #7eeaca; } .dark-mode .accent-teal .page-item .page-link { color: #20c997; } .dark-mode .accent-teal .page-item.active a, .dark-mode .accent-teal .page-item.active .page-link { background-color: #20c997; border-color: #20c997; color: #fff; } .dark-mode .accent-teal .page-item.disabled a, .dark-mode .accent-teal .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-teal .page-item .page-link:hover, .dark-mode .dark-mode.accent-teal .page-item .page-link:focus { color: #26dca6; } .dark-mode .accent-cyan .btn-link, .dark-mode .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-cyan .nav-tabs .nav-link { color: #3498db; } .dark-mode .accent-cyan .btn-link:hover, .dark-mode .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-cyan .nav-tabs .nav-link:hover { color: #1d6fa5; } .dark-mode .accent-cyan .dropdown-item:active, .dark-mode .accent-cyan .dropdown-item.active { background-color: #3498db; color: #fff; } .dark-mode .accent-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .accent-cyan .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-cyan .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-cyan .custom-select:focus, .dark-mode .accent-cyan .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-cyan .custom-file-input:focus ~ .custom-file-label { border-color: #a0cfee; } .dark-mode .accent-cyan .page-item .page-link { color: #3498db; } .dark-mode .accent-cyan .page-item.active a, .dark-mode .accent-cyan .page-item.active .page-link { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .accent-cyan .page-item.disabled a, .dark-mode .accent-cyan .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-cyan .page-item .page-link:hover, .dark-mode .dark-mode.accent-cyan .page-item .page-link:focus { color: #4aa3df; } .dark-mode .accent-white .btn-link, .dark-mode .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-white .nav-tabs .nav-link { color: #fff; } .dark-mode .accent-white .btn-link:hover, .dark-mode .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-white .nav-tabs .nav-link:hover { color: #d9d9d9; } .dark-mode .accent-white .dropdown-item:active, .dark-mode .accent-white .dropdown-item.active { background-color: #fff; color: #1f2d3d; } .dark-mode .accent-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .accent-white .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-white .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-white .custom-select:focus, .dark-mode .accent-white .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-white .custom-file-input:focus ~ .custom-file-label { border-color: white; } .dark-mode .accent-white .page-item .page-link { color: #fff; } .dark-mode .accent-white .page-item.active a, .dark-mode .accent-white .page-item.active .page-link { background-color: #fff; border-color: #fff; color: #fff; } .dark-mode .accent-white .page-item.disabled a, .dark-mode .accent-white .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-white .page-item .page-link:hover, .dark-mode .dark-mode.accent-white .page-item .page-link:focus { color: white; } .dark-mode .accent-gray .btn-link, .dark-mode .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-gray .nav-tabs .nav-link { color: #6c757d; } .dark-mode .accent-gray .btn-link:hover, .dark-mode .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-gray .nav-tabs .nav-link:hover { color: #494f54; } .dark-mode .accent-gray .dropdown-item:active, .dark-mode .accent-gray .dropdown-item.active { background-color: #6c757d; color: #fff; } .dark-mode .accent-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .accent-gray .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-gray .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-gray .custom-select:focus, .dark-mode .accent-gray .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-gray .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .dark-mode .accent-gray .page-item .page-link { color: #6c757d; } .dark-mode .accent-gray .page-item.active a, .dark-mode .accent-gray .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .accent-gray .page-item.disabled a, .dark-mode .accent-gray .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-gray .page-item .page-link:hover, .dark-mode .dark-mode.accent-gray .page-item .page-link:focus { color: #78828a; } .dark-mode .accent-gray-dark .btn-link, .dark-mode .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-gray-dark .nav-tabs .nav-link { color: #343a40; } .dark-mode .accent-gray-dark .btn-link:hover, .dark-mode .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-gray-dark .nav-tabs .nav-link:hover { color: #121416; } .dark-mode .accent-gray-dark .dropdown-item:active, .dark-mode .accent-gray-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .dark-mode .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-gray-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-gray-dark .custom-select:focus, .dark-mode .accent-gray-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-gray-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .dark-mode .accent-gray-dark .page-item .page-link { color: #343a40; } .dark-mode .accent-gray-dark .page-item.active a, .dark-mode .accent-gray-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .accent-gray-dark .page-item.disabled a, .dark-mode .accent-gray-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-gray-dark .page-item .page-link:hover, .dark-mode .dark-mode.accent-gray-dark .page-item .page-link:focus { color: #3f474e; } .dark-mode .border-dark { border-color: #4b545c !important; } /*# sourceMappingURL=adminlte.css.map */ /*-------------------------------------------------------------- # Back to top button --------------------------------------------------------------*/ .back-to-top { position: fixed; visibility: hidden; opacity: 0; right: 15px; bottom: 15px; z-index: 99999; background: #4154f1; width: 40px; height: 40px; border-radius: 4px; transition: all 0.4s; } .back-to-top i { font-size: 24px; color: #fff; line-height: 0; } .back-to-top:hover { background: #6776f4; color: #fff; } .back-to-top.active { visibility: visible; opacity: 1; } ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.components.css ================================================ /*! * AdminLTE v3.2.0 * Only Components * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .form-group.has-icon { position: relative; } .form-group.has-icon .form-control { padding-right: 35px; } .form-group.has-icon .form-icon { background-color: transparent; border: 0; cursor: pointer; font-size: 1rem; padding: 0.375rem 0.75rem; position: absolute; right: 3px; top: 0; } .btn-group-vertical .btn.btn-flat:first-of-type, .btn-group-vertical .btn.btn-flat:last-of-type { border-radius: 0; } .form-control-feedback.fa, .form-control-feedback.fas, .form-control-feedback.far, .form-control-feedback.fab, .form-control-feedback.fal, .form-control-feedback.fad, .form-control-feedback.svg-inline--fa, .form-control-feedback.ion { line-height: calc(2.25rem + 2px); } .input-lg + .form-control-feedback.fa, .input-lg + .form-control-feedback.fas, .input-lg + .form-control-feedback.far, .input-lg + .form-control-feedback.fab, .input-lg + .form-control-feedback.fal, .input-lg + .form-control-feedback.fad, .input-lg + .form-control-feedback.svg-inline--fa, .input-lg + .form-control-feedback.ion, .input-group-lg + .form-control-feedback.fa, .input-group-lg + .form-control-feedback.fas, .input-group-lg + .form-control-feedback.far, .input-group-lg + .form-control-feedback.fab, .input-group-lg + .form-control-feedback.fal, .input-group-lg + .form-control-feedback.fad, .input-group-lg + .form-control-feedback.svg-inline--fa, .input-group-lg + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .form-group-lg .form-control + .form-control-feedback.fa, .form-group-lg .form-control + .form-control-feedback.fas, .form-group-lg .form-control + .form-control-feedback.far, .form-group-lg .form-control + .form-control-feedback.fab, .form-group-lg .form-control + .form-control-feedback.fal, .form-group-lg .form-control + .form-control-feedback.fad, .form-group-lg .form-control + .form-control-feedback.svg-inline--fa, .form-group-lg .form-control + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .input-sm + .form-control-feedback.fa, .input-sm + .form-control-feedback.fas, .input-sm + .form-control-feedback.far, .input-sm + .form-control-feedback.fab, .input-sm + .form-control-feedback.fal, .input-sm + .form-control-feedback.fad, .input-sm + .form-control-feedback.svg-inline--fa, .input-sm + .form-control-feedback.ion, .input-group-sm + .form-control-feedback.fa, .input-group-sm + .form-control-feedback.fas, .input-group-sm + .form-control-feedback.far, .input-group-sm + .form-control-feedback.fab, .input-group-sm + .form-control-feedback.fal, .input-group-sm + .form-control-feedback.fad, .input-group-sm + .form-control-feedback.svg-inline--fa, .input-group-sm + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } .form-group-sm .form-control + .form-control-feedback.fa, .form-group-sm .form-control + .form-control-feedback.fas, .form-group-sm .form-control + .form-control-feedback.far, .form-group-sm .form-control + .form-control-feedback.fab, .form-group-sm .form-control + .form-control-feedback.fal, .form-group-sm .form-control + .form-control-feedback.fad, .form-group-sm .form-control + .form-control-feedback.svg-inline--fa, .form-group-sm .form-control + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } label:not(.form-check-label):not(.custom-file-label) { font-weight: 700; } .warning-feedback { font-size: 80%; color: #ffc107; display: none; margin-top: 0.25rem; width: 100%; } .warning-tooltip { border-radius: 0.25rem; font-size: 0.875rem; background-color: rgba(255, 193, 7, 0.9); color: #1f2d3d; display: none; line-height: 1.5; margin-top: .1rem; max-width: 100%; padding: 0.25rem 0.5rem; position: absolute; top: 100%; z-index: 5; } .form-control.is-warning { border-color: #ffc107; } .form-control.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .form-control.is-warning ~ .warning-feedback, .form-control.is-warning ~ .warning-tooltip { display: block; } textarea.form-control.is-warning { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .custom-select.is-warning { border-color: #ffc107; } .custom-select.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-select.is-warning ~ .warning-feedback, .custom-select.is-warning ~ .warning-tooltip { display: block; } .form-control-file.is-warning ~ .warning-feedback, .form-control-file.is-warning ~ .warning-tooltip { display: block; } .form-check-input.is-warning ~ .form-check-label { color: #ffc107; } .form-check-input.is-warning ~ .warning-feedback, .form-check-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning ~ .custom-control-label { color: #ffc107; } .custom-control-input.is-warning ~ .custom-control-label::before { border-color: #ffc107; } .custom-control-input.is-warning ~ .warning-feedback, .custom-control-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning:checked ~ .custom-control-label::before { background-color: #ffce3a; border-color: #ffce3a; } .custom-control-input.is-warning:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-control-input.is-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffc107; } .custom-file-input.is-warning ~ .custom-file-label { border-color: #ffc107; } .custom-file-input.is-warning ~ .warning-feedback, .custom-file-input.is-warning ~ .warning-tooltip { display: block; } .custom-file-input.is-warning:focus ~ .custom-file-label { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } body.text-sm .input-group-text { font-size: 0.875rem; } .form-control.form-control-border, .custom-select.form-control-border { border-top: 0; border-left: 0; border-right: 0; border-radius: 0; box-shadow: inherit; } .form-control.form-control-border.border-width-2, .custom-select.form-control-border.border-width-2 { border-bottom-width: 2px; } .form-control.form-control-border.border-width-3, .custom-select.form-control-border.border-width-3 { border-bottom-width: 3px; } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-primary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-primary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-secondary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-success .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-success .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-info .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-info .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-warning .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-warning .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-danger .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-danger .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-off-light .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::after { background-color: #aeb9c5; } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-on-light .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-off-lightblue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::after { background-color: #1d455b; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-color: #acd0e5; } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-off-navy .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::after { background-color: #006ad8; } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-off-olive .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::after { background-color: #193e2d; } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-on-olive .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::after { background-color: #99d6bb; } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-off-lime .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::after { background-color: #008138; } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-on-lime .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::after { background-color: #9affc6; } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-off-fuchsia .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::after { background-color: #7b0861; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-color: #f9a2e5; } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-off-maroon .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::after { background-color: #670d2e; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::after { background-color: #f29aba; } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-blue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-blue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-off-indigo .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::after { background-color: #33077c; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::after { background-color: #c3a1fa; } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-off-purple .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::after { background-color: #382063; } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-on-purple .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::after { background-color: #c7b5e7; } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-off-pink .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::after { background-color: #95124e; } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-on-pink .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c7dd; } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-red .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-red .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-off-orange .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::after { background-color: #904201; } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-on-orange .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::after { background-color: #fed1ac; } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-yellow .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-green .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-green .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-off-teal .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::after { background-color: #0e5b44; } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-on-teal .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::after { background-color: #94eed3; } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-cyan .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-off-white .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::after { background-color: #bfbfbf; } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-on-white .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-gray .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-gray .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-gray-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-range.custom-range-primary:focus { outline: none; } .custom-range.custom-range-primary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-secondary:focus { outline: none; } .custom-range.custom-range-secondary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-success:focus { outline: none; } .custom-range.custom-range-success:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-success::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-success::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-success::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-info:focus { outline: none; } .custom-range.custom-range-info:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-warning:focus { outline: none; } .custom-range.custom-range-warning:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-danger:focus { outline: none; } .custom-range.custom-range-danger:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-light:focus { outline: none; } .custom-range.custom-range-light:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light::-webkit-slider-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-light::-moz-range-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-light::-ms-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-ms-thumb:active { background-color: white; } .custom-range.custom-range-dark:focus { outline: none; } .custom-range.custom-range-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-ms-thumb:active { background-color: #88939e; } .custom-range.custom-range-lightblue:focus { outline: none; } .custom-range.custom-range-lightblue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue::-webkit-slider-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-webkit-slider-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-moz-range-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-moz-range-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-ms-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-ms-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-navy:focus { outline: none; } .custom-range.custom-range-navy:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy::-webkit-slider-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-webkit-slider-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-moz-range-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-moz-range-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-ms-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-ms-thumb:active { background-color: #0077f2; } .custom-range.custom-range-olive:focus { outline: none; } .custom-range.custom-range-olive:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive::-webkit-slider-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-webkit-slider-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-moz-range-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-moz-range-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-ms-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-ms-thumb:active { background-color: #abdec7; } .custom-range.custom-range-lime:focus { outline: none; } .custom-range.custom-range-lime:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime::-webkit-slider-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-webkit-slider-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-moz-range-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-moz-range-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-ms-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-ms-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-fuchsia:focus { outline: none; } .custom-range.custom-range-fuchsia:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia::-webkit-slider-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-webkit-slider-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-moz-range-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-moz-range-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-ms-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-ms-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-maroon:focus { outline: none; } .custom-range.custom-range-maroon:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon::-webkit-slider-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-webkit-slider-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-moz-range-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-moz-range-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-ms-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-ms-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-blue:focus { outline: none; } .custom-range.custom-range-blue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-indigo:focus { outline: none; } .custom-range.custom-range-indigo:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo::-webkit-slider-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-webkit-slider-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-moz-range-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-moz-range-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-ms-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-ms-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-purple:focus { outline: none; } .custom-range.custom-range-purple:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple::-webkit-slider-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-webkit-slider-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-moz-range-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-moz-range-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-ms-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-ms-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-pink:focus { outline: none; } .custom-range.custom-range-pink:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink::-webkit-slider-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-webkit-slider-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-moz-range-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-moz-range-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-ms-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-ms-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-red:focus { outline: none; } .custom-range.custom-range-red:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-orange:focus { outline: none; } .custom-range.custom-range-orange:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange::-webkit-slider-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-webkit-slider-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-moz-range-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-moz-range-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-ms-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-ms-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-yellow:focus { outline: none; } .custom-range.custom-range-yellow:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-green:focus { outline: none; } .custom-range.custom-range-green:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-green::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-green::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-green::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-teal:focus { outline: none; } .custom-range.custom-range-teal:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal::-webkit-slider-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-webkit-slider-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-moz-range-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-moz-range-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-ms-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-ms-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-cyan:focus { outline: none; } .custom-range.custom-range-cyan:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-white:focus { outline: none; } .custom-range.custom-range-white:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white::-webkit-slider-thumb { background-color: #fff; } .custom-range.custom-range-white::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-white::-moz-range-thumb { background-color: #fff; } .custom-range.custom-range-white::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-white::-ms-thumb { background-color: #fff; } .custom-range.custom-range-white::-ms-thumb:active { background-color: white; } .custom-range.custom-range-gray:focus { outline: none; } .custom-range.custom-range-gray:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray-dark:focus { outline: none; } .custom-range.custom-range-gray-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-ms-thumb:active { background-color: #88939e; } .custom-control-input-primary:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-primary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-primary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-primary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-primary:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-primary:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-secondary:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-secondary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-secondary:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-secondary:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-success:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-success.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-success.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-success:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-success:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-success:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-info:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-info.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-info.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-info:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-info:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-info:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-warning:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-warning.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-warning.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-warning:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-warning:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-danger:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-danger.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-danger.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-danger:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-danger:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-danger:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-light:checked ~ .custom-control-label::before { border-color: #f8f9fa; background-color: #f8f9fa; } .custom-control-input-light.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f8f9fa' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-light.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f8f9fa'/%3E%3C/svg%3E") !important; } .custom-control-input-light:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(248, 249, 250, 0.25); } .custom-control-input-light:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-light:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-lightblue:checked ~ .custom-control-label::before { border-color: #3c8dbc; background-color: #3c8dbc; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233c8dbc' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233c8dbc'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(60, 141, 188, 0.25); } .custom-control-input-lightblue:focus:not(:checked) ~ .custom-control-label::before { border-color: #99c5de; } .custom-control-input-lightblue:not(:disabled):active ~ .custom-control-label::before { background-color: #c0dbeb; border-color: #c0dbeb; } .custom-control-input-navy:checked ~ .custom-control-label::before { border-color: #001f3f; background-color: #001f3f; } .custom-control-input-navy.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23001f3f' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-navy.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23001f3f'/%3E%3C/svg%3E") !important; } .custom-control-input-navy:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 31, 63, 0.25); } .custom-control-input-navy:focus:not(:checked) ~ .custom-control-label::before { border-color: #005ebf; } .custom-control-input-navy:not(:disabled):active ~ .custom-control-label::before { background-color: #0077f2; border-color: #0077f2; } .custom-control-input-olive:checked ~ .custom-control-label::before { border-color: #3d9970; background-color: #3d9970; } .custom-control-input-olive.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233d9970' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-olive.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233d9970'/%3E%3C/svg%3E") !important; } .custom-control-input-olive:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(61, 153, 112, 0.25); } .custom-control-input-olive:focus:not(:checked) ~ .custom-control-label::before { border-color: #87cfaf; } .custom-control-input-olive:not(:disabled):active ~ .custom-control-label::before { background-color: #abdec7; border-color: #abdec7; } .custom-control-input-lime:checked ~ .custom-control-label::before { border-color: #01ff70; background-color: #01ff70; } .custom-control-input-lime.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2301ff70' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lime.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2301ff70'/%3E%3C/svg%3E") !important; } .custom-control-input-lime:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(1, 255, 112, 0.25); } .custom-control-input-lime:focus:not(:checked) ~ .custom-control-label::before { border-color: #81ffb8; } .custom-control-input-lime:not(:disabled):active ~ .custom-control-label::before { background-color: #b4ffd4; border-color: #b4ffd4; } .custom-control-input-fuchsia:checked ~ .custom-control-label::before { border-color: #f012be; background-color: #f012be; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f012be' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f012be'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(240, 18, 190, 0.25); } .custom-control-input-fuchsia:focus:not(:checked) ~ .custom-control-label::before { border-color: #f88adf; } .custom-control-input-fuchsia:not(:disabled):active ~ .custom-control-label::before { background-color: #fbbaec; border-color: #fbbaec; } .custom-control-input-maroon:checked ~ .custom-control-label::before { border-color: #d81b60; background-color: #d81b60; } .custom-control-input-maroon.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23d81b60' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23d81b60'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(216, 27, 96, 0.25); } .custom-control-input-maroon:focus:not(:checked) ~ .custom-control-label::before { border-color: #f083ab; } .custom-control-input-maroon:not(:disabled):active ~ .custom-control-label::before { background-color: #f5b0c9; border-color: #f5b0c9; } .custom-control-input-blue:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-blue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-blue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-blue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-blue:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-blue:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-indigo:checked ~ .custom-control-label::before { border-color: #6610f2; background-color: #6610f2; } .custom-control-input-indigo.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236610f2' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236610f2'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(102, 16, 242, 0.25); } .custom-control-input-indigo:focus:not(:checked) ~ .custom-control-label::before { border-color: #b389f9; } .custom-control-input-indigo:not(:disabled):active ~ .custom-control-label::before { background-color: #d2b9fb; border-color: #d2b9fb; } .custom-control-input-purple:checked ~ .custom-control-label::before { border-color: #6f42c1; background-color: #6f42c1; } .custom-control-input-purple.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236f42c1' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-purple.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236f42c1'/%3E%3C/svg%3E") !important; } .custom-control-input-purple:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(111, 66, 193, 0.25); } .custom-control-input-purple:focus:not(:checked) ~ .custom-control-label::before { border-color: #b8a2e0; } .custom-control-input-purple:not(:disabled):active ~ .custom-control-label::before { background-color: #d5c8ed; border-color: #d5c8ed; } .custom-control-input-pink:checked ~ .custom-control-label::before { border-color: #e83e8c; background-color: #e83e8c; } .custom-control-input-pink.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e83e8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-pink.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e83e8c'/%3E%3C/svg%3E") !important; } .custom-control-input-pink:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(232, 62, 140, 0.25); } .custom-control-input-pink:focus:not(:checked) ~ .custom-control-label::before { border-color: #f6b0d0; } .custom-control-input-pink:not(:disabled):active ~ .custom-control-label::before { background-color: #fbddeb; border-color: #fbddeb; } .custom-control-input-red:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-red.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-red.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-red:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-red:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-red:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-orange:checked ~ .custom-control-label::before { border-color: #fd7e14; background-color: #fd7e14; } .custom-control-input-orange.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fd7e14' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-orange.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fd7e14'/%3E%3C/svg%3E") !important; } .custom-control-input-orange:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(253, 126, 20, 0.25); } .custom-control-input-orange:focus:not(:checked) ~ .custom-control-label::before { border-color: #fec392; } .custom-control-input-orange:not(:disabled):active ~ .custom-control-label::before { background-color: #ffdfc5; border-color: #ffdfc5; } .custom-control-input-yellow:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-yellow.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-yellow:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-yellow:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-green:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-green.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-green.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-green:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-green:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-green:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-teal:checked ~ .custom-control-label::before { border-color: #20c997; background-color: #20c997; } .custom-control-input-teal.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2320c997' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-teal.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2320c997'/%3E%3C/svg%3E") !important; } .custom-control-input-teal:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(32, 201, 151, 0.25); } .custom-control-input-teal:focus:not(:checked) ~ .custom-control-label::before { border-color: #7eeaca; } .custom-control-input-teal:not(:disabled):active ~ .custom-control-label::before { background-color: #aaf1dc; border-color: #aaf1dc; } .custom-control-input-cyan:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-cyan.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-cyan:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-cyan:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-white:checked ~ .custom-control-label::before { border-color: #fff; background-color: #fff; } .custom-control-input-white.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-white.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") !important; } .custom-control-input-white:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 255, 255, 0.25); } .custom-control-input-white:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-white:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-gray:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-gray.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-gray:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-gray:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-gray:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-gray-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-gray-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-gray-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-outline ~ .custom-control-label::before { background-color: transparent !important; box-shadow: none; } .custom-control-input-outline:checked ~ .custom-control-label::before { background-color: transparent; } .navbar-dark .btn-navbar, .navbar-dark .form-control-navbar { background-color: #3f474e; border: 1px solid #56606a; color: white; } .navbar-dark .btn-navbar:hover { background-color: #454d55; } .navbar-dark .btn-navbar:focus { background-color: #4b545c; } .navbar-dark .form-control-navbar + .input-group-prepend > .btn-navbar, .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3f474e; color: #fff; border: 1px solid #56606a; border-left: none; } .dark-mode .form-control:not(.form-control-navbar):not(.form-control-sidebar), .dark-mode .custom-select, .dark-mode .custom-file-label, .dark-mode .custom-file-label::after, .dark-mode .custom-control-label::before, .dark-mode .input-group-text { background-color: #343a40; color: #fff; } .dark-mode .form-control:not(.form-control-navbar):not(.form-control-sidebar):not(.is-invalid):not(:focus), .dark-mode .custom-file-label, .dark-mode .custom-file-label::after { border-color: #6c757d; } .dark-mode select { background-color: #343a40; color: #fff; border-color: #6c757d; } .dark-mode .custom-select { background: #343a40 url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23fff' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat; } .dark-mode .custom-select[multiple] { background: #343a40; } .dark-mode .input-group-text { border-color: #6c757d; } .dark-mode .custom-control-input:disabled ~ .custom-control-label::before, .dark-mode .custom-control-input[disabled] ~ .custom-control-label::before { background-color: #3f474e; border-color: #6c757d; color: #fff; } .dark-mode input:-webkit-autofill, .dark-mode input:-webkit-autofill:hover, .dark-mode input:-webkit-autofill:focus, .dark-mode textarea:-webkit-autofill, .dark-mode textarea:-webkit-autofill:hover, .dark-mode textarea:-webkit-autofill:focus, .dark-mode select:-webkit-autofill, .dark-mode select:-webkit-autofill:hover, .dark-mode select:-webkit-autofill:focus { -webkit-text-fill-color: #fff; } .dark-mode .custom-range::-webkit-slider-runnable-track { background-color: #454d55; } .dark-mode .custom-range::-moz-range-track { background-color: #454d55; } .dark-mode .custom-range::-ms-track { background-color: #454d55; } .dark-mode .custom-range.custom-range-primary:focus { outline: none; } .dark-mode .custom-range.custom-range-primary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-primary::-webkit-slider-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-webkit-slider-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-primary::-moz-range-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-moz-range-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-primary::-ms-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-primary::-ms-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-secondary:focus { outline: none; } .dark-mode .custom-range.custom-range-secondary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-secondary::-webkit-slider-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-webkit-slider-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-secondary::-moz-range-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-moz-range-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-secondary::-ms-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-secondary::-ms-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-success:focus { outline: none; } .dark-mode .custom-range.custom-range-success:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-success::-webkit-slider-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-webkit-slider-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-success::-moz-range-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-moz-range-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-success::-ms-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-success::-ms-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-info:focus { outline: none; } .dark-mode .custom-range.custom-range-info:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-info::-webkit-slider-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-webkit-slider-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-info::-moz-range-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-moz-range-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-info::-ms-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-info::-ms-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-warning:focus { outline: none; } .dark-mode .custom-range.custom-range-warning:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-warning::-webkit-slider-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-webkit-slider-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-warning::-moz-range-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-moz-range-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-warning::-ms-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-warning::-ms-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-danger:focus { outline: none; } .dark-mode .custom-range.custom-range-danger:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-danger::-webkit-slider-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-webkit-slider-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-danger::-moz-range-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-moz-range-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-danger::-ms-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-danger::-ms-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-light:focus { outline: none; } .dark-mode .custom-range.custom-range-light:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-range.custom-range-light::-webkit-slider-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-light::-moz-range-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-light::-ms-thumb { background-color: #f8f9fa; } .dark-mode .custom-range.custom-range-light::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-dark:focus { outline: none; } .dark-mode .custom-range.custom-range-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-dark::-webkit-slider-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-webkit-slider-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-dark::-moz-range-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-moz-range-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-dark::-ms-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-dark::-ms-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-lightblue:focus { outline: none; } .dark-mode .custom-range.custom-range-lightblue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-range.custom-range-lightblue::-webkit-slider-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lightblue::-moz-range-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lightblue::-ms-thumb { background-color: #86bad8; } .dark-mode .custom-range.custom-range-lightblue::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-navy:focus { outline: none; } .dark-mode .custom-range.custom-range-navy:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-range.custom-range-navy::-webkit-slider-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-webkit-slider-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-navy::-moz-range-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-moz-range-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-navy::-ms-thumb { background-color: #002c59; } .dark-mode .custom-range.custom-range-navy::-ms-thumb:active { background-color: #0c84ff; } .dark-mode .custom-range.custom-range-olive:focus { outline: none; } .dark-mode .custom-range.custom-range-olive:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-range.custom-range-olive::-webkit-slider-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-webkit-slider-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-olive::-moz-range-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-moz-range-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-olive::-ms-thumb { background-color: #74c8a3; } .dark-mode .custom-range.custom-range-olive::-ms-thumb:active { background-color: #f4fbf8; } .dark-mode .custom-range.custom-range-lime:focus { outline: none; } .dark-mode .custom-range.custom-range-lime:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-range.custom-range-lime::-webkit-slider-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lime::-moz-range-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-lime::-ms-thumb { background-color: #67ffa9; } .dark-mode .custom-range.custom-range-lime::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia:focus { outline: none; } .dark-mode .custom-range.custom-range-fuchsia:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-range.custom-range-fuchsia::-webkit-slider-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia::-moz-range-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-fuchsia::-ms-thumb { background-color: #f672d8; } .dark-mode .custom-range.custom-range-fuchsia::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon:focus { outline: none; } .dark-mode .custom-range.custom-range-maroon:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-range.custom-range-maroon::-webkit-slider-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon::-moz-range-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-maroon::-ms-thumb { background-color: #ed6c9b; } .dark-mode .custom-range.custom-range-maroon::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-blue:focus { outline: none; } .dark-mode .custom-range.custom-range-blue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-range.custom-range-blue::-webkit-slider-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-webkit-slider-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-blue::-moz-range-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-moz-range-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-blue::-ms-thumb { background-color: #3f6791; } .dark-mode .custom-range.custom-range-blue::-ms-thumb:active { background-color: #a9c1da; } .dark-mode .custom-range.custom-range-indigo:focus { outline: none; } .dark-mode .custom-range.custom-range-indigo:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-range.custom-range-indigo::-webkit-slider-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-webkit-slider-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-indigo::-moz-range-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-moz-range-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-indigo::-ms-thumb { background-color: #6610f2; } .dark-mode .custom-range.custom-range-indigo::-ms-thumb:active { background-color: #d2b9fb; } .dark-mode .custom-range.custom-range-purple:focus { outline: none; } .dark-mode .custom-range.custom-range-purple:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-range.custom-range-purple::-webkit-slider-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-webkit-slider-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-purple::-moz-range-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-moz-range-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-purple::-ms-thumb { background-color: #6f42c1; } .dark-mode .custom-range.custom-range-purple::-ms-thumb:active { background-color: #d5c8ed; } .dark-mode .custom-range.custom-range-pink:focus { outline: none; } .dark-mode .custom-range.custom-range-pink:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-range.custom-range-pink::-webkit-slider-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-webkit-slider-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-pink::-moz-range-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-moz-range-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-pink::-ms-thumb { background-color: #e83e8c; } .dark-mode .custom-range.custom-range-pink::-ms-thumb:active { background-color: #fbddeb; } .dark-mode .custom-range.custom-range-red:focus { outline: none; } .dark-mode .custom-range.custom-range-red:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-range.custom-range-red::-webkit-slider-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-webkit-slider-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-red::-moz-range-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-moz-range-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-red::-ms-thumb { background-color: #e74c3c; } .dark-mode .custom-range.custom-range-red::-ms-thumb:active { background-color: #fbdedb; } .dark-mode .custom-range.custom-range-orange:focus { outline: none; } .dark-mode .custom-range.custom-range-orange:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-range.custom-range-orange::-webkit-slider-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-webkit-slider-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-orange::-moz-range-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-moz-range-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-orange::-ms-thumb { background-color: #fd7e14; } .dark-mode .custom-range.custom-range-orange::-ms-thumb:active { background-color: #ffdfc5; } .dark-mode .custom-range.custom-range-yellow:focus { outline: none; } .dark-mode .custom-range.custom-range-yellow:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-range.custom-range-yellow::-webkit-slider-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-webkit-slider-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-yellow::-moz-range-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-moz-range-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-yellow::-ms-thumb { background-color: #f39c12; } .dark-mode .custom-range.custom-range-yellow::-ms-thumb:active { background-color: #fce3bc; } .dark-mode .custom-range.custom-range-green:focus { outline: none; } .dark-mode .custom-range.custom-range-green:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-range.custom-range-green::-webkit-slider-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-webkit-slider-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-green::-moz-range-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-moz-range-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-green::-ms-thumb { background-color: #00bc8c; } .dark-mode .custom-range.custom-range-green::-ms-thumb:active { background-color: #70ffda; } .dark-mode .custom-range.custom-range-teal:focus { outline: none; } .dark-mode .custom-range.custom-range-teal:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-range.custom-range-teal::-webkit-slider-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-webkit-slider-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-teal::-moz-range-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-moz-range-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-teal::-ms-thumb { background-color: #20c997; } .dark-mode .custom-range.custom-range-teal::-ms-thumb:active { background-color: #aaf1dc; } .dark-mode .custom-range.custom-range-cyan:focus { outline: none; } .dark-mode .custom-range.custom-range-cyan:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-range.custom-range-cyan::-webkit-slider-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-webkit-slider-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-cyan::-moz-range-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-moz-range-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-cyan::-ms-thumb { background-color: #3498db; } .dark-mode .custom-range.custom-range-cyan::-ms-thumb:active { background-color: #cce5f6; } .dark-mode .custom-range.custom-range-white:focus { outline: none; } .dark-mode .custom-range.custom-range-white:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-range.custom-range-white::-webkit-slider-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-webkit-slider-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-white::-moz-range-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-moz-range-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-white::-ms-thumb { background-color: #fff; } .dark-mode .custom-range.custom-range-white::-ms-thumb:active { background-color: white; } .dark-mode .custom-range.custom-range-gray:focus { outline: none; } .dark-mode .custom-range.custom-range-gray:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-range.custom-range-gray::-webkit-slider-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-webkit-slider-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray::-moz-range-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-moz-range-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray::-ms-thumb { background-color: #6c757d; } .dark-mode .custom-range.custom-range-gray::-ms-thumb:active { background-color: #caced1; } .dark-mode .custom-range.custom-range-gray-dark:focus { outline: none; } .dark-mode .custom-range.custom-range-gray-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-range.custom-range-gray-dark::-webkit-slider-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-webkit-slider-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-gray-dark::-moz-range-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-moz-range-thumb:active { background-color: #88939e; } .dark-mode .custom-range.custom-range-gray-dark::-ms-thumb { background-color: #343a40; } .dark-mode .custom-range.custom-range-gray-dark::-ms-thumb:active { background-color: #88939e; } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::after { background-color: #182838; } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::after { background-color: #97b4d2; } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::after { background-color: #003d2d; } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::after { background-color: #56ffd4; } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::after { background-color: #16527a; } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::after { background-color: #b6daf2; } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::after { background-color: #7f5006; } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::after { background-color: #fad9a4; } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::after { background-color: #921e12; } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c9c4; } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::after { background-color: #aeb9c5; } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .dark-mode .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::after { background-color: #367fa9; } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(134, 186, 216, 0.25); } .dark-mode .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-color: #fafcfd; } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 44, 89, 0.25); } .dark-mode .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::after { background-color: #0077f2; } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::after { background-color: #368763; } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(116, 200, 163, 0.25); } .dark-mode .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::after { background-color: #e2f3eb; } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::after { background-color: #00e765; } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(103, 255, 169, 0.25); } .dark-mode .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::after { background-color: #db0ead; } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(246, 114, 216, 0.25); } .dark-mode .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::after { background-color: #c11856; } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(237, 108, 155, 0.25); } .dark-mode .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::after { background-color: #fef4f8; } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::after { background-color: #182838; } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(63, 103, 145, 0.25); } .dark-mode .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::after { background-color: #97b4d2; } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::after { background-color: #33077c; } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .dark-mode .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::after { background-color: #c3a1fa; } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::after { background-color: #382063; } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .dark-mode .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::after { background-color: #c7b5e7; } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::after { background-color: #95124e; } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c7dd; } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::after { background-color: #921e12; } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(231, 76, 60, 0.25); } .dark-mode .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c9c4; } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::after { background-color: #904201; } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .dark-mode .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::after { background-color: #fed1ac; } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::after { background-color: #7f5006; } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(243, 156, 18, 0.25); } .dark-mode .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::after { background-color: #fad9a4; } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::after { background-color: #003d2d; } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 188, 140, 0.25); } .dark-mode .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::after { background-color: #56ffd4; } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::after { background-color: #0e5b44; } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .dark-mode .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::after { background-color: #94eed3; } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::after { background-color: #16527a; } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 152, 219, 0.25); } .dark-mode .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::after { background-color: #b6daf2; } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::after { background-color: #bfbfbf; } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .dark-mode .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .dark-mode .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .dark-mode .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .dark-mode .custom-control-input-primary:checked ~ .custom-control-label::before { border-color: #3f6791; background-color: #3f6791; } .dark-mode .custom-control-input-primary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233f6791' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-primary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233f6791'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-primary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(63, 103, 145, 0.25); } .dark-mode .custom-control-input-primary:focus:not(:checked) ~ .custom-control-label::before { border-color: #85a7ca; } .dark-mode .custom-control-input-primary:not(:disabled):active ~ .custom-control-label::before { background-color: #a9c1da; border-color: #a9c1da; } .dark-mode .custom-control-input-secondary:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .dark-mode .custom-control-input-secondary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-secondary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-secondary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .dark-mode .custom-control-input-secondary:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .dark-mode .custom-control-input-secondary:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .dark-mode .custom-control-input-success:checked ~ .custom-control-label::before { border-color: #00bc8c; background-color: #00bc8c; } .dark-mode .custom-control-input-success.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2300bc8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-success.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2300bc8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-success:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 188, 140, 0.25); } .dark-mode .custom-control-input-success:focus:not(:checked) ~ .custom-control-label::before { border-color: #3dffcd; } .dark-mode .custom-control-input-success:not(:disabled):active ~ .custom-control-label::before { background-color: #70ffda; border-color: #70ffda; } .dark-mode .custom-control-input-info:checked ~ .custom-control-label::before { border-color: #3498db; background-color: #3498db; } .dark-mode .custom-control-input-info.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233498db' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-info.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233498db'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-info:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 152, 219, 0.25); } .dark-mode .custom-control-input-info:focus:not(:checked) ~ .custom-control-label::before { border-color: #a0cfee; } .dark-mode .custom-control-input-info:not(:disabled):active ~ .custom-control-label::before { background-color: #cce5f6; border-color: #cce5f6; } .dark-mode .custom-control-input-warning:checked ~ .custom-control-label::before { border-color: #f39c12; background-color: #f39c12; } .dark-mode .custom-control-input-warning.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f39c12' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-warning.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f39c12'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-warning:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(243, 156, 18, 0.25); } .dark-mode .custom-control-input-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #f9cf8b; } .dark-mode .custom-control-input-warning:not(:disabled):active ~ .custom-control-label::before { background-color: #fce3bc; border-color: #fce3bc; } .dark-mode .custom-control-input-danger:checked ~ .custom-control-label::before { border-color: #e74c3c; background-color: #e74c3c; } .dark-mode .custom-control-input-danger.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e74c3c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-danger.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e74c3c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-danger:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(231, 76, 60, 0.25); } .dark-mode .custom-control-input-danger:focus:not(:checked) ~ .custom-control-label::before { border-color: #f5b4ae; } .dark-mode .custom-control-input-danger:not(:disabled):active ~ .custom-control-label::before { background-color: #fbdedb; border-color: #fbdedb; } .dark-mode .custom-control-input-light:checked ~ .custom-control-label::before { border-color: #f8f9fa; background-color: #f8f9fa; } .dark-mode .custom-control-input-light.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f8f9fa' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-light.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f8f9fa'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-light:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(248, 249, 250, 0.25); } .dark-mode .custom-control-input-light:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .dark-mode .custom-control-input-light:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .dark-mode .custom-control-input-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .dark-mode .custom-control-input-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .dark-mode .custom-control-input-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .dark-mode .custom-control-input-lightblue:checked ~ .custom-control-label::before { border-color: #86bad8; background-color: #86bad8; } .dark-mode .custom-control-input-lightblue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2386bad8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lightblue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2386bad8'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lightblue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(134, 186, 216, 0.25); } .dark-mode .custom-control-input-lightblue:focus:not(:checked) ~ .custom-control-label::before { border-color: #e6f1f7; } .dark-mode .custom-control-input-lightblue:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-navy:checked ~ .custom-control-label::before { border-color: #002c59; background-color: #002c59; } .dark-mode .custom-control-input-navy.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23002c59' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-navy.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23002c59'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-navy:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 44, 89, 0.25); } .dark-mode .custom-control-input-navy:focus:not(:checked) ~ .custom-control-label::before { border-color: #006ad8; } .dark-mode .custom-control-input-navy:not(:disabled):active ~ .custom-control-label::before { background-color: #0c84ff; border-color: #0c84ff; } .dark-mode .custom-control-input-olive:checked ~ .custom-control-label::before { border-color: #74c8a3; background-color: #74c8a3; } .dark-mode .custom-control-input-olive.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2374c8a3' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-olive.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2374c8a3'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-olive:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(116, 200, 163, 0.25); } .dark-mode .custom-control-input-olive:focus:not(:checked) ~ .custom-control-label::before { border-color: #cfecdf; } .dark-mode .custom-control-input-olive:not(:disabled):active ~ .custom-control-label::before { background-color: #f4fbf8; border-color: #f4fbf8; } .dark-mode .custom-control-input-lime:checked ~ .custom-control-label::before { border-color: #67ffa9; background-color: #67ffa9; } .dark-mode .custom-control-input-lime.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2367ffa9' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lime.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2367ffa9'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-lime:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(103, 255, 169, 0.25); } .dark-mode .custom-control-input-lime:focus:not(:checked) ~ .custom-control-label::before { border-color: #e7fff1; } .dark-mode .custom-control-input-lime:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-fuchsia:checked ~ .custom-control-label::before { border-color: #f672d8; background-color: #f672d8; } .dark-mode .custom-control-input-fuchsia.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f672d8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-fuchsia.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f672d8'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-fuchsia:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(246, 114, 216, 0.25); } .dark-mode .custom-control-input-fuchsia:focus:not(:checked) ~ .custom-control-label::before { border-color: #feeaf9; } .dark-mode .custom-control-input-fuchsia:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-maroon:checked ~ .custom-control-label::before { border-color: #ed6c9b; background-color: #ed6c9b; } .dark-mode .custom-control-input-maroon.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ed6c9b' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-maroon.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ed6c9b'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-maroon:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(237, 108, 155, 0.25); } .dark-mode .custom-control-input-maroon:focus:not(:checked) ~ .custom-control-label::before { border-color: #fbdee8; } .dark-mode .custom-control-input-maroon:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-blue:checked ~ .custom-control-label::before { border-color: #3f6791; background-color: #3f6791; } .dark-mode .custom-control-input-blue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233f6791' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-blue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233f6791'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-blue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(63, 103, 145, 0.25); } .dark-mode .custom-control-input-blue:focus:not(:checked) ~ .custom-control-label::before { border-color: #85a7ca; } .dark-mode .custom-control-input-blue:not(:disabled):active ~ .custom-control-label::before { background-color: #a9c1da; border-color: #a9c1da; } .dark-mode .custom-control-input-indigo:checked ~ .custom-control-label::before { border-color: #6610f2; background-color: #6610f2; } .dark-mode .custom-control-input-indigo.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236610f2' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-indigo.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236610f2'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-indigo:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(102, 16, 242, 0.25); } .dark-mode .custom-control-input-indigo:focus:not(:checked) ~ .custom-control-label::before { border-color: #b389f9; } .dark-mode .custom-control-input-indigo:not(:disabled):active ~ .custom-control-label::before { background-color: #d2b9fb; border-color: #d2b9fb; } .dark-mode .custom-control-input-purple:checked ~ .custom-control-label::before { border-color: #6f42c1; background-color: #6f42c1; } .dark-mode .custom-control-input-purple.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236f42c1' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-purple.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236f42c1'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-purple:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(111, 66, 193, 0.25); } .dark-mode .custom-control-input-purple:focus:not(:checked) ~ .custom-control-label::before { border-color: #b8a2e0; } .dark-mode .custom-control-input-purple:not(:disabled):active ~ .custom-control-label::before { background-color: #d5c8ed; border-color: #d5c8ed; } .dark-mode .custom-control-input-pink:checked ~ .custom-control-label::before { border-color: #e83e8c; background-color: #e83e8c; } .dark-mode .custom-control-input-pink.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e83e8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-pink.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e83e8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-pink:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(232, 62, 140, 0.25); } .dark-mode .custom-control-input-pink:focus:not(:checked) ~ .custom-control-label::before { border-color: #f6b0d0; } .dark-mode .custom-control-input-pink:not(:disabled):active ~ .custom-control-label::before { background-color: #fbddeb; border-color: #fbddeb; } .dark-mode .custom-control-input-red:checked ~ .custom-control-label::before { border-color: #e74c3c; background-color: #e74c3c; } .dark-mode .custom-control-input-red.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e74c3c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-red.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e74c3c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-red:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(231, 76, 60, 0.25); } .dark-mode .custom-control-input-red:focus:not(:checked) ~ .custom-control-label::before { border-color: #f5b4ae; } .dark-mode .custom-control-input-red:not(:disabled):active ~ .custom-control-label::before { background-color: #fbdedb; border-color: #fbdedb; } .dark-mode .custom-control-input-orange:checked ~ .custom-control-label::before { border-color: #fd7e14; background-color: #fd7e14; } .dark-mode .custom-control-input-orange.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fd7e14' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-orange.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fd7e14'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-orange:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(253, 126, 20, 0.25); } .dark-mode .custom-control-input-orange:focus:not(:checked) ~ .custom-control-label::before { border-color: #fec392; } .dark-mode .custom-control-input-orange:not(:disabled):active ~ .custom-control-label::before { background-color: #ffdfc5; border-color: #ffdfc5; } .dark-mode .custom-control-input-yellow:checked ~ .custom-control-label::before { border-color: #f39c12; background-color: #f39c12; } .dark-mode .custom-control-input-yellow.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f39c12' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-yellow.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f39c12'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-yellow:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(243, 156, 18, 0.25); } .dark-mode .custom-control-input-yellow:focus:not(:checked) ~ .custom-control-label::before { border-color: #f9cf8b; } .dark-mode .custom-control-input-yellow:not(:disabled):active ~ .custom-control-label::before { background-color: #fce3bc; border-color: #fce3bc; } .dark-mode .custom-control-input-green:checked ~ .custom-control-label::before { border-color: #00bc8c; background-color: #00bc8c; } .dark-mode .custom-control-input-green.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2300bc8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-green.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2300bc8c'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-green:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 188, 140, 0.25); } .dark-mode .custom-control-input-green:focus:not(:checked) ~ .custom-control-label::before { border-color: #3dffcd; } .dark-mode .custom-control-input-green:not(:disabled):active ~ .custom-control-label::before { background-color: #70ffda; border-color: #70ffda; } .dark-mode .custom-control-input-teal:checked ~ .custom-control-label::before { border-color: #20c997; background-color: #20c997; } .dark-mode .custom-control-input-teal.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2320c997' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-teal.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2320c997'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-teal:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(32, 201, 151, 0.25); } .dark-mode .custom-control-input-teal:focus:not(:checked) ~ .custom-control-label::before { border-color: #7eeaca; } .dark-mode .custom-control-input-teal:not(:disabled):active ~ .custom-control-label::before { background-color: #aaf1dc; border-color: #aaf1dc; } .dark-mode .custom-control-input-cyan:checked ~ .custom-control-label::before { border-color: #3498db; background-color: #3498db; } .dark-mode .custom-control-input-cyan.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233498db' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-cyan.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233498db'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-cyan:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 152, 219, 0.25); } .dark-mode .custom-control-input-cyan:focus:not(:checked) ~ .custom-control-label::before { border-color: #a0cfee; } .dark-mode .custom-control-input-cyan:not(:disabled):active ~ .custom-control-label::before { background-color: #cce5f6; border-color: #cce5f6; } .dark-mode .custom-control-input-white:checked ~ .custom-control-label::before { border-color: #fff; background-color: #fff; } .dark-mode .custom-control-input-white.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-white.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-white:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 255, 255, 0.25); } .dark-mode .custom-control-input-white:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .dark-mode .custom-control-input-white:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .dark-mode .custom-control-input-gray:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .dark-mode .custom-control-input-gray.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .dark-mode .custom-control-input-gray:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .dark-mode .custom-control-input-gray:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .dark-mode .custom-control-input-gray-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .dark-mode .custom-control-input-gray-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .dark-mode .custom-control-input-gray-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .dark-mode .custom-control-input-gray-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .dark-mode .custom-control-input-gray-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .progress { box-shadow: none; border-radius: 1px; } .progress.vertical { display: inline-block; height: 200px; margin-right: 10px; position: relative; width: 30px; } .progress.vertical > .progress-bar { bottom: 0; position: absolute; width: 100%; } .progress.vertical.sm, .progress.vertical.progress-sm { width: 20px; } .progress.vertical.xs, .progress.vertical.progress-xs { width: 10px; } .progress.vertical.xxs, .progress.vertical.progress-xxs { width: 3px; } .progress-group { margin-bottom: 0.5rem; } .progress-sm { height: 10px; } .progress-xs { height: 7px; } .progress-xxs { height: 3px; } .table tr > td .progress { margin: 0; } .dark-mode .progress { background: #454d55; } .card-primary:not(.card-outline) > .card-header { background-color: #007bff; } .card-primary:not(.card-outline) > .card-header, .card-primary:not(.card-outline) > .card-header a { color: #fff; } .card-primary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-primary.card-outline { border-top: 3px solid #007bff; } .card-primary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-primary.card-outline-tabs > .card-header a.active, .card-primary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-primary > .card-header .btn-tool, .bg-gradient-primary > .card-header .btn-tool, .card-primary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-primary > .card-header .btn-tool:hover, .bg-gradient-primary > .card-header .btn-tool:hover, .card-primary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget .table td, .card.bg-primary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-primary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-secondary:not(.card-outline) > .card-header { background-color: #6c757d; } .card-secondary:not(.card-outline) > .card-header, .card-secondary:not(.card-outline) > .card-header a { color: #fff; } .card-secondary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-secondary.card-outline { border-top: 3px solid #6c757d; } .card-secondary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-secondary.card-outline-tabs > .card-header a.active, .card-secondary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-secondary > .card-header .btn-tool, .bg-gradient-secondary > .card-header .btn-tool, .card-secondary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-secondary > .card-header .btn-tool:hover, .bg-gradient-secondary > .card-header .btn-tool:hover, .card-secondary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-secondary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-secondary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-success:not(.card-outline) > .card-header { background-color: #28a745; } .card-success:not(.card-outline) > .card-header, .card-success:not(.card-outline) > .card-header a { color: #fff; } .card-success:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-success.card-outline { border-top: 3px solid #28a745; } .card-success.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-success.card-outline-tabs > .card-header a.active, .card-success.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-success > .card-header .btn-tool, .bg-gradient-success > .card-header .btn-tool, .card-success:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-success > .card-header .btn-tool:hover, .bg-gradient-success > .card-header .btn-tool:hover, .card-success:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget .table td, .card.bg-success .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.active, .card.bg-success .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-info:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-info:not(.card-outline) > .card-header, .card-info:not(.card-outline) > .card-header a { color: #fff; } .card-info:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-info.card-outline { border-top: 3px solid #17a2b8; } .card-info.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-info.card-outline-tabs > .card-header a.active, .card-info.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-info > .card-header .btn-tool, .bg-gradient-info > .card-header .btn-tool, .card-info:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-info > .card-header .btn-tool:hover, .bg-gradient-info > .card-header .btn-tool:hover, .card-info:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget .table td, .card.bg-info .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.active, .card.bg-info .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-warning:not(.card-outline) > .card-header { background-color: #ffc107; } .card-warning:not(.card-outline) > .card-header, .card-warning:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-warning:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-warning.card-outline { border-top: 3px solid #ffc107; } .card-warning.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-warning.card-outline-tabs > .card-header a.active, .card-warning.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-warning > .card-header .btn-tool, .bg-gradient-warning > .card-header .btn-tool, .card-warning:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-warning > .card-header .btn-tool:hover, .bg-gradient-warning > .card-header .btn-tool:hover, .card-warning:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget .table td, .card.bg-warning .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-warning .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-danger:not(.card-outline) > .card-header { background-color: #dc3545; } .card-danger:not(.card-outline) > .card-header, .card-danger:not(.card-outline) > .card-header a { color: #fff; } .card-danger:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-danger.card-outline { border-top: 3px solid #dc3545; } .card-danger.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-danger.card-outline-tabs > .card-header a.active, .card-danger.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-danger > .card-header .btn-tool, .bg-gradient-danger > .card-header .btn-tool, .card-danger:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-danger > .card-header .btn-tool:hover, .bg-gradient-danger > .card-header .btn-tool:hover, .card-danger:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget .table td, .card.bg-danger .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-danger .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-light:not(.card-outline) > .card-header { background-color: #f8f9fa; } .card-light:not(.card-outline) > .card-header, .card-light:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-light:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-light.card-outline { border-top: 3px solid #f8f9fa; } .card-light.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-light.card-outline-tabs > .card-header a.active, .card-light.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f8f9fa; } .bg-light > .card-header .btn-tool, .bg-gradient-light > .card-header .btn-tool, .card-light:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-light > .card-header .btn-tool:hover, .bg-gradient-light > .card-header .btn-tool:hover, .card-light:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget .table td, .card.bg-light .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e0e5e9; color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.active, .card.bg-light .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-dark:not(.card-outline) > .card-header, .card-dark:not(.card-outline) > .card-header a { color: #fff; } .card-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-dark.card-outline { border-top: 3px solid #343a40; } .card-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-dark.card-outline-tabs > .card-header a.active, .card-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-dark > .card-header .btn-tool, .bg-gradient-dark > .card-header .btn-tool, .card-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-dark > .card-header .btn-tool:hover, .bg-gradient-dark > .card-header .btn-tool:hover, .card-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget .table td, .card.bg-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card-lightblue:not(.card-outline) > .card-header { background-color: #3c8dbc; } .card-lightblue:not(.card-outline) > .card-header, .card-lightblue:not(.card-outline) > .card-header a { color: #fff; } .card-lightblue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lightblue.card-outline { border-top: 3px solid #3c8dbc; } .card-lightblue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lightblue.card-outline-tabs > .card-header a.active, .card-lightblue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3c8dbc; } .bg-lightblue > .card-header .btn-tool, .bg-gradient-lightblue > .card-header .btn-tool, .card-lightblue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-lightblue > .card-header .btn-tool:hover, .bg-gradient-lightblue > .card-header .btn-tool:hover, .card-lightblue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-lightblue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #32769d; color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5fa4cc; color: #fff; } .card-navy:not(.card-outline) > .card-header { background-color: #001f3f; } .card-navy:not(.card-outline) > .card-header, .card-navy:not(.card-outline) > .card-header a { color: #fff; } .card-navy:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-navy.card-outline { border-top: 3px solid #001f3f; } .card-navy.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-navy.card-outline-tabs > .card-header a.active, .card-navy.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #001f3f; } .bg-navy > .card-header .btn-tool, .bg-gradient-navy > .card-header .btn-tool, .card-navy:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-navy > .card-header .btn-tool:hover, .bg-gradient-navy > .card-header .btn-tool:hover, .card-navy:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget .table td, .card.bg-navy .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.second:hover { background-color: #000b16; color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-navy .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active:hover { background-color: #003872; color: #fff; } .card-olive:not(.card-outline) > .card-header { background-color: #3d9970; } .card-olive:not(.card-outline) > .card-header, .card-olive:not(.card-outline) > .card-header a { color: #fff; } .card-olive:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-olive.card-outline { border-top: 3px solid #3d9970; } .card-olive.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-olive.card-outline-tabs > .card-header a.active, .card-olive.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3d9970; } .bg-olive > .card-header .btn-tool, .bg-gradient-olive > .card-header .btn-tool, .card-olive:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-olive > .card-header .btn-tool:hover, .bg-gradient-olive > .card-header .btn-tool:hover, .card-olive:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget .table td, .card.bg-olive .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.second:hover { background-color: #317c5b; color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-olive .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active:hover { background-color: #50b98a; color: #fff; } .card-lime:not(.card-outline) > .card-header { background-color: #01ff70; } .card-lime:not(.card-outline) > .card-header, .card-lime:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-lime:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lime.card-outline { border-top: 3px solid #01ff70; } .card-lime.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lime.card-outline-tabs > .card-header a.active, .card-lime.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #01ff70; } .bg-lime > .card-header .btn-tool, .bg-gradient-lime > .card-header .btn-tool, .card-lime:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-lime > .card-header .btn-tool:hover, .bg-gradient-lime > .card-header .btn-tool:hover, .card-lime:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget .table td, .card.bg-lime .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00d75e; color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-lime .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ff8d; color: #1f2d3d; } .card-fuchsia:not(.card-outline) > .card-header { background-color: #f012be; } .card-fuchsia:not(.card-outline) > .card-header, .card-fuchsia:not(.card-outline) > .card-header a { color: #fff; } .card-fuchsia:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-fuchsia.card-outline { border-top: 3px solid #f012be; } .card-fuchsia.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-fuchsia.card-outline-tabs > .card-header a.active, .card-fuchsia.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f012be; } .bg-fuchsia > .card-header .btn-tool, .bg-gradient-fuchsia > .card-header .btn-tool, .card-fuchsia:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-fuchsia > .card-header .btn-tool:hover, .bg-gradient-fuchsia > .card-header .btn-tool:hover, .card-fuchsia:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-fuchsia .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.second:hover { background-color: #cc0da1; color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f342cb; color: #fff; } .card-maroon:not(.card-outline) > .card-header { background-color: #d81b60; } .card-maroon:not(.card-outline) > .card-header, .card-maroon:not(.card-outline) > .card-header a { color: #fff; } .card-maroon:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-maroon.card-outline { border-top: 3px solid #d81b60; } .card-maroon.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-maroon.card-outline-tabs > .card-header a.active, .card-maroon.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #d81b60; } .bg-maroon > .card-header .btn-tool, .bg-gradient-maroon > .card-header .btn-tool, .card-maroon:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-maroon > .card-header .btn-tool:hover, .bg-gradient-maroon > .card-header .btn-tool:hover, .card-maroon:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-maroon .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.second:hover { background-color: #b41650; color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-maroon .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e73f7c; color: #fff; } .card-blue:not(.card-outline) > .card-header { background-color: #007bff; } .card-blue:not(.card-outline) > .card-header, .card-blue:not(.card-outline) > .card-header a { color: #fff; } .card-blue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-blue.card-outline { border-top: 3px solid #007bff; } .card-blue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-blue.card-outline-tabs > .card-header a.active, .card-blue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-blue > .card-header .btn-tool, .bg-gradient-blue > .card-header .btn-tool, .card-blue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-blue > .card-header .btn-tool:hover, .bg-gradient-blue > .card-header .btn-tool:hover, .card-blue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget .table td, .card.bg-blue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-blue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-indigo:not(.card-outline) > .card-header { background-color: #6610f2; } .card-indigo:not(.card-outline) > .card-header, .card-indigo:not(.card-outline) > .card-header a { color: #fff; } .card-indigo:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-indigo.card-outline { border-top: 3px solid #6610f2; } .card-indigo.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-indigo.card-outline-tabs > .card-header a.active, .card-indigo.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6610f2; } .bg-indigo > .card-header .btn-tool, .bg-gradient-indigo > .card-header .btn-tool, .card-indigo:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-indigo > .card-header .btn-tool:hover, .bg-gradient-indigo > .card-header .btn-tool:hover, .card-indigo:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-indigo .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.second:hover { background-color: #550bce; color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-indigo .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8540f5; color: #fff; } .card-purple:not(.card-outline) > .card-header { background-color: #6f42c1; } .card-purple:not(.card-outline) > .card-header, .card-purple:not(.card-outline) > .card-header a { color: #fff; } .card-purple:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-purple.card-outline { border-top: 3px solid #6f42c1; } .card-purple.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-purple.card-outline-tabs > .card-header a.active, .card-purple.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6f42c1; } .bg-purple > .card-header .btn-tool, .bg-gradient-purple > .card-header .btn-tool, .card-purple:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-purple > .card-header .btn-tool:hover, .bg-gradient-purple > .card-header .btn-tool:hover, .card-purple:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget .table td, .card.bg-purple .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.second:hover { background-color: #5d36a4; color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-purple .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8c68ce; color: #fff; } .card-pink:not(.card-outline) > .card-header { background-color: #e83e8c; } .card-pink:not(.card-outline) > .card-header, .card-pink:not(.card-outline) > .card-header a { color: #fff; } .card-pink:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-pink.card-outline { border-top: 3px solid #e83e8c; } .card-pink.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-pink.card-outline-tabs > .card-header a.active, .card-pink.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e83e8c; } .bg-pink > .card-header .btn-tool, .bg-gradient-pink > .card-header .btn-tool, .card-pink:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-pink > .card-header .btn-tool:hover, .bg-gradient-pink > .card-header .btn-tool:hover, .card-pink:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget .table td, .card.bg-pink .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e21b76; color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-pink .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed6ca7; color: #fff; } .card-red:not(.card-outline) > .card-header { background-color: #dc3545; } .card-red:not(.card-outline) > .card-header, .card-red:not(.card-outline) > .card-header a { color: #fff; } .card-red:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-red.card-outline { border-top: 3px solid #dc3545; } .card-red.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-red.card-outline-tabs > .card-header a.active, .card-red.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-red > .card-header .btn-tool, .bg-gradient-red > .card-header .btn-tool, .card-red:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-red > .card-header .btn-tool:hover, .bg-gradient-red > .card-header .btn-tool:hover, .card-red:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget .table td, .card.bg-red .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.active, .card.bg-red .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-orange:not(.card-outline) > .card-header { background-color: #fd7e14; } .card-orange:not(.card-outline) > .card-header, .card-orange:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-orange:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-orange.card-outline { border-top: 3px solid #fd7e14; } .card-orange.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-orange.card-outline-tabs > .card-header a.active, .card-orange.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fd7e14; } .bg-orange > .card-header .btn-tool, .bg-gradient-orange > .card-header .btn-tool, .card-orange:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-orange > .card-header .btn-tool:hover, .bg-gradient-orange > .card-header .btn-tool:hover, .card-orange:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget .table td, .card.bg-orange .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e66a02; color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-orange .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active:hover { background-color: #fd9a47; color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header { background-color: #ffc107; } .card-yellow:not(.card-outline) > .card-header, .card-yellow:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-yellow.card-outline { border-top: 3px solid #ffc107; } .card-yellow.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-yellow.card-outline-tabs > .card-header a.active, .card-yellow.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-yellow > .card-header .btn-tool, .bg-gradient-yellow > .card-header .btn-tool, .card-yellow:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-yellow > .card-header .btn-tool:hover, .bg-gradient-yellow > .card-header .btn-tool:hover, .card-yellow:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-yellow .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-yellow .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-green:not(.card-outline) > .card-header { background-color: #28a745; } .card-green:not(.card-outline) > .card-header, .card-green:not(.card-outline) > .card-header a { color: #fff; } .card-green:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-green.card-outline { border-top: 3px solid #28a745; } .card-green.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-green.card-outline-tabs > .card-header a.active, .card-green.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-green > .card-header .btn-tool, .bg-gradient-green > .card-header .btn-tool, .card-green:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-green > .card-header .btn-tool:hover, .bg-gradient-green > .card-header .btn-tool:hover, .card-green:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget .table td, .card.bg-green .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.active, .card.bg-green .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-teal:not(.card-outline) > .card-header { background-color: #20c997; } .card-teal:not(.card-outline) > .card-header, .card-teal:not(.card-outline) > .card-header a { color: #fff; } .card-teal:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-teal.card-outline { border-top: 3px solid #20c997; } .card-teal.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-teal.card-outline-tabs > .card-header a.active, .card-teal.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #20c997; } .bg-teal > .card-header .btn-tool, .bg-gradient-teal > .card-header .btn-tool, .card-teal:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-teal > .card-header .btn-tool:hover, .bg-gradient-teal > .card-header .btn-tool:hover, .card-teal:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget .table td, .card.bg-teal .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.second:hover { background-color: #1aa67d; color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-teal .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3ce0af; color: #fff; } .card-cyan:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-cyan:not(.card-outline) > .card-header, .card-cyan:not(.card-outline) > .card-header a { color: #fff; } .card-cyan:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-cyan.card-outline { border-top: 3px solid #17a2b8; } .card-cyan.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-cyan.card-outline-tabs > .card-header a.active, .card-cyan.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-cyan > .card-header .btn-tool, .bg-gradient-cyan > .card-header .btn-tool, .card-cyan:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-cyan > .card-header .btn-tool:hover, .bg-gradient-cyan > .card-header .btn-tool:hover, .card-cyan:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-cyan .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-cyan .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-white:not(.card-outline) > .card-header { background-color: #fff; } .card-white:not(.card-outline) > .card-header, .card-white:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-white:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-white.card-outline { border-top: 3px solid #fff; } .card-white.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-white.card-outline-tabs > .card-header a.active, .card-white.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fff; } .bg-white > .card-header .btn-tool, .bg-gradient-white > .card-header .btn-tool, .card-white:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-white > .card-header .btn-tool:hover, .bg-gradient-white > .card-header .btn-tool:hover, .card-white:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget .table td, .card.bg-white .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.second:hover { background-color: #ebebeb; color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.active, .card.bg-white .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-gray:not(.card-outline) > .card-header { background-color: #6c757d; } .card-gray:not(.card-outline) > .card-header, .card-gray:not(.card-outline) > .card-header a { color: #fff; } .card-gray:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray.card-outline { border-top: 3px solid #6c757d; } .card-gray.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray.card-outline-tabs > .card-header a.active, .card-gray.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-gray > .card-header .btn-tool, .bg-gradient-gray > .card-header .btn-tool, .card-gray:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray > .card-header .btn-tool:hover, .bg-gradient-gray > .card-header .btn-tool:hover, .card-gray:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gray .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gray .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-gray-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-gray-dark:not(.card-outline) > .card-header, .card-gray-dark:not(.card-outline) > .card-header a { color: #fff; } .card-gray-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray-dark.card-outline { border-top: 3px solid #343a40; } .card-gray-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray-dark.card-outline-tabs > .card-header a.active, .card-gray-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-gray-dark > .card-header .btn-tool, .bg-gradient-gray-dark > .card-header .btn-tool, .card-gray-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray-dark > .card-header .btn-tool:hover, .bg-gradient-gray-dark > .card-header .btn-tool:hover, .card-gray-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gray-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); margin-bottom: 1rem; } .card.bg-dark .card-header { border-color: #383f45; } .card.bg-dark, .card.bg-dark .card-body { color: #fff; } .card.maximized-card { height: 100% !important; left: 0; max-height: 100% !important; max-width: 100% !important; position: fixed; top: 0; width: 100% !important; z-index: 1040; } .card.maximized-card.was-collapsed .card-body { display: block !important; } .card.maximized-card .card-body { overflow: auto; } .card.maximized-card [data-card-widgett="collapse"] { display: none; } .card.maximized-card .card-header, .card.maximized-card .card-footer { border-radius: 0 !important; } .card.collapsed-card .card-body, .card.collapsed-card .card-footer { display: none; } .card .nav.flex-column:not(.nav-sidebar) > li { border-bottom: 1px solid rgba(0, 0, 0, 0.125); margin: 0; } .card .nav.flex-column:not(.nav-sidebar) > li:last-of-type { border-bottom: 0; } .card.height-control .card-body { max-height: 300px; overflow: auto; } .card .border-right { border-right: 1px solid rgba(0, 0, 0, 0.125); } .card .border-left { border-left: 1px solid rgba(0, 0, 0, 0.125); } .card.card-tabs:not(.card-outline) > .card-header { border-bottom: 0; } .card.card-tabs:not(.card-outline) > .card-header .nav-item:first-child .nav-link { border-left-color: transparent; } .card.card-tabs.card-outline .nav-item { border-bottom: 0; } .card.card-tabs.card-outline .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-tabs .card-tools { margin: .3rem .5rem; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } .card.card-outline-tabs { border-top: 0; } .card.card-outline-tabs .card-header .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-outline-tabs .card-header a { border-top: 3px solid transparent; } .card.card-outline-tabs .card-header a:hover { border-top: 3px solid #dee2e6; } .card.card-outline-tabs .card-header a.active:hover { margin-top: 0; } .card.card-outline-tabs .card-tools { margin: .5rem .5rem .3rem; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-outline-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } html.maximized-card { overflow: hidden; } .card-header::after, .card-body::after, .card-footer::after { display: block; clear: both; content: ""; } .card-header { background-color: transparent; border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 0.75rem 1.25rem; position: relative; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .collapsed-card .card-header { border-bottom: 0; } .card-header > .card-tools { float: right; margin-right: -0.625rem; } .card-header > .card-tools .input-group, .card-header > .card-tools .nav, .card-header > .card-tools .pagination { margin-bottom: -0.3rem; margin-top: -0.3rem; } .card-header > .card-tools [data-toggle="tooltip"] { position: relative; } .card-title { float: left; font-size: 1.1rem; font-weight: 400; margin: 0; } .card-text { clear: both; } .btn-tool { background-color: transparent; color: #adb5bd; font-size: 0.875rem; margin: -0.75rem 0; padding: .25rem .5rem; } .btn-group.show .btn-tool, .btn-tool:hover { color: #495057; } .show .btn-tool, .btn-tool:focus { box-shadow: none !important; } .text-sm .card-title { font-size: 1rem; } .text-sm .nav-link { padding: 0.4rem 0.8rem; } .card-body > .table { margin-bottom: 0; } .card-body > .table > thead > tr > th, .card-body > .table > thead > tr > td { border-top-width: 0; } .card-body .fc { margin-top: 5px; } .card-body .full-width-chart { margin: -19px; } .card-body.p-0 .full-width-chart { margin: -9px; } .chart-legend { padding-left: 0; list-style: none; margin: 10px 0; } @media (max-width: 576px) { .chart-legend > li { float: left; margin-right: 10px; } } .card-comments { background-color: #f8f9fa; } .card-comments .card-comment { border-bottom: 1px solid #e9ecef; padding: 8px 0; } .card-comments .card-comment::after { display: block; clear: both; content: ""; } .card-comments .card-comment:last-of-type { border-bottom: 0; } .card-comments .card-comment:first-of-type { padding-top: 0; } .card-comments .card-comment img { height: 1.875rem; width: 1.875rem; float: left; } .card-comments .comment-text { color: #78838e; margin-left: 40px; } .card-comments .username { color: #495057; display: block; font-weight: 600; } .card-comments .text-muted { font-size: 12px; font-weight: 400; } .todo-list { list-style: none; margin: 0; overflow: auto; padding: 0; } .todo-list > li { border-radius: 2px; background-color: #f8f9fa; border-left: 2px solid #e9ecef; color: #495057; margin-bottom: 2px; padding: 10px; } .todo-list > li:last-of-type { margin-bottom: 0; } .todo-list > li > input[type="checkbox"] { margin: 0 10px 0 5px; } .todo-list > li .text { display: inline-block; font-weight: 600; margin-left: 5px; } .todo-list > li .badge { font-size: .7rem; margin-left: 10px; } .todo-list > li .tools { color: #dc3545; display: none; float: right; } .todo-list > li .tools > .fa, .todo-list > li .tools > .fas, .todo-list > li .tools > .far, .todo-list > li .tools > .fab, .todo-list > li .tools > .fal, .todo-list > li .tools > .fad, .todo-list > li .tools > .svg-inline--fa, .todo-list > li .tools > .ion { cursor: pointer; margin-right: 5px; } .todo-list > li:hover .tools { display: inline-block; } .todo-list > li.done { color: #697582; } .todo-list > li.done .text { font-weight: 500; text-decoration: line-through; } .todo-list > li.done .badge { background-color: #adb5bd !important; } .todo-list .primary { border-left-color: #007bff; } .todo-list .secondary { border-left-color: #6c757d; } .todo-list .success { border-left-color: #28a745; } .todo-list .info { border-left-color: #17a2b8; } .todo-list .warning { border-left-color: #ffc107; } .todo-list .danger { border-left-color: #dc3545; } .todo-list .light { border-left-color: #f8f9fa; } .todo-list .dark { border-left-color: #343a40; } .todo-list .lightblue { border-left-color: #3c8dbc; } .todo-list .navy { border-left-color: #001f3f; } .todo-list .olive { border-left-color: #3d9970; } .todo-list .lime { border-left-color: #01ff70; } .todo-list .fuchsia { border-left-color: #f012be; } .todo-list .maroon { border-left-color: #d81b60; } .todo-list .blue { border-left-color: #007bff; } .todo-list .indigo { border-left-color: #6610f2; } .todo-list .purple { border-left-color: #6f42c1; } .todo-list .pink { border-left-color: #e83e8c; } .todo-list .red { border-left-color: #dc3545; } .todo-list .orange { border-left-color: #fd7e14; } .todo-list .yellow { border-left-color: #ffc107; } .todo-list .green { border-left-color: #28a745; } .todo-list .teal { border-left-color: #20c997; } .todo-list .cyan { border-left-color: #17a2b8; } .todo-list .white { border-left-color: #fff; } .todo-list .gray { border-left-color: #6c757d; } .todo-list .gray-dark { border-left-color: #343a40; } .todo-list .handle { cursor: move; display: inline-block; margin: 0 5px; } .card-input { max-width: 200px; } .card-default .nav-item:first-child .nav-link { border-left: 0; } .dark-mode .card-primary:not(.card-outline) > .card-header { background-color: #3f6791; } .dark-mode .card-primary:not(.card-outline) > .card-header, .dark-mode .card-primary:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-primary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-primary.card-outline { border-top: 3px solid #3f6791; } .dark-mode .card-primary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-primary.card-outline-tabs > .card-header a.active, .dark-mode .card-primary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3f6791; } .dark-mode .bg-primary > .card-header .btn-tool, .dark-mode .bg-gradient-primary > .card-header .btn-tool, .dark-mode .card-primary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-primary > .card-header .btn-tool:hover, .dark-mode .bg-gradient-primary > .card-header .btn-tool:hover, .dark-mode .card-primary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #335375; color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-primary .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5080b3; color: #fff; } .dark-mode .card-secondary:not(.card-outline) > .card-header { background-color: #6c757d; } .dark-mode .card-secondary:not(.card-outline) > .card-header, .dark-mode .card-secondary:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-secondary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-secondary.card-outline { border-top: 3px solid #6c757d; } .dark-mode .card-secondary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-secondary.card-outline-tabs > .card-header a.active, .dark-mode .card-secondary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .dark-mode .bg-secondary > .card-header .btn-tool, .dark-mode .bg-gradient-secondary > .card-header .btn-tool, .dark-mode .card-secondary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-secondary > .card-header .btn-tool:hover, .dark-mode .bg-gradient-secondary > .card-header .btn-tool:hover, .dark-mode .card-secondary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-secondary .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .dark-mode .card-success:not(.card-outline) > .card-header { background-color: #00bc8c; } .dark-mode .card-success:not(.card-outline) > .card-header, .dark-mode .card-success:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-success:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-success.card-outline { border-top: 3px solid #00bc8c; } .dark-mode .card-success.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-success.card-outline-tabs > .card-header a.active, .dark-mode .card-success.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #00bc8c; } .dark-mode .bg-success > .card-header .btn-tool, .dark-mode .bg-gradient-success > .card-header .btn-tool, .dark-mode .card-success:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-success > .card-header .btn-tool:hover, .dark-mode .bg-gradient-success > .card-header .btn-tool:hover, .dark-mode .card-success:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00936e; color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-success .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00efb2; color: #fff; } .dark-mode .card-info:not(.card-outline) > .card-header { background-color: #3498db; } .dark-mode .card-info:not(.card-outline) > .card-header, .dark-mode .card-info:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-info:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-info.card-outline { border-top: 3px solid #3498db; } .dark-mode .card-info.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-info.card-outline-tabs > .card-header a.active, .dark-mode .card-info.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3498db; } .dark-mode .bg-info > .card-header .btn-tool, .dark-mode .bg-gradient-info > .card-header .btn-tool, .dark-mode .card-info:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-info > .card-header .btn-tool:hover, .dark-mode .bg-gradient-info > .card-header .btn-tool:hover, .dark-mode .card-info:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.second:hover { background-color: #2383c4; color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-info .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5faee3; color: #fff; } .dark-mode .card-warning:not(.card-outline) > .card-header { background-color: #f39c12; } .dark-mode .card-warning:not(.card-outline) > .card-header, .dark-mode .card-warning:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-warning:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-warning.card-outline { border-top: 3px solid #f39c12; } .dark-mode .card-warning.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-warning.card-outline-tabs > .card-header a.active, .dark-mode .card-warning.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f39c12; } .dark-mode .bg-warning > .card-header .btn-tool, .dark-mode .bg-gradient-warning > .card-header .btn-tool, .dark-mode .card-warning:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-warning > .card-header .btn-tool:hover, .dark-mode .bg-gradient-warning > .card-header .btn-tool:hover, .dark-mode .card-warning:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.second:hover { background-color: #d2850b; color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-warning .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f5b043; color: #1f2d3d; } .dark-mode .card-danger:not(.card-outline) > .card-header { background-color: #e74c3c; } .dark-mode .card-danger:not(.card-outline) > .card-header, .dark-mode .card-danger:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-danger:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-danger.card-outline { border-top: 3px solid #e74c3c; } .dark-mode .card-danger.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-danger.card-outline-tabs > .card-header a.active, .dark-mode .card-danger.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e74c3c; } .dark-mode .bg-danger > .card-header .btn-tool, .dark-mode .bg-gradient-danger > .card-header .btn-tool, .dark-mode .card-danger:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-danger > .card-header .btn-tool:hover, .dark-mode .bg-gradient-danger > .card-header .btn-tool:hover, .dark-mode .card-danger:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.second:hover { background-color: #df2e1b; color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-danger .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed7669; color: #fff; } .dark-mode .card-light:not(.card-outline) > .card-header { background-color: #f8f9fa; } .dark-mode .card-light:not(.card-outline) > .card-header, .dark-mode .card-light:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-light:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-light.card-outline { border-top: 3px solid #f8f9fa; } .dark-mode .card-light.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-light.card-outline-tabs > .card-header a.active, .dark-mode .card-light.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f8f9fa; } .dark-mode .bg-light > .card-header .btn-tool, .dark-mode .bg-gradient-light > .card-header .btn-tool, .dark-mode .card-light:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-light > .card-header .btn-tool:hover, .dark-mode .bg-gradient-light > .card-header .btn-tool:hover, .dark-mode .card-light:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e0e5e9; color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-light .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .dark-mode .card-dark:not(.card-outline) > .card-header { background-color: #343a40; } .dark-mode .card-dark:not(.card-outline) > .card-header, .dark-mode .card-dark:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-dark.card-outline { border-top: 3px solid #343a40; } .dark-mode .card-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-dark.card-outline-tabs > .card-header a.active, .dark-mode .card-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .dark-mode .bg-dark > .card-header .btn-tool, .dark-mode .bg-gradient-dark > .card-header .btn-tool, .dark-mode .card-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-dark > .card-header .btn-tool:hover, .dark-mode .bg-gradient-dark > .card-header .btn-tool:hover, .dark-mode .card-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-dark .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .dark-mode .card-lightblue:not(.card-outline) > .card-header { background-color: #86bad8; } .dark-mode .card-lightblue:not(.card-outline) > .card-header, .dark-mode .card-lightblue:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-lightblue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-lightblue.card-outline { border-top: 3px solid #86bad8; } .dark-mode .card-lightblue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-lightblue.card-outline-tabs > .card-header a.active, .dark-mode .card-lightblue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #86bad8; } .dark-mode .bg-lightblue > .card-header .btn-tool, .dark-mode .bg-gradient-lightblue > .card-header .btn-tool, .dark-mode .card-lightblue:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-lightblue > .card-header .btn-tool:hover, .dark-mode .bg-gradient-lightblue > .card-header .btn-tool:hover, .dark-mode .card-lightblue:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #67a8ce; color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #acd0e5; color: #1f2d3d; } .dark-mode .card-navy:not(.card-outline) > .card-header { background-color: #002c59; } .dark-mode .card-navy:not(.card-outline) > .card-header, .dark-mode .card-navy:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-navy:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-navy.card-outline { border-top: 3px solid #002c59; } .dark-mode .card-navy.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-navy.card-outline-tabs > .card-header a.active, .dark-mode .card-navy.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #002c59; } .dark-mode .bg-navy > .card-header .btn-tool, .dark-mode .bg-gradient-navy > .card-header .btn-tool, .dark-mode .card-navy:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-navy > .card-header .btn-tool:hover, .dark-mode .bg-gradient-navy > .card-header .btn-tool:hover, .dark-mode .card-navy:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.second:hover { background-color: #001730; color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-navy .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00458c; color: #fff; } .dark-mode .card-olive:not(.card-outline) > .card-header { background-color: #74c8a3; } .dark-mode .card-olive:not(.card-outline) > .card-header, .dark-mode .card-olive:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-olive:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-olive.card-outline { border-top: 3px solid #74c8a3; } .dark-mode .card-olive.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-olive.card-outline-tabs > .card-header a.active, .dark-mode .card-olive.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #74c8a3; } .dark-mode .bg-olive > .card-header .btn-tool, .dark-mode .bg-gradient-olive > .card-header .btn-tool, .dark-mode .card-olive:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-olive > .card-header .btn-tool:hover, .dark-mode .bg-gradient-olive > .card-header .btn-tool:hover, .dark-mode .card-olive:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.second:hover { background-color: #57bc8f; color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-olive .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active:hover { background-color: #99d6bb; color: #1f2d3d; } .dark-mode .card-lime:not(.card-outline) > .card-header { background-color: #67ffa9; } .dark-mode .card-lime:not(.card-outline) > .card-header, .dark-mode .card-lime:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-lime:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-lime.card-outline { border-top: 3px solid #67ffa9; } .dark-mode .card-lime.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-lime.card-outline-tabs > .card-header a.active, .dark-mode .card-lime.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #67ffa9; } .dark-mode .bg-lime > .card-header .btn-tool, .dark-mode .bg-gradient-lime > .card-header .btn-tool, .dark-mode .card-lime:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-lime > .card-header .btn-tool:hover, .dark-mode .bg-gradient-lime > .card-header .btn-tool:hover, .dark-mode .card-lime:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.second:hover { background-color: #3eff92; color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-lime .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active:hover { background-color: #9affc6; color: #1f2d3d; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header { background-color: #f672d8; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header, .dark-mode .card-fuchsia:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-fuchsia:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-fuchsia.card-outline { border-top: 3px solid #f672d8; } .dark-mode .card-fuchsia.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-fuchsia.card-outline-tabs > .card-header a.active, .dark-mode .card-fuchsia.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f672d8; } .dark-mode .bg-fuchsia > .card-header .btn-tool, .dark-mode .bg-gradient-fuchsia > .card-header .btn-tool, .dark-mode .card-fuchsia:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-fuchsia > .card-header .btn-tool:hover, .dark-mode .bg-gradient-fuchsia > .card-header .btn-tool:hover, .dark-mode .card-fuchsia:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.second:hover { background-color: #f44cce; color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f9a2e5; color: #1f2d3d; } .dark-mode .card-maroon:not(.card-outline) > .card-header { background-color: #ed6c9b; } .dark-mode .card-maroon:not(.card-outline) > .card-header, .dark-mode .card-maroon:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-maroon:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-maroon.card-outline { border-top: 3px solid #ed6c9b; } .dark-mode .card-maroon.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-maroon.card-outline-tabs > .card-header a.active, .dark-mode .card-maroon.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ed6c9b; } .dark-mode .bg-maroon > .card-header .btn-tool, .dark-mode .bg-gradient-maroon > .card-header .btn-tool, .dark-mode .card-maroon:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-maroon > .card-header .btn-tool:hover, .dark-mode .bg-gradient-maroon > .card-header .btn-tool:hover, .dark-mode .card-maroon:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e84883; color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-maroon .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f29aba; color: #1f2d3d; } .dark-mode .card-blue:not(.card-outline) > .card-header { background-color: #3f6791; } .dark-mode .card-blue:not(.card-outline) > .card-header, .dark-mode .card-blue:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-blue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-blue.card-outline { border-top: 3px solid #3f6791; } .dark-mode .card-blue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-blue.card-outline-tabs > .card-header a.active, .dark-mode .card-blue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3f6791; } .dark-mode .bg-blue > .card-header .btn-tool, .dark-mode .bg-gradient-blue > .card-header .btn-tool, .dark-mode .card-blue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-blue > .card-header .btn-tool:hover, .dark-mode .bg-gradient-blue > .card-header .btn-tool:hover, .dark-mode .card-blue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #335375; color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-blue .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5080b3; color: #fff; } .dark-mode .card-indigo:not(.card-outline) > .card-header { background-color: #6610f2; } .dark-mode .card-indigo:not(.card-outline) > .card-header, .dark-mode .card-indigo:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-indigo:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-indigo.card-outline { border-top: 3px solid #6610f2; } .dark-mode .card-indigo.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-indigo.card-outline-tabs > .card-header a.active, .dark-mode .card-indigo.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6610f2; } .dark-mode .bg-indigo > .card-header .btn-tool, .dark-mode .bg-gradient-indigo > .card-header .btn-tool, .dark-mode .card-indigo:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-indigo > .card-header .btn-tool:hover, .dark-mode .bg-gradient-indigo > .card-header .btn-tool:hover, .dark-mode .card-indigo:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.second:hover { background-color: #550bce; color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-indigo .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8540f5; color: #fff; } .dark-mode .card-purple:not(.card-outline) > .card-header { background-color: #6f42c1; } .dark-mode .card-purple:not(.card-outline) > .card-header, .dark-mode .card-purple:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-purple:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-purple.card-outline { border-top: 3px solid #6f42c1; } .dark-mode .card-purple.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-purple.card-outline-tabs > .card-header a.active, .dark-mode .card-purple.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6f42c1; } .dark-mode .bg-purple > .card-header .btn-tool, .dark-mode .bg-gradient-purple > .card-header .btn-tool, .dark-mode .card-purple:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-purple > .card-header .btn-tool:hover, .dark-mode .bg-gradient-purple > .card-header .btn-tool:hover, .dark-mode .card-purple:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.second:hover { background-color: #5d36a4; color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-purple .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8c68ce; color: #fff; } .dark-mode .card-pink:not(.card-outline) > .card-header { background-color: #e83e8c; } .dark-mode .card-pink:not(.card-outline) > .card-header, .dark-mode .card-pink:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-pink:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-pink.card-outline { border-top: 3px solid #e83e8c; } .dark-mode .card-pink.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-pink.card-outline-tabs > .card-header a.active, .dark-mode .card-pink.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e83e8c; } .dark-mode .bg-pink > .card-header .btn-tool, .dark-mode .bg-gradient-pink > .card-header .btn-tool, .dark-mode .card-pink:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-pink > .card-header .btn-tool:hover, .dark-mode .bg-gradient-pink > .card-header .btn-tool:hover, .dark-mode .card-pink:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e21b76; color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-pink .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed6ca7; color: #fff; } .dark-mode .card-red:not(.card-outline) > .card-header { background-color: #e74c3c; } .dark-mode .card-red:not(.card-outline) > .card-header, .dark-mode .card-red:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-red:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-red.card-outline { border-top: 3px solid #e74c3c; } .dark-mode .card-red.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-red.card-outline-tabs > .card-header a.active, .dark-mode .card-red.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e74c3c; } .dark-mode .bg-red > .card-header .btn-tool, .dark-mode .bg-gradient-red > .card-header .btn-tool, .dark-mode .card-red:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-red > .card-header .btn-tool:hover, .dark-mode .bg-gradient-red > .card-header .btn-tool:hover, .dark-mode .card-red:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.second:hover { background-color: #df2e1b; color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-red .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed7669; color: #fff; } .dark-mode .card-orange:not(.card-outline) > .card-header { background-color: #fd7e14; } .dark-mode .card-orange:not(.card-outline) > .card-header, .dark-mode .card-orange:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-orange:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-orange.card-outline { border-top: 3px solid #fd7e14; } .dark-mode .card-orange.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-orange.card-outline-tabs > .card-header a.active, .dark-mode .card-orange.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fd7e14; } .dark-mode .bg-orange > .card-header .btn-tool, .dark-mode .bg-gradient-orange > .card-header .btn-tool, .dark-mode .card-orange:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-orange > .card-header .btn-tool:hover, .dark-mode .bg-gradient-orange > .card-header .btn-tool:hover, .dark-mode .card-orange:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e66a02; color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-orange .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active:hover { background-color: #fd9a47; color: #1f2d3d; } .dark-mode .card-yellow:not(.card-outline) > .card-header { background-color: #f39c12; } .dark-mode .card-yellow:not(.card-outline) > .card-header, .dark-mode .card-yellow:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-yellow:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-yellow.card-outline { border-top: 3px solid #f39c12; } .dark-mode .card-yellow.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-yellow.card-outline-tabs > .card-header a.active, .dark-mode .card-yellow.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f39c12; } .dark-mode .bg-yellow > .card-header .btn-tool, .dark-mode .bg-gradient-yellow > .card-header .btn-tool, .dark-mode .card-yellow:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-yellow > .card-header .btn-tool:hover, .dark-mode .bg-gradient-yellow > .card-header .btn-tool:hover, .dark-mode .card-yellow:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.second:hover { background-color: #d2850b; color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-yellow .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f5b043; color: #1f2d3d; } .dark-mode .card-green:not(.card-outline) > .card-header { background-color: #00bc8c; } .dark-mode .card-green:not(.card-outline) > .card-header, .dark-mode .card-green:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-green:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-green.card-outline { border-top: 3px solid #00bc8c; } .dark-mode .card-green.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-green.card-outline-tabs > .card-header a.active, .dark-mode .card-green.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #00bc8c; } .dark-mode .bg-green > .card-header .btn-tool, .dark-mode .bg-gradient-green > .card-header .btn-tool, .dark-mode .card-green:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-green > .card-header .btn-tool:hover, .dark-mode .bg-gradient-green > .card-header .btn-tool:hover, .dark-mode .card-green:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00936e; color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-green .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active:hover { background-color: #00efb2; color: #fff; } .dark-mode .card-teal:not(.card-outline) > .card-header { background-color: #20c997; } .dark-mode .card-teal:not(.card-outline) > .card-header, .dark-mode .card-teal:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-teal:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-teal.card-outline { border-top: 3px solid #20c997; } .dark-mode .card-teal.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-teal.card-outline-tabs > .card-header a.active, .dark-mode .card-teal.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #20c997; } .dark-mode .bg-teal > .card-header .btn-tool, .dark-mode .bg-gradient-teal > .card-header .btn-tool, .dark-mode .card-teal:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-teal > .card-header .btn-tool:hover, .dark-mode .bg-gradient-teal > .card-header .btn-tool:hover, .dark-mode .card-teal:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.second:hover { background-color: #1aa67d; color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-teal .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3ce0af; color: #fff; } .dark-mode .card-cyan:not(.card-outline) > .card-header { background-color: #3498db; } .dark-mode .card-cyan:not(.card-outline) > .card-header, .dark-mode .card-cyan:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-cyan:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-cyan.card-outline { border-top: 3px solid #3498db; } .dark-mode .card-cyan.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-cyan.card-outline-tabs > .card-header a.active, .dark-mode .card-cyan.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3498db; } .dark-mode .bg-cyan > .card-header .btn-tool, .dark-mode .bg-gradient-cyan > .card-header .btn-tool, .dark-mode .card-cyan:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-cyan > .card-header .btn-tool:hover, .dark-mode .bg-gradient-cyan > .card-header .btn-tool:hover, .dark-mode .card-cyan:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.second:hover { background-color: #2383c4; color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-cyan .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5faee3; color: #fff; } .dark-mode .card-white:not(.card-outline) > .card-header { background-color: #fff; } .dark-mode .card-white:not(.card-outline) > .card-header, .dark-mode .card-white:not(.card-outline) > .card-header a { color: #1f2d3d; } .dark-mode .card-white:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-white.card-outline { border-top: 3px solid #fff; } .dark-mode .card-white.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-white.card-outline-tabs > .card-header a.active, .dark-mode .card-white.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fff; } .dark-mode .bg-white > .card-header .btn-tool, .dark-mode .bg-gradient-white > .card-header .btn-tool, .dark-mode .card-white:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .dark-mode .bg-white > .card-header .btn-tool:hover, .dark-mode .bg-gradient-white > .card-header .btn-tool:hover, .dark-mode .card-white:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.second:hover { background-color: #ebebeb; color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-white .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .dark-mode .card-gray:not(.card-outline) > .card-header { background-color: #6c757d; } .dark-mode .card-gray:not(.card-outline) > .card-header, .dark-mode .card-gray:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-gray:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-gray.card-outline { border-top: 3px solid #6c757d; } .dark-mode .card-gray.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-gray.card-outline-tabs > .card-header a.active, .dark-mode .card-gray.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .dark-mode .bg-gray > .card-header .btn-tool, .dark-mode .bg-gradient-gray > .card-header .btn-tool, .dark-mode .card-gray:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-gray > .card-header .btn-tool:hover, .dark-mode .bg-gradient-gray > .card-header .btn-tool:hover, .dark-mode .card-gray:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gray .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header { background-color: #343a40; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header, .dark-mode .card-gray-dark:not(.card-outline) > .card-header a { color: #fff; } .dark-mode .card-gray-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .dark-mode .card-gray-dark.card-outline { border-top: 3px solid #343a40; } .dark-mode .card-gray-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .dark-mode .card-gray-dark.card-outline-tabs > .card-header a.active, .dark-mode .card-gray-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .dark-mode .bg-gray-dark > .card-header .btn-tool, .dark-mode .bg-gradient-gray-dark > .card-header .btn-tool, .dark-mode .card-gray-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .dark-mode .bg-gray-dark > .card-header .btn-tool:hover, .dark-mode .bg-gradient-gray-dark > .card-header .btn-tool:hover, .dark-mode .card-gray-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget .table th, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table td, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table th { border: none; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.second:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.today::before, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active:hover, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active, .dark-mode .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .dark-mode .card { background-color: #343a40; color: #fff; } .dark-mode .card .card { background-color: #3f474e; color: #fff; } .dark-mode .card .nav.flex-column > li { border-bottom-color: #6c757d; } .dark-mode .card .card-footer { background-color: rgba(0, 0, 0, 0.1); } .dark-mode .card.card-outline-tabs { border-top: 0; } .dark-mode .card.card-outline-tabs .card-header a:hover { border-top-color: #6c757d; border-bottom-color: transparent; } .dark-mode .card:not(.card-outline) > .card-header a.active { color: #fff; } .dark-mode .card-comments { background-color: #373d44; } .dark-mode .card-comments .username { color: #ced4da; } .dark-mode .card-comments .card-comment { border-bottom-color: #454d55; } .dark-mode .todo-list > li { background-color: #3f474e; border-color: #454d55; color: #fff; } .dark-mode .todo-list .primary { border-left-color: #3f6791; } .dark-mode .todo-list .secondary { border-left-color: #6c757d; } .dark-mode .todo-list .success { border-left-color: #00bc8c; } .dark-mode .todo-list .info { border-left-color: #3498db; } .dark-mode .todo-list .warning { border-left-color: #f39c12; } .dark-mode .todo-list .danger { border-left-color: #e74c3c; } .dark-mode .todo-list .light { border-left-color: #f8f9fa; } .dark-mode .todo-list .dark { border-left-color: #343a40; } .dark-mode .todo-list .lightblue { border-left-color: #86bad8; } .dark-mode .todo-list .navy { border-left-color: #002c59; } .dark-mode .todo-list .olive { border-left-color: #74c8a3; } .dark-mode .todo-list .lime { border-left-color: #67ffa9; } .dark-mode .todo-list .fuchsia { border-left-color: #f672d8; } .dark-mode .todo-list .maroon { border-left-color: #ed6c9b; } .dark-mode .todo-list .blue { border-left-color: #3f6791; } .dark-mode .todo-list .indigo { border-left-color: #6610f2; } .dark-mode .todo-list .purple { border-left-color: #6f42c1; } .dark-mode .todo-list .pink { border-left-color: #e83e8c; } .dark-mode .todo-list .red { border-left-color: #e74c3c; } .dark-mode .todo-list .orange { border-left-color: #fd7e14; } .dark-mode .todo-list .yellow { border-left-color: #f39c12; } .dark-mode .todo-list .green { border-left-color: #00bc8c; } .dark-mode .todo-list .teal { border-left-color: #20c997; } .dark-mode .todo-list .cyan { border-left-color: #3498db; } .dark-mode .todo-list .white { border-left-color: #fff; } .dark-mode .todo-list .gray { border-left-color: #6c757d; } .dark-mode .todo-list .gray-dark { border-left-color: #343a40; } .modal-dialog .overlay { display: -ms-flexbox; display: flex; position: absolute; left: 0; top: 0; bottom: 0; right: 0; margin: -1px; z-index: 1052; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; background-color: rgba(0, 0, 0, 0.7); color: #666f76; border-radius: 0.3rem; } .modal-content.bg-warning .modal-header, .modal-content.bg-warning .modal-footer { border-color: #343a40; } .modal-content.bg-primary .close, .modal-content.bg-secondary .close, .modal-content.bg-info .close, .modal-content.bg-danger .close, .modal-content.bg-success .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .modal-header, .dark-mode .modal-footer { border-color: #6c757d; } .dark-mode .modal-content { background-color: #343a40; } .dark-mode .modal-content.bg-warning .modal-header, .dark-mode .modal-content.bg-warning .modal-footer { border-color: #6c757d; } .dark-mode .modal-content.bg-warning .close { color: #343a40 !important; text-shadow: 0 1px 0 #495057 !important; } .dark-mode .modal-content.bg-primary .modal-header, .dark-mode .modal-content.bg-primary .modal-footer, .dark-mode .modal-content.bg-secondary .modal-header, .dark-mode .modal-content.bg-secondary .modal-footer, .dark-mode .modal-content.bg-info .modal-header, .dark-mode .modal-content.bg-info .modal-footer, .dark-mode .modal-content.bg-danger .modal-header, .dark-mode .modal-content.bg-danger .modal-footer, .dark-mode .modal-content.bg-success .modal-header, .dark-mode .modal-content.bg-success .modal-footer { border-color: #fff; } .toasts-top-right { position: absolute; right: 0; top: 0; z-index: 1040; } .toasts-top-right.fixed { position: fixed; } .toasts-top-left { left: 0; position: absolute; top: 0; z-index: 1040; } .toasts-top-left.fixed { position: fixed; } .toasts-bottom-right { bottom: 0; position: absolute; right: 0; z-index: 1040; } .toasts-bottom-right.fixed { position: fixed; } .toasts-bottom-left { bottom: 0; left: 0; position: absolute; z-index: 1040; } .toasts-bottom-left.fixed { position: fixed; } .dark-mode .toast { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .dark-mode .toast .toast-header { background-color: rgba(52, 58, 64, 0.7); color: #f8f9fa; } .dark-mode .toast.bg-primary { background-color: rgba(63, 103, 145, 0.9) !important; } .dark-mode .toast.bg-primary .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-primary .toast-header { background-color: rgba(63, 103, 145, 0.85); color: #fff; } .dark-mode .toast.bg-secondary { background-color: rgba(108, 117, 125, 0.9) !important; } .dark-mode .toast.bg-secondary .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-secondary .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .dark-mode .toast.bg-success { background-color: rgba(0, 188, 140, 0.9) !important; } .dark-mode .toast.bg-success .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-success .toast-header { background-color: rgba(0, 188, 140, 0.85); color: #fff; } .dark-mode .toast.bg-info { background-color: rgba(52, 152, 219, 0.9) !important; } .dark-mode .toast.bg-info .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-info .toast-header { background-color: rgba(52, 152, 219, 0.85); color: #fff; } .dark-mode .toast.bg-warning { background-color: rgba(243, 156, 18, 0.9) !important; } .dark-mode .toast.bg-warning .toast-header { background-color: rgba(243, 156, 18, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-danger { background-color: rgba(231, 76, 60, 0.9) !important; } .dark-mode .toast.bg-danger .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-danger .toast-header { background-color: rgba(231, 76, 60, 0.85); color: #fff; } .dark-mode .toast.bg-light { background-color: rgba(248, 249, 250, 0.9) !important; } .dark-mode .toast.bg-light .toast-header { background-color: rgba(248, 249, 250, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .dark-mode .toast.bg-dark .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .dark-mode .toast.bg-lightblue { background-color: rgba(134, 186, 216, 0.9) !important; } .dark-mode .toast.bg-lightblue .toast-header { background-color: rgba(134, 186, 216, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-navy { background-color: rgba(0, 44, 89, 0.9) !important; } .dark-mode .toast.bg-navy .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-navy .toast-header { background-color: rgba(0, 44, 89, 0.85); color: #fff; } .dark-mode .toast.bg-olive { background-color: rgba(116, 200, 163, 0.9) !important; } .dark-mode .toast.bg-olive .toast-header { background-color: rgba(116, 200, 163, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-lime { background-color: rgba(103, 255, 169, 0.9) !important; } .dark-mode .toast.bg-lime .toast-header { background-color: rgba(103, 255, 169, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-fuchsia { background-color: rgba(246, 114, 216, 0.9) !important; } .dark-mode .toast.bg-fuchsia .toast-header { background-color: rgba(246, 114, 216, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-maroon { background-color: rgba(237, 108, 155, 0.9) !important; } .dark-mode .toast.bg-maroon .toast-header { background-color: rgba(237, 108, 155, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-blue { background-color: rgba(63, 103, 145, 0.9) !important; } .dark-mode .toast.bg-blue .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-blue .toast-header { background-color: rgba(63, 103, 145, 0.85); color: #fff; } .dark-mode .toast.bg-indigo { background-color: rgba(102, 16, 242, 0.9) !important; } .dark-mode .toast.bg-indigo .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-indigo .toast-header { background-color: rgba(102, 16, 242, 0.85); color: #fff; } .dark-mode .toast.bg-purple { background-color: rgba(111, 66, 193, 0.9) !important; } .dark-mode .toast.bg-purple .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-purple .toast-header { background-color: rgba(111, 66, 193, 0.85); color: #fff; } .dark-mode .toast.bg-pink { background-color: rgba(232, 62, 140, 0.9) !important; } .dark-mode .toast.bg-pink .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-pink .toast-header { background-color: rgba(232, 62, 140, 0.85); color: #fff; } .dark-mode .toast.bg-red { background-color: rgba(231, 76, 60, 0.9) !important; } .dark-mode .toast.bg-red .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-red .toast-header { background-color: rgba(231, 76, 60, 0.85); color: #fff; } .dark-mode .toast.bg-orange { background-color: rgba(253, 126, 20, 0.9) !important; } .dark-mode .toast.bg-orange .toast-header { background-color: rgba(253, 126, 20, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-yellow { background-color: rgba(243, 156, 18, 0.9) !important; } .dark-mode .toast.bg-yellow .toast-header { background-color: rgba(243, 156, 18, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-green { background-color: rgba(0, 188, 140, 0.9) !important; } .dark-mode .toast.bg-green .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-green .toast-header { background-color: rgba(0, 188, 140, 0.85); color: #fff; } .dark-mode .toast.bg-teal { background-color: rgba(32, 201, 151, 0.9) !important; } .dark-mode .toast.bg-teal .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-teal .toast-header { background-color: rgba(32, 201, 151, 0.85); color: #fff; } .dark-mode .toast.bg-cyan { background-color: rgba(52, 152, 219, 0.9) !important; } .dark-mode .toast.bg-cyan .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-cyan .toast-header { background-color: rgba(52, 152, 219, 0.85); color: #fff; } .dark-mode .toast.bg-white { background-color: rgba(255, 255, 255, 0.9) !important; } .dark-mode .toast.bg-white .toast-header { background-color: rgba(255, 255, 255, 0.85); color: #1f2d3d; } .dark-mode .toast.bg-gray { background-color: rgba(108, 117, 125, 0.9) !important; } .dark-mode .toast.bg-gray .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-gray .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .dark-mode .toast.bg-gray-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .dark-mode .toast.bg-gray-dark .close { color: #fff; text-shadow: 0 1px 0 #000; } .dark-mode .toast.bg-gray-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .toast.bg-primary { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-primary .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-primary .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-secondary { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-secondary .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-secondary .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-success { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-success .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-success .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-info { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-info .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-info .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-warning { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-warning .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-danger { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-danger .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-danger .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-light { background-color: rgba(248, 249, 250, 0.9) !important; } .toast.bg-light .toast-header { background-color: rgba(248, 249, 250, 0.85); color: #1f2d3d; } .toast.bg-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-dark .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .toast.bg-lightblue { background-color: rgba(60, 141, 188, 0.9) !important; } .toast.bg-lightblue .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-lightblue .toast-header { background-color: rgba(60, 141, 188, 0.85); color: #fff; } .toast.bg-navy { background-color: rgba(0, 31, 63, 0.9) !important; } .toast.bg-navy .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-navy .toast-header { background-color: rgba(0, 31, 63, 0.85); color: #fff; } .toast.bg-olive { background-color: rgba(61, 153, 112, 0.9) !important; } .toast.bg-olive .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-olive .toast-header { background-color: rgba(61, 153, 112, 0.85); color: #fff; } .toast.bg-lime { background-color: rgba(1, 255, 112, 0.9) !important; } .toast.bg-lime .toast-header { background-color: rgba(1, 255, 112, 0.85); color: #1f2d3d; } .toast.bg-fuchsia { background-color: rgba(240, 18, 190, 0.9) !important; } .toast.bg-fuchsia .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-fuchsia .toast-header { background-color: rgba(240, 18, 190, 0.85); color: #fff; } .toast.bg-maroon { background-color: rgba(216, 27, 96, 0.9) !important; } .toast.bg-maroon .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-maroon .toast-header { background-color: rgba(216, 27, 96, 0.85); color: #fff; } .toast.bg-blue { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-blue .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-blue .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-indigo { background-color: rgba(102, 16, 242, 0.9) !important; } .toast.bg-indigo .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-indigo .toast-header { background-color: rgba(102, 16, 242, 0.85); color: #fff; } .toast.bg-purple { background-color: rgba(111, 66, 193, 0.9) !important; } .toast.bg-purple .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-purple .toast-header { background-color: rgba(111, 66, 193, 0.85); color: #fff; } .toast.bg-pink { background-color: rgba(232, 62, 140, 0.9) !important; } .toast.bg-pink .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-pink .toast-header { background-color: rgba(232, 62, 140, 0.85); color: #fff; } .toast.bg-red { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-red .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-red .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-orange { background-color: rgba(253, 126, 20, 0.9) !important; } .toast.bg-orange .toast-header { background-color: rgba(253, 126, 20, 0.85); color: #1f2d3d; } .toast.bg-yellow { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-yellow .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-green { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-green .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-green .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-teal { background-color: rgba(32, 201, 151, 0.9) !important; } .toast.bg-teal .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-teal .toast-header { background-color: rgba(32, 201, 151, 0.85); color: #fff; } .toast.bg-cyan { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-cyan .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-cyan .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-white { background-color: rgba(255, 255, 255, 0.9) !important; } .toast.bg-white .toast-header { background-color: rgba(255, 255, 255, 0.85); color: #1f2d3d; } .toast.bg-gray { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-gray .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-gray-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-gray-dark .close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .btn.disabled, .btn:disabled { cursor: not-allowed; } .btn.btn-flat { border-radius: 0; border-width: 1px; box-shadow: none; } .btn.btn-file { overflow: hidden; position: relative; } .btn.btn-file > input[type="file"] { background-color: #fff; cursor: inherit; display: block; font-size: 100px; min-height: 100%; min-width: 100%; opacity: 0; outline: none; position: absolute; right: 0; text-align: right; top: 0; } .text-sm .btn { font-size: 0.875rem !important; } .btn-default { background-color: #f8f9fa; border-color: #ddd; color: #444; } .btn-default:hover, .btn-default:active, .btn-default.hover { background-color: #e9ecef; color: #2b2b2b; } .btn-default.disabled, .btn-default:disabled { color: #444; background-color: #f8f9fa; } .btn-outline-light { color: #bdc6d0; border-color: #bdc6d0; } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #bdc6d0; border-color: #bdc6d0; } .btn-app { border-radius: 3px; background-color: #f8f9fa; border: 1px solid #ddd; color: #6c757d; font-size: 12px; height: 60px; margin: 0 0 10px 10px; min-width: 80px; padding: 15px 5px; position: relative; text-align: center; } .btn-app > .fa, .btn-app > .fas, .btn-app > .far, .btn-app > .fab, .btn-app > .fal, .btn-app > .fad, .btn-app > .svg-inline--fa, .btn-app > .ion { display: block; font-size: 20px; } .btn-app > .svg-inline--fa { margin: 0 auto; } .btn-app:hover { background-color: #f8f9fa; border-color: #aaaaaa; color: #444; } .btn-app:active, .btn-app:focus { box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-app > .badge { font-size: 10px; font-weight: 400; position: absolute; right: -10px; top: -3px; } .btn-xs { padding: 0.125rem 0.25rem; font-size: 0.75rem; line-height: 1.5; border-radius: 0.15rem; } .dark-mode .btn-default, .dark-mode .btn-app { background-color: #3a4047; color: #fff; border-color: #6c757d; } .dark-mode .btn-default:hover, .dark-mode .btn-default:focus, .dark-mode .btn-app:hover, .dark-mode .btn-app:focus { background-color: #3f474e; color: #dee2e6; border-color: #727b84; } .dark-mode .btn-light { background-color: #454d55; color: #fff; border-color: #6c757d; } .dark-mode .btn-light:hover, .dark-mode .btn-light:focus { background-color: #4b545c; color: #dee2e6; border-color: #78828a; } .dark-mode .btn-primary { color: #fff; background-color: #3f6791; border-color: #3f6791; box-shadow: none; } .dark-mode .btn-primary:hover { color: #fff; background-color: #335476; border-color: #304e6d; } .dark-mode .btn-primary:focus, .dark-mode .btn-primary.focus { color: #fff; background-color: #335476; border-color: #304e6d; box-shadow: 0 0 0 0 rgba(92, 126, 162, 0.5); } .dark-mode .btn-primary.disabled, .dark-mode .btn-primary:disabled { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-primary:not(:disabled):not(.disabled):active, .dark-mode .btn-primary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-primary.dropdown-toggle { color: #fff; background-color: #304e6d; border-color: #2c4765; } .dark-mode .btn-primary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(92, 126, 162, 0.5); } .dark-mode .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; box-shadow: none; } .dark-mode .btn-secondary:hover { color: #fff; background-color: #5a6268; border-color: #545b62; } .dark-mode .btn-secondary:focus, .dark-mode .btn-secondary.focus { color: #fff; background-color: #5a6268; border-color: #545b62; box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .dark-mode .btn-secondary.disabled, .dark-mode .btn-secondary:disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-secondary:not(:disabled):not(.disabled):active, .dark-mode .btn-secondary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-secondary.dropdown-toggle { color: #fff; background-color: #545b62; border-color: #4e555b; } .dark-mode .btn-secondary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .dark-mode .btn-success { color: #fff; background-color: #00bc8c; border-color: #00bc8c; box-shadow: none; } .dark-mode .btn-success:hover { color: #fff; background-color: #009670; border-color: #008966; } .dark-mode .btn-success:focus, .dark-mode .btn-success.focus { color: #fff; background-color: #009670; border-color: #008966; box-shadow: 0 0 0 0 rgba(38, 198, 157, 0.5); } .dark-mode .btn-success.disabled, .dark-mode .btn-success:disabled { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-success:not(:disabled):not(.disabled):active, .dark-mode .btn-success:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-success.dropdown-toggle { color: #fff; background-color: #008966; border-color: #007c5d; } .dark-mode .btn-success:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-success:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(38, 198, 157, 0.5); } .dark-mode .btn-info { color: #fff; background-color: #3498db; border-color: #3498db; box-shadow: none; } .dark-mode .btn-info:hover { color: #fff; background-color: #2384c6; border-color: #217dbb; } .dark-mode .btn-info:focus, .dark-mode .btn-info.focus { color: #fff; background-color: #2384c6; border-color: #217dbb; box-shadow: 0 0 0 0 rgba(82, 167, 224, 0.5); } .dark-mode .btn-info.disabled, .dark-mode .btn-info:disabled { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-info:not(:disabled):not(.disabled):active, .dark-mode .btn-info:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-info.dropdown-toggle { color: #fff; background-color: #217dbb; border-color: #1f76b0; } .dark-mode .btn-info:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-info:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(82, 167, 224, 0.5); } .dark-mode .btn-warning { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; box-shadow: none; } .dark-mode .btn-warning:hover { color: #fff; background-color: #d4860b; border-color: #c87f0a; } .dark-mode .btn-warning:focus, .dark-mode .btn-warning.focus { color: #fff; background-color: #d4860b; border-color: #c87f0a; box-shadow: 0 0 0 0 rgba(211, 139, 24, 0.5); } .dark-mode .btn-warning.disabled, .dark-mode .btn-warning:disabled { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-warning:not(:disabled):not(.disabled):active, .dark-mode .btn-warning:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-warning.dropdown-toggle { color: #fff; background-color: #c87f0a; border-color: #bc770a; } .dark-mode .btn-warning:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(211, 139, 24, 0.5); } .dark-mode .btn-danger { color: #fff; background-color: #e74c3c; border-color: #e74c3c; box-shadow: none; } .dark-mode .btn-danger:hover { color: #fff; background-color: #e12e1c; border-color: #d62c1a; } .dark-mode .btn-danger:focus, .dark-mode .btn-danger.focus { color: #fff; background-color: #e12e1c; border-color: #d62c1a; box-shadow: 0 0 0 0 rgba(235, 103, 89, 0.5); } .dark-mode .btn-danger.disabled, .dark-mode .btn-danger:disabled { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-danger:not(:disabled):not(.disabled):active, .dark-mode .btn-danger:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-danger.dropdown-toggle { color: #fff; background-color: #d62c1a; border-color: #ca2a19; } .dark-mode .btn-danger:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(235, 103, 89, 0.5); } .dark-mode .btn-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: none; } .dark-mode .btn-light:hover { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; } .dark-mode .btn-light:focus, .dark-mode .btn-light.focus { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .dark-mode .btn-light.disabled, .dark-mode .btn-light:disabled { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-light:not(:disabled):not(.disabled):active, .dark-mode .btn-light:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-light.dropdown-toggle { color: #1f2d3d; background-color: #dae0e5; border-color: #d3d9df; } .dark-mode .btn-light:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-light:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .dark-mode .btn-dark { color: #fff; background-color: #292d32; border-color: #4b545c; box-shadow: none; } .dark-mode .btn-dark:hover { color: #fff; background-color: #171a1d; border-color: #343a40; } .dark-mode .btn-dark:focus, .dark-mode .btn-dark.focus { color: #fff; background-color: #171a1d; border-color: #343a40; box-shadow: 0 0 0 0 rgba(102, 109, 117, 0.5); } .dark-mode .btn-dark.disabled, .dark-mode .btn-dark:disabled { color: #fff; background-color: #292d32; border-color: #4b545c; } .dark-mode .btn-dark:not(:disabled):not(.disabled):active, .dark-mode .btn-dark:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-dark.dropdown-toggle { color: #fff; background-color: #121416; border-color: #2e3439; } .dark-mode .btn-dark:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(102, 109, 117, 0.5); } .dark-mode .btn-outline-primary { color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:hover { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:focus, .dark-mode .btn-outline-primary.focus { box-shadow: 0 0 0 0 rgba(63, 103, 145, 0.5); } .dark-mode .btn-outline-primary.disabled, .dark-mode .btn-outline-primary:disabled { color: #3f6791; background-color: transparent; } .dark-mode .btn-outline-primary:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #3f6791; border-color: #3f6791; } .dark-mode .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(63, 103, 145, 0.5); } .dark-mode .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:focus, .dark-mode .btn-outline-secondary.focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .dark-mode .btn-outline-secondary.disabled, .dark-mode .btn-outline-secondary:disabled { color: #6c757d; background-color: transparent; } .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #6c757d; } .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .dark-mode .btn-outline-success { color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:hover { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:focus, .dark-mode .btn-outline-success.focus { box-shadow: 0 0 0 0 rgba(0, 188, 140, 0.5); } .dark-mode .btn-outline-success.disabled, .dark-mode .btn-outline-success:disabled { color: #00bc8c; background-color: transparent; } .dark-mode .btn-outline-success:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-success:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-success.dropdown-toggle { color: #fff; background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .btn-outline-success:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(0, 188, 140, 0.5); } .dark-mode .btn-outline-info { color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:hover { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:focus, .dark-mode .btn-outline-info.focus { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.5); } .dark-mode .btn-outline-info.disabled, .dark-mode .btn-outline-info:disabled { color: #3498db; background-color: transparent; } .dark-mode .btn-outline-info:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-info:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-info.dropdown-toggle { color: #fff; background-color: #3498db; border-color: #3498db; } .dark-mode .btn-outline-info:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.5); } .dark-mode .btn-outline-warning { color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:hover { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:focus, .dark-mode .btn-outline-warning.focus { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0.5); } .dark-mode .btn-outline-warning.disabled, .dark-mode .btn-outline-warning:disabled { color: #f39c12; background-color: transparent; } .dark-mode .btn-outline-warning:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-warning.dropdown-toggle { color: #1f2d3d; background-color: #f39c12; border-color: #f39c12; } .dark-mode .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(243, 156, 18, 0.5); } .dark-mode .btn-outline-danger { color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:hover { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:focus, .dark-mode .btn-outline-danger.focus { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); } .dark-mode .btn-outline-danger.disabled, .dark-mode .btn-outline-danger:disabled { color: #e74c3c; background-color: transparent; } .dark-mode .btn-outline-danger:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.5); } .dark-mode .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:hover { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:focus, .dark-mode .btn-outline-light.focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .dark-mode .btn-outline-light.disabled, .dark-mode .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .dark-mode .btn-outline-light:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-light:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-light.dropdown-toggle { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .btn-outline-light:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .dark-mode .btn-outline-dark { color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:hover { color: #fff; background-color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:focus, .dark-mode .btn-outline-dark.focus { box-shadow: 0 0 0 0 rgba(6, 7, 8, 0.5); } .dark-mode .btn-outline-dark.disabled, .dark-mode .btn-outline-dark:disabled { color: #060708; background-color: transparent; } .dark-mode .btn-outline-dark:not(:disabled):not(.disabled):active, .dark-mode .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .dark-mode .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #060708; border-color: #060708; } .dark-mode .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .dark-mode .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .dark-mode .btn-outline-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(6, 7, 8, 0.5); } .callout { border-radius: 0.25rem; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); background-color: #fff; border-left: 5px solid #e9ecef; margin-bottom: 1rem; padding: 1rem; } .callout a { color: #495057; text-decoration: underline; } .callout a:hover { color: #e9ecef; } .callout p:last-child { margin-bottom: 0; } .callout.callout-danger { border-left-color: #bd2130; } .callout.callout-warning { border-left-color: #d39e00; } .callout.callout-info { border-left-color: #117a8b; } .callout.callout-success { border-left-color: #1e7e34; } .dark-mode .callout { background-color: #3f474e; } .dark-mode .callout.callout-danger { border-left-color: #ed7669; } .dark-mode .callout.callout-warning { border-left-color: #f5b043; } .dark-mode .callout.callout-info { border-left-color: #5faee3; } .dark-mode .callout.callout-success { border-left-color: #00efb2; } .alert .icon { margin-right: 10px; } .alert .close { color: #000; opacity: .2; } .alert .close:hover { opacity: .5; } .alert a { color: #fff; text-decoration: underline; } .alert-primary { color: #fff; background-color: #007bff; border-color: #006fe6; } .alert-default-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-default-primary hr { border-top-color: #9fcdff; } .alert-default-primary .alert-link { color: #002752; } .alert-secondary { color: #fff; background-color: #6c757d; border-color: #60686f; } .alert-default-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-default-secondary hr { border-top-color: #c8cbcf; } .alert-default-secondary .alert-link { color: #202326; } .alert-success { color: #fff; background-color: #28a745; border-color: #23923d; } .alert-default-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-default-success hr { border-top-color: #b1dfbb; } .alert-default-success .alert-link { color: #0b2e13; } .alert-info { color: #fff; background-color: #17a2b8; border-color: #148ea1; } .alert-default-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-default-info hr { border-top-color: #abdde5; } .alert-default-info .alert-link { color: #062c33; } .alert-warning { color: #1f2d3d; background-color: #ffc107; border-color: #edb100; } .alert-default-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-default-warning hr { border-top-color: #ffe8a1; } .alert-default-warning .alert-link { color: #533f03; } .alert-danger { color: #fff; background-color: #dc3545; border-color: #d32535; } .alert-default-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-default-danger hr { border-top-color: #f1b0b7; } .alert-default-danger .alert-link { color: #491217; } .alert-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #e9ecef; } .alert-default-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-default-light hr { border-top-color: #ececf6; } .alert-default-light .alert-link { color: #686868; } .alert-dark { color: #fff; background-color: #343a40; border-color: #292d32; } .alert-default-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-default-dark hr { border-top-color: #b9bbbe; } .alert-default-dark .alert-link { color: #040505; } .dark-mode .alert-primary { color: #fff; background-color: #3f6791; border-color: #375a7f; } .dark-mode .alert-default-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .dark-mode .alert-default-primary hr { border-top-color: #9fcdff; } .dark-mode .alert-default-primary .alert-link { color: #002752; } .dark-mode .alert-secondary { color: #fff; background-color: #6c757d; border-color: #60686f; } .dark-mode .alert-default-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .dark-mode .alert-default-secondary hr { border-top-color: #c8cbcf; } .dark-mode .alert-default-secondary .alert-link { color: #202326; } .dark-mode .alert-success { color: #fff; background-color: #00bc8c; border-color: #00a379; } .dark-mode .alert-default-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .dark-mode .alert-default-success hr { border-top-color: #b1dfbb; } .dark-mode .alert-default-success .alert-link { color: #0b2e13; } .dark-mode .alert-info { color: #fff; background-color: #3498db; border-color: #258cd1; } .dark-mode .alert-default-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .dark-mode .alert-default-info hr { border-top-color: #abdde5; } .dark-mode .alert-default-info .alert-link { color: #062c33; } .dark-mode .alert-warning { color: #1f2d3d; background-color: #f39c12; border-color: #e08e0b; } .dark-mode .alert-default-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .dark-mode .alert-default-warning hr { border-top-color: #ffe8a1; } .dark-mode .alert-default-warning .alert-link { color: #533f03; } .dark-mode .alert-danger { color: #fff; background-color: #e74c3c; border-color: #e43725; } .dark-mode .alert-default-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .dark-mode .alert-default-danger hr { border-top-color: #f1b0b7; } .dark-mode .alert-default-danger .alert-link { color: #491217; } .dark-mode .alert-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #e9ecef; } .dark-mode .alert-default-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .dark-mode .alert-default-light hr { border-top-color: #ececf6; } .dark-mode .alert-default-light .alert-link { color: #686868; } .dark-mode .alert-dark { color: #fff; background-color: #343a40; border-color: #292d32; } .dark-mode .alert-default-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .dark-mode .alert-default-dark hr { border-top-color: #b9bbbe; } .dark-mode .alert-default-dark .alert-link { color: #040505; } .table:not(.table-dark) { color: inherit; } .table.table-head-fixed thead tr:nth-child(1) th { background-color: #fff; border-bottom: 0; box-shadow: inset 0 1px 0 #dee2e6, inset 0 -1px 0 #dee2e6; position: -webkit-sticky; position: sticky; top: 0; z-index: 10; } .table.table-head-fixed.table-dark thead tr:nth-child(1) th { background-color: #212529; box-shadow: inset 0 1px 0 #383f45, inset 0 -1px 0 #383f45; } .table.no-border, .table.no-border td, .table.no-border th { border: 0; } .table.text-center, .table.text-center td, .table.text-center th { text-align: center; } .table.table-valign-middle thead > tr > th, .table.table-valign-middle thead > tr > td, .table.table-valign-middle tbody > tr > th, .table.table-valign-middle tbody > tr > td { vertical-align: middle; } .card-body.p-0 .table thead > tr > th:first-of-type, .card-body.p-0 .table thead > tr > td:first-of-type, .card-body.p-0 .table tfoot > tr > th:first-of-type, .card-body.p-0 .table tfoot > tr > td:first-of-type, .card-body.p-0 .table tbody > tr > th:first-of-type, .card-body.p-0 .table tbody > tr > td:first-of-type { padding-left: 1.5rem; } .card-body.p-0 .table thead > tr > th:last-of-type, .card-body.p-0 .table thead > tr > td:last-of-type, .card-body.p-0 .table tfoot > tr > th:last-of-type, .card-body.p-0 .table tfoot > tr > td:last-of-type, .card-body.p-0 .table tbody > tr > th:last-of-type, .card-body.p-0 .table tbody > tr > td:last-of-type { padding-right: 1.5rem; } .table-hover tbody tr.expandable-body:hover { background-color: inherit !important; } [data-widget="expandable-table"] { cursor: pointer; } [data-widget="expandable-table"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } [aria-expanded="true"] { cursor: pointer; } [aria-expanded="true"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .expandable-body > td { padding: 0 !important; width: 100%; } .expandable-body > td > div, .expandable-body > td > p { padding: 0.75rem; } .expandable-body .table { width: calc(100% - 0.75rem); margin: 0 0 0 0.75rem; } .expandable-body .table tr:first-child td, .expandable-body .table tr:first-child th { border-top: none; } .dark-mode .table-bordered, .dark-mode .table-bordered td, .dark-mode .table-bordered th { border-color: #6c757d; } .dark-mode .table-hover tbody tr:hover { color: #dee2e6; background-color: #3a4047; border-color: #6c757d; } .dark-mode .table thead th { border-bottom-color: #6c757d; } .dark-mode .table th, .dark-mode .table td { border-top-color: #6c757d; } .dark-mode .table.table-head-fixed thead tr:nth-child(1) th { background-color: #3f474e; } .carousel-control-prev .carousel-control-custom-icon { margin-left: -20px; } .carousel-control-next .carousel-control-custom-icon { margin-right: 20px; } .carousel-control-custom-icon > .fa, .carousel-control-custom-icon > .fas, .carousel-control-custom-icon > .far, .carousel-control-custom-icon > .fab, .carousel-control-custom-icon > .fal, .carousel-control-custom-icon > .fad, .carousel-control-custom-icon > .svg-inline--fa, .carousel-control-custom-icon > .ion { display: inline-block; font-size: 40px; margin-top: -20px; position: absolute; top: 50%; z-index: 5; } .close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { opacity: .75; } .close:focus { outline: none; } button.close { padding: 0; background-color: transparent; border: 0; } a.close.disabled { pointer-events: none; } /*# sourceMappingURL=adminlte.components.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.core.css ================================================ /*! * AdminLTE v3.2.0 * Only Core * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ /*! * Bootstrap v4.6.1 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: #fd7e14; --yellow: #ffc107; --green: #28a745; --teal: #20c997; --cyan: #17a2b8; --white: #fff; --gray: #6c757d; --gray-dark: #343a40; --primary: #007bff; --secondary: #6c757d; --success: #28a745; --info: #17a2b8; --warning: #ffc107; --danger: #dc3545; --light: #f8f9fa; --dark: #343a40; --breakpoint-xs: 0; --breakpoint-sm: 576px; --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; --font-family-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus:not(:focus-visible) { outline: 0 !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; } a:hover { color: #0056b3; text-decoration: none; } a:not([href]):not([class]) { color: inherit; text-decoration: none; } a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg { overflow: hidden; vertical-align: middle; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #6c757d; text-align: left; caption-side: bottom; } th { text-align: inherit; text-align: -webkit-match-parent; } label { display: inline-block; margin-bottom: 0.5rem; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } [role="button"] { cursor: pointer; } select { word-wrap: normal; } button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) { cursor: pointer; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; cursor: pointer; } template { display: none; } [hidden] { display: none !important; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; font-family: inherit; font-weight: 500; line-height: 1.2; color: inherit; } h1, .h1 { font-size: 2.5rem; } h2, .h2 { font-size: 2rem; } h3, .h3 { font-size: 1.75rem; } h4, .h4 { font-size: 1.5rem; } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: 6rem; font-weight: 300; line-height: 1.2; } .display-2 { font-size: 5.5rem; font-weight: 300; line-height: 1.2; } .display-3 { font-size: 4.5rem; font-weight: 300; line-height: 1.2; } .display-4 { font-size: 3.5rem; font-weight: 300; line-height: 1.2; } hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } small, .small { font-size: 80%; font-weight: 400; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 90%; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote-footer { display: block; font-size: 80%; color: #6c757d; } .blockquote-footer::before { content: "\2014\00A0"; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.25rem; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 90%; color: #6c757d; } code { font-size: 87.5%; color: #e83e8c; word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 87.5%; color: #fff; background-color: #212529; border-radius: 0.2rem; box-shadow: inset 0 -0.1rem 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; box-shadow: none; } pre { display: block; font-size: 87.5%; color: #212529; } pre code { font-size: inherit; color: inherit; word-break: normal; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container, .container-fluid, .container-sm, .container-md, .container-lg, .container-xl { width: 100%; padding-right: 7.5px; padding-left: 7.5px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container, .container-sm { max-width: 540px; } } @media (min-width: 768px) { .container, .container-sm, .container-md { max-width: 720px; } } @media (min-width: 992px) { .container, .container-sm, .container-md, .container-lg { max-width: 960px; } } @media (min-width: 1200px) { .container, .container-sm, .container-md, .container-lg, .container-xl { max-width: 1140px; } } .row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -7.5px; margin-left: -7.5px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; padding-right: 7.5px; padding-left: 7.5px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -ms-flex-order: -1; order: -1; } .order-last { -ms-flex-order: 13; order: 13; } .order-0 { -ms-flex-order: 0; order: 0; } .order-1 { -ms-flex-order: 1; order: 1; } .order-2 { -ms-flex-order: 2; order: 2; } .order-3 { -ms-flex-order: 3; order: 3; } .order-4 { -ms-flex-order: 4; order: 4; } .order-5 { -ms-flex-order: 5; order: 5; } .order-6 { -ms-flex-order: 6; order: 6; } .order-7 { -ms-flex-order: 7; order: 7; } .order-8 { -ms-flex-order: 8; order: 8; } .order-9 { -ms-flex-order: 9; order: 9; } .order-10 { -ms-flex-order: 10; order: 10; } .order-11 { -ms-flex-order: 11; order: 11; } .order-12 { -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-sm-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-sm-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-sm-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-sm-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-sm-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-sm-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-sm-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -ms-flex-order: -1; order: -1; } .order-sm-last { -ms-flex-order: 13; order: 13; } .order-sm-0 { -ms-flex-order: 0; order: 0; } .order-sm-1 { -ms-flex-order: 1; order: 1; } .order-sm-2 { -ms-flex-order: 2; order: 2; } .order-sm-3 { -ms-flex-order: 3; order: 3; } .order-sm-4 { -ms-flex-order: 4; order: 4; } .order-sm-5 { -ms-flex-order: 5; order: 5; } .order-sm-6 { -ms-flex-order: 6; order: 6; } .order-sm-7 { -ms-flex-order: 7; order: 7; } .order-sm-8 { -ms-flex-order: 8; order: 8; } .order-sm-9 { -ms-flex-order: 9; order: 9; } .order-sm-10 { -ms-flex-order: 10; order: 10; } .order-sm-11 { -ms-flex-order: 11; order: 11; } .order-sm-12 { -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-md-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-md-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-md-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-md-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-md-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-md-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-md-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -ms-flex-order: -1; order: -1; } .order-md-last { -ms-flex-order: 13; order: 13; } .order-md-0 { -ms-flex-order: 0; order: 0; } .order-md-1 { -ms-flex-order: 1; order: 1; } .order-md-2 { -ms-flex-order: 2; order: 2; } .order-md-3 { -ms-flex-order: 3; order: 3; } .order-md-4 { -ms-flex-order: 4; order: 4; } .order-md-5 { -ms-flex-order: 5; order: 5; } .order-md-6 { -ms-flex-order: 6; order: 6; } .order-md-7 { -ms-flex-order: 7; order: 7; } .order-md-8 { -ms-flex-order: 8; order: 8; } .order-md-9 { -ms-flex-order: 9; order: 9; } .order-md-10 { -ms-flex-order: 10; order: 10; } .order-md-11 { -ms-flex-order: 11; order: 11; } .order-md-12 { -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-lg-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-lg-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-lg-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-lg-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-lg-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-lg-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-lg-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -ms-flex-order: -1; order: -1; } .order-lg-last { -ms-flex-order: 13; order: 13; } .order-lg-0 { -ms-flex-order: 0; order: 0; } .order-lg-1 { -ms-flex-order: 1; order: 1; } .order-lg-2 { -ms-flex-order: 2; order: 2; } .order-lg-3 { -ms-flex-order: 3; order: 3; } .order-lg-4 { -ms-flex-order: 4; order: 4; } .order-lg-5 { -ms-flex-order: 5; order: 5; } .order-lg-6 { -ms-flex-order: 6; order: 6; } .order-lg-7 { -ms-flex-order: 7; order: 7; } .order-lg-8 { -ms-flex-order: 8; order: 8; } .order-lg-9 { -ms-flex-order: 9; order: 9; } .order-lg-10 { -ms-flex-order: 10; order: 10; } .order-lg-11 { -ms-flex-order: 11; order: 11; } .order-lg-12 { -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-xl-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-xl-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-xl-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-xl-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-xl-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-xl-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-xl-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -ms-flex-order: -1; order: -1; } .order-xl-last { -ms-flex-order: 13; order: 13; } .order-xl-0 { -ms-flex-order: 0; order: 0; } .order-xl-1 { -ms-flex-order: 1; order: 1; } .order-xl-2 { -ms-flex-order: 2; order: 2; } .order-xl-3 { -ms-flex-order: 3; order: 3; } .order-xl-4 { -ms-flex-order: 4; order: 4; } .order-xl-5 { -ms-flex-order: 5; order: 5; } .order-xl-6 { -ms-flex-order: 6; order: 6; } .order-xl-7 { -ms-flex-order: 7; order: 7; } .order-xl-8 { -ms-flex-order: 8; order: 8; } .order-xl-9 { -ms-flex-order: 9; order: 9; } .order-xl-10 { -ms-flex-order: 10; order: 10; } .order-xl-11 { -ms-flex-order: 11; order: 11; } .order-xl-12 { -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .table { width: 100%; margin-bottom: 1rem; color: #212529; background-color: transparent; } .table th, .table td { padding: 0.75rem; vertical-align: top; border-top: 1px solid #dee2e6; } .table thead th { vertical-align: bottom; border-bottom: 2px solid #dee2e6; } .table tbody + tbody { border-top: 2px solid #dee2e6; } .table-sm th, .table-sm td { padding: 0.3rem; } .table-bordered { border: 1px solid #dee2e6; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6; } .table-bordered thead th, .table-bordered thead td { border-bottom-width: 2px; } .table-borderless th, .table-borderless td, .table-borderless thead th, .table-borderless tbody + tbody { border: 0; } .table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0, 0, 0, 0.05); } .table-hover tbody tr:hover { color: #212529; background-color: rgba(0, 0, 0, 0.075); } .table-primary, .table-primary > th, .table-primary > td { background-color: #b8daff; } .table-primary th, .table-primary td, .table-primary thead th, .table-primary tbody + tbody { border-color: #7abaff; } .table-hover .table-primary:hover { background-color: #9fcdff; } .table-hover .table-primary:hover > td, .table-hover .table-primary:hover > th { background-color: #9fcdff; } .table-secondary, .table-secondary > th, .table-secondary > td { background-color: #d6d8db; } .table-secondary th, .table-secondary td, .table-secondary thead th, .table-secondary tbody + tbody { border-color: #b3b7bb; } .table-hover .table-secondary:hover { background-color: #c8cbcf; } .table-hover .table-secondary:hover > td, .table-hover .table-secondary:hover > th { background-color: #c8cbcf; } .table-success, .table-success > th, .table-success > td { background-color: #c3e6cb; } .table-success th, .table-success td, .table-success thead th, .table-success tbody + tbody { border-color: #8fd19e; } .table-hover .table-success:hover { background-color: #b1dfbb; } .table-hover .table-success:hover > td, .table-hover .table-success:hover > th { background-color: #b1dfbb; } .table-info, .table-info > th, .table-info > td { background-color: #bee5eb; } .table-info th, .table-info td, .table-info thead th, .table-info tbody + tbody { border-color: #86cfda; } .table-hover .table-info:hover { background-color: #abdde5; } .table-hover .table-info:hover > td, .table-hover .table-info:hover > th { background-color: #abdde5; } .table-warning, .table-warning > th, .table-warning > td { background-color: #ffeeba; } .table-warning th, .table-warning td, .table-warning thead th, .table-warning tbody + tbody { border-color: #ffdf7e; } .table-hover .table-warning:hover { background-color: #ffe8a1; } .table-hover .table-warning:hover > td, .table-hover .table-warning:hover > th { background-color: #ffe8a1; } .table-danger, .table-danger > th, .table-danger > td { background-color: #f5c6cb; } .table-danger th, .table-danger td, .table-danger thead th, .table-danger tbody + tbody { border-color: #ed969e; } .table-hover .table-danger:hover { background-color: #f1b0b7; } .table-hover .table-danger:hover > td, .table-hover .table-danger:hover > th { background-color: #f1b0b7; } .table-light, .table-light > th, .table-light > td { background-color: #fdfdfe; } .table-light th, .table-light td, .table-light thead th, .table-light tbody + tbody { border-color: #fbfcfc; } .table-hover .table-light:hover { background-color: #ececf6; } .table-hover .table-light:hover > td, .table-hover .table-light:hover > th { background-color: #ececf6; } .table-dark, .table-dark > th, .table-dark > td { background-color: #c6c8ca; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #95999c; } .table-hover .table-dark:hover { background-color: #b9bbbe; } .table-hover .table-dark:hover > td, .table-hover .table-dark:hover > th { background-color: #b9bbbe; } .table-active, .table-active > th, .table-active > td { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover > td, .table-hover .table-active:hover > th { background-color: rgba(0, 0, 0, 0.075); } .table .thead-dark th { color: #fff; background-color: #212529; border-color: #383f45; } .table .thead-light th { color: #495057; background-color: #e9ecef; border-color: #dee2e6; } .table-dark { color: #fff; background-color: #212529; } .table-dark th, .table-dark td, .table-dark thead th { border-color: #383f45; } .table-dark.table-bordered { border: 0; } .table-dark.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.05); } .table-dark.table-hover tbody tr:hover { color: #fff; background-color: rgba(255, 255, 255, 0.075); } @media (max-width: 575.98px) { .table-responsive-sm { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-sm > .table-bordered { border: 0; } } @media (max-width: 767.98px) { .table-responsive-md { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-md > .table-bordered { border: 0; } } @media (max-width: 991.98px) { .table-responsive-lg { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-lg > .table-bordered { border: 0; } } @media (max-width: 1199.98px) { .table-responsive-xl { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-xl > .table-bordered { border: 0; } } .table-responsive { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive > .table-bordered { border: 0; } .form-control { display: block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control:focus { color: #495057; background-color: #fff; border-color: #80bdff; outline: 0; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); } .form-control::-webkit-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-moz-placeholder { color: #939ba2; opacity: 1; } .form-control:-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::placeholder { color: #939ba2; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control { -webkit-appearance: none; -moz-appearance: none; appearance: none; } select.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } select.form-control:focus::-ms-value { color: #495057; background-color: #fff; } .form-control-file, .form-control-range { display: block; width: 100%; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; line-height: 1.5; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; line-height: 1.5; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; font-size: 1rem; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } .form-control-sm { height: calc(1.8125rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .form-control-lg { height: calc(2.875rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } select.form-control[size], select.form-control[multiple] { height: auto; } textarea.form-control { height: auto; } .form-group { margin-bottom: 1rem; } .form-text { display: block; margin-top: 0.25rem; } .form-row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; } .form-row > .col, .form-row > [class*="col-"] { padding-right: 5px; padding-left: 5px; } .form-check { position: relative; display: block; padding-left: 1.25rem; } .form-check-input { position: absolute; margin-top: 0.3rem; margin-left: -1.25rem; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { color: #6c757d; } .form-check-label { margin-bottom: 0; } .form-check-inline { display: -ms-inline-flexbox; display: inline-flex; -ms-flex-align: center; align-items: center; padding-left: 0; margin-right: 0.75rem; } .form-check-inline .form-check-input { position: static; margin-top: 0; margin-right: 0.3125rem; margin-left: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #28a745; } .valid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(40, 167, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .valid-tooltip, .form-row > [class*="col-"] > .valid-tooltip { left: 5px; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #28a745; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated select.form-control:valid, select.form-control.is-valid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:valid, .custom-select.is-valid { border-color: #28a745; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #28a745; } .was-validated .form-check-input:valid ~ .valid-feedback, .was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, .form-check-input.is-valid ~ .valid-tooltip { display: block; } .was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { border-color: #34ce57; background-color: #34ce57; } .was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { border-color: #28a745; } .was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .invalid-tooltip, .form-row > [class*="col-"] > .invalid-tooltip { left: 5px; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated select.form-control:invalid, select.form-control.is-invalid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:invalid, .custom-select.is-invalid { border-color: #dc3545; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .was-validated .form-check-input:invalid ~ .invalid-feedback, .was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, .form-check-input.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { border-color: #e4606d; background-color: #e4606d; } .was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { border-color: #dc3545; } .was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .form-inline { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; } .form-inline .form-check { width: 100%; } @media (min-width: 576px) { .form-inline label { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; margin-bottom: 0; } .form-inline .form-group { display: -ms-flexbox; display: flex; -ms-flex: 0 0 auto; flex: 0 0 auto; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; margin-bottom: 0; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-plaintext { display: inline-block; } .form-inline .input-group, .form-inline .custom-select { width: auto; } .form-inline .form-check { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: auto; padding-left: 0; } .form-inline .form-check-input { position: relative; -ms-flex-negative: 0; flex-shrink: 0; margin-top: 0; margin-right: 0.25rem; margin-left: 0; } .form-inline .custom-control { -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; } .form-inline .custom-control-label { margin-bottom: 0; } } .btn { display: inline-block; font-weight: 400; color: #212529; text-align: center; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: #212529; text-decoration: none; } .btn:focus, .btn.focus { outline: 0; box-shadow: none; } .btn.disabled, .btn:disabled { opacity: 0.65; box-shadow: none; } .btn:not(:disabled):not(.disabled) { cursor: pointer; } .btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { box-shadow: none; } a.btn.disabled, fieldset:disabled a.btn { pointer-events: none; } .btn-primary { color: #fff; background-color: #007bff; border-color: #007bff; box-shadow: none; } .btn-primary:hover { color: #fff; background-color: #0069d9; border-color: #0062cc; } .btn-primary:focus, .btn-primary.focus { color: #fff; background-color: #0069d9; border-color: #0062cc; box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0062cc; border-color: #005cbf; } .btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; box-shadow: none; } .btn-secondary:hover { color: #fff; background-color: #5a6268; border-color: #545b62; } .btn-secondary:focus, .btn-secondary.focus { color: #fff; background-color: #5a6268; border-color: #545b62; box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #545b62; border-color: #4e555b; } .btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-success { color: #fff; background-color: #28a745; border-color: #28a745; box-shadow: none; } .btn-success:hover { color: #fff; background-color: #218838; border-color: #1e7e34; } .btn-success:focus, .btn-success.focus { color: #fff; background-color: #218838; border-color: #1e7e34; box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-success.disabled, .btn-success:disabled { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #1e7e34; border-color: #1c7430; } .btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-info { color: #fff; background-color: #17a2b8; border-color: #17a2b8; box-shadow: none; } .btn-info:hover { color: #fff; background-color: #138496; border-color: #117a8b; } .btn-info:focus, .btn-info.focus { color: #fff; background-color: #138496; border-color: #117a8b; box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-info.disabled, .btn-info:disabled { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, .show > .btn-info.dropdown-toggle { color: #fff; background-color: #117a8b; border-color: #10707f; } .btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-warning { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; box-shadow: none; } .btn-warning:hover { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; } .btn-warning:focus, .btn-warning.focus { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-warning.disabled, .btn-warning:disabled { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, .show > .btn-warning.dropdown-toggle { color: #1f2d3d; background-color: #d39e00; border-color: #c69500; } .btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; box-shadow: none; } .btn-danger:hover { color: #fff; background-color: #c82333; border-color: #bd2130; } .btn-danger:focus, .btn-danger.focus { color: #fff; background-color: #c82333; border-color: #bd2130; box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-danger.disabled, .btn-danger:disabled { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #bd2130; border-color: #b21f2d; } .btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: none; } .btn-light:hover { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; } .btn-light:focus, .btn-light.focus { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-light.disabled, .btn-light:disabled { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, .show > .btn-light.dropdown-toggle { color: #1f2d3d; background-color: #dae0e5; border-color: #d3d9df; } .btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-dark { color: #fff; background-color: #343a40; border-color: #343a40; box-shadow: none; } .btn-dark:hover { color: #fff; background-color: #23272b; border-color: #1d2124; } .btn-dark:focus, .btn-dark.focus { color: #fff; background-color: #23272b; border-color: #1d2124; box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-dark.disabled, .btn-dark:disabled { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1d2124; border-color: #171a1d; } .btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-outline-primary { color: #007bff; border-color: #007bff; } .btn-outline-primary:hover { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:focus, .btn-outline-primary.focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-primary.disabled, .btn-outline-primary:disabled { color: #007bff; background-color: transparent; } .btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:focus, .btn-outline-secondary.focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-secondary.disabled, .btn-outline-secondary:disabled { color: #6c757d; background-color: transparent; } .btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-success { color: #28a745; border-color: #28a745; } .btn-outline-success:hover { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:focus, .btn-outline-success.focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-success.disabled, .btn-outline-success:disabled { color: #28a745; background-color: transparent; } .btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-info { color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:hover { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:focus, .btn-outline-info.focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-info.disabled, .btn-outline-info:disabled { color: #17a2b8; background-color: transparent; } .btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-warning { color: #ffc107; border-color: #ffc107; } .btn-outline-warning:hover { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:focus, .btn-outline-warning.focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-warning.disabled, .btn-outline-warning:disabled { color: #ffc107; background-color: transparent; } .btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-danger { color: #dc3545; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:focus, .btn-outline-danger.focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-danger.disabled, .btn-outline-danger:disabled { color: #dc3545; background-color: transparent; } .btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:hover { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:focus, .btn-outline-light.focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-dark { color: #343a40; border-color: #343a40; } .btn-outline-dark:hover { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:focus, .btn-outline-dark.focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-outline-dark.disabled, .btn-outline-dark:disabled { color: #343a40; background-color: transparent; } .btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-link { font-weight: 400; color: #007bff; text-decoration: none; } .btn-link:hover { color: #0056b3; text-decoration: none; } .btn-link:focus, .btn-link.focus { text-decoration: none; } .btn-link:disabled, .btn-link.disabled { color: #6c757d; pointer-events: none; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 0.5rem; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .dropup, .dropright, .dropdown, .dropleft { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 10rem; padding: 0.5rem 0; margin: 0.125rem 0 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.175); } .dropdown-menu-left { right: auto; left: 0; } .dropdown-menu-right { right: 0; left: auto; } @media (min-width: 576px) { .dropdown-menu-sm-left { right: auto; left: 0; } .dropdown-menu-sm-right { right: 0; left: auto; } } @media (min-width: 768px) { .dropdown-menu-md-left { right: auto; left: 0; } .dropdown-menu-md-right { right: 0; left: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-left { right: auto; left: 0; } .dropdown-menu-lg-right { right: 0; left: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-left { right: auto; left: 0; } .dropdown-menu-xl-right { right: 0; left: auto; } } .dropup .dropdown-menu { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-menu { top: 0; right: auto; left: 100%; margin-top: 0; margin-left: 0.125rem; } .dropright .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropright .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-toggle::after { vertical-align: 0; } .dropleft .dropdown-menu { top: 0; right: 100%; left: auto; margin-top: 0; margin-right: 0.125rem; } .dropleft .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropleft .dropdown-toggle::after { display: none; } .dropleft .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropleft .dropdown-toggle:empty::after { margin-left: 0; } .dropleft .dropdown-toggle::before { vertical-align: 0; } .dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { right: auto; bottom: auto; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid #e9ecef; } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: #16181b; text-decoration: none; background-color: #f8f9fa; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #007bff; } .dropdown-item.disabled, .dropdown-item:disabled { color: #6c757d; pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1rem; margin-bottom: 0; font-size: 0.875rem; color: #6c757d; white-space: nowrap; } .dropdown-item-text { display: block; padding: 0.25rem 1rem; color: #212529; } .btn-group, .btn-group-vertical { position: relative; display: -ms-inline-flexbox; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover { z-index: 1; } .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-pack: start; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) { margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropright .dropdown-toggle-split::after { margin-left: 0; } .dropleft .dropdown-toggle-split::before { margin-right: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group.show .dropdown-toggle { box-shadow: none; } .btn-group.show .dropdown-toggle.btn-link { box-shadow: none; } .btn-group-vertical { -ms-flex-direction: column; flex-direction: column; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: center; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-toggle > .btn, .btn-group-toggle > .btn-group > .btn { margin-bottom: 0; } .btn-group-toggle > .btn input[type="radio"], .btn-group-toggle > .btn input[type="checkbox"], .btn-group-toggle > .btn-group > .btn input[type="radio"], .btn-group-toggle > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: stretch; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-control-plaintext, .input-group > .custom-select, .input-group > .custom-file { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; width: 1%; min-width: 0; margin-bottom: 0; } .input-group > .form-control + .form-control, .input-group > .form-control + .custom-select, .input-group > .form-control + .custom-file, .input-group > .form-control-plaintext + .form-control, .input-group > .form-control-plaintext + .custom-select, .input-group > .form-control-plaintext + .custom-file, .input-group > .custom-select + .form-control, .input-group > .custom-select + .custom-select, .input-group > .custom-select + .custom-file, .input-group > .custom-file + .form-control, .input-group > .custom-file + .custom-select, .input-group > .custom-file + .custom-file { margin-left: -1px; } .input-group > .form-control:focus, .input-group > .custom-select:focus, .input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { z-index: 3; } .input-group > .custom-file .custom-file-input:focus { z-index: 4; } .input-group > .form-control:not(:first-child), .input-group > .custom-select:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group > .custom-file { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; } .input-group > .custom-file:not(:last-child) .custom-file-label, .input-group > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .custom-file:not(:first-child) .custom-file-label { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group:not(.has-validation) > .form-control:not(:last-child), .input-group:not(.has-validation) > .custom-select:not(:last-child), .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label, .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group.has-validation > .form-control:nth-last-child(n + 3), .input-group.has-validation > .custom-select:nth-last-child(n + 3), .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label, .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-prepend, .input-group-append { display: -ms-flexbox; display: flex; } .input-group-prepend .btn, .input-group-append .btn { position: relative; z-index: 2; } .input-group-prepend .btn:focus, .input-group-append .btn:focus { z-index: 3; } .input-group-prepend .btn + .btn, .input-group-prepend .btn + .input-group-text, .input-group-prepend .input-group-text + .input-group-text, .input-group-prepend .input-group-text + .btn, .input-group-append .btn + .btn, .input-group-append .btn + .input-group-text, .input-group-append .input-group-text + .input-group-text, .input-group-append .input-group-text + .btn { margin-left: -1px; } .input-group-prepend { margin-right: -1px; } .input-group-append { margin-left: -1px; } .input-group-text { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.375rem 0.75rem; margin-bottom: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-text input[type="radio"], .input-group-text input[type="checkbox"] { margin-top: 0; } .input-group-lg > .form-control:not(textarea), .input-group-lg > .custom-select { height: calc(2.875rem + 2px); } .input-group-lg > .form-control, .input-group-lg > .custom-select, .input-group-lg > .input-group-prepend > .input-group-text, .input-group-lg > .input-group-append > .input-group-text, .input-group-lg > .input-group-prepend > .btn, .input-group-lg > .input-group-append > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .input-group-sm > .form-control:not(textarea), .input-group-sm > .custom-select { height: calc(1.8125rem + 2px); } .input-group-sm > .form-control, .input-group-sm > .custom-select, .input-group-sm > .input-group-prepend > .input-group-text, .input-group-sm > .input-group-append > .input-group-text, .input-group-sm > .input-group-prepend > .btn, .input-group-sm > .input-group-append > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .input-group-lg > .custom-select, .input-group-sm > .custom-select { padding-right: 1.75rem; } .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .btn, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .input-group-text, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .btn, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .input-group-text, .input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .input-group-append > .btn, .input-group > .input-group-append > .input-group-text, .input-group > .input-group-prepend:not(:first-child) > .btn, .input-group > .input-group-prepend:not(:first-child) > .input-group-text, .input-group > .input-group-prepend:first-child > .btn:not(:first-child), .input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .custom-control { position: relative; z-index: 1; display: block; min-height: 1.5rem; padding-left: 1.5rem; -webkit-print-color-adjust: exact; color-adjust: exact; } .custom-control-inline { display: -ms-inline-flexbox; display: inline-flex; margin-right: 1rem; } .custom-control-input { position: absolute; left: 0; z-index: -1; width: 1rem; height: 1.25rem; opacity: 0; } .custom-control-input:checked ~ .custom-control-label::before { color: #fff; border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-control-input:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input:not(:disabled):active ~ .custom-control-label::before { color: #fff; background-color: #b3d7ff; border-color: #b3d7ff; box-shadow: none; } .custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label { color: #6c757d; } .custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before { background-color: #e9ecef; } .custom-control-label { position: relative; margin-bottom: 0; vertical-align: top; } .custom-control-label::before { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; pointer-events: none; content: ""; background-color: #dee2e6; border: #adb5bd solid 1px; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-control-label::after { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; content: ""; background: 50% / 50% 50% no-repeat; } .custom-checkbox .custom-control-label::before { border-radius: 0.25rem; } .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-radio .custom-control-label::before { border-radius: 50%; } .custom-radio .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } .custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-switch { padding-left: 2.25rem; } .custom-switch .custom-control-label::before { left: -2.25rem; width: 1.75rem; pointer-events: all; border-radius: 0.5rem; } .custom-switch .custom-control-label::after { top: calc(0.25rem + 2px); left: calc(-2.25rem + 2px); width: calc(1rem - 4px); height: calc(1rem - 4px); background-color: #adb5bd; border-radius: 0.5rem; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-switch .custom-control-label::after { transition: none; } } .custom-switch .custom-control-input:checked ~ .custom-control-label::after { background-color: #dee2e6; -webkit-transform: translateX(0.75rem); transform: translateX(0.75rem); } .custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-select { display: inline-block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; vertical-align: middle; background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-select:focus { border-color: #80bdff; outline: 0; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); } .custom-select:focus::-ms-value { color: #495057; background-color: #fff; } .custom-select[multiple], .custom-select[size]:not([size="1"]) { height: auto; padding-right: 0.75rem; background-image: none; } .custom-select:disabled { color: #6c757d; background-color: #e9ecef; } .custom-select::-ms-expand { display: none; } .custom-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } .custom-select-sm { height: calc(1.8125rem + 2px); padding-top: 0.25rem; padding-bottom: 0.25rem; padding-left: 0.5rem; font-size: 75%; } .custom-select-lg { height: calc(2.875rem + 2px); padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 1rem; font-size: 125%; } .custom-file { position: relative; display: inline-block; width: 100%; height: calc(2.25rem + 2px); margin-bottom: 0; } .custom-file-input { position: relative; z-index: 2; width: 100%; height: calc(2.25rem + 2px); margin: 0; overflow: hidden; opacity: 0; } .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; box-shadow: none; } .custom-file-input[disabled] ~ .custom-file-label, .custom-file-input:disabled ~ .custom-file-label { background-color: #e9ecef; } .custom-file-input:lang(en) ~ .custom-file-label::after { content: "Browse"; } .custom-file-input ~ .custom-file-label[data-browse]::after { content: attr(data-browse); } .custom-file-label { position: absolute; top: 0; right: 0; left: 0; z-index: 1; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; overflow: hidden; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: none; } .custom-file-label::after { position: absolute; top: 0; right: 0; bottom: 0; z-index: 3; display: block; height: 2.25rem; padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; content: "Browse"; background-color: #e9ecef; border-left: inherit; border-radius: 0 0.25rem 0.25rem 0; } .custom-range { width: 100%; height: 1rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-range:focus { outline: 0; } .custom-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range::-moz-focus-outer { border: 0; } .custom-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .custom-range::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .custom-range::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-thumb { width: 1rem; height: 1rem; margin-top: 0; margin-right: 0; margin-left: 0; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-ms-thumb { -ms-transition: none; transition: none; } } .custom-range::-ms-thumb:active { background-color: #b3d7ff; } .custom-range::-ms-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: transparent; border-color: transparent; border-width: 0.5rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-fill-lower { background-color: #dee2e6; border-radius: 1rem; } .custom-range::-ms-fill-upper { margin-right: 15px; background-color: #dee2e6; border-radius: 1rem; } .custom-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .custom-range:disabled::-webkit-slider-runnable-track { cursor: default; } .custom-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .custom-range:disabled::-moz-range-track { cursor: default; } .custom-range:disabled::-ms-thumb { background-color: #adb5bd; } .custom-control-label::before, .custom-file-label, .custom-select { transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-control-label::before, .custom-file-label, .custom-select { transition: none; } } .nav { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; } .nav-link:hover, .nav-link:focus { text-decoration: none; } .nav-link.disabled { color: #6c757d; pointer-events: none; cursor: default; } .nav-tabs { border-bottom: 1px solid #dee2e6; } .nav-tabs .nav-link { margin-bottom: -1px; border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { border-color: #e9ecef #e9ecef #dee2e6; } .nav-tabs .nav-link.disabled { color: #6c757d; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #dee2e6 #dee2e6 #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #007bff; } .nav-fill > .nav-link, .nav-fill .nav-item { -ms-flex: 1 1 auto; flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; text-align: center; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; padding: 0.5rem 0.5rem; } .navbar .container, .navbar .container-fluid, .navbar .container-sm, .navbar .container-md, .navbar .container-lg, .navbar .container-xl { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; } .navbar-brand { display: inline-block; padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 0.5rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-nav { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-text { display: inline-block; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { -ms-flex-preferred-size: 100%; flex-basis: 100%; -ms-flex-positive: 1; flex-grow: 1; -ms-flex-align: center; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .navbar-toggler:hover, .navbar-toggler:focus { text-decoration: none; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; content: ""; background: 50% / 100% 100% no-repeat; } .navbar-nav-scroll { max-height: 75vh; overflow-y: auto; } @media (max-width: 575.98px) { .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 576px) { .navbar-expand-sm { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } } @media (max-width: 767.98px) { .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 768px) { .navbar-expand-md { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-md .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } } @media (max-width: 991.98px) { .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 992px) { .navbar-expand-lg { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } } @media (max-width: 1199.98px) { .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 1200px) { .navbar-expand-xl { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } } .navbar-expand { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { padding-right: 0; padding-left: 0; } .navbar-expand .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.5); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-text a { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { color: white; } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.75); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-text a { color: #fff; } .navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { color: #fff; } .card { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 0 solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { -ms-flex: 1 1 auto; flex: 1 1 auto; min-height: 1px; padding: 1.25rem; } .card-title { margin-bottom: 0.75rem; } .card-subtitle { margin-top: -0.375rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1.25rem; } .card-header { padding: 0.75rem 1.25rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 0 solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 0) calc(0.25rem - 0) 0 0; } .card-footer { padding: 0.75rem 1.25rem; background-color: rgba(0, 0, 0, 0.03); border-top: 0 solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 0) calc(0.25rem - 0); } .card-header-tabs { margin-right: -0.625rem; margin-bottom: -0.75rem; margin-left: -0.625rem; border-bottom: 0; } .card-header-pills { margin-right: -0.625rem; margin-left: -0.625rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1.25rem; border-radius: calc(0.25rem - 0); } .card-img, .card-img-top, .card-img-bottom { -ms-flex-negative: 0; flex-shrink: 0; width: 100%; } .card-img, .card-img-top { border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card-img, .card-img-bottom { border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card-deck .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-deck { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; margin-right: -7.5px; margin-left: -7.5px; } .card-deck .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-right: 7.5px; margin-bottom: 0; margin-left: 7.5px; } } .card-group > .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-group { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; } .card-group > .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } } .card-columns .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-columns { -webkit-column-count: 3; -moz-column-count: 3; column-count: 3; -webkit-column-gap: 1.25rem; -moz-column-gap: 1.25rem; column-gap: 1.25rem; orphans: 1; widows: 1; } .card-columns .card { display: inline-block; width: 100%; } } .accordion { overflow-anchor: none; } .accordion > .card { overflow: hidden; } .accordion > .card:not(:last-of-type) { border-bottom: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .accordion > .card:not(:first-of-type) { border-top-left-radius: 0; border-top-right-radius: 0; } .accordion > .card > .card-header { border-radius: 0; margin-bottom: 0; } .breadcrumb { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0.75rem 1rem; margin-bottom: 1rem; list-style: none; background-color: #e9ecef; border-radius: 0.25rem; } .breadcrumb-item + .breadcrumb-item { padding-left: 0.5rem; } .breadcrumb-item + .breadcrumb-item::before { float: left; padding-right: 0.5rem; color: #6c757d; content: "/"; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: underline; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: none; } .breadcrumb-item.active { color: #6c757d; } .pagination { display: -ms-flexbox; display: flex; padding-left: 0; list-style: none; border-radius: 0.25rem; } .page-link { position: relative; display: block; padding: 0.5rem 0.75rem; margin-left: -1px; line-height: 1.25; color: #007bff; background-color: #fff; border: 1px solid #dee2e6; } .page-link:hover { z-index: 2; color: #0056b3; text-decoration: none; background-color: #e9ecef; border-color: #dee2e6; } .page-link:focus { z-index: 3; outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .page-item.active .page-link { z-index: 3; color: #fff; background-color: #007bff; border-color: #007bff; } .page-item.disabled .page-link { color: #6c757d; pointer-events: none; cursor: auto; background-color: #fff; border-color: #dee2e6; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; line-height: 1.5; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .badge { transition: none; } } a.badge:hover, a.badge:focus { text-decoration: none; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .badge-pill { padding-right: 0.6em; padding-left: 0.6em; border-radius: 10rem; } .badge-primary { color: #fff; background-color: #007bff; } a.badge-primary:hover, a.badge-primary:focus { color: #fff; background-color: #0062cc; } a.badge-primary:focus, a.badge-primary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .badge-secondary { color: #fff; background-color: #6c757d; } a.badge-secondary:hover, a.badge-secondary:focus { color: #fff; background-color: #545b62; } a.badge-secondary:focus, a.badge-secondary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); } .badge-success { color: #fff; background-color: #28a745; } a.badge-success:hover, a.badge-success:focus { color: #fff; background-color: #1e7e34; } a.badge-success:focus, a.badge-success.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .badge-info { color: #fff; background-color: #17a2b8; } a.badge-info:hover, a.badge-info:focus { color: #fff; background-color: #117a8b; } a.badge-info:focus, a.badge-info.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .badge-warning { color: #1f2d3d; background-color: #ffc107; } a.badge-warning:hover, a.badge-warning:focus { color: #1f2d3d; background-color: #d39e00; } a.badge-warning:focus, a.badge-warning.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .badge-danger { color: #fff; background-color: #dc3545; } a.badge-danger:hover, a.badge-danger:focus { color: #fff; background-color: #bd2130; } a.badge-danger:focus, a.badge-danger.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .badge-light { color: #1f2d3d; background-color: #f8f9fa; } a.badge-light:hover, a.badge-light:focus { color: #1f2d3d; background-color: #dae0e5; } a.badge-light:focus, a.badge-light.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .badge-dark { color: #fff; background-color: #343a40; } a.badge-dark:hover, a.badge-dark:focus { color: #fff; background-color: #1d2124; } a.badge-dark:focus, a.badge-dark.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; background-color: #e9ecef; border-radius: 0.3rem; } @media (min-width: 576px) { .jumbotron { padding: 4rem 2rem; } } .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; } .alert { position: relative; padding: 0.75rem 1.25rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 4rem; } .alert-dismissible .close { position: absolute; top: 0; right: 0; z-index: 2; padding: 0.75rem 1.25rem; color: inherit; } .alert-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-primary hr { border-top-color: #9fcdff; } .alert-primary .alert-link { color: #002752; } .alert-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-secondary hr { border-top-color: #c8cbcf; } .alert-secondary .alert-link { color: #202326; } .alert-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-success hr { border-top-color: #b1dfbb; } .alert-success .alert-link { color: #0b2e13; } .alert-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-info hr { border-top-color: #abdde5; } .alert-info .alert-link { color: #062c33; } .alert-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-warning hr { border-top-color: #ffe8a1; } .alert-warning .alert-link { color: #533f03; } .alert-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-danger hr { border-top-color: #f1b0b7; } .alert-danger .alert-link { color: #491217; } .alert-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-light hr { border-top-color: #ececf6; } .alert-light .alert-link { color: #686868; } .alert-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-dark hr { border-top-color: #b9bbbe; } .alert-dark .alert-link { color: #040505; } @-webkit-keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } .progress { display: -ms-flexbox; display: flex; height: 1rem; overflow: hidden; line-height: 0; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; box-shadow: inset 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1); } .progress-bar { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; overflow: hidden; color: #fff; text-align: center; white-space: nowrap; background-color: #007bff; transition: width 0.6s ease; } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: 1s linear infinite progress-bar-stripes; animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { -webkit-animation: none; animation: none; } } .media { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; } .media-body { -ms-flex: 1; flex: 1; } .list-group { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; border-radius: 0.25rem; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.75rem 1.25rem; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } .list-group-item:last-child { border-bottom-right-radius: inherit; border-bottom-left-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: #6c757d; pointer-events: none; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: -1px; border-top-width: 1px; } .list-group-horizontal { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } @media (min-width: 576px) { .list-group-horizontal-sm { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 768px) { .list-group-horizontal-md { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 992px) { .list-group-horizontal-lg { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 1200px) { .list-group-horizontal-xl { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 1px; } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #004085; background-color: #b8daff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #004085; background-color: #9fcdff; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #004085; border-color: #004085; } .list-group-item-secondary { color: #383d41; background-color: #d6d8db; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #383d41; background-color: #c8cbcf; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #383d41; border-color: #383d41; } .list-group-item-success { color: #155724; background-color: #c3e6cb; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #155724; background-color: #b1dfbb; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #155724; border-color: #155724; } .list-group-item-info { color: #0c5460; background-color: #bee5eb; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #0c5460; background-color: #abdde5; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #0c5460; border-color: #0c5460; } .list-group-item-warning { color: #856404; background-color: #ffeeba; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #856404; background-color: #ffe8a1; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #856404; border-color: #856404; } .list-group-item-danger { color: #721c24; background-color: #f5c6cb; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #721c24; background-color: #f1b0b7; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #721c24; border-color: #721c24; } .list-group-item-light { color: #818182; background-color: #fdfdfe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #818182; background-color: #ececf6; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #818182; border-color: #818182; } .list-group-item-dark { color: #1b1e21; background-color: #c6c8ca; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #1b1e21; background-color: #b9bbbe; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #1b1e21; border-color: #1b1e21; } .close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { opacity: .75; } button.close { padding: 0; background-color: transparent; border: 0; } a.close.disabled { pointer-events: none; } .toast { -ms-flex-preferred-size: 350px; flex-basis: 350px; max-width: 350px; font-size: 0.875rem; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); opacity: 0; border-radius: 0.25rem; } .toast:not(:last-child) { margin-bottom: 0.75rem; } .toast.showing { opacity: 1; } .toast.show { display: block; opacity: 1; } .toast.hide { display: none; } .toast-header { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.25rem 0.75rem; color: #6c757d; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .toast-body { padding: 0.75rem; } .modal-open { overflow: hidden; } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal { position: fixed; top: 0; left: 0; z-index: 1050; display: none; width: 100%; height: 100%; overflow: hidden; outline: 0; } .modal-dialog { position: relative; width: auto; margin: 0.5rem; pointer-events: none; } .modal.fade .modal-dialog { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; -webkit-transform: translate(0, -50px); transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { -webkit-transform: none; transform: none; } .modal.modal-static .modal-dialog { -webkit-transform: scale(1.02); transform: scale(1.02); } .modal-dialog-scrollable { display: -ms-flexbox; display: flex; max-height: calc(100% - 1rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 1rem); overflow: hidden; } .modal-dialog-scrollable .modal-header, .modal-dialog-scrollable .modal-footer { -ms-flex-negative: 0; flex-shrink: 0; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; min-height: calc(100% - 1rem); } .modal-dialog-centered::before { display: block; height: calc(100vh - 1rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; content: ""; } .modal-dialog-centered.modal-dialog-scrollable { -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; height: 100%; } .modal-dialog-centered.modal-dialog-scrollable .modal-content { max-height: none; } .modal-dialog-centered.modal-dialog-scrollable::before { content: none; } .modal-content { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; width: 100%; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.5); outline: 0; } .modal-backdrop { position: fixed; top: 0; left: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: justify; justify-content: space-between; padding: 1rem; border-bottom: 1px solid #e9ecef; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .modal-header .close { padding: 1rem; margin: -1rem -1rem -1rem auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1rem; } .modal-footer { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: end; justify-content: flex-end; padding: 0.75rem; border-top: 1px solid #e9ecef; border-bottom-right-radius: calc(0.3rem - 1px); border-bottom-left-radius: calc(0.3rem - 1px); } .modal-footer > * { margin: 0.25rem; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 1.75rem auto; } .modal-dialog-scrollable { max-height: calc(100% - 3.5rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 3.5rem); } .modal-dialog-centered { min-height: calc(100% - 3.5rem); } .modal-dialog-centered::before { height: calc(100vh - 3.5rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; } .modal-content { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.5); } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { max-width: 800px; } } @media (min-width: 1200px) { .modal-xl { max-width: 1140px; } } .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .tooltip .arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { padding: 0.4rem 0; } .bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { bottom: 0; } .bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { top: 0; border-width: 0.4rem 0.4rem 0; border-top-color: #000; } .bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { padding: 0 0.4rem; } .bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { left: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { right: 0; border-width: 0.4rem 0.4rem 0.4rem 0; border-right-color: #000; } .bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { padding: 0.4rem 0; } .bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { top: 0; } .bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { bottom: 0; border-width: 0 0.4rem 0.4rem; border-bottom-color: #000; } .bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { padding: 0 0.4rem; } .bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { right: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { left: 0; border-width: 0.4rem 0 0.4rem 0.4rem; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: block; max-width: 276px; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.2); } .popover .arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; margin: 0 0.3rem; } .popover .arrow::before, .popover .arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; } .bs-popover-top, .bs-popover-auto[x-placement^="top"] { margin-bottom: 0.5rem; } .bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow { bottom: calc(-0.5rem - 1px); } .bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before { bottom: 0; border-width: 0.5rem 0.5rem 0; border-top-color: rgba(0, 0, 0, 0.25); } .bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^="top"] > .arrow::after { bottom: 1px; border-width: 0.5rem 0.5rem 0; border-top-color: #fff; } .bs-popover-right, .bs-popover-auto[x-placement^="right"] { margin-left: 0.5rem; } .bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow { left: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^="right"] > .arrow::before { left: 0; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: rgba(0, 0, 0, 0.25); } .bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^="right"] > .arrow::after { left: 1px; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: #fff; } .bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { margin-top: 0.5rem; } .bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow { top: calc(-0.5rem - 1px); } .bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before { top: 0; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: rgba(0, 0, 0, 0.25); } .bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^="bottom"] > .arrow::after { top: 1px; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: #fff; } .bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 1rem; margin-left: -0.5rem; content: ""; border-bottom: 1px solid #f7f7f7; } .bs-popover-left, .bs-popover-auto[x-placement^="left"] { margin-right: 0.5rem; } .bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow { right: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^="left"] > .arrow::before { right: 0; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: rgba(0, 0, 0, 0.25); } .bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^="left"] > .arrow::after { right: 1px; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: #fff; } .popover-header { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 0.5rem 0.75rem; color: #212529; } .carousel { position: relative; } .carousel.pointer-event { -ms-touch-action: pan-y; touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; width: 100%; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: -webkit-transform 0.6s ease; transition: transform 0.6s ease; transition: transform 0.6s ease, -webkit-transform 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-left), .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-right), .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; -webkit-transform: none; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-left, .carousel-fade .carousel-item-prev.carousel-item-right { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: 50% / 100% 100% no-repeat; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 15; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; } .carousel-indicators li { box-sizing: content-box; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: .5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators li { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; } @-webkit-keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } .spinner-border { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; border: 0.25em solid currentColor; border-right-color: transparent; border-radius: 50%; -webkit-animation: .75s linear infinite spinner-border; animation: .75s linear infinite spinner-border; } .spinner-border-sm { width: 1rem; height: 1rem; border-width: 0.2em; } @-webkit-keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } .spinner-grow { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; background-color: currentColor; border-radius: 50%; opacity: 0; -webkit-animation: .75s linear infinite spinner-grow; animation: .75s linear infinite spinner-grow; } .spinner-grow-sm { width: 1rem; height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { -webkit-animation-duration: 1.5s; animation-duration: 1.5s; } } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .bg-primary { background-color: #007bff !important; } a.bg-primary:hover, a.bg-primary:focus, button.bg-primary:hover, button.bg-primary:focus { background-color: #0062cc !important; } .bg-secondary { background-color: #6c757d !important; } a.bg-secondary:hover, a.bg-secondary:focus, button.bg-secondary:hover, button.bg-secondary:focus { background-color: #545b62 !important; } .bg-success { background-color: #28a745 !important; } a.bg-success:hover, a.bg-success:focus, button.bg-success:hover, button.bg-success:focus { background-color: #1e7e34 !important; } .bg-info { background-color: #17a2b8 !important; } a.bg-info:hover, a.bg-info:focus, button.bg-info:hover, button.bg-info:focus { background-color: #117a8b !important; } .bg-warning { background-color: #ffc107 !important; } a.bg-warning:hover, a.bg-warning:focus, button.bg-warning:hover, button.bg-warning:focus { background-color: #d39e00 !important; } .bg-danger { background-color: #dc3545 !important; } a.bg-danger:hover, a.bg-danger:focus, button.bg-danger:hover, button.bg-danger:focus { background-color: #bd2130 !important; } .bg-light { background-color: #f8f9fa !important; } a.bg-light:hover, a.bg-light:focus, button.bg-light:hover, button.bg-light:focus { background-color: #dae0e5 !important; } .bg-dark { background-color: #343a40 !important; } a.bg-dark:hover, a.bg-dark:focus, button.bg-dark:hover, button.bg-dark:focus { background-color: #1d2124 !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .border { border: 1px solid #dee2e6 !important; } .border-top { border-top: 1px solid #dee2e6 !important; } .border-right { border-right: 1px solid #dee2e6 !important; } .border-bottom { border-bottom: 1px solid #dee2e6 !important; } .border-left { border-left: 1px solid #dee2e6 !important; } .border-0 { border: 0 !important; } .border-top-0 { border-top: 0 !important; } .border-right-0 { border-right: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-left-0 { border-left: 0 !important; } .border-primary { border-color: #007bff !important; } .border-secondary { border-color: #6c757d !important; } .border-success { border-color: #28a745 !important; } .border-info { border-color: #17a2b8 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #343a40 !important; } .border-white { border-color: #fff !important; } .rounded-sm { border-radius: 0.2rem !important; } .rounded { border-radius: 0.25rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-right { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-left { border-top-left-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-lg { border-radius: 0.3rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: 50rem !important; } .rounded-0 { border-radius: 0 !important; } .clearfix::after { display: block; clear: both; content: ""; } .d-none { display: none !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: -ms-flexbox !important; display: flex !important; } .d-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } @media (min-width: 576px) { .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: -ms-flexbox !important; display: flex !important; } .d-sm-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 768px) { .d-md-none { display: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: -ms-flexbox !important; display: flex !important; } .d-md-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 992px) { .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: -ms-flexbox !important; display: flex !important; } .d-lg-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 1200px) { .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: -ms-flexbox !important; display: flex !important; } .d-xl-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media print { .d-print-none { display: none !important; } .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: -ms-flexbox !important; display: flex !important; } .d-print-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } .embed-responsive { position: relative; display: block; width: 100%; padding: 0; overflow: hidden; } .embed-responsive::before { display: block; content: ""; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-21by9::before { padding-top: 42.857143%; } .embed-responsive-16by9::before { padding-top: 56.25%; } .embed-responsive-4by3::before { padding-top: 75%; } .embed-responsive-1by1::before { padding-top: 100%; } .flex-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-sm-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-sm-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-sm-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-sm-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-sm-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-sm-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-md-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-md-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-md-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-md-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-md-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-md-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-lg-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-lg-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-lg-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-lg-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-lg-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-lg-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-xl-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-xl-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-xl-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-xl-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-xl-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-xl-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } .float-left { float: left !important; } .float-right { float: right !important; } .float-none { float: none !important; } @media (min-width: 576px) { .float-sm-left { float: left !important; } .float-sm-right { float: right !important; } .float-sm-none { float: none !important; } } @media (min-width: 768px) { .float-md-left { float: left !important; } .float-md-right { float: right !important; } .float-md-none { float: none !important; } } @media (min-width: 992px) { .float-lg-left { float: left !important; } .float-lg-right { float: right !important; } .float-lg-none { float: none !important; } } @media (min-width: 1200px) { .float-xl-left { float: left !important; } .float-xl-right { float: right !important; } .float-xl-none { float: none !important; } } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } @supports ((position: -webkit-sticky) or (position: sticky)) { .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } .min-vw-100 { min-width: 100vw !important; } .min-vh-100 { min-height: 100vh !important; } .vw-100 { width: 100vw !important; } .vh-100 { height: 100vh !important; } .m-0 { margin: 0 !important; } .mt-0, .my-0 { margin-top: 0 !important; } .mr-0, .mx-0 { margin-right: 0 !important; } .mb-0, .my-0 { margin-bottom: 0 !important; } .ml-0, .mx-0 { margin-left: 0 !important; } .m-1 { margin: 0.25rem !important; } .mt-1, .my-1 { margin-top: 0.25rem !important; } .mr-1, .mx-1 { margin-right: 0.25rem !important; } .mb-1, .my-1 { margin-bottom: 0.25rem !important; } .ml-1, .mx-1 { margin-left: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .mt-2, .my-2 { margin-top: 0.5rem !important; } .mr-2, .mx-2 { margin-right: 0.5rem !important; } .mb-2, .my-2 { margin-bottom: 0.5rem !important; } .ml-2, .mx-2 { margin-left: 0.5rem !important; } .m-3 { margin: 1rem !important; } .mt-3, .my-3 { margin-top: 1rem !important; } .mr-3, .mx-3 { margin-right: 1rem !important; } .mb-3, .my-3 { margin-bottom: 1rem !important; } .ml-3, .mx-3 { margin-left: 1rem !important; } .m-4 { margin: 1.5rem !important; } .mt-4, .my-4 { margin-top: 1.5rem !important; } .mr-4, .mx-4 { margin-right: 1.5rem !important; } .mb-4, .my-4 { margin-bottom: 1.5rem !important; } .ml-4, .mx-4 { margin-left: 1.5rem !important; } .m-5 { margin: 3rem !important; } .mt-5, .my-5 { margin-top: 3rem !important; } .mr-5, .mx-5 { margin-right: 3rem !important; } .mb-5, .my-5 { margin-bottom: 3rem !important; } .ml-5, .mx-5 { margin-left: 3rem !important; } .p-0 { padding: 0 !important; } .pt-0, .py-0 { padding-top: 0 !important; } .pr-0, .px-0 { padding-right: 0 !important; } .pb-0, .py-0 { padding-bottom: 0 !important; } .pl-0, .px-0 { padding-left: 0 !important; } .p-1 { padding: 0.25rem !important; } .pt-1, .py-1 { padding-top: 0.25rem !important; } .pr-1, .px-1 { padding-right: 0.25rem !important; } .pb-1, .py-1 { padding-bottom: 0.25rem !important; } .pl-1, .px-1 { padding-left: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .pt-2, .py-2 { padding-top: 0.5rem !important; } .pr-2, .px-2 { padding-right: 0.5rem !important; } .pb-2, .py-2 { padding-bottom: 0.5rem !important; } .pl-2, .px-2 { padding-left: 0.5rem !important; } .p-3 { padding: 1rem !important; } .pt-3, .py-3 { padding-top: 1rem !important; } .pr-3, .px-3 { padding-right: 1rem !important; } .pb-3, .py-3 { padding-bottom: 1rem !important; } .pl-3, .px-3 { padding-left: 1rem !important; } .p-4 { padding: 1.5rem !important; } .pt-4, .py-4 { padding-top: 1.5rem !important; } .pr-4, .px-4 { padding-right: 1.5rem !important; } .pb-4, .py-4 { padding-bottom: 1.5rem !important; } .pl-4, .px-4 { padding-left: 1.5rem !important; } .p-5 { padding: 3rem !important; } .pt-5, .py-5 { padding-top: 3rem !important; } .pr-5, .px-5 { padding-right: 3rem !important; } .pb-5, .py-5 { padding-bottom: 3rem !important; } .pl-5, .px-5 { padding-left: 3rem !important; } .m-n1 { margin: -0.25rem !important; } .mt-n1, .my-n1 { margin-top: -0.25rem !important; } .mr-n1, .mx-n1 { margin-right: -0.25rem !important; } .mb-n1, .my-n1 { margin-bottom: -0.25rem !important; } .ml-n1, .mx-n1 { margin-left: -0.25rem !important; } .m-n2 { margin: -0.5rem !important; } .mt-n2, .my-n2 { margin-top: -0.5rem !important; } .mr-n2, .mx-n2 { margin-right: -0.5rem !important; } .mb-n2, .my-n2 { margin-bottom: -0.5rem !important; } .ml-n2, .mx-n2 { margin-left: -0.5rem !important; } .m-n3 { margin: -1rem !important; } .mt-n3, .my-n3 { margin-top: -1rem !important; } .mr-n3, .mx-n3 { margin-right: -1rem !important; } .mb-n3, .my-n3 { margin-bottom: -1rem !important; } .ml-n3, .mx-n3 { margin-left: -1rem !important; } .m-n4 { margin: -1.5rem !important; } .mt-n4, .my-n4 { margin-top: -1.5rem !important; } .mr-n4, .mx-n4 { margin-right: -1.5rem !important; } .mb-n4, .my-n4 { margin-bottom: -1.5rem !important; } .ml-n4, .mx-n4 { margin-left: -1.5rem !important; } .m-n5 { margin: -3rem !important; } .mt-n5, .my-n5 { margin-top: -3rem !important; } .mr-n5, .mx-n5 { margin-right: -3rem !important; } .mb-n5, .my-n5 { margin-bottom: -3rem !important; } .ml-n5, .mx-n5 { margin-left: -3rem !important; } .m-auto { margin: auto !important; } .mt-auto, .my-auto { margin-top: auto !important; } .mr-auto, .mx-auto { margin-right: auto !important; } .mb-auto, .my-auto { margin-bottom: auto !important; } .ml-auto, .mx-auto { margin-left: auto !important; } @media (min-width: 576px) { .m-sm-0 { margin: 0 !important; } .mt-sm-0, .my-sm-0 { margin-top: 0 !important; } .mr-sm-0, .mx-sm-0 { margin-right: 0 !important; } .mb-sm-0, .my-sm-0 { margin-bottom: 0 !important; } .ml-sm-0, .mx-sm-0 { margin-left: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .mt-sm-1, .my-sm-1 { margin-top: 0.25rem !important; } .mr-sm-1, .mx-sm-1 { margin-right: 0.25rem !important; } .mb-sm-1, .my-sm-1 { margin-bottom: 0.25rem !important; } .ml-sm-1, .mx-sm-1 { margin-left: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .mt-sm-2, .my-sm-2 { margin-top: 0.5rem !important; } .mr-sm-2, .mx-sm-2 { margin-right: 0.5rem !important; } .mb-sm-2, .my-sm-2 { margin-bottom: 0.5rem !important; } .ml-sm-2, .mx-sm-2 { margin-left: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .mt-sm-3, .my-sm-3 { margin-top: 1rem !important; } .mr-sm-3, .mx-sm-3 { margin-right: 1rem !important; } .mb-sm-3, .my-sm-3 { margin-bottom: 1rem !important; } .ml-sm-3, .mx-sm-3 { margin-left: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .mt-sm-4, .my-sm-4 { margin-top: 1.5rem !important; } .mr-sm-4, .mx-sm-4 { margin-right: 1.5rem !important; } .mb-sm-4, .my-sm-4 { margin-bottom: 1.5rem !important; } .ml-sm-4, .mx-sm-4 { margin-left: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .mt-sm-5, .my-sm-5 { margin-top: 3rem !important; } .mr-sm-5, .mx-sm-5 { margin-right: 3rem !important; } .mb-sm-5, .my-sm-5 { margin-bottom: 3rem !important; } .ml-sm-5, .mx-sm-5 { margin-left: 3rem !important; } .p-sm-0 { padding: 0 !important; } .pt-sm-0, .py-sm-0 { padding-top: 0 !important; } .pr-sm-0, .px-sm-0 { padding-right: 0 !important; } .pb-sm-0, .py-sm-0 { padding-bottom: 0 !important; } .pl-sm-0, .px-sm-0 { padding-left: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .pt-sm-1, .py-sm-1 { padding-top: 0.25rem !important; } .pr-sm-1, .px-sm-1 { padding-right: 0.25rem !important; } .pb-sm-1, .py-sm-1 { padding-bottom: 0.25rem !important; } .pl-sm-1, .px-sm-1 { padding-left: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .pt-sm-2, .py-sm-2 { padding-top: 0.5rem !important; } .pr-sm-2, .px-sm-2 { padding-right: 0.5rem !important; } .pb-sm-2, .py-sm-2 { padding-bottom: 0.5rem !important; } .pl-sm-2, .px-sm-2 { padding-left: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .pt-sm-3, .py-sm-3 { padding-top: 1rem !important; } .pr-sm-3, .px-sm-3 { padding-right: 1rem !important; } .pb-sm-3, .py-sm-3 { padding-bottom: 1rem !important; } .pl-sm-3, .px-sm-3 { padding-left: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .pt-sm-4, .py-sm-4 { padding-top: 1.5rem !important; } .pr-sm-4, .px-sm-4 { padding-right: 1.5rem !important; } .pb-sm-4, .py-sm-4 { padding-bottom: 1.5rem !important; } .pl-sm-4, .px-sm-4 { padding-left: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .pt-sm-5, .py-sm-5 { padding-top: 3rem !important; } .pr-sm-5, .px-sm-5 { padding-right: 3rem !important; } .pb-sm-5, .py-sm-5 { padding-bottom: 3rem !important; } .pl-sm-5, .px-sm-5 { padding-left: 3rem !important; } .m-sm-n1 { margin: -0.25rem !important; } .mt-sm-n1, .my-sm-n1 { margin-top: -0.25rem !important; } .mr-sm-n1, .mx-sm-n1 { margin-right: -0.25rem !important; } .mb-sm-n1, .my-sm-n1 { margin-bottom: -0.25rem !important; } .ml-sm-n1, .mx-sm-n1 { margin-left: -0.25rem !important; } .m-sm-n2 { margin: -0.5rem !important; } .mt-sm-n2, .my-sm-n2 { margin-top: -0.5rem !important; } .mr-sm-n2, .mx-sm-n2 { margin-right: -0.5rem !important; } .mb-sm-n2, .my-sm-n2 { margin-bottom: -0.5rem !important; } .ml-sm-n2, .mx-sm-n2 { margin-left: -0.5rem !important; } .m-sm-n3 { margin: -1rem !important; } .mt-sm-n3, .my-sm-n3 { margin-top: -1rem !important; } .mr-sm-n3, .mx-sm-n3 { margin-right: -1rem !important; } .mb-sm-n3, .my-sm-n3 { margin-bottom: -1rem !important; } .ml-sm-n3, .mx-sm-n3 { margin-left: -1rem !important; } .m-sm-n4 { margin: -1.5rem !important; } .mt-sm-n4, .my-sm-n4 { margin-top: -1.5rem !important; } .mr-sm-n4, .mx-sm-n4 { margin-right: -1.5rem !important; } .mb-sm-n4, .my-sm-n4 { margin-bottom: -1.5rem !important; } .ml-sm-n4, .mx-sm-n4 { margin-left: -1.5rem !important; } .m-sm-n5 { margin: -3rem !important; } .mt-sm-n5, .my-sm-n5 { margin-top: -3rem !important; } .mr-sm-n5, .mx-sm-n5 { margin-right: -3rem !important; } .mb-sm-n5, .my-sm-n5 { margin-bottom: -3rem !important; } .ml-sm-n5, .mx-sm-n5 { margin-left: -3rem !important; } .m-sm-auto { margin: auto !important; } .mt-sm-auto, .my-sm-auto { margin-top: auto !important; } .mr-sm-auto, .mx-sm-auto { margin-right: auto !important; } .mb-sm-auto, .my-sm-auto { margin-bottom: auto !important; } .ml-sm-auto, .mx-sm-auto { margin-left: auto !important; } } @media (min-width: 768px) { .m-md-0 { margin: 0 !important; } .mt-md-0, .my-md-0 { margin-top: 0 !important; } .mr-md-0, .mx-md-0 { margin-right: 0 !important; } .mb-md-0, .my-md-0 { margin-bottom: 0 !important; } .ml-md-0, .mx-md-0 { margin-left: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .mt-md-1, .my-md-1 { margin-top: 0.25rem !important; } .mr-md-1, .mx-md-1 { margin-right: 0.25rem !important; } .mb-md-1, .my-md-1 { margin-bottom: 0.25rem !important; } .ml-md-1, .mx-md-1 { margin-left: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .mt-md-2, .my-md-2 { margin-top: 0.5rem !important; } .mr-md-2, .mx-md-2 { margin-right: 0.5rem !important; } .mb-md-2, .my-md-2 { margin-bottom: 0.5rem !important; } .ml-md-2, .mx-md-2 { margin-left: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .mt-md-3, .my-md-3 { margin-top: 1rem !important; } .mr-md-3, .mx-md-3 { margin-right: 1rem !important; } .mb-md-3, .my-md-3 { margin-bottom: 1rem !important; } .ml-md-3, .mx-md-3 { margin-left: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .mt-md-4, .my-md-4 { margin-top: 1.5rem !important; } .mr-md-4, .mx-md-4 { margin-right: 1.5rem !important; } .mb-md-4, .my-md-4 { margin-bottom: 1.5rem !important; } .ml-md-4, .mx-md-4 { margin-left: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .mt-md-5, .my-md-5 { margin-top: 3rem !important; } .mr-md-5, .mx-md-5 { margin-right: 3rem !important; } .mb-md-5, .my-md-5 { margin-bottom: 3rem !important; } .ml-md-5, .mx-md-5 { margin-left: 3rem !important; } .p-md-0 { padding: 0 !important; } .pt-md-0, .py-md-0 { padding-top: 0 !important; } .pr-md-0, .px-md-0 { padding-right: 0 !important; } .pb-md-0, .py-md-0 { padding-bottom: 0 !important; } .pl-md-0, .px-md-0 { padding-left: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .pt-md-1, .py-md-1 { padding-top: 0.25rem !important; } .pr-md-1, .px-md-1 { padding-right: 0.25rem !important; } .pb-md-1, .py-md-1 { padding-bottom: 0.25rem !important; } .pl-md-1, .px-md-1 { padding-left: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .pt-md-2, .py-md-2 { padding-top: 0.5rem !important; } .pr-md-2, .px-md-2 { padding-right: 0.5rem !important; } .pb-md-2, .py-md-2 { padding-bottom: 0.5rem !important; } .pl-md-2, .px-md-2 { padding-left: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .pt-md-3, .py-md-3 { padding-top: 1rem !important; } .pr-md-3, .px-md-3 { padding-right: 1rem !important; } .pb-md-3, .py-md-3 { padding-bottom: 1rem !important; } .pl-md-3, .px-md-3 { padding-left: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .pt-md-4, .py-md-4 { padding-top: 1.5rem !important; } .pr-md-4, .px-md-4 { padding-right: 1.5rem !important; } .pb-md-4, .py-md-4 { padding-bottom: 1.5rem !important; } .pl-md-4, .px-md-4 { padding-left: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .pt-md-5, .py-md-5 { padding-top: 3rem !important; } .pr-md-5, .px-md-5 { padding-right: 3rem !important; } .pb-md-5, .py-md-5 { padding-bottom: 3rem !important; } .pl-md-5, .px-md-5 { padding-left: 3rem !important; } .m-md-n1 { margin: -0.25rem !important; } .mt-md-n1, .my-md-n1 { margin-top: -0.25rem !important; } .mr-md-n1, .mx-md-n1 { margin-right: -0.25rem !important; } .mb-md-n1, .my-md-n1 { margin-bottom: -0.25rem !important; } .ml-md-n1, .mx-md-n1 { margin-left: -0.25rem !important; } .m-md-n2 { margin: -0.5rem !important; } .mt-md-n2, .my-md-n2 { margin-top: -0.5rem !important; } .mr-md-n2, .mx-md-n2 { margin-right: -0.5rem !important; } .mb-md-n2, .my-md-n2 { margin-bottom: -0.5rem !important; } .ml-md-n2, .mx-md-n2 { margin-left: -0.5rem !important; } .m-md-n3 { margin: -1rem !important; } .mt-md-n3, .my-md-n3 { margin-top: -1rem !important; } .mr-md-n3, .mx-md-n3 { margin-right: -1rem !important; } .mb-md-n3, .my-md-n3 { margin-bottom: -1rem !important; } .ml-md-n3, .mx-md-n3 { margin-left: -1rem !important; } .m-md-n4 { margin: -1.5rem !important; } .mt-md-n4, .my-md-n4 { margin-top: -1.5rem !important; } .mr-md-n4, .mx-md-n4 { margin-right: -1.5rem !important; } .mb-md-n4, .my-md-n4 { margin-bottom: -1.5rem !important; } .ml-md-n4, .mx-md-n4 { margin-left: -1.5rem !important; } .m-md-n5 { margin: -3rem !important; } .mt-md-n5, .my-md-n5 { margin-top: -3rem !important; } .mr-md-n5, .mx-md-n5 { margin-right: -3rem !important; } .mb-md-n5, .my-md-n5 { margin-bottom: -3rem !important; } .ml-md-n5, .mx-md-n5 { margin-left: -3rem !important; } .m-md-auto { margin: auto !important; } .mt-md-auto, .my-md-auto { margin-top: auto !important; } .mr-md-auto, .mx-md-auto { margin-right: auto !important; } .mb-md-auto, .my-md-auto { margin-bottom: auto !important; } .ml-md-auto, .mx-md-auto { margin-left: auto !important; } } @media (min-width: 992px) { .m-lg-0 { margin: 0 !important; } .mt-lg-0, .my-lg-0 { margin-top: 0 !important; } .mr-lg-0, .mx-lg-0 { margin-right: 0 !important; } .mb-lg-0, .my-lg-0 { margin-bottom: 0 !important; } .ml-lg-0, .mx-lg-0 { margin-left: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .mt-lg-1, .my-lg-1 { margin-top: 0.25rem !important; } .mr-lg-1, .mx-lg-1 { margin-right: 0.25rem !important; } .mb-lg-1, .my-lg-1 { margin-bottom: 0.25rem !important; } .ml-lg-1, .mx-lg-1 { margin-left: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .mt-lg-2, .my-lg-2 { margin-top: 0.5rem !important; } .mr-lg-2, .mx-lg-2 { margin-right: 0.5rem !important; } .mb-lg-2, .my-lg-2 { margin-bottom: 0.5rem !important; } .ml-lg-2, .mx-lg-2 { margin-left: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .mt-lg-3, .my-lg-3 { margin-top: 1rem !important; } .mr-lg-3, .mx-lg-3 { margin-right: 1rem !important; } .mb-lg-3, .my-lg-3 { margin-bottom: 1rem !important; } .ml-lg-3, .mx-lg-3 { margin-left: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .mt-lg-4, .my-lg-4 { margin-top: 1.5rem !important; } .mr-lg-4, .mx-lg-4 { margin-right: 1.5rem !important; } .mb-lg-4, .my-lg-4 { margin-bottom: 1.5rem !important; } .ml-lg-4, .mx-lg-4 { margin-left: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .mt-lg-5, .my-lg-5 { margin-top: 3rem !important; } .mr-lg-5, .mx-lg-5 { margin-right: 3rem !important; } .mb-lg-5, .my-lg-5 { margin-bottom: 3rem !important; } .ml-lg-5, .mx-lg-5 { margin-left: 3rem !important; } .p-lg-0 { padding: 0 !important; } .pt-lg-0, .py-lg-0 { padding-top: 0 !important; } .pr-lg-0, .px-lg-0 { padding-right: 0 !important; } .pb-lg-0, .py-lg-0 { padding-bottom: 0 !important; } .pl-lg-0, .px-lg-0 { padding-left: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .pt-lg-1, .py-lg-1 { padding-top: 0.25rem !important; } .pr-lg-1, .px-lg-1 { padding-right: 0.25rem !important; } .pb-lg-1, .py-lg-1 { padding-bottom: 0.25rem !important; } .pl-lg-1, .px-lg-1 { padding-left: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .pt-lg-2, .py-lg-2 { padding-top: 0.5rem !important; } .pr-lg-2, .px-lg-2 { padding-right: 0.5rem !important; } .pb-lg-2, .py-lg-2 { padding-bottom: 0.5rem !important; } .pl-lg-2, .px-lg-2 { padding-left: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .pt-lg-3, .py-lg-3 { padding-top: 1rem !important; } .pr-lg-3, .px-lg-3 { padding-right: 1rem !important; } .pb-lg-3, .py-lg-3 { padding-bottom: 1rem !important; } .pl-lg-3, .px-lg-3 { padding-left: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .pt-lg-4, .py-lg-4 { padding-top: 1.5rem !important; } .pr-lg-4, .px-lg-4 { padding-right: 1.5rem !important; } .pb-lg-4, .py-lg-4 { padding-bottom: 1.5rem !important; } .pl-lg-4, .px-lg-4 { padding-left: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .pt-lg-5, .py-lg-5 { padding-top: 3rem !important; } .pr-lg-5, .px-lg-5 { padding-right: 3rem !important; } .pb-lg-5, .py-lg-5 { padding-bottom: 3rem !important; } .pl-lg-5, .px-lg-5 { padding-left: 3rem !important; } .m-lg-n1 { margin: -0.25rem !important; } .mt-lg-n1, .my-lg-n1 { margin-top: -0.25rem !important; } .mr-lg-n1, .mx-lg-n1 { margin-right: -0.25rem !important; } .mb-lg-n1, .my-lg-n1 { margin-bottom: -0.25rem !important; } .ml-lg-n1, .mx-lg-n1 { margin-left: -0.25rem !important; } .m-lg-n2 { margin: -0.5rem !important; } .mt-lg-n2, .my-lg-n2 { margin-top: -0.5rem !important; } .mr-lg-n2, .mx-lg-n2 { margin-right: -0.5rem !important; } .mb-lg-n2, .my-lg-n2 { margin-bottom: -0.5rem !important; } .ml-lg-n2, .mx-lg-n2 { margin-left: -0.5rem !important; } .m-lg-n3 { margin: -1rem !important; } .mt-lg-n3, .my-lg-n3 { margin-top: -1rem !important; } .mr-lg-n3, .mx-lg-n3 { margin-right: -1rem !important; } .mb-lg-n3, .my-lg-n3 { margin-bottom: -1rem !important; } .ml-lg-n3, .mx-lg-n3 { margin-left: -1rem !important; } .m-lg-n4 { margin: -1.5rem !important; } .mt-lg-n4, .my-lg-n4 { margin-top: -1.5rem !important; } .mr-lg-n4, .mx-lg-n4 { margin-right: -1.5rem !important; } .mb-lg-n4, .my-lg-n4 { margin-bottom: -1.5rem !important; } .ml-lg-n4, .mx-lg-n4 { margin-left: -1.5rem !important; } .m-lg-n5 { margin: -3rem !important; } .mt-lg-n5, .my-lg-n5 { margin-top: -3rem !important; } .mr-lg-n5, .mx-lg-n5 { margin-right: -3rem !important; } .mb-lg-n5, .my-lg-n5 { margin-bottom: -3rem !important; } .ml-lg-n5, .mx-lg-n5 { margin-left: -3rem !important; } .m-lg-auto { margin: auto !important; } .mt-lg-auto, .my-lg-auto { margin-top: auto !important; } .mr-lg-auto, .mx-lg-auto { margin-right: auto !important; } .mb-lg-auto, .my-lg-auto { margin-bottom: auto !important; } .ml-lg-auto, .mx-lg-auto { margin-left: auto !important; } } @media (min-width: 1200px) { .m-xl-0 { margin: 0 !important; } .mt-xl-0, .my-xl-0 { margin-top: 0 !important; } .mr-xl-0, .mx-xl-0 { margin-right: 0 !important; } .mb-xl-0, .my-xl-0 { margin-bottom: 0 !important; } .ml-xl-0, .mx-xl-0 { margin-left: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .mt-xl-1, .my-xl-1 { margin-top: 0.25rem !important; } .mr-xl-1, .mx-xl-1 { margin-right: 0.25rem !important; } .mb-xl-1, .my-xl-1 { margin-bottom: 0.25rem !important; } .ml-xl-1, .mx-xl-1 { margin-left: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .mt-xl-2, .my-xl-2 { margin-top: 0.5rem !important; } .mr-xl-2, .mx-xl-2 { margin-right: 0.5rem !important; } .mb-xl-2, .my-xl-2 { margin-bottom: 0.5rem !important; } .ml-xl-2, .mx-xl-2 { margin-left: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .mt-xl-3, .my-xl-3 { margin-top: 1rem !important; } .mr-xl-3, .mx-xl-3 { margin-right: 1rem !important; } .mb-xl-3, .my-xl-3 { margin-bottom: 1rem !important; } .ml-xl-3, .mx-xl-3 { margin-left: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .mt-xl-4, .my-xl-4 { margin-top: 1.5rem !important; } .mr-xl-4, .mx-xl-4 { margin-right: 1.5rem !important; } .mb-xl-4, .my-xl-4 { margin-bottom: 1.5rem !important; } .ml-xl-4, .mx-xl-4 { margin-left: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .mt-xl-5, .my-xl-5 { margin-top: 3rem !important; } .mr-xl-5, .mx-xl-5 { margin-right: 3rem !important; } .mb-xl-5, .my-xl-5 { margin-bottom: 3rem !important; } .ml-xl-5, .mx-xl-5 { margin-left: 3rem !important; } .p-xl-0 { padding: 0 !important; } .pt-xl-0, .py-xl-0 { padding-top: 0 !important; } .pr-xl-0, .px-xl-0 { padding-right: 0 !important; } .pb-xl-0, .py-xl-0 { padding-bottom: 0 !important; } .pl-xl-0, .px-xl-0 { padding-left: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .pt-xl-1, .py-xl-1 { padding-top: 0.25rem !important; } .pr-xl-1, .px-xl-1 { padding-right: 0.25rem !important; } .pb-xl-1, .py-xl-1 { padding-bottom: 0.25rem !important; } .pl-xl-1, .px-xl-1 { padding-left: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .pt-xl-2, .py-xl-2 { padding-top: 0.5rem !important; } .pr-xl-2, .px-xl-2 { padding-right: 0.5rem !important; } .pb-xl-2, .py-xl-2 { padding-bottom: 0.5rem !important; } .pl-xl-2, .px-xl-2 { padding-left: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .pt-xl-3, .py-xl-3 { padding-top: 1rem !important; } .pr-xl-3, .px-xl-3 { padding-right: 1rem !important; } .pb-xl-3, .py-xl-3 { padding-bottom: 1rem !important; } .pl-xl-3, .px-xl-3 { padding-left: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .pt-xl-4, .py-xl-4 { padding-top: 1.5rem !important; } .pr-xl-4, .px-xl-4 { padding-right: 1.5rem !important; } .pb-xl-4, .py-xl-4 { padding-bottom: 1.5rem !important; } .pl-xl-4, .px-xl-4 { padding-left: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .pt-xl-5, .py-xl-5 { padding-top: 3rem !important; } .pr-xl-5, .px-xl-5 { padding-right: 3rem !important; } .pb-xl-5, .py-xl-5 { padding-bottom: 3rem !important; } .pl-xl-5, .px-xl-5 { padding-left: 3rem !important; } .m-xl-n1 { margin: -0.25rem !important; } .mt-xl-n1, .my-xl-n1 { margin-top: -0.25rem !important; } .mr-xl-n1, .mx-xl-n1 { margin-right: -0.25rem !important; } .mb-xl-n1, .my-xl-n1 { margin-bottom: -0.25rem !important; } .ml-xl-n1, .mx-xl-n1 { margin-left: -0.25rem !important; } .m-xl-n2 { margin: -0.5rem !important; } .mt-xl-n2, .my-xl-n2 { margin-top: -0.5rem !important; } .mr-xl-n2, .mx-xl-n2 { margin-right: -0.5rem !important; } .mb-xl-n2, .my-xl-n2 { margin-bottom: -0.5rem !important; } .ml-xl-n2, .mx-xl-n2 { margin-left: -0.5rem !important; } .m-xl-n3 { margin: -1rem !important; } .mt-xl-n3, .my-xl-n3 { margin-top: -1rem !important; } .mr-xl-n3, .mx-xl-n3 { margin-right: -1rem !important; } .mb-xl-n3, .my-xl-n3 { margin-bottom: -1rem !important; } .ml-xl-n3, .mx-xl-n3 { margin-left: -1rem !important; } .m-xl-n4 { margin: -1.5rem !important; } .mt-xl-n4, .my-xl-n4 { margin-top: -1.5rem !important; } .mr-xl-n4, .mx-xl-n4 { margin-right: -1.5rem !important; } .mb-xl-n4, .my-xl-n4 { margin-bottom: -1.5rem !important; } .ml-xl-n4, .mx-xl-n4 { margin-left: -1.5rem !important; } .m-xl-n5 { margin: -3rem !important; } .mt-xl-n5, .my-xl-n5 { margin-top: -3rem !important; } .mr-xl-n5, .mx-xl-n5 { margin-right: -3rem !important; } .mb-xl-n5, .my-xl-n5 { margin-bottom: -3rem !important; } .ml-xl-n5, .mx-xl-n5 { margin-left: -3rem !important; } .m-xl-auto { margin: auto !important; } .mt-xl-auto, .my-xl-auto { margin-top: auto !important; } .mr-xl-auto, .mx-xl-auto { margin-right: auto !important; } .mb-xl-auto, .my-xl-auto { margin-bottom: auto !important; } .ml-xl-auto, .mx-xl-auto { margin-left: auto !important; } } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; pointer-events: auto; content: ""; background-color: rgba(0, 0, 0, 0); } .text-monospace { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; } .text-justify { text-align: justify !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .text-center { text-align: center !important; } @media (min-width: 576px) { .text-sm-left { text-align: left !important; } .text-sm-right { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .text-md-left { text-align: left !important; } .text-md-right { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .text-lg-left { text-align: left !important; } .text-lg-right { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .text-xl-left { text-align: left !important; } .text-xl-right { text-align: right !important; } .text-xl-center { text-align: center !important; } } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .font-weight-light { font-weight: 300 !important; } .font-weight-lighter { font-weight: lighter !important; } .font-weight-normal { font-weight: 400 !important; } .font-weight-bold { font-weight: 700 !important; } .font-weight-bolder { font-weight: bolder !important; } .font-italic { font-style: italic !important; } .text-white { color: #fff !important; } .text-primary { color: #007bff !important; } a.text-primary:hover, a.text-primary:focus { color: #0056b3 !important; } .text-secondary { color: #6c757d !important; } a.text-secondary:hover, a.text-secondary:focus { color: #494f54 !important; } .text-success { color: #28a745 !important; } a.text-success:hover, a.text-success:focus { color: #19692c !important; } .text-info { color: #17a2b8 !important; } a.text-info:hover, a.text-info:focus { color: #0f6674 !important; } .text-warning { color: #ffc107 !important; } a.text-warning:hover, a.text-warning:focus { color: #ba8b00 !important; } .text-danger { color: #dc3545 !important; } a.text-danger:hover, a.text-danger:focus { color: #a71d2a !important; } .text-light { color: #f8f9fa !important; } a.text-light:hover, a.text-light:focus { color: #cbd3da !important; } .text-dark { color: #343a40 !important; } a.text-dark:hover, a.text-dark:focus { color: #121416 !important; } .text-body { color: #212529 !important; } .text-muted { color: #6c757d !important; } .text-black-50 { color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { color: rgba(255, 255, 255, 0.5) !important; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .text-decoration-none { text-decoration: none !important; } .text-break { word-break: break-word !important; word-wrap: break-word !important; } .text-reset { color: inherit !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media print { *, *::before, *::after { text-shadow: none !important; box-shadow: none !important; } a:not(.btn) { text-decoration: underline; } abbr[title]::after { content: " (" attr(title) ")"; } pre { white-space: pre-wrap !important; } pre, blockquote { border: 1px solid #adb5bd; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } @page { size: a3; } body { min-width: 992px !important; } .container { min-width: 992px !important; } .navbar { display: none; } .badge { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6 !important; } .table-dark { color: inherit; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #dee2e6; } .table .thead-dark th { color: inherit; border-color: #dee2e6; } } @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .dark-mode :root { --lightblue: #86bad8; --navy: #002c59; --olive: #74c8a3; --lime: #67ffa9; --fuchsia: #f672d8; --maroon: #ed6c9b; --blue: #3f6791; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #e74c3c; --orange: #fd7e14; --yellow: #f39c12; --green: #00bc8c; --teal: #20c997; --cyan: #3498db; --white: #fff; --gray: #6c757d; --gray-dark: #343a40; --primary: #3f6791; --secondary: #6c757d; --success: #00bc8c; --info: #3498db; --warning: #f39c12; --danger: #e74c3c; --light: #f8f9fa; --dark: #343a40; } .animation__shake { -webkit-animation: shake 1500ms; animation: shake 1500ms; } .animation__wobble { -webkit-animation: wobble 1500ms; animation: wobble 1500ms; } .preloader { display: -ms-flexbox; display: flex; background-color: #f4f6f9; height: 100vh; width: 100%; transition: height 200ms linear; position: fixed; left: 0; top: 0; z-index: 9999; } .dark-mode .preloader { background-color: #454d55 !important; color: #fff; } html.scroll-smooth { scroll-behavior: smooth; } html, body, .wrapper { min-height: 100%; } .wrapper { position: relative; } .wrapper .content-wrapper { min-height: calc(100vh - calc(3.5rem + 1px) - calc(3.5rem + 1px)); } .layout-boxed .wrapper { box-shadow: 0 0 10 rgba(0, 0, 0, 0.3); } .layout-boxed .wrapper, .layout-boxed .wrapper::before { margin: 0 auto; max-width: 1250px; overflow: hidden; } .layout-boxed .wrapper .main-sidebar { left: inherit; } @supports not (-webkit-touch-callout: none) { .layout-fixed .wrapper .sidebar { height: calc(100vh - (3.5rem + 1px)); } .layout-fixed.text-sm .wrapper .sidebar { height: calc(100vh - (2.93725rem + 1px)); } } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link { height: calc(3.5rem + 1px); width: 4.6rem; } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse.text-sm .wrapper .brand-link { height: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lightblue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lightblue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-navy .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-navy .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-olive .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-olive .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lime .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lime .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-fuchsia .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-fuchsia .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-maroon .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-maroon .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-blue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-blue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-indigo .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-indigo .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-purple .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-purple .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-pink .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-pink .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-red .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-red .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-orange .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-orange .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-yellow .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-yellow .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-green .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-green .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-teal .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-teal .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-cyan .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-cyan .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-white .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-white .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .main-header.border-bottom-0 ~ .content-wrapper { margin-top: 3.5rem; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1033; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } @media (min-width: 576px) { .layout-sm-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-sm-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-sm-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-sm-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-sm-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-sm-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-sm-navbar-not-fixed .wrapper .sidebar, .layout-sm-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-sm-navbar-not-fixed .wrapper .main-header { position: static; } .layout-sm-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 768px) { .layout-md-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-md-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-md-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-md-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-md-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-md-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-md-navbar-not-fixed .wrapper .sidebar, .layout-md-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-md-navbar-not-fixed .wrapper .main-header { position: static; } .layout-md-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 992px) { .layout-lg-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-lg-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-lg-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-lg-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-lg-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-lg-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-lg-navbar-not-fixed .wrapper .sidebar, .layout-lg-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-lg-navbar-not-fixed .wrapper .main-header { position: static; } .layout-lg-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 1200px) { .layout-xl-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-xl-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-xl-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-xl-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-xl-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-xl-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-xl-navbar-not-fixed .wrapper .sidebar, .layout-xl-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-xl-navbar-not-fixed .wrapper .main-header { position: static; } .layout-xl-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-not-fixed .wrapper .main-footer { position: static; } .layout-footer-not-fixed .wrapper .content-wrapper { margin-bottom: 0; } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-footer-not-fixed .wrapper .main-footer { position: static; } @media (min-width: 576px) { .layout-sm-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-sm-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-sm-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-sm-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 768px) { .layout-md-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-md-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-md-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-md-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 992px) { .layout-lg-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-lg-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-lg-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-lg-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 1200px) { .layout-xl-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-xl-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-xl-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-xl-footer-not-fixed .wrapper .main-footer { position: static; } } .layout-top-nav .wrapper { margin-left: 0; } .layout-top-nav .wrapper .main-header .brand-image { margin-top: -.5rem; margin-right: .2rem; height: 33px; } .layout-top-nav .wrapper .main-sidebar { bottom: inherit; height: inherit; } .layout-top-nav .wrapper .content-wrapper, .layout-top-nav .wrapper .main-header, .layout-top-nav .wrapper .main-footer { margin-left: 0; } body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header::before { margin-left: 0; } @media (min-width: 768px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (max-width: 991.98px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-md .content-wrapper, .sidebar-collapse .sidebar-mini-md .main-footer, .sidebar-collapse .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-xs .content-wrapper, .sidebar-collapse .sidebar-mini-xs .main-footer, .sidebar-collapse .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } .content-wrapper { background-color: #f4f6f9; } .content-wrapper > .content { padding: 0 0.5rem; } .main-sidebar, .main-sidebar::before { transition: margin-left 0.3s ease-in-out, width 0.3s ease-in-out; width: 250px; } @media (prefers-reduced-motion: reduce) { .main-sidebar, .main-sidebar::before { transition: none; } } .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar, .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar::before { box-shadow: none !important; } .sidebar-collapse .main-sidebar, .sidebar-collapse .main-sidebar::before { margin-left: -250px; } .sidebar-collapse .main-sidebar .nav-sidebar.nav-child-indent .nav-treeview { padding: 0; } @media (max-width: 767.98px) { .main-sidebar, .main-sidebar::before { box-shadow: none !important; margin-left: -250px; } .sidebar-open .main-sidebar, .sidebar-open .main-sidebar::before { margin-left: 0; } } body:not(.layout-fixed) .main-sidebar { height: inherit; min-height: 100%; position: absolute; top: 0; } body:not(.layout-fixed) .main-sidebar .sidebar { overflow-y: auto; } .layout-fixed .brand-link { width: 250px; } .layout-fixed .main-sidebar { bottom: 0; float: none; left: 0; position: fixed; top: 0; } .layout-fixed .control-sidebar { bottom: 0; float: none; position: fixed; top: 0; } .layout-fixed .control-sidebar .control-sidebar-content { height: calc(100vh - calc(3.5rem + 1px)); overflow-y: auto; scrollbar-width: thin; scrollbar-color: #a9a9a9 transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar { width: .5rem; height: .5rem; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-track { background-color: transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-corner { background-color: transparent; } @supports (-webkit-touch-callout: none) { .layout-fixed .main-sidebar { height: inherit; } } .main-footer { background-color: #fff; border-top: 1px solid #dee2e6; color: #869099; padding: 1rem; } .text-sm .main-footer, .main-footer.text-sm { padding: 0.812rem; } .content-header { padding: 15px 0.5rem; } .text-sm .content-header { padding: 10px 0.5rem; } .content-header h1 { font-size: 1.8rem; margin: 0; } .text-sm .content-header h1 { font-size: 1.5rem; } .content-header .breadcrumb { background-color: transparent; line-height: 1.8rem; margin-bottom: 0; padding: 0; } .text-sm .content-header .breadcrumb { line-height: 1.5rem; } .hold-transition .content-wrapper, .hold-transition .main-header, .hold-transition .main-sidebar, .hold-transition .main-sidebar *, .hold-transition .control-sidebar, .hold-transition .control-sidebar *, .hold-transition .main-footer { transition: none !important; -webkit-animation-duration: 0s !important; animation-duration: 0s !important; } .dark-mode { background-color: #454d55 !important; color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } @media (min-width: 576px) { .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-sm-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 768px) { .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-md-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 992px) { .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-lg-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } @media (min-width: 1200px) { .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-xl-navbar-fixed .dark-mode .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } } .dark-mode .breadcrumb-item.active, .dark-mode .breadcrumb-item + .breadcrumb-item::before { color: #adb5bd; } .dark-mode .main-footer { background-color: #343a40; border-color: #4b545c; } .dark-mode .content-wrapper { background-color: #454d55; color: #fff; } .dark-mode .content-wrapper .content-header { color: #fff; } .main-header { border-bottom: 1px solid #dee2e6; z-index: 1034; } .main-header .nav-link { height: 2.5rem; position: relative; } .text-sm .main-header .nav-link, .main-header.text-sm .nav-link { height: 1.93725rem; padding: 0.35rem 1rem; } .text-sm .main-header .nav-link > .fa, .text-sm .main-header .nav-link > .fas, .text-sm .main-header .nav-link > .far, .text-sm .main-header .nav-link > .fab, .text-sm .main-header .nav-link > .fal, .text-sm .main-header .nav-link > .fad, .text-sm .main-header .nav-link > .svg-inline--fa, .text-sm .main-header .nav-link > .ion, .main-header.text-sm .nav-link > .fa, .main-header.text-sm .nav-link > .fas, .main-header.text-sm .nav-link > .far, .main-header.text-sm .nav-link > .fab, .main-header.text-sm .nav-link > .fal, .main-header.text-sm .nav-link > .fad, .main-header.text-sm .nav-link > .svg-inline--fa, .main-header.text-sm .nav-link > .ion { font-size: 0.875rem; } .main-header .navbar-nav .nav-item { margin: 0; } .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: auto; margin-top: -3px; right: 0; } @media (max-width: 575.98px) { .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: 0; right: auto; } } .main-header.dropdown-legacy .dropdown-menu { top: 3rem; margin-top: 0; } .navbar-img { height: calc(calc(3.5rem + 1px) * .5); width: auto; } .navbar-badge { font-size: .6rem; font-weight: 300; padding: 2px 4px; position: absolute; right: 5px; top: 9px; } .btn-navbar { background-color: transparent; border-left-width: 0; } .form-control-navbar { border-right-width: 0; } .form-control-navbar + .input-group-append { margin-left: 0; } .form-control-navbar, .btn-navbar { transition: none; } .navbar-dark .form-control-navbar, .navbar-dark .btn-navbar { background-color: #343a40; border-color: #6c757d; } .navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:focus, .navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #495057; border-color: #6c757d !important; color: #ced4da; } .navbar-light .form-control-navbar, .navbar-light .btn-navbar { background-color: #dadfe4; border-color: #ced4da; } .navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-moz-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:focus, .navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d3d9df; border-color: #c7ced5 !important; color: #ced4da; } .navbar-light .navbar-search-block .form-control-navbar:focus, .navbar-light .navbar-search-block .form-control-navbar:focus + .input-group-append .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-search-block { position: absolute; padding: 0 1rem; left: 0; top: 0; right: 0; bottom: 0; z-index: 10; display: none; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; background-color: initial; } .navbar-search-block.navbar-search-open { display: -ms-flexbox; display: flex; } .navbar-search-block .input-group { width: 100%; } .brand-link { display: block; font-size: 1.25rem; line-height: 1.5; padding: 0.8125rem 0.5rem; transition: width 0.3s ease-in-out; white-space: nowrap; } .brand-link:hover { color: #fff; text-decoration: none; } .text-sm .brand-link { font-size: inherit; } [class*="sidebar-dark"] .brand-link { border-bottom: 1px solid #4b545c; } [class*="sidebar-dark"] .brand-link, [class*="sidebar-dark"] .brand-link .pushmenu { color: rgba(255, 255, 255, 0.8); } [class*="sidebar-dark"] .brand-link:hover, [class*="sidebar-dark"] .brand-link .pushmenu:hover { color: #fff; } [class*="sidebar-light"] .brand-link { border-bottom: 1px solid #dee2e6; } [class*="sidebar-light"] .brand-link, [class*="sidebar-light"] .brand-link .pushmenu { color: rgba(0, 0, 0, 0.8); } [class*="sidebar-light"] .brand-link:hover, [class*="sidebar-light"] .brand-link .pushmenu:hover { color: #000; } .brand-link .pushmenu { margin-right: 0.5rem; font-size: 1rem; } .brand-link .brand-link { padding: 0; border-bottom: none; } .brand-link .brand-image { float: left; line-height: .8; margin-left: .8rem; margin-right: .5rem; margin-top: -3px; max-height: 33px; width: auto; } .brand-link .brand-image-xs { float: left; line-height: .8; margin-top: -.1rem; max-height: 33px; width: auto; } .brand-link .brand-image-xl { line-height: .8; max-height: 40px; width: auto; } .brand-link .brand-image-xl.single { margin-top: -.3rem; } .brand-link.text-sm .brand-image, .text-sm .brand-link .brand-image { height: 29px; margin-bottom: -.25rem; margin-left: .95rem; margin-top: -.25rem; } .brand-link.text-sm .brand-image-xs, .text-sm .brand-link .brand-image-xs { margin-top: -.2rem; max-height: 29px; } .brand-link.text-sm .brand-image-xl, .text-sm .brand-link .brand-image-xl { margin-top: -.225rem; max-height: 38px; } .main-sidebar { height: 100vh; overflow-y: hidden; z-index: 1038; } .main-sidebar a:-moz-focusring { border: 0; outline: none; } .sidebar { height: calc(100% - (3.5rem + 1px)); overflow-x: hidden; overflow-y: initial; padding-bottom: 0; padding-left: 0.5rem; padding-right: 0.5rem; padding-top: 0; scrollbar-color: #a9a9a9 transparent; scrollbar-width: none; } .sidebar::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .sidebar::-webkit-scrollbar-track { background-color: transparent; } .sidebar::-webkit-scrollbar-corner { background-color: transparent; } .sidebar::-webkit-scrollbar { width: 0; } .sidebar:hover { scrollbar-width: thin; } .sidebar:hover::-webkit-scrollbar { width: .5rem; height: .5rem; } .brand-link.border-bottom-0 ~ .sidebar { height: calc(100% - 3.5rem); } .user-panel { position: relative; } [class*="sidebar-dark"] .user-panel { border-bottom: 1px solid #4f5962; } [class*="sidebar-light"] .user-panel { border-bottom: 1px solid #dee2e6; } .user-panel, .user-panel .info { overflow: hidden; white-space: nowrap; } .user-panel .image { display: inline-block; padding-left: 0.8rem; } .user-panel img { height: auto; width: 2.1rem; } .user-panel .info { display: inline-block; padding: 5px 5px 5px 10px; } .user-panel .status, .user-panel .dropdown-menu { font-size: 0.875rem; } .nav-sidebar .nav-item > .nav-link { margin-bottom: .2rem; } .nav-sidebar .nav-item > .nav-link .right { transition: -webkit-transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s, -webkit-transform ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-sidebar .nav-item > .nav-link .right { transition: none; } } .nav-sidebar .nav-link > .right, .nav-sidebar .nav-link > p > .right { position: absolute; right: 1rem; top: .7rem; } .nav-sidebar .nav-link > .right i, .nav-sidebar .nav-link > .right span, .nav-sidebar .nav-link > p > .right i, .nav-sidebar .nav-link > p > .right span { margin-left: .5rem; } .nav-sidebar .nav-link > .right:nth-child(2), .nav-sidebar .nav-link > p > .right:nth-child(2) { right: 2.2rem; } .nav-sidebar .menu-open > .nav-treeview { display: block; } .nav-sidebar .menu-open > .nav-link svg.right, .nav-sidebar .menu-open > .nav-link i.right, .nav-sidebar .menu-is-opening > .nav-link svg.right, .nav-sidebar .menu-is-opening > .nav-link i.right { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .nav-sidebar > .nav-item { margin-bottom: 0; } .nav-sidebar > .nav-item .nav-icon { margin-left: .05rem; font-size: 1.2rem; margin-right: .2rem; text-align: center; width: 1.6rem; } .nav-sidebar > .nav-item .nav-icon.fa, .nav-sidebar > .nav-item .nav-icon.fas, .nav-sidebar > .nav-item .nav-icon.far, .nav-sidebar > .nav-item .nav-icon.fab, .nav-sidebar > .nav-item .nav-icon.fal, .nav-sidebar > .nav-item .nav-icon.fad, .nav-sidebar > .nav-item .nav-icon.svg-inline--fa, .nav-sidebar > .nav-item .nav-icon.ion { font-size: 1.1rem; } .nav-sidebar > .nav-item .float-right { margin-top: 3px; } .nav-sidebar .nav-treeview { display: none; list-style: none; padding: 0; } .nav-sidebar .nav-treeview > .nav-item > .nav-link > .nav-icon { width: 1.6rem; } .nav-sidebar.nav-child-indent .nav-treeview { transition: padding 0.3s ease-in-out; padding-left: 1rem; } .text-sm .nav-sidebar.nav-child-indent .nav-treeview { padding-left: .5rem; } .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .text-sm .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-sidebar .nav-header { font-size: .9rem; padding: 0.5rem 0.75rem; } .nav-sidebar .nav-link p { display: inline; margin: 0; white-space: normal; } .sidebar-is-opening .sidebar .nav-sidebar .nav-link p { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } #sidebar-overlay { background-color: rgba(0, 0, 0, 0.1); bottom: 0; display: none; left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } @media (max-width: 991.98px) { .sidebar-open #sidebar-overlay { display: block; } } [class*="sidebar-light-"] { background-color: #fff; } [class*="sidebar-light-"] .user-panel a:hover { color: #212529; } [class*="sidebar-light-"] .user-panel .status { background-color: rgba(0, 0, 0, 0.1); color: #343a40; } [class*="sidebar-light-"] .user-panel .status:hover, [class*="sidebar-light-"] .user-panel .status:focus, [class*="sidebar-light-"] .user-panel .status:active { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:active, [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:focus { color: #343a40; } [class*="sidebar-light-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-light-"] .nav-sidebar > .nav-item:hover > .nav-link { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link.active { color: #000; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-light-"] .nav-header { background-color: inherit; color: #292d32; } [class*="sidebar-light-"] .sidebar a { color: #343a40; } [class*="sidebar-light-"] .sidebar a:hover { text-decoration: none; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link { color: #777; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(0, 0, 0, 0.1); color: #000; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active:hover { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover { background-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-dark-"] { background-color: #343a40; } [class*="sidebar-dark-"] .user-panel a:hover { color: #fff; } [class*="sidebar-dark-"] .user-panel .status { background-color: rgba(255, 255, 255, 0.1); color: #c2c7d0; } [class*="sidebar-dark-"] .user-panel .status:hover, [class*="sidebar-dark-"] .user-panel .status:focus, [class*="sidebar-dark-"] .user-panel .status:active { background-color: rgba(247, 247, 247, 0.1); color: #fff; } [class*="sidebar-dark-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(242, 242, 242, 0.1); } [class*="sidebar-dark-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:active { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item:hover > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link.active { color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-dark-"] .nav-header { background-color: inherit; color: #d0d4db; } [class*="sidebar-dark-"] .sidebar a { color: #c2c7d0; } [class*="sidebar-dark-"] .sidebar a:hover, [class*="sidebar-dark-"] .sidebar a:focus { text-decoration: none; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:focus { background-color: rgba(255, 255, 255, 0.9); color: #343a40; } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(255, 255, 255, 0.9); } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(255, 255, 255, 0.9); } .sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-secondary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-success .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-info .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-warning .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-danger .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-light .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar > .nav-item > .nav-link.active { background-color: #f8f9fa; color: #1f2d3d; } .sidebar-dark-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f8f9fa; } .sidebar-dark-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-dark-lightblue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar > .nav-item > .nav-link.active { background-color: #3c8dbc; color: #fff; } .sidebar-dark-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3c8dbc; } .sidebar-dark-navy .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar > .nav-item > .nav-link.active { background-color: #001f3f; color: #fff; } .sidebar-dark-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #001f3f; } .sidebar-dark-olive .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar > .nav-item > .nav-link.active { background-color: #3d9970; color: #fff; } .sidebar-dark-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3d9970; } .sidebar-dark-lime .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar > .nav-item > .nav-link.active { background-color: #01ff70; color: #1f2d3d; } .sidebar-dark-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #01ff70; } .sidebar-dark-fuchsia .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar > .nav-item > .nav-link.active { background-color: #f012be; color: #fff; } .sidebar-dark-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f012be; } .sidebar-dark-maroon .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar > .nav-item > .nav-link.active { background-color: #d81b60; color: #fff; } .sidebar-dark-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #d81b60; } .sidebar-dark-blue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-indigo .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar > .nav-item > .nav-link.active { background-color: #6610f2; color: #fff; } .sidebar-dark-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6610f2; } .sidebar-dark-purple .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar > .nav-item > .nav-link.active { background-color: #6f42c1; color: #fff; } .sidebar-dark-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6f42c1; } .sidebar-dark-pink .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar > .nav-item > .nav-link.active { background-color: #e83e8c; color: #fff; } .sidebar-dark-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e83e8c; } .sidebar-dark-red .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-orange .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar > .nav-item > .nav-link.active { background-color: #fd7e14; color: #1f2d3d; } .sidebar-dark-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fd7e14; } .sidebar-dark-yellow .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-green .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-teal .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar > .nav-item > .nav-link.active { background-color: #20c997; color: #fff; } .sidebar-dark-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #20c997; } .sidebar-dark-cyan .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-white .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar > .nav-item > .nav-link.active { background-color: #fff; color: #1f2d3d; } .sidebar-dark-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fff; } .sidebar-dark-gray .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-gray-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-flat { margin: -0.25rem -0.5rem 0; } .nav-flat .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-flat .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .nav-flat:not(.nav-child-indent) .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: .4rem; } .nav-flat.nav-child-indent .nav-treeview { padding-left: 0; } .nav-flat.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview { border-left: .2rem solid; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-icon { margin-left: .55rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-link { padding-left: calc(1rem - .2rem); } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-icon { margin-left: .35rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: .15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.35rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon { margin-left: .4rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .nav-flat .nav-icon { transition: margin-left ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-flat .nav-icon { transition: none; } } .nav-flat .nav-treeview .nav-icon { margin-left: -.2rem; } .nav-flat.nav-sidebar > .nav-item .nav-treeview, .nav-flat.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } .nav-flat.nav-sidebar > .nav-item .nav-treeview .nav-item > .nav-link, .nav-flat.nav-sidebar > .nav-item > .nav-treeview .nav-item > .nav-link { border-left: .2rem solid; } .nav-legacy { margin: -0.25rem -0.5rem 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .text-sm .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .75rem; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { background-color: inherit; border-left: 3px solid transparent; box-shadow: none; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.55rem - 3px); } .text-sm .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } .text-sm .nav-legacy.nav-sidebar.nav-flat .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: calc(.75rem - 3px); } .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: margin-left ease-in-out 0.3s; margin-left: .6rem; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: none; } } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview { padding-left: 1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview { padding-left: .5rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .55rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: .36rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview { padding-left: 0; margin-left: 0; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .75rem; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #fff; } [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #fff; } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(0, 0, 0, 0.05); } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #000; } [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #000; } .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .sidebar-collapse .sidebar:not(:hover) .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: 0; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .nav-compact .nav-link, .nav-compact .nav-header { padding-top: 0.25rem; padding-bottom: 0.25rem; } .nav-compact .nav-header:not(:first-of-type) { padding-top: 0.75rem; padding-bottom: 0.25rem; } .nav-compact .nav-link > .right, .nav-compact .nav-link > p > .right { top: .465rem; } .text-sm .nav-compact .nav-link > .right, .text-sm .nav-compact .nav-link > p > .right { top: .7rem; } [class*="sidebar-dark"] .form-control-sidebar, [class*="sidebar-dark"] .btn-sidebar { background-color: #3f474e; border: 1px solid #56606a; color: white; } [class*="sidebar-dark"] .form-control-sidebar:focus, [class*="sidebar-dark"] .btn-sidebar:focus { border: 1px solid #7a8793; } [class*="sidebar-dark"] .btn-sidebar:hover { background-color: #454d55; } [class*="sidebar-dark"] .btn-sidebar:focus { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item { background-color: #454d55; border-color: #56606a; color: #c2c7d0; } [class*="sidebar-dark"] .list-group-item:hover { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item:focus { background-color: #515a63; } [class*="sidebar-dark"] .list-group-item .search-path { color: #adb5bd; } [class*="sidebar-light"] .form-control-sidebar, [class*="sidebar-light"] .btn-sidebar { background-color: #f2f2f2; border: 1px solid #d9d9d9; color: #1f2d3d; } [class*="sidebar-light"] .form-control-sidebar:focus, [class*="sidebar-light"] .btn-sidebar:focus { border: 1px solid #b3b3b3; } [class*="sidebar-light"] .btn-sidebar:hover { background-color: #ececec; } [class*="sidebar-light"] .btn-sidebar:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item { border-color: #d9d9d9; } [class*="sidebar-light"] .list-group-item:hover { background-color: #ececec; } [class*="sidebar-light"] .list-group-item:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item .search-path { color: #6c757d; } .sidebar .form-inline .input-group { width: 100%; -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .sidebar nav .form-inline { margin-bottom: .2rem; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs).sidebar-collapse .main-sidebar { margin-left: 0; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .content-wrapper, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-header, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-footer { z-index: 9999; position: relative; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .control-sidebar { z-index: 9999; } .sidebar-collapse .form-control-sidebar, .sidebar-collapse .form-control-sidebar ~ .input-group-append, .sidebar-collapse .sidebar-search-results { display: none; } [data-widget="sidebar-search"] input[type="search"]::-ms-clear, [data-widget="sidebar-search"] input[type="search"]::-ms-reveal { display: none; width: 0; height: 0; } [data-widget="sidebar-search"] input[type="search"]::-webkit-search-cancel-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-decoration, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-decoration { display: none; } .sidebar-search-results { position: relative; display: none; width: 100%; } .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-search-results .search-title { margin-bottom: -.1rem; } .sidebar-search-results .list-group { position: absolute; width: 100%; z-index: 1039; } .sidebar-search-results .list-group > .list-group-item { padding: 0.375rem 0.75rem; } .sidebar-search-results .list-group > .list-group-item:-moz-focusring { margin-top: 0; border-left: 1px solid transparent; border-top: 0; border-bottom: 1px solid transparent; } .sidebar-search-results .list-group > .list-group-item:first-child { margin-top: 0; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .sidebar-search-results .search-path { font-size: 80%; } .sidebar-search-open .btn, .sidebar-search-open .form-control { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } [class*="sidebar-dark"] .sidebar-custom { border-top: 1px solid #4f5962; } [class*="sidebar-light"] .sidebar-custom { border-top: 1px solid #dee2e6; } .layout-fixed.sidebar-collapse .hide-on-collapse { display: none; } .layout-fixed.sidebar-collapse:hover .hide-on-collapse { display: block; } .layout-fixed.text-sm .main-sidebar-custom .sidebar { height: calc(100% - ((2.93725rem + 3.8rem) + 1px)); } .layout-fixed.text-sm .main-sidebar-custom .sidebar-custom { height: 3.8rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom { height: -webkit-fill-available; height: -moz-available; height: -ms-stretch; height: stretch; } .layout-fixed .main-sidebar-custom .sidebar { height: calc(100% - ((3.5rem + 4rem) + 1px)); } .layout-fixed .main-sidebar-custom .sidebar-custom { height: 4rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom-lg .sidebar { height: calc(100% - ((3.5rem + 6rem) + 1px)); } .layout-fixed .main-sidebar-custom-lg .sidebar-custom { height: 6rem; } .layout-fixed .main-sidebar-custom-xl .sidebar { height: calc(100% - ((3.5rem + 8rem) + 1px)); } .layout-fixed .main-sidebar-custom-xl .sidebar-custom { height: 8rem; } .layout-fixed .main-sidebar-custom .pos-right, .layout-fixed .main-sidebar-custom-lg .pos-right, .layout-fixed .main-sidebar-custom-xl .pos-right { position: absolute; right: .5rem; } .sidebar-hidden .main-sidebar, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-sidebar { display: none !important; } .sidebar-hidden .content-wrapper, .sidebar-hidden .main-header, .sidebar-hidden.sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-header { margin-left: 0 !important; } .dark-mode .sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-primary .nav-sidebar > .nav-item > .nav-link.active { background-color: #3f6791; color: #fff; } .dark-mode .sidebar-dark-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3f6791; } .dark-mode .sidebar-dark-secondary .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-secondary .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .dark-mode .sidebar-dark-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .dark-mode .sidebar-dark-success .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-success .nav-sidebar > .nav-item > .nav-link.active { background-color: #00bc8c; color: #fff; } .dark-mode .sidebar-dark-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #00bc8c; } .dark-mode .sidebar-dark-info .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-info .nav-sidebar > .nav-item > .nav-link.active { background-color: #3498db; color: #fff; } .dark-mode .sidebar-dark-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3498db; } .dark-mode .sidebar-dark-warning .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-warning .nav-sidebar > .nav-item > .nav-link.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .sidebar-dark-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f39c12; } .dark-mode .sidebar-dark-danger .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-danger .nav-sidebar > .nav-item > .nav-link.active { background-color: #e74c3c; color: #fff; } .dark-mode .sidebar-dark-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e74c3c; } .dark-mode .sidebar-dark-light .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-light .nav-sidebar > .nav-item > .nav-link.active { background-color: #f8f9fa; color: #1f2d3d; } .dark-mode .sidebar-dark-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f8f9fa; } .dark-mode .sidebar-dark-dark .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .dark-mode .sidebar-dark-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .dark-mode .sidebar-dark-lightblue .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lightblue .nav-sidebar > .nav-item > .nav-link.active { background-color: #86bad8; color: #1f2d3d; } .dark-mode .sidebar-dark-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #86bad8; } .dark-mode .sidebar-dark-navy .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-navy .nav-sidebar > .nav-item > .nav-link.active { background-color: #002c59; color: #fff; } .dark-mode .sidebar-dark-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #002c59; } .dark-mode .sidebar-dark-olive .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-olive .nav-sidebar > .nav-item > .nav-link.active { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .sidebar-dark-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #74c8a3; } .dark-mode .sidebar-dark-lime .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lime .nav-sidebar > .nav-item > .nav-link.active { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .sidebar-dark-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #67ffa9; } .dark-mode .sidebar-dark-fuchsia .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-fuchsia .nav-sidebar > .nav-item > .nav-link.active { background-color: #f672d8; color: #1f2d3d; } .dark-mode .sidebar-dark-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f672d8; } .dark-mode .sidebar-dark-maroon .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-maroon .nav-sidebar > .nav-item > .nav-link.active { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .sidebar-dark-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ed6c9b; } .dark-mode .sidebar-dark-blue .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-blue .nav-sidebar > .nav-item > .nav-link.active { background-color: #3f6791; color: #fff; } .dark-mode .sidebar-dark-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3f6791; } .dark-mode .sidebar-dark-indigo .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-indigo .nav-sidebar > .nav-item > .nav-link.active { background-color: #6610f2; color: #fff; } .dark-mode .sidebar-dark-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6610f2; } .dark-mode .sidebar-dark-purple .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-purple .nav-sidebar > .nav-item > .nav-link.active { background-color: #6f42c1; color: #fff; } .dark-mode .sidebar-dark-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6f42c1; } .dark-mode .sidebar-dark-pink .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-pink .nav-sidebar > .nav-item > .nav-link.active { background-color: #e83e8c; color: #fff; } .dark-mode .sidebar-dark-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e83e8c; } .dark-mode .sidebar-dark-red .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-red .nav-sidebar > .nav-item > .nav-link.active { background-color: #e74c3c; color: #fff; } .dark-mode .sidebar-dark-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e74c3c; } .dark-mode .sidebar-dark-orange .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-orange .nav-sidebar > .nav-item > .nav-link.active { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .sidebar-dark-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fd7e14; } .dark-mode .sidebar-dark-yellow .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-yellow .nav-sidebar > .nav-item > .nav-link.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .sidebar-dark-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f39c12; } .dark-mode .sidebar-dark-green .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-green .nav-sidebar > .nav-item > .nav-link.active { background-color: #00bc8c; color: #fff; } .dark-mode .sidebar-dark-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #00bc8c; } .dark-mode .sidebar-dark-teal .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-teal .nav-sidebar > .nav-item > .nav-link.active { background-color: #20c997; color: #fff; } .dark-mode .sidebar-dark-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #20c997; } .dark-mode .sidebar-dark-cyan .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-cyan .nav-sidebar > .nav-item > .nav-link.active { background-color: #3498db; color: #fff; } .dark-mode .sidebar-dark-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3498db; } .dark-mode .sidebar-dark-white .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-white .nav-sidebar > .nav-item > .nav-link.active { background-color: #fff; color: #1f2d3d; } .dark-mode .sidebar-dark-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fff; } .dark-mode .sidebar-dark-gray .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .dark-mode .sidebar-dark-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .dark-mode .sidebar-dark-gray-dark .nav-sidebar > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .dark-mode .sidebar-dark-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .dark-mode .sidebar-light-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .dark-mode [class*="sidebar-light-"] .sidebar a { color: #343a40; } .dark-mode [class*="sidebar-light-"] .sidebar a:hover { text-decoration: none; } .logo-xs, .logo-xl { opacity: 1; position: absolute; visibility: visible; } .logo-xs.brand-image-xs, .logo-xl.brand-image-xs { left: 18px; top: 12px; } .logo-xs.brand-image-xl, .logo-xl.brand-image-xl { left: 12px; top: 6px; } .logo-xs { opacity: 0; visibility: hidden; } .logo-xs.brand-image-xl { left: 16px; top: 8px; } .brand-link.logo-switch::before { content: "\00a0"; } @media (min-width: 992px) { .sidebar-mini .nav-sidebar, .sidebar-mini .nav-sidebar > .nav-header, .sidebar-mini .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-mini.sidebar-collapse .main-footer, .sidebar-mini.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar, .sidebar-mini.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini.sidebar-collapse .main-sidebar { box-shadow: none !important; } } @media (min-width: 768px) { .sidebar-mini-md .nav-sidebar, .sidebar-mini-md .nav-sidebar > .nav-header, .sidebar-mini-md .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-md.sidebar-collapse .content-wrapper, .sidebar-mini-md.sidebar-collapse .main-footer, .sidebar-mini-md.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-md.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar, .sidebar-mini-md.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-md.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-md.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md.sidebar-collapse .main-sidebar { box-shadow: none !important; } } .sidebar-mini-xs .nav-sidebar, .sidebar-mini-xs .nav-sidebar > .nav-header, .sidebar-mini-xs .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-xs.sidebar-collapse .content-wrapper, .sidebar-mini-xs.sidebar-collapse .main-footer, .sidebar-mini-xs.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-xs.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar, .sidebar-mini-xs.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-xs.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 3rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 4rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 5rem); } .sidebar-mini .main-sidebar .nav-legacy .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-mini .main-sidebar .nav-flat .nav-link, .sidebar-mini-md .main-sidebar .nav-flat .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { width: calc(250px - 0.5rem * 2); transition: width ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { transition: none; } } .sidebar-collapse.sidebar-mini .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar .sidebar-search-results { display: none; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar .nav-link { width: 3.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-legacy .nav-link { width: 4.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview { padding-left: 0 !important; margin-left: 0 !important; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link { width: calc(4.6rem - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append { display: -ms-flexbox; display: flex; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-compact .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover { width: 4.6rem; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-header { display: none; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .brand-link { width: 4.6rem !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .user-panel .image { float: none !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xs { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview { padding-left: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; display: inline-block; width: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon { margin-right: 0; } .nav-sidebar { position: relative; } .nav-sidebar:hover { overflow: visible; } .sidebar-form, .nav-sidebar > .nav-header { overflow: hidden; text-overflow: clip; } .nav-sidebar .nav-item > .nav-link { position: relative; } .nav-sidebar .nav-item > .nav-link > .float-right { margin-top: -7px; position: absolute; right: 10px; top: 50%; } .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: margin-left 0.3s linear, opacity 0.3s ease, visibility 0.3s ease; } @media (prefers-reduced-motion: reduce) { .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: none; } } html.control-sidebar-animate { overflow-x: hidden; } .control-sidebar { bottom: calc(3.5rem + 1px); position: absolute; top: calc(3.5rem + 1px); z-index: 1031; } .control-sidebar, .control-sidebar::before { bottom: calc(3.5rem + 1px); display: none; right: -250px; width: 250px; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar, .control-sidebar::before { transition: none; } } .control-sidebar::before { content: ""; display: block; position: fixed; top: 0; z-index: -1; } body.text-sm .control-sidebar { bottom: calc(2.9365rem + 1px); top: calc(2.93725rem + 1px); } .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .main-footer.text-sm ~ .control-sidebar { bottom: calc(2.9365rem + 1px); } .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: margin-right 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: none; } } .control-sidebar-open .control-sidebar { display: block !important; } .control-sidebar-open .control-sidebar, .control-sidebar-open .control-sidebar::before { right: 0; } .control-sidebar-open.control-sidebar-push .content-wrapper, .control-sidebar-open.control-sidebar-push .main-footer, .control-sidebar-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-slide-open .control-sidebar { display: block; } .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { right: 0; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { transition: none; } } .control-sidebar-slide-open.control-sidebar-push .content-wrapper, .control-sidebar-slide-open.control-sidebar-push .main-footer, .control-sidebar-slide-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-slide-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-dark { background-color: #343a40; } .control-sidebar-dark, .control-sidebar-dark a, .control-sidebar-dark .nav-link { color: #c2c7d0; } .control-sidebar-dark a:hover { color: #fff; } .control-sidebar-dark h1, .control-sidebar-dark h2, .control-sidebar-dark h3, .control-sidebar-dark h4, .control-sidebar-dark h5, .control-sidebar-dark h6, .control-sidebar-dark label { color: #fff; } .control-sidebar-dark .nav-tabs { background-color: rgba(255, 255, 255, 0.1); border-bottom: 0; margin-bottom: 5px; } .control-sidebar-dark .nav-tabs .nav-item { margin: 0; } .control-sidebar-dark .nav-tabs .nav-link { border-radius: 0; padding: 10px 20px; position: relative; text-align: center; } .control-sidebar-dark .nav-tabs .nav-link, .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border: 0; } .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border-bottom-color: transparent; border-left-color: transparent; border-top-color: transparent; color: #fff; } .control-sidebar-dark .nav-tabs .nav-link.active { background-color: #343a40; } .control-sidebar-dark .tab-pane { padding: 10px 15px; } .control-sidebar-light { color: #4b545c; background-color: #fff; border-left: 1px solid #dee2e6; } .text-sm .dropdown-menu { font-size: 0.875rem !important; } .text-sm .dropdown-toggle::after { vertical-align: .2rem; } .dropdown-item-title { font-size: 1rem; margin: 0; } .dropdown-icon::after { margin-left: 0; } .dropdown-menu-lg { max-width: 300px; min-width: 280px; padding: 0; } .dropdown-menu-lg .dropdown-divider { margin: 0; } .dropdown-menu-lg .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-lg p { margin: 0; white-space: normal; } .dropdown-submenu { position: relative; } .dropdown-submenu > a::after { border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; float: right; margin-left: .5rem; margin-top: .5rem; } .dropdown-submenu > .dropdown-menu { left: 100%; margin-left: 0; margin-top: 0; top: 0; } .dropdown-hover:hover > .dropdown-menu, .dropdown-hover.nav-item.dropdown:hover > .dropdown-menu, .dropdown-hover .dropdown-submenu:hover > .dropdown-menu, .dropdown-hover.dropdown-submenu:hover > .dropdown-menu { display: block; } .dropdown-menu-xl { max-width: 420px; min-width: 360px; padding: 0; } .dropdown-menu-xl .dropdown-divider { margin: 0; } .dropdown-menu-xl .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-xl p { margin: 0; white-space: normal; } .dropdown-footer, .dropdown-header { display: block; font-size: 0.875rem; padding: 0.5rem 1rem; text-align: center; } .open:not(.dropup) > .animated-dropdown-menu { -webkit-animation: flipInX 0.7s both; animation: flipInX 0.7s both; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; } .navbar-custom-menu > .navbar-nav > li { position: relative; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 0; left: auto; } @media (max-width: 767.98px) { .navbar-custom-menu > .navbar-nav { float: right; } .navbar-custom-menu > .navbar-nav > li { position: static; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 5%; left: auto; border: 1px solid #ddd; background-color: #fff; } } .navbar-nav > .user-menu > .nav-link::after { content: none; } .navbar-nav > .user-menu > .dropdown-menu { border-top-left-radius: 0; border-top-right-radius: 0; padding: 0; width: 280px; } .navbar-nav > .user-menu > .dropdown-menu, .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header { height: 175px; padding: 10px; text-align: center; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > img { z-index: 5; height: 90px; width: 90px; border: 3px solid; border-color: transparent; border-color: rgba(255, 255, 255, 0.2); } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p { z-index: 5; font-size: 17px; margin-top: 10px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p > small { display: block; font-size: 12px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom: 1px solid #495057; border-top: 1px solid #dee2e6; padding: 15px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body::after { display: block; clear: both; content: ""; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-body a { background-color: #fff !important; color: #495057 !important; } } .navbar-nav > .user-menu > .dropdown-menu > .user-footer { background-color: #f8f9fa; padding: 10px; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer::after { display: block; clear: both; content: ""; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default { color: #6c757d; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:hover { background-color: #f8f9fa; } } .navbar-nav > .user-menu .user-image { border-radius: 50%; float: left; height: 2.1rem; margin-right: 10px; margin-top: -2px; width: 2.1rem; } @media (min-width: 576px) { .navbar-nav > .user-menu .user-image { float: none; line-height: 10px; margin-right: .4rem; margin-top: -8px; } } .dark-mode .dropdown-menu { background-color: #343a40; color: #fff; } .dark-mode .dropdown-item { color: #fff; } .dark-mode .dropdown-item:focus, .dark-mode .dropdown-item:hover { background-color: #3f474e; } .dark-mode .dropdown-divider { border-color: #6c757d; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer { background-color: #3a4047; color: #fff; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default { color: #fff; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:hover, .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:focus { background-color: #3f474e; color: #dee2e6; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:focus { background-color: #454d55; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-color: #6c757d; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a { background-color: transparent !important; color: #fff !important; } .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a:hover, .dark-mode .navbar-nav > .user-menu > .dropdown-menu > .user-body a:focus { color: #ced4da !important; } .nav-pills .nav-link { color: #6c757d; } .nav-pills .nav-link:not(.active):hover { color: #007bff; } .nav-pills .nav-item.dropdown.show .nav-link:hover { color: #fff; } .nav-tabs.flex-column { border-bottom: 0; border-right: 1px solid #dee2e6; } .nav-tabs.flex-column .nav-link { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; margin-right: -1px; } .nav-tabs.flex-column .nav-link:hover, .nav-tabs.flex-column .nav-link:focus { border-color: #e9ecef transparent #e9ecef #e9ecef; } .nav-tabs.flex-column .nav-link.active, .nav-tabs.flex-column .nav-item.show .nav-link { border-color: #dee2e6 transparent #dee2e6 #dee2e6; } .nav-tabs.flex-column.nav-tabs-right { border-left: 1px solid #dee2e6; border-right: 0; } .nav-tabs.flex-column.nav-tabs-right .nav-link { border-bottom-left-radius: 0; border-bottom-right-radius: 0.25rem; border-top-left-radius: 0; border-top-right-radius: 0.25rem; margin-left: -1px; } .nav-tabs.flex-column.nav-tabs-right .nav-link:hover, .nav-tabs.flex-column.nav-tabs-right .nav-link:focus { border-color: #e9ecef #e9ecef #e9ecef transparent; } .nav-tabs.flex-column.nav-tabs-right .nav-link.active, .nav-tabs.flex-column.nav-tabs-right .nav-item.show .nav-link { border-color: #dee2e6 #dee2e6 #dee2e6 transparent; } .navbar-no-expand { -ms-flex-direction: row; flex-direction: row; } .navbar-no-expand .nav-link { padding-left: 1rem; padding-right: 1rem; } .navbar-no-expand .dropdown-menu { position: absolute; } .navbar-light { background-color: #f8f9fa; } .navbar-dark { background-color: #343a40; border-color: #4b545c; } .navbar-primary { background-color: #007bff; color: #fff; } .navbar-primary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar, .navbar-primary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus, .navbar-primary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-primary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar, .navbar-primary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus, .navbar-primary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-secondary { background-color: #6c757d; color: #fff; } .navbar-secondary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar, .navbar-secondary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus, .navbar-secondary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-secondary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar, .navbar-secondary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus, .navbar-secondary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-success { background-color: #28a745; color: #fff; } .navbar-success.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar, .navbar-success.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus, .navbar-success.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-success.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar, .navbar-success.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus, .navbar-success.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-info { background-color: #17a2b8; color: #fff; } .navbar-info.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar, .navbar-info.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus, .navbar-info.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-info.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar, .navbar-info.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus, .navbar-info.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-warning { background-color: #ffc107; color: #1f2d3d; } .navbar-warning.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar, .navbar-warning.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus, .navbar-warning.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-warning.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar, .navbar-warning.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus, .navbar-warning.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-danger { background-color: #dc3545; color: #fff; } .navbar-danger.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar, .navbar-danger.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus, .navbar-danger.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-danger.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar, .navbar-danger.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus, .navbar-danger.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-lightblue { background-color: #3c8dbc; color: #fff; } .navbar-lightblue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar, .navbar-lightblue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3781ad; border-color: #317399; color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus, .navbar-lightblue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #367fa9; border-color: #317399 !important; color: #343a40; } .navbar-lightblue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar, .navbar-lightblue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #4897c5; border-color: #5ba2cb; color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus, .navbar-lightblue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4c99c6; border-color: #5ba2cb !important; color: #fff; } .navbar-navy { background-color: #001f3f; color: #fff; } .navbar-navy.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar, .navbar-navy.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00152b; border-color: #000811; color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus, .navbar-navy.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #001226; border-color: #000811 !important; color: #343a40; } .navbar-navy.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar, .navbar-navy.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #002953; border-color: #00366d; color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus, .navbar-navy.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #002c59; border-color: #00366d !important; color: #fff; } .navbar-olive { background-color: #3d9970; color: #fff; } .navbar-olive.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar, .navbar-olive.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #378a65; border-color: #307858; color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus, .navbar-olive.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #368763; border-color: #307858 !important; color: #343a40; } .navbar-olive.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar, .navbar-olive.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #43a87b; border-color: #4cb888; color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus, .navbar-olive.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #44ab7d; border-color: #4cb888 !important; color: #fff; } .navbar-lime { background-color: #01ff70; color: #1f2d3d; } .navbar-lime.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar, .navbar-lime.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00ec67; border-color: #00d25c; color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus, .navbar-lime.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00e765; border-color: #00d25c !important; color: #343a40; } .navbar-lime.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar, .navbar-lime.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #15ff7b; border-color: #2fff8a; color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus, .navbar-lime.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1bff7e; border-color: #2fff8a !important; color: #fff; } .navbar-fuchsia { background-color: #f012be; color: #fff; } .navbar-fuchsia.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar, .navbar-fuchsia.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df0eb0; border-color: #c70d9d; color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus, .navbar-fuchsia.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #db0ead; border-color: #c70d9d !important; color: #343a40; } .navbar-fuchsia.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar, .navbar-fuchsia.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f125c3; border-color: #f33dca; color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus, .navbar-fuchsia.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f22ac5; border-color: #f33dca !important; color: #fff; } .navbar-maroon { background-color: #d81b60; color: #fff; } .navbar-maroon.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar, .navbar-maroon.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #c61958; border-color: #af164e; color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus, .navbar-maroon.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #c11856; border-color: #af164e !important; color: #343a40; } .navbar-maroon.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar, .navbar-maroon.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e4246a; border-color: #e63a79; color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus, .navbar-maroon.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e4286d; border-color: #e63a79 !important; color: #fff; } .navbar-blue { background-color: #007bff; color: #fff; } .navbar-blue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar, .navbar-blue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus, .navbar-blue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-blue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar, .navbar-blue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus, .navbar-blue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-indigo { background-color: #6610f2; color: #fff; } .navbar-indigo.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar, .navbar-indigo.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #5d0ce1; border-color: #530bc9; color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus, .navbar-indigo.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #5b0cdd; border-color: #530bc9 !important; color: #343a40; } .navbar-indigo.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar, .navbar-indigo.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7223f3; border-color: #823cf4; color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus, .navbar-indigo.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7528f3; border-color: #823cf4 !important; color: #fff; } .navbar-purple { background-color: #6f42c1; color: #fff; } .navbar-purple.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar, .navbar-purple.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #663bb4; border-color: #5b35a0; color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus, .navbar-purple.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #643ab0; border-color: #5b35a0 !important; color: #343a40; } .navbar-purple.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar, .navbar-purple.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7b51c6; border-color: #8965cc; color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus, .navbar-purple.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7e55c7; border-color: #8965cc !important; color: #fff; } .navbar-pink { background-color: #e83e8c; color: #fff; } .navbar-pink.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar, .navbar-pink.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e62c81; border-color: #de1a74; color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus, .navbar-pink.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e5277e; border-color: #de1a74 !important; color: #343a40; } .navbar-pink.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar, .navbar-pink.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5097; border-color: #ed67a4; color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus, .navbar-pink.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #eb559a; border-color: #ed67a4 !important; color: #fff; } .navbar-red { background-color: #dc3545; color: #fff; } .navbar-red.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar, .navbar-red.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus, .navbar-red.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-red.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar, .navbar-red.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus, .navbar-red.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-orange { background-color: #fd7e14; color: #1f2d3d; } .navbar-orange.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar, .navbar-orange.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fa7302; border-color: #e16702; color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus, .navbar-orange.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f57102; border-color: #e16702 !important; color: #343a40; } .navbar-orange.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar, .navbar-orange.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fd8928; border-color: #fd9742; color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus, .navbar-orange.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #fd8c2d; border-color: #fd9742 !important; color: #fff; } .navbar-yellow { background-color: #ffc107; color: #1f2d3d; } .navbar-yellow.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar, .navbar-yellow.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus, .navbar-yellow.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-yellow.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar, .navbar-yellow.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus, .navbar-yellow.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-green { background-color: #28a745; color: #fff; } .navbar-green.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar, .navbar-green.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus, .navbar-green.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-green.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar, .navbar-green.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus, .navbar-green.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-teal { background-color: #20c997; color: #fff; } .navbar-teal.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar, .navbar-teal.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1db78a; border-color: #1aa179; color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus, .navbar-teal.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1cb386; border-color: #1aa179 !important; color: #343a40; } .navbar-teal.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar, .navbar-teal.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #23dba4; border-color: #38dfae; color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus, .navbar-teal.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #26dca6; border-color: #38dfae !important; color: #fff; } .navbar-cyan { background-color: #17a2b8; color: #fff; } .navbar-cyan.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar, .navbar-cyan.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus, .navbar-cyan.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-cyan.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar, .navbar-cyan.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus, .navbar-cyan.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-white { background-color: #fff; color: #1f2d3d; } .navbar-white.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar, .navbar-white.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: whitesmoke; border-color: #e8e8e8; color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus, .navbar-white.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f2f2f2; border-color: #e8e8e8 !important; color: #343a40; } .navbar-white.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar, .navbar-white.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: white; border-color: white; color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus, .navbar-white.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: white; border-color: white !important; color: #fff; } .navbar-gray { background-color: #6c757d; color: #fff; } .navbar-gray.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar, .navbar-gray.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus, .navbar-gray.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-gray.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar, .navbar-gray.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus, .navbar-gray.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-gray-dark { background-color: #343a40; color: #fff; } .navbar-gray-dark.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar, .navbar-gray-dark.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2b3035; border-color: #1f2327; color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus, .navbar-gray-dark.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #292d32; border-color: #1f2327 !important; color: #343a40; } .navbar-gray-dark.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar, .navbar-gray-dark.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3d444b; border-color: #495159; color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus, .navbar-gray-dark.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #3f474e; border-color: #495159 !important; color: #fff; } .navbar-nav-not-expanded { -ms-flex-direction: row; flex-direction: row; } .navbar-nav-not-expanded .dropdown-menu { position: absolute; } .navbar-nav-not-expanded .nav-link { padding-right: 1rem; padding-left: 1rem; } .dark-mode .nav-pills .nav-link { color: #ced4da; } .dark-mode .nav-tabs { border-color: #56606a; } .dark-mode .nav-tabs .nav-link:focus, .dark-mode .nav-tabs .nav-link:hover { border-color: #56606a; } .dark-mode .nav-tabs .nav-item.show .nav-link, .dark-mode .nav-tabs .nav-link.active { background-color: #343a40; border-color: #56606a #56606a transparent #56606a; color: #fff; } .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link.active, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:hover, .dark-mode .nav-tabs.flex-column .nav-link.active, .dark-mode .nav-tabs.flex-column .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-link:hover { border-color: #56606a transparent #56606a #56606a; } .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-item.show .nav-link:hover, .dark-mode .nav-tabs.flex-column .nav-link:focus, .dark-mode .nav-tabs.flex-column .nav-link:hover { background-color: #3f474e; } .dark-mode .nav-tabs.flex-column.nav-tabs-right { border-color: #56606a; } .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link.active, .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link:focus, .dark-mode .nav-tabs.flex-column.nav-tabs-right .nav-link:hover { border-color: #56606a #56606a #56606a transparent; } .dark-mode .navbar-light { background-color: #f8f9fa; } .dark-mode .navbar-dark { background-color: #343a40; border-color: #4b545c; } .dark-mode .navbar-primary { background-color: #3f6791; color: #fff; } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar, .dark-mode .navbar-primary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #395d83; border-color: #315071; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus, .dark-mode .navbar-primary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #375a7f; border-color: #315071 !important; color: #343a40; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar, .dark-mode .navbar-primary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45719f; border-color: #4d7eb1; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-primary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4774a3; border-color: #4d7eb1 !important; color: #fff; } .dark-mode .navbar-secondary { background-color: #6c757d; color: #fff; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar, .dark-mode .navbar-secondary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus, .dark-mode .navbar-secondary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar, .dark-mode .navbar-secondary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-secondary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .dark-mode .navbar-success { background-color: #00bc8c; color: #fff; } .dark-mode .navbar-success.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar, .dark-mode .navbar-success.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00a87d; border-color: #008e6a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-success.navbar-light .form-control-navbar:focus, .dark-mode .navbar-success.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00a379; border-color: #008e6a !important; color: #343a40; } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar, .dark-mode .navbar-success.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00d09b; border-color: #00eaae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-success.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00d69f; border-color: #00eaae !important; color: #fff; } .dark-mode .navbar-info { background-color: #3498db; color: #fff; } .dark-mode .navbar-info.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar, .dark-mode .navbar-info.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #268fd5; border-color: #2280bf; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-info.navbar-light .form-control-navbar:focus, .dark-mode .navbar-info.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #258cd1; border-color: #2280bf !important; color: #343a40; } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar, .dark-mode .navbar-info.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45a1de; border-color: #5bace2; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-info.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4aa3df; border-color: #5bace2 !important; color: #fff; } .dark-mode .navbar-warning { background-color: #f39c12; color: #1f2d3d; } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar, .dark-mode .navbar-warning.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e5910c; border-color: #cd820a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus, .dark-mode .navbar-warning.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e08e0b; border-color: #cd820a !important; color: #343a40; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar, .dark-mode .navbar-warning.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f4a425; border-color: #f5ae3e; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-warning.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f4a62a; border-color: #f5ae3e !important; color: #fff; } .dark-mode .navbar-danger { background-color: #e74c3c; color: #fff; } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar, .dark-mode .navbar-danger.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e53b2a; border-color: #da2d1b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus, .dark-mode .navbar-danger.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e43725; border-color: #da2d1b !important; color: #343a40; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar, .dark-mode .navbar-danger.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e95d4e; border-color: #ec7265; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-danger.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea6153; border-color: #ec7265 !important; color: #fff; } .dark-mode .navbar-lightblue { background-color: #86bad8; color: #1f2d3d; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar, .dark-mode .navbar-lightblue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #76b1d3; border-color: #63a6cd; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus, .dark-mode .navbar-lightblue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #72afd2; border-color: #63a6cd !important; color: #343a40; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar, .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #95c3dd; border-color: #a9cee3; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-lightblue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #99c5de; border-color: #a9cee3 !important; color: #fff; } .dark-mode .navbar-navy { background-color: #002c59; color: #fff; } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar, .dark-mode .navbar-navy.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #002244; border-color: #00152b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus, .dark-mode .navbar-navy.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #001f3f; border-color: #00152b !important; color: #343a40; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar, .dark-mode .navbar-navy.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00366d; border-color: #004286; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-navy.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #003872; border-color: #004286 !important; color: #fff; } .dark-mode .navbar-olive { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar, .dark-mode .navbar-olive.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #66c299; border-color: #53bb8d; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus, .dark-mode .navbar-olive.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #62c096; border-color: #53bb8d !important; color: #343a40; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar, .dark-mode .navbar-olive.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #83ceac; border-color: #95d5b8; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-olive.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #87cfaf; border-color: #95d5b8 !important; color: #fff; } .dark-mode .navbar-lime { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar, .dark-mode .navbar-lime.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #53ff9e; border-color: #39ff90; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus, .dark-mode .navbar-lime.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4eff9b; border-color: #39ff90 !important; color: #343a40; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar, .dark-mode .navbar-lime.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7bffb5; border-color: #95ffc3; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-lime.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #81ffb8; border-color: #95ffc3 !important; color: #fff; } .dark-mode .navbar-fuchsia { background-color: #f672d8; color: #1f2d3d; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar, .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f55fd3; border-color: #f347cc; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus, .dark-mode .navbar-fuchsia.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f55ad2; border-color: #f347cc !important; color: #343a40; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar, .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f785de; border-color: #f99de4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-fuchsia.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f88adf; border-color: #f99de4 !important; color: #fff; } .dark-mode .navbar-maroon { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar, .dark-mode .navbar-maroon.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5a8f; border-color: #e8447f; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus, .dark-mode .navbar-maroon.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea568c; border-color: #e8447f !important; color: #343a40; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar, .dark-mode .navbar-maroon.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ef7ea8; border-color: #f295b7; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-maroon.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f083ab; border-color: #f295b7 !important; color: #fff; } .dark-mode .navbar-blue { background-color: #3f6791; color: #fff; } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar, .dark-mode .navbar-blue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #395d83; border-color: #315071; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus, .dark-mode .navbar-blue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #375a7f; border-color: #315071 !important; color: #343a40; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar, .dark-mode .navbar-blue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45719f; border-color: #4d7eb1; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-blue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4774a3; border-color: #4d7eb1 !important; color: #fff; } .dark-mode .navbar-indigo { background-color: #6610f2; color: #fff; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar, .dark-mode .navbar-indigo.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #5d0ce1; border-color: #530bc9; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus, .dark-mode .navbar-indigo.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #5b0cdd; border-color: #530bc9 !important; color: #343a40; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar, .dark-mode .navbar-indigo.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7223f3; border-color: #823cf4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-indigo.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7528f3; border-color: #823cf4 !important; color: #fff; } .dark-mode .navbar-purple { background-color: #6f42c1; color: #fff; } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar, .dark-mode .navbar-purple.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #663bb4; border-color: #5b35a0; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus, .dark-mode .navbar-purple.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #643ab0; border-color: #5b35a0 !important; color: #343a40; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar, .dark-mode .navbar-purple.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7b51c6; border-color: #8965cc; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-purple.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7e55c7; border-color: #8965cc !important; color: #fff; } .dark-mode .navbar-pink { background-color: #e83e8c; color: #fff; } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar, .dark-mode .navbar-pink.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e62c81; border-color: #de1a74; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus, .dark-mode .navbar-pink.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e5277e; border-color: #de1a74 !important; color: #343a40; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar, .dark-mode .navbar-pink.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5097; border-color: #ed67a4; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-pink.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #eb559a; border-color: #ed67a4 !important; color: #fff; } .dark-mode .navbar-red { background-color: #e74c3c; color: #fff; } .dark-mode .navbar-red.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar, .dark-mode .navbar-red.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e53b2a; border-color: #da2d1b; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-red.navbar-light .form-control-navbar:focus, .dark-mode .navbar-red.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e43725; border-color: #da2d1b !important; color: #343a40; } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar, .dark-mode .navbar-red.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e95d4e; border-color: #ec7265; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-red.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ea6153; border-color: #ec7265 !important; color: #fff; } .dark-mode .navbar-orange { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar, .dark-mode .navbar-orange.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fa7302; border-color: #e16702; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus, .dark-mode .navbar-orange.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f57102; border-color: #e16702 !important; color: #343a40; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar, .dark-mode .navbar-orange.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fd8928; border-color: #fd9742; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-orange.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #fd8c2d; border-color: #fd9742 !important; color: #fff; } .dark-mode .navbar-yellow { background-color: #f39c12; color: #1f2d3d; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar, .dark-mode .navbar-yellow.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e5910c; border-color: #cd820a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus, .dark-mode .navbar-yellow.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e08e0b; border-color: #cd820a !important; color: #343a40; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar, .dark-mode .navbar-yellow.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f4a425; border-color: #f5ae3e; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-yellow.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f4a62a; border-color: #f5ae3e !important; color: #fff; } .dark-mode .navbar-green { background-color: #00bc8c; color: #fff; } .dark-mode .navbar-green.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar, .dark-mode .navbar-green.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00a87d; border-color: #008e6a; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-green.navbar-light .form-control-navbar:focus, .dark-mode .navbar-green.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00a379; border-color: #008e6a !important; color: #343a40; } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar, .dark-mode .navbar-green.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00d09b; border-color: #00eaae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-green.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00d69f; border-color: #00eaae !important; color: #fff; } .dark-mode .navbar-teal { background-color: #20c997; color: #fff; } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar, .dark-mode .navbar-teal.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1db78a; border-color: #1aa179; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus, .dark-mode .navbar-teal.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1cb386; border-color: #1aa179 !important; color: #343a40; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar, .dark-mode .navbar-teal.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #23dba4; border-color: #38dfae; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-teal.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #26dca6; border-color: #38dfae !important; color: #fff; } .dark-mode .navbar-cyan { background-color: #3498db; color: #fff; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar, .dark-mode .navbar-cyan.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #268fd5; border-color: #2280bf; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus, .dark-mode .navbar-cyan.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #258cd1; border-color: #2280bf !important; color: #343a40; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar, .dark-mode .navbar-cyan.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #45a1de; border-color: #5bace2; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-cyan.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4aa3df; border-color: #5bace2 !important; color: #fff; } .dark-mode .navbar-white { background-color: #fff; color: #1f2d3d; } .dark-mode .navbar-white.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar, .dark-mode .navbar-white.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: whitesmoke; border-color: #e8e8e8; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-white.navbar-light .form-control-navbar:focus, .dark-mode .navbar-white.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f2f2f2; border-color: #e8e8e8 !important; color: #343a40; } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar, .dark-mode .navbar-white.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: white; border-color: white; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-white.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: white; border-color: white !important; color: #fff; } .dark-mode .navbar-gray { background-color: #6c757d; color: #fff; } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar, .dark-mode .navbar-gray.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus, .dark-mode .navbar-gray.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar, .dark-mode .navbar-gray.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-gray.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .dark-mode .navbar-gray-dark { background-color: #343a40; color: #fff; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar, .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2b3035; border-color: #1f2327; color: rgba(52, 58, 64, 0.8); } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus, .dark-mode .navbar-gray-dark.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #292d32; border-color: #1f2327 !important; color: #343a40; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar, .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3d444b; border-color: #495159; color: rgba(255, 255, 255, 0.8); } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus, .dark-mode .navbar-gray-dark.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #3f474e; border-color: #495159 !important; color: #fff; } .pagination-month .page-item { justify-self: stretch; } .pagination-month .page-item .page-link { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; box-shadow: none; } .pagination-month .page-item:first-child .page-link, .pagination-month .page-item:last-child .page-link { height: 100%; font-size: 1.25rem; } .pagination-month .page-item .page-month { margin-bottom: 0; font-size: 1.25rem; font-weight: 700; } .pagination-month .page-item .page-year { margin-bottom: 0; } .pagination-month.pagination-lg .page-month { font-size: 1.5625rem; } .pagination-month.pagination-sm .page-month { font-size: 1rem; } .dark-mode .page-item.disabled a, .dark-mode .page-item.disabled .page-link { background-color: #3a4047 !important; border-color: #6c757d !important; color: #6c757d; } .dark-mode .page-item .page-link { color: #3f6791; } .dark-mode .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .page-item.active .page-link:hover, .dark-mode .page-item.active .page-link:focus { color: #ced4da !important; } .dark-mode .page-item:not(.active) .page-link { background-color: #343a40; border-color: #6c757d; } .dark-mode .page-item:not(.active) .page-link:hover, .dark-mode .page-item:not(.active) .page-link:focus { color: #4774a3; background-color: #3f474e; } .border-transparent { border-color: transparent !important; } .description-block { display: block; margin: 10px 0; text-align: center; } .description-block.margin-bottom { margin-bottom: 25px; } .description-block > .description-header { font-size: 16px; font-weight: 600; margin: 0; padding: 0; } .description-block > .description-text { text-transform: uppercase; } .description-block .description-icon { font-size: 16px; } .list-group-unbordered > .list-group-item { border-left: 0; border-radius: 0; border-right: 0; padding-left: 0; padding-right: 0; } .list-header { color: #6c757d; font-size: 15px; font-weight: 700; padding: 10px 4px; } .list-seperator { background-color: rgba(0, 0, 0, 0.125); height: 1px; margin: 15px 0 9px; } .list-link > a { color: #6c757d; padding: 4px; } .list-link > a:hover { color: #212529; } .user-block { float: left; } .user-block img { float: left; height: 40px; width: 40px; } .user-block .username, .user-block .description, .user-block .comment { display: block; margin-left: 50px; } .user-block .username { font-size: 16px; font-weight: 600; margin-top: -1px; } .user-block .description { color: #6c757d; font-size: 13px; margin-top: -3px; } .user-block.user-block-sm img { width: 1.875rem; height: 1.875rem; } .user-block.user-block-sm .username, .user-block.user-block-sm .description, .user-block.user-block-sm .comment { margin-left: 40px; } .user-block.user-block-sm .username { font-size: 14px; } .img-sm, .img-md, .img-lg { float: left; } .img-sm { height: 1.875rem; width: 1.875rem; } .img-sm + .img-push { margin-left: 2.5rem; } .img-md { width: 3.75rem; height: 3.75rem; } .img-md + .img-push { margin-left: 4.375rem; } .img-lg { width: 6.25rem; height: 6.25rem; } .img-lg + .img-push { margin-left: 6.875rem; } .img-bordered { border: 3px solid #adb5bd; padding: 3px; } .img-bordered-sm { border: 2px solid #adb5bd; padding: 2px; } .img-rounded { border-radius: 0.25rem; } .img-circle { border-radius: 50%; } .img-size-64, .img-size-50, .img-size-32 { height: auto; } .img-size-64 { width: 64px; } .img-size-50 { width: 50px; } .img-size-32 { width: 32px; } .size-32, .size-40, .size-50 { display: block; text-align: center; } .size-32 { height: 32px; line-height: 32px; width: 32px; } .size-40 { height: 40px; line-height: 40px; width: 40px; } .size-50 { height: 50px; line-height: 50px; width: 50px; } .attachment-block { background-color: #f8f9fa; border: 1px solid rgba(0, 0, 0, 0.125); margin-bottom: 10px; padding: 5px; } .attachment-block .attachment-img { float: left; height: auto; max-height: 100px; max-width: 100px; } .attachment-block .attachment-pushed { margin-left: 110px; } .attachment-block .attachment-heading { margin: 0; } .attachment-block .attachment-text { color: #495057; } .card > .overlay, .card > .loading-img, .overlay-wrapper > .overlay, .overlay-wrapper > .loading-img, .info-box > .overlay, .info-box > .loading-img, .small-box > .overlay, .small-box > .loading-img { height: 100%; left: 0; position: absolute; top: 0; width: 100%; } .card .overlay, .overlay-wrapper .overlay, .info-box .overlay, .small-box .overlay { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; background-color: rgba(255, 255, 255, 0.7); display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; z-index: 50; } .card .overlay > .fa, .card .overlay > .fas, .card .overlay > .far, .card .overlay > .fab, .card .overlay > .fal, .card .overlay > .fad, .card .overlay > .svg-inline--fa, .card .overlay > .ion, .overlay-wrapper .overlay > .fa, .overlay-wrapper .overlay > .fas, .overlay-wrapper .overlay > .far, .overlay-wrapper .overlay > .fab, .overlay-wrapper .overlay > .fal, .overlay-wrapper .overlay > .fad, .overlay-wrapper .overlay > .svg-inline--fa, .overlay-wrapper .overlay > .ion, .info-box .overlay > .fa, .info-box .overlay > .fas, .info-box .overlay > .far, .info-box .overlay > .fab, .info-box .overlay > .fal, .info-box .overlay > .fad, .info-box .overlay > .svg-inline--fa, .info-box .overlay > .ion, .small-box .overlay > .fa, .small-box .overlay > .fas, .small-box .overlay > .far, .small-box .overlay > .fab, .small-box .overlay > .fal, .small-box .overlay > .fad, .small-box .overlay > .svg-inline--fa, .small-box .overlay > .ion { color: #343a40; } .card .overlay.dark, .overlay-wrapper .overlay.dark, .info-box .overlay.dark, .small-box .overlay.dark { background-color: rgba(0, 0, 0, 0.5); } .card .overlay.dark > .fa, .card .overlay.dark > .fas, .card .overlay.dark > .far, .card .overlay.dark > .fab, .card .overlay.dark > .fal, .card .overlay.dark > .fad, .card .overlay.dark > .svg-inline--fa, .card .overlay.dark > .ion, .overlay-wrapper .overlay.dark > .fa, .overlay-wrapper .overlay.dark > .fas, .overlay-wrapper .overlay.dark > .far, .overlay-wrapper .overlay.dark > .fab, .overlay-wrapper .overlay.dark > .fal, .overlay-wrapper .overlay.dark > .fad, .overlay-wrapper .overlay.dark > .svg-inline--fa, .overlay-wrapper .overlay.dark > .ion, .info-box .overlay.dark > .fa, .info-box .overlay.dark > .fas, .info-box .overlay.dark > .far, .info-box .overlay.dark > .fab, .info-box .overlay.dark > .fal, .info-box .overlay.dark > .fad, .info-box .overlay.dark > .svg-inline--fa, .info-box .overlay.dark > .ion, .small-box .overlay.dark > .fa, .small-box .overlay.dark > .fas, .small-box .overlay.dark > .far, .small-box .overlay.dark > .fab, .small-box .overlay.dark > .fal, .small-box .overlay.dark > .fad, .small-box .overlay.dark > .svg-inline--fa, .small-box .overlay.dark > .ion { color: #ced4da; } .tab-pane > .overlay-wrapper { position: relative; } .tab-pane > .overlay-wrapper > .overlay { border-top-left-radius: 0; border-top-right-radius: 0; -ms-flex-direction: column; flex-direction: column; margin-top: -1.25rem; margin-left: -1.25rem; height: calc(100% + 2 * 1.25rem); width: calc(100% + 2 * 1.25rem); } .tab-pane > .overlay-wrapper > .overlay.dark { color: #fff; } .ribbon-wrapper { height: 70px; overflow: hidden; position: absolute; right: -2px; top: -2px; width: 70px; z-index: 10; } .ribbon-wrapper.ribbon-lg { height: 120px; width: 120px; } .ribbon-wrapper.ribbon-lg .ribbon { right: 0; top: 26px; width: 160px; } .ribbon-wrapper.ribbon-xl { height: 180px; width: 180px; } .ribbon-wrapper.ribbon-xl .ribbon { right: 4px; top: 47px; width: 240px; } .ribbon-wrapper .ribbon { box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); font-size: 0.8rem; line-height: 100%; padding: 0.375rem 0; position: relative; right: -2px; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); text-transform: uppercase; top: 10px; -webkit-transform: rotate(45deg); transform: rotate(45deg); width: 90px; } .ribbon-wrapper .ribbon::before, .ribbon-wrapper .ribbon::after { border-left: 3px solid transparent; border-right: 3px solid transparent; border-top: 3px solid #9e9e9e; bottom: -3px; content: ""; position: absolute; } .ribbon-wrapper .ribbon::before { left: 0; } .ribbon-wrapper .ribbon::after { right: 0; } .back-to-top { bottom: 1.25rem; position: fixed; right: 1.25rem; z-index: 1032; } .back-to-top:focus { box-shadow: none; } pre { padding: .75rem; } blockquote { background-color: #fff; border-left: 0.7rem solid #007bff; margin: 1.5em .7rem; padding: .5em .7rem; } .box blockquote { background-color: #e9ecef; } blockquote p:last-child { margin-bottom: 0; } blockquote h1, blockquote h2, blockquote h3, blockquote h4, blockquote h5, blockquote h6 { color: #007bff; font-size: 1.25rem; font-weight: 600; } blockquote.quote-primary { border-color: #007bff; } blockquote.quote-primary h1, blockquote.quote-primary h2, blockquote.quote-primary h3, blockquote.quote-primary h4, blockquote.quote-primary h5, blockquote.quote-primary h6 { color: #007bff; } blockquote.quote-secondary { border-color: #6c757d; } blockquote.quote-secondary h1, blockquote.quote-secondary h2, blockquote.quote-secondary h3, blockquote.quote-secondary h4, blockquote.quote-secondary h5, blockquote.quote-secondary h6 { color: #6c757d; } blockquote.quote-success { border-color: #28a745; } blockquote.quote-success h1, blockquote.quote-success h2, blockquote.quote-success h3, blockquote.quote-success h4, blockquote.quote-success h5, blockquote.quote-success h6 { color: #28a745; } blockquote.quote-info { border-color: #17a2b8; } blockquote.quote-info h1, blockquote.quote-info h2, blockquote.quote-info h3, blockquote.quote-info h4, blockquote.quote-info h5, blockquote.quote-info h6 { color: #17a2b8; } blockquote.quote-warning { border-color: #ffc107; } blockquote.quote-warning h1, blockquote.quote-warning h2, blockquote.quote-warning h3, blockquote.quote-warning h4, blockquote.quote-warning h5, blockquote.quote-warning h6 { color: #ffc107; } blockquote.quote-danger { border-color: #dc3545; } blockquote.quote-danger h1, blockquote.quote-danger h2, blockquote.quote-danger h3, blockquote.quote-danger h4, blockquote.quote-danger h5, blockquote.quote-danger h6 { color: #dc3545; } blockquote.quote-light { border-color: #f8f9fa; } blockquote.quote-light h1, blockquote.quote-light h2, blockquote.quote-light h3, blockquote.quote-light h4, blockquote.quote-light h5, blockquote.quote-light h6 { color: #f8f9fa; } blockquote.quote-dark { border-color: #343a40; } blockquote.quote-dark h1, blockquote.quote-dark h2, blockquote.quote-dark h3, blockquote.quote-dark h4, blockquote.quote-dark h5, blockquote.quote-dark h6 { color: #343a40; } blockquote.quote-lightblue { border-color: #3c8dbc; } blockquote.quote-lightblue h1, blockquote.quote-lightblue h2, blockquote.quote-lightblue h3, blockquote.quote-lightblue h4, blockquote.quote-lightblue h5, blockquote.quote-lightblue h6 { color: #3c8dbc; } blockquote.quote-navy { border-color: #001f3f; } blockquote.quote-navy h1, blockquote.quote-navy h2, blockquote.quote-navy h3, blockquote.quote-navy h4, blockquote.quote-navy h5, blockquote.quote-navy h6 { color: #001f3f; } blockquote.quote-olive { border-color: #3d9970; } blockquote.quote-olive h1, blockquote.quote-olive h2, blockquote.quote-olive h3, blockquote.quote-olive h4, blockquote.quote-olive h5, blockquote.quote-olive h6 { color: #3d9970; } blockquote.quote-lime { border-color: #01ff70; } blockquote.quote-lime h1, blockquote.quote-lime h2, blockquote.quote-lime h3, blockquote.quote-lime h4, blockquote.quote-lime h5, blockquote.quote-lime h6 { color: #01ff70; } blockquote.quote-fuchsia { border-color: #f012be; } blockquote.quote-fuchsia h1, blockquote.quote-fuchsia h2, blockquote.quote-fuchsia h3, blockquote.quote-fuchsia h4, blockquote.quote-fuchsia h5, blockquote.quote-fuchsia h6 { color: #f012be; } blockquote.quote-maroon { border-color: #d81b60; } blockquote.quote-maroon h1, blockquote.quote-maroon h2, blockquote.quote-maroon h3, blockquote.quote-maroon h4, blockquote.quote-maroon h5, blockquote.quote-maroon h6 { color: #d81b60; } blockquote.quote-blue { border-color: #007bff; } blockquote.quote-blue h1, blockquote.quote-blue h2, blockquote.quote-blue h3, blockquote.quote-blue h4, blockquote.quote-blue h5, blockquote.quote-blue h6 { color: #007bff; } blockquote.quote-indigo { border-color: #6610f2; } blockquote.quote-indigo h1, blockquote.quote-indigo h2, blockquote.quote-indigo h3, blockquote.quote-indigo h4, blockquote.quote-indigo h5, blockquote.quote-indigo h6 { color: #6610f2; } blockquote.quote-purple { border-color: #6f42c1; } blockquote.quote-purple h1, blockquote.quote-purple h2, blockquote.quote-purple h3, blockquote.quote-purple h4, blockquote.quote-purple h5, blockquote.quote-purple h6 { color: #6f42c1; } blockquote.quote-pink { border-color: #e83e8c; } blockquote.quote-pink h1, blockquote.quote-pink h2, blockquote.quote-pink h3, blockquote.quote-pink h4, blockquote.quote-pink h5, blockquote.quote-pink h6 { color: #e83e8c; } blockquote.quote-red { border-color: #dc3545; } blockquote.quote-red h1, blockquote.quote-red h2, blockquote.quote-red h3, blockquote.quote-red h4, blockquote.quote-red h5, blockquote.quote-red h6 { color: #dc3545; } blockquote.quote-orange { border-color: #fd7e14; } blockquote.quote-orange h1, blockquote.quote-orange h2, blockquote.quote-orange h3, blockquote.quote-orange h4, blockquote.quote-orange h5, blockquote.quote-orange h6 { color: #fd7e14; } blockquote.quote-yellow { border-color: #ffc107; } blockquote.quote-yellow h1, blockquote.quote-yellow h2, blockquote.quote-yellow h3, blockquote.quote-yellow h4, blockquote.quote-yellow h5, blockquote.quote-yellow h6 { color: #ffc107; } blockquote.quote-green { border-color: #28a745; } blockquote.quote-green h1, blockquote.quote-green h2, blockquote.quote-green h3, blockquote.quote-green h4, blockquote.quote-green h5, blockquote.quote-green h6 { color: #28a745; } blockquote.quote-teal { border-color: #20c997; } blockquote.quote-teal h1, blockquote.quote-teal h2, blockquote.quote-teal h3, blockquote.quote-teal h4, blockquote.quote-teal h5, blockquote.quote-teal h6 { color: #20c997; } blockquote.quote-cyan { border-color: #17a2b8; } blockquote.quote-cyan h1, blockquote.quote-cyan h2, blockquote.quote-cyan h3, blockquote.quote-cyan h4, blockquote.quote-cyan h5, blockquote.quote-cyan h6 { color: #17a2b8; } blockquote.quote-white { border-color: #fff; } blockquote.quote-white h1, blockquote.quote-white h2, blockquote.quote-white h3, blockquote.quote-white h4, blockquote.quote-white h5, blockquote.quote-white h6 { color: #fff; } blockquote.quote-gray { border-color: #6c757d; } blockquote.quote-gray h1, blockquote.quote-gray h2, blockquote.quote-gray h3, blockquote.quote-gray h4, blockquote.quote-gray h5, blockquote.quote-gray h6 { color: #6c757d; } blockquote.quote-gray-dark { border-color: #343a40; } blockquote.quote-gray-dark h1, blockquote.quote-gray-dark h2, blockquote.quote-gray-dark h3, blockquote.quote-gray-dark h4, blockquote.quote-gray-dark h5, blockquote.quote-gray-dark h6 { color: #343a40; } .tab-custom-content { border-top: 1px solid #dee2e6; margin-top: .5rem; padding-top: .5rem; } .nav + .tab-custom-content { border-top: none; border-bottom: 1px solid #dee2e6; margin-top: 0; margin-bottom: .5rem; padding-bottom: .5rem; } .badge-btn { border-radius: 0.15rem; font-size: 0.75rem; font-weight: 400; padding: 0.25rem 0.5rem; } .badge-btn.badge-pill { padding: .375rem .6rem; } .dark-mode a:not(.btn):hover { color: #3395ff; } .dark-mode .attachment-block { background-color: #3d444b; } .dark-mode .attachment-block .attachment-text { color: #ced4da; } .dark-mode blockquote { background-color: #3f474e; } .dark-mode blockquote.quote-primary { border-color: #007bff; } .dark-mode blockquote.quote-primary h1, .dark-mode blockquote.quote-primary h2, .dark-mode blockquote.quote-primary h3, .dark-mode blockquote.quote-primary h4, .dark-mode blockquote.quote-primary h5, .dark-mode blockquote.quote-primary h6 { color: #007bff; } .dark-mode blockquote.quote-secondary { border-color: #6c757d; } .dark-mode blockquote.quote-secondary h1, .dark-mode blockquote.quote-secondary h2, .dark-mode blockquote.quote-secondary h3, .dark-mode blockquote.quote-secondary h4, .dark-mode blockquote.quote-secondary h5, .dark-mode blockquote.quote-secondary h6 { color: #6c757d; } .dark-mode blockquote.quote-success { border-color: #28a745; } .dark-mode blockquote.quote-success h1, .dark-mode blockquote.quote-success h2, .dark-mode blockquote.quote-success h3, .dark-mode blockquote.quote-success h4, .dark-mode blockquote.quote-success h5, .dark-mode blockquote.quote-success h6 { color: #28a745; } .dark-mode blockquote.quote-info { border-color: #17a2b8; } .dark-mode blockquote.quote-info h1, .dark-mode blockquote.quote-info h2, .dark-mode blockquote.quote-info h3, .dark-mode blockquote.quote-info h4, .dark-mode blockquote.quote-info h5, .dark-mode blockquote.quote-info h6 { color: #17a2b8; } .dark-mode blockquote.quote-warning { border-color: #ffc107; } .dark-mode blockquote.quote-warning h1, .dark-mode blockquote.quote-warning h2, .dark-mode blockquote.quote-warning h3, .dark-mode blockquote.quote-warning h4, .dark-mode blockquote.quote-warning h5, .dark-mode blockquote.quote-warning h6 { color: #ffc107; } .dark-mode blockquote.quote-danger { border-color: #dc3545; } .dark-mode blockquote.quote-danger h1, .dark-mode blockquote.quote-danger h2, .dark-mode blockquote.quote-danger h3, .dark-mode blockquote.quote-danger h4, .dark-mode blockquote.quote-danger h5, .dark-mode blockquote.quote-danger h6 { color: #dc3545; } .dark-mode blockquote.quote-light { border-color: #f8f9fa; } .dark-mode blockquote.quote-light h1, .dark-mode blockquote.quote-light h2, .dark-mode blockquote.quote-light h3, .dark-mode blockquote.quote-light h4, .dark-mode blockquote.quote-light h5, .dark-mode blockquote.quote-light h6 { color: #f8f9fa; } .dark-mode blockquote.quote-dark { border-color: #343a40; } .dark-mode blockquote.quote-dark h1, .dark-mode blockquote.quote-dark h2, .dark-mode blockquote.quote-dark h3, .dark-mode blockquote.quote-dark h4, .dark-mode blockquote.quote-dark h5, .dark-mode blockquote.quote-dark h6 { color: #343a40; } .dark-mode blockquote.quote-lightblue { border-color: #3c8dbc; } .dark-mode blockquote.quote-lightblue h1, .dark-mode blockquote.quote-lightblue h2, .dark-mode blockquote.quote-lightblue h3, .dark-mode blockquote.quote-lightblue h4, .dark-mode blockquote.quote-lightblue h5, .dark-mode blockquote.quote-lightblue h6 { color: #3c8dbc; } .dark-mode blockquote.quote-navy { border-color: #001f3f; } .dark-mode blockquote.quote-navy h1, .dark-mode blockquote.quote-navy h2, .dark-mode blockquote.quote-navy h3, .dark-mode blockquote.quote-navy h4, .dark-mode blockquote.quote-navy h5, .dark-mode blockquote.quote-navy h6 { color: #001f3f; } .dark-mode blockquote.quote-olive { border-color: #3d9970; } .dark-mode blockquote.quote-olive h1, .dark-mode blockquote.quote-olive h2, .dark-mode blockquote.quote-olive h3, .dark-mode blockquote.quote-olive h4, .dark-mode blockquote.quote-olive h5, .dark-mode blockquote.quote-olive h6 { color: #3d9970; } .dark-mode blockquote.quote-lime { border-color: #01ff70; } .dark-mode blockquote.quote-lime h1, .dark-mode blockquote.quote-lime h2, .dark-mode blockquote.quote-lime h3, .dark-mode blockquote.quote-lime h4, .dark-mode blockquote.quote-lime h5, .dark-mode blockquote.quote-lime h6 { color: #01ff70; } .dark-mode blockquote.quote-fuchsia { border-color: #f012be; } .dark-mode blockquote.quote-fuchsia h1, .dark-mode blockquote.quote-fuchsia h2, .dark-mode blockquote.quote-fuchsia h3, .dark-mode blockquote.quote-fuchsia h4, .dark-mode blockquote.quote-fuchsia h5, .dark-mode blockquote.quote-fuchsia h6 { color: #f012be; } .dark-mode blockquote.quote-maroon { border-color: #d81b60; } .dark-mode blockquote.quote-maroon h1, .dark-mode blockquote.quote-maroon h2, .dark-mode blockquote.quote-maroon h3, .dark-mode blockquote.quote-maroon h4, .dark-mode blockquote.quote-maroon h5, .dark-mode blockquote.quote-maroon h6 { color: #d81b60; } .dark-mode blockquote.quote-blue { border-color: #007bff; } .dark-mode blockquote.quote-blue h1, .dark-mode blockquote.quote-blue h2, .dark-mode blockquote.quote-blue h3, .dark-mode blockquote.quote-blue h4, .dark-mode blockquote.quote-blue h5, .dark-mode blockquote.quote-blue h6 { color: #007bff; } .dark-mode blockquote.quote-indigo { border-color: #6610f2; } .dark-mode blockquote.quote-indigo h1, .dark-mode blockquote.quote-indigo h2, .dark-mode blockquote.quote-indigo h3, .dark-mode blockquote.quote-indigo h4, .dark-mode blockquote.quote-indigo h5, .dark-mode blockquote.quote-indigo h6 { color: #6610f2; } .dark-mode blockquote.quote-purple { border-color: #6f42c1; } .dark-mode blockquote.quote-purple h1, .dark-mode blockquote.quote-purple h2, .dark-mode blockquote.quote-purple h3, .dark-mode blockquote.quote-purple h4, .dark-mode blockquote.quote-purple h5, .dark-mode blockquote.quote-purple h6 { color: #6f42c1; } .dark-mode blockquote.quote-pink { border-color: #e83e8c; } .dark-mode blockquote.quote-pink h1, .dark-mode blockquote.quote-pink h2, .dark-mode blockquote.quote-pink h3, .dark-mode blockquote.quote-pink h4, .dark-mode blockquote.quote-pink h5, .dark-mode blockquote.quote-pink h6 { color: #e83e8c; } .dark-mode blockquote.quote-red { border-color: #dc3545; } .dark-mode blockquote.quote-red h1, .dark-mode blockquote.quote-red h2, .dark-mode blockquote.quote-red h3, .dark-mode blockquote.quote-red h4, .dark-mode blockquote.quote-red h5, .dark-mode blockquote.quote-red h6 { color: #dc3545; } .dark-mode blockquote.quote-orange { border-color: #fd7e14; } .dark-mode blockquote.quote-orange h1, .dark-mode blockquote.quote-orange h2, .dark-mode blockquote.quote-orange h3, .dark-mode blockquote.quote-orange h4, .dark-mode blockquote.quote-orange h5, .dark-mode blockquote.quote-orange h6 { color: #fd7e14; } .dark-mode blockquote.quote-yellow { border-color: #ffc107; } .dark-mode blockquote.quote-yellow h1, .dark-mode blockquote.quote-yellow h2, .dark-mode blockquote.quote-yellow h3, .dark-mode blockquote.quote-yellow h4, .dark-mode blockquote.quote-yellow h5, .dark-mode blockquote.quote-yellow h6 { color: #ffc107; } .dark-mode blockquote.quote-green { border-color: #28a745; } .dark-mode blockquote.quote-green h1, .dark-mode blockquote.quote-green h2, .dark-mode blockquote.quote-green h3, .dark-mode blockquote.quote-green h4, .dark-mode blockquote.quote-green h5, .dark-mode blockquote.quote-green h6 { color: #28a745; } .dark-mode blockquote.quote-teal { border-color: #20c997; } .dark-mode blockquote.quote-teal h1, .dark-mode blockquote.quote-teal h2, .dark-mode blockquote.quote-teal h3, .dark-mode blockquote.quote-teal h4, .dark-mode blockquote.quote-teal h5, .dark-mode blockquote.quote-teal h6 { color: #20c997; } .dark-mode blockquote.quote-cyan { border-color: #17a2b8; } .dark-mode blockquote.quote-cyan h1, .dark-mode blockquote.quote-cyan h2, .dark-mode blockquote.quote-cyan h3, .dark-mode blockquote.quote-cyan h4, .dark-mode blockquote.quote-cyan h5, .dark-mode blockquote.quote-cyan h6 { color: #17a2b8; } .dark-mode blockquote.quote-white { border-color: #fff; } .dark-mode blockquote.quote-white h1, .dark-mode blockquote.quote-white h2, .dark-mode blockquote.quote-white h3, .dark-mode blockquote.quote-white h4, .dark-mode blockquote.quote-white h5, .dark-mode blockquote.quote-white h6 { color: #fff; } .dark-mode blockquote.quote-gray { border-color: #6c757d; } .dark-mode blockquote.quote-gray h1, .dark-mode blockquote.quote-gray h2, .dark-mode blockquote.quote-gray h3, .dark-mode blockquote.quote-gray h4, .dark-mode blockquote.quote-gray h5, .dark-mode blockquote.quote-gray h6 { color: #6c757d; } .dark-mode blockquote.quote-gray-dark { border-color: #343a40; } .dark-mode blockquote.quote-gray-dark h1, .dark-mode blockquote.quote-gray-dark h2, .dark-mode blockquote.quote-gray-dark h3, .dark-mode blockquote.quote-gray-dark h4, .dark-mode blockquote.quote-gray-dark h5, .dark-mode blockquote.quote-gray-dark h6 { color: #343a40; } .dark-mode .close, .dark-mode .mailbox-attachment-close { color: #adb5bd; text-shadow: 0 1px 0 #495057; } .dark-mode .tab-custom-content { border-color: #6c757d; } .dark-mode .list-group-item { background-color: #343a40; border-color: #6c757d; } @media print { .no-print, .main-sidebar, .main-header, .content-header { display: none !important; } .content-wrapper, .main-footer { -webkit-transform: translate(0, 0); transform: translate(0, 0); margin-left: 0 !important; min-height: 0 !important; } .layout-fixed .content-wrapper { padding-top: 0 !important; } .invoice { border: 0; margin: 0; padding: 0; width: 100%; } .invoice-col { float: left; width: 33.3333333%; } .table-responsive { overflow: auto; } .table-responsive > .table tr th, .table-responsive > .table tr td { white-space: normal !important; } } .text-bold, .text-bold.table td, .text-bold.table th { font-weight: 700; } .text-xs { font-size: 0.75rem !important; } .text-sm { font-size: 0.875rem !important; } .text-md { font-size: 1rem !important; } .text-lg { font-size: 1.25rem !important; } .text-xl { font-size: 2rem !important; } .text-lightblue { color: #3c8dbc !important; } .text-navy { color: #001f3f !important; } .text-olive { color: #3d9970 !important; } .text-lime { color: #01ff70 !important; } .text-fuchsia { color: #f012be !important; } .text-maroon { color: #d81b60 !important; } .text-blue { color: #007bff !important; } .text-indigo { color: #6610f2 !important; } .text-purple { color: #6f42c1 !important; } .text-pink { color: #e83e8c !important; } .text-red { color: #dc3545 !important; } .text-orange { color: #fd7e14 !important; } .text-yellow { color: #ffc107 !important; } .text-green { color: #28a745 !important; } .text-teal { color: #20c997 !important; } .text-cyan { color: #17a2b8 !important; } .text-white { color: #fff !important; } .text-gray { color: #6c757d !important; } .text-gray-dark { color: #343a40 !important; } .dark-mode .text-muted { color: #adb5bd !important; } .dark-mode .text-lightblue { color: #86bad8 !important; } .dark-mode .text-navy { color: #002c59 !important; } .dark-mode .text-olive { color: #74c8a3 !important; } .dark-mode .text-lime { color: #67ffa9 !important; } .dark-mode .text-fuchsia { color: #f672d8 !important; } .dark-mode .text-maroon { color: #ed6c9b !important; } .dark-mode .text-blue { color: #3f6791 !important; } .dark-mode .text-indigo { color: #6610f2 !important; } .dark-mode .text-purple { color: #6f42c1 !important; } .dark-mode .text-pink { color: #e83e8c !important; } .dark-mode .text-red { color: #e74c3c !important; } .dark-mode .text-orange { color: #fd7e14 !important; } .dark-mode .text-yellow { color: #f39c12 !important; } .dark-mode .text-green { color: #00bc8c !important; } .dark-mode .text-teal { color: #20c997 !important; } .dark-mode .text-cyan { color: #3498db !important; } .dark-mode .text-white { color: #fff !important; } .dark-mode .text-gray { color: #6c757d !important; } .dark-mode .text-gray-dark { color: #343a40 !important; } .elevation-0 { box-shadow: none !important; } .elevation-1 { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important; } .elevation-2 { box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-3 { box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-4 { box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22) !important; } .elevation-5 { box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22) !important; } .bg-primary { background-color: #007bff !important; } .bg-primary, .bg-primary > a { color: #fff !important; } .bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .bg-primary.btn:not(:disabled):not(.disabled):active, .bg-primary.btn:not(:disabled):not(.disabled).active, .bg-primary.btn:active, .bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-secondary { background-color: #6c757d !important; } .bg-secondary, .bg-secondary > a { color: #fff !important; } .bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .bg-secondary.btn:not(:disabled):not(.disabled):active, .bg-secondary.btn:not(:disabled):not(.disabled).active, .bg-secondary.btn:active, .bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-success { background-color: #28a745 !important; } .bg-success, .bg-success > a { color: #fff !important; } .bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-success.btn:not(:disabled):not(.disabled):active, .bg-success.btn:not(:disabled):not(.disabled).active, .bg-success.btn:active, .bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-info { background-color: #17a2b8 !important; } .bg-info, .bg-info > a { color: #fff !important; } .bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .bg-info.btn:not(:disabled):not(.disabled):active, .bg-info.btn:not(:disabled):not(.disabled).active, .bg-info.btn:active, .bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-warning { background-color: #ffc107 !important; } .bg-warning, .bg-warning > a { color: #1f2d3d !important; } .bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .bg-warning.btn:not(:disabled):not(.disabled):active, .bg-warning.btn:not(:disabled):not(.disabled).active, .bg-warning.btn:active, .bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-danger { background-color: #dc3545 !important; } .bg-danger, .bg-danger > a { color: #fff !important; } .bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .bg-danger.btn:not(:disabled):not(.disabled):active, .bg-danger.btn:not(:disabled):not(.disabled).active, .bg-danger.btn:active, .bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-light { background-color: #f8f9fa !important; } .bg-light, .bg-light > a { color: #1f2d3d !important; } .bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .bg-light.btn:not(:disabled):not(.disabled):active, .bg-light.btn:not(:disabled):not(.disabled).active, .bg-light.btn:active, .bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .bg-dark { background-color: #343a40 !important; } .bg-dark, .bg-dark > a { color: #fff !important; } .bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-dark.btn:not(:disabled):not(.disabled):active, .bg-dark.btn:not(:disabled):not(.disabled).active, .bg-dark.btn:active, .bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .bg-lightblue { background-color: #3c8dbc !important; } .bg-lightblue, .bg-lightblue > a { color: #fff !important; } .bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .bg-lightblue.btn:not(:disabled):not(.disabled):active, .bg-lightblue.btn:not(:disabled):not(.disabled).active, .bg-lightblue.btn:active, .bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .bg-navy { background-color: #001f3f !important; } .bg-navy, .bg-navy > a { color: #fff !important; } .bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .bg-navy.btn:not(:disabled):not(.disabled):active, .bg-navy.btn:not(:disabled):not(.disabled).active, .bg-navy.btn:active, .bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .bg-olive { background-color: #3d9970 !important; } .bg-olive, .bg-olive > a { color: #fff !important; } .bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .bg-olive.btn:not(:disabled):not(.disabled):active, .bg-olive.btn:not(:disabled):not(.disabled).active, .bg-olive.btn:active, .bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .bg-lime { background-color: #01ff70 !important; } .bg-lime, .bg-lime > a { color: #1f2d3d !important; } .bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .bg-lime.btn:not(:disabled):not(.disabled):active, .bg-lime.btn:not(:disabled):not(.disabled).active, .bg-lime.btn:active, .bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .bg-fuchsia { background-color: #f012be !important; } .bg-fuchsia, .bg-fuchsia > a { color: #fff !important; } .bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .bg-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-fuchsia.btn:active, .bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .bg-maroon { background-color: #d81b60 !important; } .bg-maroon, .bg-maroon > a { color: #fff !important; } .bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .bg-maroon.btn:not(:disabled):not(.disabled):active, .bg-maroon.btn:not(:disabled):not(.disabled).active, .bg-maroon.btn:active, .bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .bg-blue { background-color: #007bff !important; } .bg-blue, .bg-blue > a { color: #fff !important; } .bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .bg-blue.btn:not(:disabled):not(.disabled):active, .bg-blue.btn:not(:disabled):not(.disabled).active, .bg-blue.btn:active, .bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-indigo { background-color: #6610f2 !important; } .bg-indigo, .bg-indigo > a { color: #fff !important; } .bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .bg-indigo.btn:not(:disabled):not(.disabled):active, .bg-indigo.btn:not(:disabled):not(.disabled).active, .bg-indigo.btn:active, .bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .bg-purple { background-color: #6f42c1 !important; } .bg-purple, .bg-purple > a { color: #fff !important; } .bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .bg-purple.btn:not(:disabled):not(.disabled):active, .bg-purple.btn:not(:disabled):not(.disabled).active, .bg-purple.btn:active, .bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .bg-pink { background-color: #e83e8c !important; } .bg-pink, .bg-pink > a { color: #fff !important; } .bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .bg-pink.btn:not(:disabled):not(.disabled):active, .bg-pink.btn:not(:disabled):not(.disabled).active, .bg-pink.btn:active, .bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .bg-red { background-color: #dc3545 !important; } .bg-red, .bg-red > a { color: #fff !important; } .bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .bg-red.btn:not(:disabled):not(.disabled):active, .bg-red.btn:not(:disabled):not(.disabled).active, .bg-red.btn:active, .bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-orange { background-color: #fd7e14 !important; } .bg-orange, .bg-orange > a { color: #1f2d3d !important; } .bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .bg-orange.btn:not(:disabled):not(.disabled):active, .bg-orange.btn:not(:disabled):not(.disabled).active, .bg-orange.btn:active, .bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .bg-yellow { background-color: #ffc107 !important; } .bg-yellow, .bg-yellow > a { color: #1f2d3d !important; } .bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .bg-yellow.btn:not(:disabled):not(.disabled):active, .bg-yellow.btn:not(:disabled):not(.disabled).active, .bg-yellow.btn:active, .bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-green { background-color: #28a745 !important; } .bg-green, .bg-green > a { color: #fff !important; } .bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-green.btn:not(:disabled):not(.disabled):active, .bg-green.btn:not(:disabled):not(.disabled).active, .bg-green.btn:active, .bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-teal { background-color: #20c997 !important; } .bg-teal, .bg-teal > a { color: #fff !important; } .bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .bg-teal.btn:not(:disabled):not(.disabled):active, .bg-teal.btn:not(:disabled):not(.disabled).active, .bg-teal.btn:active, .bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .bg-cyan { background-color: #17a2b8 !important; } .bg-cyan, .bg-cyan > a { color: #fff !important; } .bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .bg-cyan.btn:not(:disabled):not(.disabled):active, .bg-cyan.btn:not(:disabled):not(.disabled).active, .bg-cyan.btn:active, .bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-white { background-color: #fff !important; } .bg-white, .bg-white > a { color: #1f2d3d !important; } .bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .bg-white.btn:not(:disabled):not(.disabled):active, .bg-white.btn:not(:disabled):not(.disabled).active, .bg-white.btn:active, .bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gray { background-color: #6c757d !important; } .bg-gray, .bg-gray > a { color: #fff !important; } .bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .bg-gray.btn:not(:disabled):not(.disabled):active, .bg-gray.btn:not(:disabled):not(.disabled).active, .bg-gray.btn:active, .bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-gray-dark { background-color: #343a40 !important; } .bg-gray-dark, .bg-gray-dark > a { color: #fff !important; } .bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gray-dark.btn:active, .bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } @media print { .table td.bg-primary, .table th.bg-primary { background-color: #007bff !important; } .table td.bg-primary, .table td.bg-primary > a, .table th.bg-primary, .table th.bg-primary > a { color: #fff !important; } .table td.bg-primary.btn:hover, .table th.bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-primary.btn:not(:disabled):not(.disabled):active, .table td.bg-primary.btn:not(:disabled):not(.disabled).active, .table td.bg-primary.btn:active, .table td.bg-primary.btn.active, .table th.bg-primary.btn:not(:disabled):not(.disabled):active, .table th.bg-primary.btn:not(:disabled):not(.disabled).active, .table th.bg-primary.btn:active, .table th.bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-secondary, .table th.bg-secondary { background-color: #6c757d !important; } .table td.bg-secondary, .table td.bg-secondary > a, .table th.bg-secondary, .table th.bg-secondary > a { color: #fff !important; } .table td.bg-secondary.btn:hover, .table th.bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-secondary.btn:not(:disabled):not(.disabled):active, .table td.bg-secondary.btn:not(:disabled):not(.disabled).active, .table td.bg-secondary.btn:active, .table td.bg-secondary.btn.active, .table th.bg-secondary.btn:not(:disabled):not(.disabled):active, .table th.bg-secondary.btn:not(:disabled):not(.disabled).active, .table th.bg-secondary.btn:active, .table th.bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-success, .table th.bg-success { background-color: #28a745 !important; } .table td.bg-success, .table td.bg-success > a, .table th.bg-success, .table th.bg-success > a { color: #fff !important; } .table td.bg-success.btn:hover, .table th.bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-success.btn:not(:disabled):not(.disabled):active, .table td.bg-success.btn:not(:disabled):not(.disabled).active, .table td.bg-success.btn:active, .table td.bg-success.btn.active, .table th.bg-success.btn:not(:disabled):not(.disabled):active, .table th.bg-success.btn:not(:disabled):not(.disabled).active, .table th.bg-success.btn:active, .table th.bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-info, .table th.bg-info { background-color: #17a2b8 !important; } .table td.bg-info, .table td.bg-info > a, .table th.bg-info, .table th.bg-info > a { color: #fff !important; } .table td.bg-info.btn:hover, .table th.bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-info.btn:not(:disabled):not(.disabled):active, .table td.bg-info.btn:not(:disabled):not(.disabled).active, .table td.bg-info.btn:active, .table td.bg-info.btn.active, .table th.bg-info.btn:not(:disabled):not(.disabled):active, .table th.bg-info.btn:not(:disabled):not(.disabled).active, .table th.bg-info.btn:active, .table th.bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-warning, .table th.bg-warning { background-color: #ffc107 !important; } .table td.bg-warning, .table td.bg-warning > a, .table th.bg-warning, .table th.bg-warning > a { color: #1f2d3d !important; } .table td.bg-warning.btn:hover, .table th.bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-warning.btn:not(:disabled):not(.disabled):active, .table td.bg-warning.btn:not(:disabled):not(.disabled).active, .table td.bg-warning.btn:active, .table td.bg-warning.btn.active, .table th.bg-warning.btn:not(:disabled):not(.disabled):active, .table th.bg-warning.btn:not(:disabled):not(.disabled).active, .table th.bg-warning.btn:active, .table th.bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-danger, .table th.bg-danger { background-color: #dc3545 !important; } .table td.bg-danger, .table td.bg-danger > a, .table th.bg-danger, .table th.bg-danger > a { color: #fff !important; } .table td.bg-danger.btn:hover, .table th.bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-danger.btn:not(:disabled):not(.disabled):active, .table td.bg-danger.btn:not(:disabled):not(.disabled).active, .table td.bg-danger.btn:active, .table td.bg-danger.btn.active, .table th.bg-danger.btn:not(:disabled):not(.disabled):active, .table th.bg-danger.btn:not(:disabled):not(.disabled).active, .table th.bg-danger.btn:active, .table th.bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-light, .table th.bg-light { background-color: #f8f9fa !important; } .table td.bg-light, .table td.bg-light > a, .table th.bg-light, .table th.bg-light > a { color: #1f2d3d !important; } .table td.bg-light.btn:hover, .table th.bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .table td.bg-light.btn:not(:disabled):not(.disabled):active, .table td.bg-light.btn:not(:disabled):not(.disabled).active, .table td.bg-light.btn:active, .table td.bg-light.btn.active, .table th.bg-light.btn:not(:disabled):not(.disabled):active, .table th.bg-light.btn:not(:disabled):not(.disabled).active, .table th.bg-light.btn:active, .table th.bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .table td.bg-dark, .table th.bg-dark { background-color: #343a40 !important; } .table td.bg-dark, .table td.bg-dark > a, .table th.bg-dark, .table th.bg-dark > a { color: #fff !important; } .table td.bg-dark.btn:hover, .table th.bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-dark.btn:active, .table td.bg-dark.btn.active, .table th.bg-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-dark.btn:active, .table th.bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .table td.bg-lightblue, .table th.bg-lightblue { background-color: #3c8dbc !important; } .table td.bg-lightblue, .table td.bg-lightblue > a, .table th.bg-lightblue, .table th.bg-lightblue > a { color: #fff !important; } .table td.bg-lightblue.btn:hover, .table th.bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .table td.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table td.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table td.bg-lightblue.btn:active, .table td.bg-lightblue.btn.active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table th.bg-lightblue.btn:active, .table th.bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .table td.bg-navy, .table th.bg-navy { background-color: #001f3f !important; } .table td.bg-navy, .table td.bg-navy > a, .table th.bg-navy, .table th.bg-navy > a { color: #fff !important; } .table td.bg-navy.btn:hover, .table th.bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .table td.bg-navy.btn:not(:disabled):not(.disabled):active, .table td.bg-navy.btn:not(:disabled):not(.disabled).active, .table td.bg-navy.btn:active, .table td.bg-navy.btn.active, .table th.bg-navy.btn:not(:disabled):not(.disabled):active, .table th.bg-navy.btn:not(:disabled):not(.disabled).active, .table th.bg-navy.btn:active, .table th.bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .table td.bg-olive, .table th.bg-olive { background-color: #3d9970 !important; } .table td.bg-olive, .table td.bg-olive > a, .table th.bg-olive, .table th.bg-olive > a { color: #fff !important; } .table td.bg-olive.btn:hover, .table th.bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .table td.bg-olive.btn:not(:disabled):not(.disabled):active, .table td.bg-olive.btn:not(:disabled):not(.disabled).active, .table td.bg-olive.btn:active, .table td.bg-olive.btn.active, .table th.bg-olive.btn:not(:disabled):not(.disabled):active, .table th.bg-olive.btn:not(:disabled):not(.disabled).active, .table th.bg-olive.btn:active, .table th.bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .table td.bg-lime, .table th.bg-lime { background-color: #01ff70 !important; } .table td.bg-lime, .table td.bg-lime > a, .table th.bg-lime, .table th.bg-lime > a { color: #1f2d3d !important; } .table td.bg-lime.btn:hover, .table th.bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .table td.bg-lime.btn:not(:disabled):not(.disabled):active, .table td.bg-lime.btn:not(:disabled):not(.disabled).active, .table td.bg-lime.btn:active, .table td.bg-lime.btn.active, .table th.bg-lime.btn:not(:disabled):not(.disabled):active, .table th.bg-lime.btn:not(:disabled):not(.disabled).active, .table th.bg-lime.btn:active, .table th.bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .table td.bg-fuchsia, .table th.bg-fuchsia { background-color: #f012be !important; } .table td.bg-fuchsia, .table td.bg-fuchsia > a, .table th.bg-fuchsia, .table th.bg-fuchsia > a { color: #fff !important; } .table td.bg-fuchsia.btn:hover, .table th.bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .table td.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table td.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table td.bg-fuchsia.btn:active, .table td.bg-fuchsia.btn.active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table th.bg-fuchsia.btn:active, .table th.bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .table td.bg-maroon, .table th.bg-maroon { background-color: #d81b60 !important; } .table td.bg-maroon, .table td.bg-maroon > a, .table th.bg-maroon, .table th.bg-maroon > a { color: #fff !important; } .table td.bg-maroon.btn:hover, .table th.bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .table td.bg-maroon.btn:not(:disabled):not(.disabled):active, .table td.bg-maroon.btn:not(:disabled):not(.disabled).active, .table td.bg-maroon.btn:active, .table td.bg-maroon.btn.active, .table th.bg-maroon.btn:not(:disabled):not(.disabled):active, .table th.bg-maroon.btn:not(:disabled):not(.disabled).active, .table th.bg-maroon.btn:active, .table th.bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .table td.bg-blue, .table th.bg-blue { background-color: #007bff !important; } .table td.bg-blue, .table td.bg-blue > a, .table th.bg-blue, .table th.bg-blue > a { color: #fff !important; } .table td.bg-blue.btn:hover, .table th.bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-blue.btn:not(:disabled):not(.disabled):active, .table td.bg-blue.btn:not(:disabled):not(.disabled).active, .table td.bg-blue.btn:active, .table td.bg-blue.btn.active, .table th.bg-blue.btn:not(:disabled):not(.disabled):active, .table th.bg-blue.btn:not(:disabled):not(.disabled).active, .table th.bg-blue.btn:active, .table th.bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-indigo, .table th.bg-indigo { background-color: #6610f2 !important; } .table td.bg-indigo, .table td.bg-indigo > a, .table th.bg-indigo, .table th.bg-indigo > a { color: #fff !important; } .table td.bg-indigo.btn:hover, .table th.bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .table td.bg-indigo.btn:not(:disabled):not(.disabled):active, .table td.bg-indigo.btn:not(:disabled):not(.disabled).active, .table td.bg-indigo.btn:active, .table td.bg-indigo.btn.active, .table th.bg-indigo.btn:not(:disabled):not(.disabled):active, .table th.bg-indigo.btn:not(:disabled):not(.disabled).active, .table th.bg-indigo.btn:active, .table th.bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .table td.bg-purple, .table th.bg-purple { background-color: #6f42c1 !important; } .table td.bg-purple, .table td.bg-purple > a, .table th.bg-purple, .table th.bg-purple > a { color: #fff !important; } .table td.bg-purple.btn:hover, .table th.bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .table td.bg-purple.btn:not(:disabled):not(.disabled):active, .table td.bg-purple.btn:not(:disabled):not(.disabled).active, .table td.bg-purple.btn:active, .table td.bg-purple.btn.active, .table th.bg-purple.btn:not(:disabled):not(.disabled):active, .table th.bg-purple.btn:not(:disabled):not(.disabled).active, .table th.bg-purple.btn:active, .table th.bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .table td.bg-pink, .table th.bg-pink { background-color: #e83e8c !important; } .table td.bg-pink, .table td.bg-pink > a, .table th.bg-pink, .table th.bg-pink > a { color: #fff !important; } .table td.bg-pink.btn:hover, .table th.bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .table td.bg-pink.btn:not(:disabled):not(.disabled):active, .table td.bg-pink.btn:not(:disabled):not(.disabled).active, .table td.bg-pink.btn:active, .table td.bg-pink.btn.active, .table th.bg-pink.btn:not(:disabled):not(.disabled):active, .table th.bg-pink.btn:not(:disabled):not(.disabled).active, .table th.bg-pink.btn:active, .table th.bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .table td.bg-red, .table th.bg-red { background-color: #dc3545 !important; } .table td.bg-red, .table td.bg-red > a, .table th.bg-red, .table th.bg-red > a { color: #fff !important; } .table td.bg-red.btn:hover, .table th.bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-red.btn:not(:disabled):not(.disabled):active, .table td.bg-red.btn:not(:disabled):not(.disabled).active, .table td.bg-red.btn:active, .table td.bg-red.btn.active, .table th.bg-red.btn:not(:disabled):not(.disabled):active, .table th.bg-red.btn:not(:disabled):not(.disabled).active, .table th.bg-red.btn:active, .table th.bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-orange, .table th.bg-orange { background-color: #fd7e14 !important; } .table td.bg-orange, .table td.bg-orange > a, .table th.bg-orange, .table th.bg-orange > a { color: #1f2d3d !important; } .table td.bg-orange.btn:hover, .table th.bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .table td.bg-orange.btn:not(:disabled):not(.disabled):active, .table td.bg-orange.btn:not(:disabled):not(.disabled).active, .table td.bg-orange.btn:active, .table td.bg-orange.btn.active, .table th.bg-orange.btn:not(:disabled):not(.disabled):active, .table th.bg-orange.btn:not(:disabled):not(.disabled).active, .table th.bg-orange.btn:active, .table th.bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .table td.bg-yellow, .table th.bg-yellow { background-color: #ffc107 !important; } .table td.bg-yellow, .table td.bg-yellow > a, .table th.bg-yellow, .table th.bg-yellow > a { color: #1f2d3d !important; } .table td.bg-yellow.btn:hover, .table th.bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-yellow.btn:not(:disabled):not(.disabled):active, .table td.bg-yellow.btn:not(:disabled):not(.disabled).active, .table td.bg-yellow.btn:active, .table td.bg-yellow.btn.active, .table th.bg-yellow.btn:not(:disabled):not(.disabled):active, .table th.bg-yellow.btn:not(:disabled):not(.disabled).active, .table th.bg-yellow.btn:active, .table th.bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-green, .table th.bg-green { background-color: #28a745 !important; } .table td.bg-green, .table td.bg-green > a, .table th.bg-green, .table th.bg-green > a { color: #fff !important; } .table td.bg-green.btn:hover, .table th.bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-green.btn:not(:disabled):not(.disabled):active, .table td.bg-green.btn:not(:disabled):not(.disabled).active, .table td.bg-green.btn:active, .table td.bg-green.btn.active, .table th.bg-green.btn:not(:disabled):not(.disabled):active, .table th.bg-green.btn:not(:disabled):not(.disabled).active, .table th.bg-green.btn:active, .table th.bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-teal, .table th.bg-teal { background-color: #20c997 !important; } .table td.bg-teal, .table td.bg-teal > a, .table th.bg-teal, .table th.bg-teal > a { color: #fff !important; } .table td.bg-teal.btn:hover, .table th.bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .table td.bg-teal.btn:not(:disabled):not(.disabled):active, .table td.bg-teal.btn:not(:disabled):not(.disabled).active, .table td.bg-teal.btn:active, .table td.bg-teal.btn.active, .table th.bg-teal.btn:not(:disabled):not(.disabled):active, .table th.bg-teal.btn:not(:disabled):not(.disabled).active, .table th.bg-teal.btn:active, .table th.bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .table td.bg-cyan, .table th.bg-cyan { background-color: #17a2b8 !important; } .table td.bg-cyan, .table td.bg-cyan > a, .table th.bg-cyan, .table th.bg-cyan > a { color: #fff !important; } .table td.bg-cyan.btn:hover, .table th.bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-cyan.btn:not(:disabled):not(.disabled):active, .table td.bg-cyan.btn:not(:disabled):not(.disabled).active, .table td.bg-cyan.btn:active, .table td.bg-cyan.btn.active, .table th.bg-cyan.btn:not(:disabled):not(.disabled):active, .table th.bg-cyan.btn:not(:disabled):not(.disabled).active, .table th.bg-cyan.btn:active, .table th.bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-white, .table th.bg-white { background-color: #fff !important; } .table td.bg-white, .table td.bg-white > a, .table th.bg-white, .table th.bg-white > a { color: #1f2d3d !important; } .table td.bg-white.btn:hover, .table th.bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .table td.bg-white.btn:not(:disabled):not(.disabled):active, .table td.bg-white.btn:not(:disabled):not(.disabled).active, .table td.bg-white.btn:active, .table td.bg-white.btn.active, .table th.bg-white.btn:not(:disabled):not(.disabled):active, .table th.bg-white.btn:not(:disabled):not(.disabled).active, .table th.bg-white.btn:active, .table th.bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .table td.bg-gray, .table th.bg-gray { background-color: #6c757d !important; } .table td.bg-gray, .table td.bg-gray > a, .table th.bg-gray, .table th.bg-gray > a { color: #fff !important; } .table td.bg-gray.btn:hover, .table th.bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-gray.btn:not(:disabled):not(.disabled):active, .table td.bg-gray.btn:not(:disabled):not(.disabled).active, .table td.bg-gray.btn:active, .table td.bg-gray.btn.active, .table th.bg-gray.btn:not(:disabled):not(.disabled):active, .table th.bg-gray.btn:not(:disabled):not(.disabled).active, .table th.bg-gray.btn:active, .table th.bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-gray-dark, .table th.bg-gray-dark { background-color: #343a40 !important; } .table td.bg-gray-dark, .table td.bg-gray-dark > a, .table th.bg-gray-dark, .table th.bg-gray-dark > a { color: #fff !important; } .table td.bg-gray-dark.btn:hover, .table th.bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-gray-dark.btn:active, .table td.bg-gray-dark.btn.active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-gray-dark.btn:active, .table th.bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } } .bg-gray { background-color: #adb5bd; color: #1f2d3d; } .bg-gray-light { background-color: #f2f4f5; color: #1f2d3d !important; } .bg-black { background-color: #000; color: #fff !important; } .bg-white { background-color: #fff; color: #1f2d3d !important; } .bg-gradient-primary { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-primary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-primary.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .bg-gradient-primary.btn:active, .bg-gradient-primary.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-primary.btn:disabled, .bg-gradient-primary.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-secondary { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-secondary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-secondary.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .bg-gradient-secondary.btn:active, .bg-gradient-secondary.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-secondary.btn:disabled, .bg-gradient-secondary.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-success { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-success.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-success.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .bg-gradient-success.btn:active, .bg-gradient-success.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-success.btn:disabled, .bg-gradient-success.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-info { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-info.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-info.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .bg-gradient-info.btn:active, .bg-gradient-info.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-info.btn:disabled, .bg-gradient-info.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-warning { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-warning.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-warning.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .bg-gradient-warning.btn:active, .bg-gradient-warning.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-warning.btn:disabled, .bg-gradient-warning.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-danger { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-danger.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-danger.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .bg-gradient-danger.btn:active, .bg-gradient-danger.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-danger.btn:disabled, .bg-gradient-danger.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-light { background: #f8f9fa linear-gradient(180deg, #f9fafb, #f8f9fa) repeat-x !important; color: #1f2d3d; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-light.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-light.btn:hover { background: #f8f9fa linear-gradient(180deg, #e6eaed, #e2e6ea) repeat-x !important; border-color: #dae0e5; color: #121a24; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .bg-gradient-light.btn:active, .bg-gradient-light.btn.active { background: #f8f9fa linear-gradient(180deg, #e0e4e9, #dae0e5) repeat-x !important; border-color: #d3d9df; color: #1f2d3d; } .bg-gradient-light.btn:disabled, .bg-gradient-light.btn.disabled { background-image: none !important; border-color: #f8f9fa; color: #1f2d3d; } .bg-gradient-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-dark.btn:active, .bg-gradient-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-dark.btn:disabled, .bg-gradient-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .bg-gradient-lightblue { background: #3c8dbc linear-gradient(180deg, #599ec6, #3c8dbc) repeat-x !important; color: #fff; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lightblue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lightblue.btn:hover { background: #3c8dbc linear-gradient(180deg, #518cad, #33779f) repeat-x !important; border-color: #307095; color: #ececec; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .bg-gradient-lightblue.btn:active, .bg-gradient-lightblue.btn.active { background: #3c8dbc linear-gradient(180deg, #4f85a5, #307095) repeat-x !important; border-color: #2d698c; color: #fff; } .bg-gradient-lightblue.btn:disabled, .bg-gradient-lightblue.btn.disabled { background-image: none !important; border-color: #3c8dbc; color: #fff; } .bg-gradient-navy { background: #001f3f linear-gradient(180deg, #26415c, #001f3f) repeat-x !important; color: #fff; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-navy.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-navy.btn:hover { background: #001f3f linear-gradient(180deg, #26313b, #000c19) repeat-x !important; border-color: #00060c; color: #ececec; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .bg-gradient-navy.btn:active, .bg-gradient-navy.btn.active { background: #001f3f linear-gradient(180deg, #262b30, #00060c) repeat-x !important; border-color: black; color: #fff; } .bg-gradient-navy.btn:disabled, .bg-gradient-navy.btn.disabled { background-image: none !important; border-color: #001f3f; color: #fff; } .bg-gradient-olive { background: #3d9970 linear-gradient(180deg, #5aa885, #3d9970) repeat-x !important; color: #fff; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-olive.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-olive.btn:hover { background: #3d9970 linear-gradient(180deg, #519174, #327e5c) repeat-x !important; border-color: #2e7555; color: #ececec; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .bg-gradient-olive.btn:active, .bg-gradient-olive.btn.active { background: #3d9970 linear-gradient(180deg, #4e896f, #2e7555) repeat-x !important; border-color: #2b6b4f; color: #fff; } .bg-gradient-olive.btn:disabled, .bg-gradient-olive.btn.disabled { background-image: none !important; border-color: #3d9970; color: #fff; } .bg-gradient-lime { background: #01ff70 linear-gradient(180deg, #27ff85, #01ff70) repeat-x !important; color: #1f2d3d; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lime.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lime.btn:hover { background: #01ff70 linear-gradient(180deg, #26df77, #00da5f) repeat-x !important; border-color: #00cd5a; color: #121a24; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .bg-gradient-lime.btn:active, .bg-gradient-lime.btn.active { background: #01ff70 linear-gradient(180deg, #26d572, #00cd5a) repeat-x !important; border-color: #00c054; color: #fff; } .bg-gradient-lime.btn:disabled, .bg-gradient-lime.btn.disabled { background-image: none !important; border-color: #01ff70; color: #1f2d3d; } .bg-gradient-fuchsia { background: #f012be linear-gradient(180deg, #f236c8, #f012be) repeat-x !important; color: #fff; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-fuchsia.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-fuchsia.btn:hover { background: #f012be linear-gradient(180deg, #d631b1, #cf0da3) repeat-x !important; border-color: #c30c9a; color: #ececec; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-gradient-fuchsia.btn:active, .bg-gradient-fuchsia.btn.active { background: #f012be linear-gradient(180deg, #cc31a9, #c30c9a) repeat-x !important; border-color: #b70c90; color: #fff; } .bg-gradient-fuchsia.btn:disabled, .bg-gradient-fuchsia.btn.disabled { background-image: none !important; border-color: #f012be; color: #fff; } .bg-gradient-maroon { background: #d81b60 linear-gradient(180deg, #de3d78, #d81b60) repeat-x !important; color: #fff; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-maroon.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-maroon.btn:hover { background: #d81b60 linear-gradient(180deg, #c13a6b, #b61751) repeat-x !important; border-color: #ab154c; color: #ececec; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .bg-gradient-maroon.btn:active, .bg-gradient-maroon.btn.active { background: #d81b60 linear-gradient(180deg, #b73867, #ab154c) repeat-x !important; border-color: #9f1447; color: #fff; } .bg-gradient-maroon.btn:disabled, .bg-gradient-maroon.btn.disabled { background-image: none !important; border-color: #d81b60; color: #fff; } .bg-gradient-blue { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-blue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-blue.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .bg-gradient-blue.btn:active, .bg-gradient-blue.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-blue.btn:disabled, .bg-gradient-blue.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-indigo { background: #6610f2 linear-gradient(180deg, #7d34f4, #6610f2) repeat-x !important; color: #fff; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-indigo.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-indigo.btn:hover { background: #6610f2 linear-gradient(180deg, #7030d7, #560bd0) repeat-x !important; border-color: #510bc4; color: #ececec; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .bg-gradient-indigo.btn:active, .bg-gradient-indigo.btn.active { background: #6610f2 linear-gradient(180deg, #6b2fcd, #510bc4) repeat-x !important; border-color: #4c0ab8; color: #fff; } .bg-gradient-indigo.btn:disabled, .bg-gradient-indigo.btn.disabled { background-image: none !important; border-color: #6610f2; color: #fff; } .bg-gradient-purple { background: #6f42c1 linear-gradient(180deg, #855eca, #6f42c1) repeat-x !important; color: #fff; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-purple.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-purple.btn:hover { background: #6f42c1 linear-gradient(180deg, #7655b4, #5e37a6) repeat-x !important; border-color: #59339d; color: #ececec; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .bg-gradient-purple.btn:active, .bg-gradient-purple.btn.active { background: #6f42c1 linear-gradient(180deg, #7252ab, #59339d) repeat-x !important; border-color: #533093; color: #fff; } .bg-gradient-purple.btn:disabled, .bg-gradient-purple.btn.disabled { background-image: none !important; border-color: #6f42c1; color: #fff; } .bg-gradient-pink { background: #e83e8c linear-gradient(180deg, #eb5b9d, #e83e8c) repeat-x !important; color: #fff; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-pink.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-pink.btn:hover { background: #e83e8c linear-gradient(180deg, #e83e8c, #e41c78) repeat-x !important; border-color: #d91a72; color: #ececec; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .bg-gradient-pink.btn:active, .bg-gradient-pink.btn.active { background: #e83e8c linear-gradient(180deg, #df3c87, #d91a72) repeat-x !important; border-color: #ce196c; color: #fff; } .bg-gradient-pink.btn:disabled, .bg-gradient-pink.btn.disabled { background-image: none !important; border-color: #e83e8c; color: #fff; } .bg-gradient-red { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-red.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-red.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .bg-gradient-red.btn:active, .bg-gradient-red.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-red.btn:disabled, .bg-gradient-red.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-orange { background: #fd7e14 linear-gradient(180deg, #fd9137, #fd7e14) repeat-x !important; color: #1f2d3d; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-orange.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-orange.btn:hover { background: #fd7e14 linear-gradient(180deg, #ec8128, #e96b02) repeat-x !important; border-color: #dc6502; color: #121a24; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .bg-gradient-orange.btn:active, .bg-gradient-orange.btn.active { background: #fd7e14 linear-gradient(180deg, #e17c28, #dc6502) repeat-x !important; border-color: #cf5f02; color: #fff; } .bg-gradient-orange.btn:disabled, .bg-gradient-orange.btn.disabled { background-image: none !important; border-color: #fd7e14; color: #1f2d3d; } .bg-gradient-yellow { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-yellow.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-yellow.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .bg-gradient-yellow.btn:active, .bg-gradient-yellow.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-yellow.btn:disabled, .bg-gradient-yellow.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-green { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-green.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-green.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .bg-gradient-green.btn:active, .bg-gradient-green.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-green.btn:disabled, .bg-gradient-green.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-teal { background: #20c997 linear-gradient(180deg, #41d1a7, #20c997) repeat-x !important; color: #fff; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-teal.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-teal.btn:hover { background: #20c997 linear-gradient(180deg, #3db592, #1ba87e) repeat-x !important; border-color: #199d76; color: #ececec; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .bg-gradient-teal.btn:active, .bg-gradient-teal.btn.active { background: #20c997 linear-gradient(180deg, #3bac8b, #199d76) repeat-x !important; border-color: #17926e; color: #fff; } .bg-gradient-teal.btn:disabled, .bg-gradient-teal.btn.disabled { background-image: none !important; border-color: #20c997; color: #fff; } .bg-gradient-cyan { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-cyan.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-cyan.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .bg-gradient-cyan.btn:active, .bg-gradient-cyan.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-cyan.btn:disabled, .bg-gradient-cyan.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-white { background: #fff linear-gradient(180deg, white, #fff) repeat-x !important; color: #1f2d3d; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-white.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-white.btn:hover { background: #fff linear-gradient(180deg, #efefef, #ececec) repeat-x !important; border-color: #e6e6e6; color: #121a24; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .bg-gradient-white.btn:active, .bg-gradient-white.btn.active { background: #fff linear-gradient(180deg, #e9e9e9, #e6e6e6) repeat-x !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gradient-white.btn:disabled, .bg-gradient-white.btn.disabled { background-image: none !important; border-color: #fff; color: #1f2d3d; } .bg-gradient-gray { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray.btn:active, .bg-gradient-gray.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-gray.btn:disabled, .bg-gradient-gray.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-gray-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray-dark.btn:active, .bg-gradient-gray-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-gray-dark.btn:disabled, .bg-gradient-gray-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } [class^="bg-"].disabled { opacity: .65; } a.text-muted:hover { color: #007bff !important; } .link-muted { color: #5d6974; } .link-muted:hover, .link-muted:focus { color: #464f58; } .link-black { color: #6c757d; } .link-black:hover, .link-black:focus { color: #e6e8ea; } .accent-primary .btn-link, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-primary .nav-tabs .nav-link { color: #007bff; } .accent-primary .btn-link:hover, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-primary .nav-tabs .nav-link:hover { color: #0056b3; } .accent-primary .dropdown-item:active, .accent-primary .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-primary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-primary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-primary .custom-select:focus, .accent-primary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-primary .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-primary .page-item .page-link { color: #007bff; } .accent-primary .page-item.active a, .accent-primary .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-primary .page-item.disabled a, .accent-primary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-primary .page-item .page-link:hover, .dark-mode.accent-primary .page-item .page-link:focus { color: #1a88ff; } .accent-secondary .btn-link, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-secondary .nav-tabs .nav-link { color: #6c757d; } .accent-secondary .btn-link:hover, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-secondary .nav-tabs .nav-link:hover { color: #494f54; } .accent-secondary .dropdown-item:active, .accent-secondary .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-secondary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-secondary .custom-select:focus, .accent-secondary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-secondary .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-secondary .page-item .page-link { color: #6c757d; } .accent-secondary .page-item.active a, .accent-secondary .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-secondary .page-item.disabled a, .accent-secondary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-secondary .page-item .page-link:hover, .dark-mode.accent-secondary .page-item .page-link:focus { color: #78828a; } .accent-success .btn-link, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-success .nav-tabs .nav-link { color: #28a745; } .accent-success .btn-link:hover, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-success .nav-tabs .nav-link:hover { color: #19692c; } .accent-success .dropdown-item:active, .accent-success .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-success .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-success .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-success .custom-select:focus, .accent-success .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-success .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-success .page-item .page-link { color: #28a745; } .accent-success .page-item.active a, .accent-success .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-success .page-item.disabled a, .accent-success .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-success .page-item .page-link:hover, .dark-mode.accent-success .page-item .page-link:focus { color: #2dbc4e; } .accent-info .btn-link, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-info .nav-tabs .nav-link { color: #17a2b8; } .accent-info .btn-link:hover, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-info .nav-tabs .nav-link:hover { color: #0f6674; } .accent-info .dropdown-item:active, .accent-info .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-info .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-info .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-info .custom-select:focus, .accent-info .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-info .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-info .page-item .page-link { color: #17a2b8; } .accent-info .page-item.active a, .accent-info .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-info .page-item.disabled a, .accent-info .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-info .page-item .page-link:hover, .dark-mode.accent-info .page-item .page-link:focus { color: #1ab6cf; } .accent-warning .btn-link, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-warning .nav-tabs .nav-link { color: #ffc107; } .accent-warning .btn-link:hover, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-warning .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-warning .dropdown-item:active, .accent-warning .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-warning .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-warning .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-warning .custom-select:focus, .accent-warning .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-warning .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-warning .page-item .page-link { color: #ffc107; } .accent-warning .page-item.active a, .accent-warning .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-warning .page-item.disabled a, .accent-warning .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-warning .page-item .page-link:hover, .dark-mode.accent-warning .page-item .page-link:focus { color: #ffc721; } .accent-danger .btn-link, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-danger .nav-tabs .nav-link { color: #dc3545; } .accent-danger .btn-link:hover, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-danger .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-danger .dropdown-item:active, .accent-danger .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-danger .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-danger .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-danger .custom-select:focus, .accent-danger .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-danger .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-danger .page-item .page-link { color: #dc3545; } .accent-danger .page-item.active a, .accent-danger .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-danger .page-item.disabled a, .accent-danger .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-danger .page-item .page-link:hover, .dark-mode.accent-danger .page-item .page-link:focus { color: #e04b59; } .accent-light .btn-link, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-light .nav-tabs .nav-link { color: #f8f9fa; } .accent-light .btn-link:hover, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-light .nav-tabs .nav-link:hover { color: #cbd3da; } .accent-light .dropdown-item:active, .accent-light .dropdown-item.active { background-color: #f8f9fa; color: #1f2d3d; } .accent-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .accent-light .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-light .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-light .custom-select:focus, .accent-light .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-light .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-light .page-item .page-link { color: #f8f9fa; } .accent-light .page-item.active a, .accent-light .page-item.active .page-link { background-color: #f8f9fa; border-color: #f8f9fa; color: #fff; } .accent-light .page-item.disabled a, .accent-light .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-light .page-item .page-link:hover, .dark-mode.accent-light .page-item .page-link:focus { color: white; } .accent-dark .btn-link, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-dark .nav-tabs .nav-link { color: #343a40; } .accent-dark .btn-link:hover, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-dark .dropdown-item:active, .accent-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-dark .custom-select:focus, .accent-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-dark .page-item .page-link { color: #343a40; } .accent-dark .page-item.active a, .accent-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-dark .page-item.disabled a, .accent-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-dark .page-item .page-link:hover, .dark-mode.accent-dark .page-item .page-link:focus { color: #3f474e; } .accent-lightblue .btn-link, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lightblue .nav-tabs .nav-link { color: #3c8dbc; } .accent-lightblue .btn-link:hover, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lightblue .nav-tabs .nav-link:hover { color: #296282; } .accent-lightblue .dropdown-item:active, .accent-lightblue .dropdown-item.active { background-color: #3c8dbc; color: #fff; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lightblue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lightblue .custom-select:focus, .accent-lightblue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lightblue .custom-file-input:focus ~ .custom-file-label { border-color: #99c5de; } .accent-lightblue .page-item .page-link { color: #3c8dbc; } .accent-lightblue .page-item.active a, .accent-lightblue .page-item.active .page-link { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .accent-lightblue .page-item.disabled a, .accent-lightblue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-lightblue .page-item .page-link:hover, .dark-mode.accent-lightblue .page-item .page-link:focus { color: #4c99c6; } .accent-navy .btn-link, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-navy .nav-tabs .nav-link { color: #001f3f; } .accent-navy .btn-link:hover, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-navy .nav-tabs .nav-link:hover { color: black; } .accent-navy .dropdown-item:active, .accent-navy .dropdown-item.active { background-color: #001f3f; color: #fff; } .accent-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .accent-navy .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-navy .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-navy .custom-select:focus, .accent-navy .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-navy .custom-file-input:focus ~ .custom-file-label { border-color: #005ebf; } .accent-navy .page-item .page-link { color: #001f3f; } .accent-navy .page-item.active a, .accent-navy .page-item.active .page-link { background-color: #001f3f; border-color: #001f3f; color: #fff; } .accent-navy .page-item.disabled a, .accent-navy .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-navy .page-item .page-link:hover, .dark-mode.accent-navy .page-item .page-link:focus { color: #002c59; } .accent-olive .btn-link, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-olive .nav-tabs .nav-link { color: #3d9970; } .accent-olive .btn-link:hover, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-olive .nav-tabs .nav-link:hover { color: #276248; } .accent-olive .dropdown-item:active, .accent-olive .dropdown-item.active { background-color: #3d9970; color: #fff; } .accent-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .accent-olive .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-olive .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-olive .custom-select:focus, .accent-olive .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-olive .custom-file-input:focus ~ .custom-file-label { border-color: #87cfaf; } .accent-olive .page-item .page-link { color: #3d9970; } .accent-olive .page-item.active a, .accent-olive .page-item.active .page-link { background-color: #3d9970; border-color: #3d9970; color: #fff; } .accent-olive .page-item.disabled a, .accent-olive .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-olive .page-item .page-link:hover, .dark-mode.accent-olive .page-item .page-link:focus { color: #44ab7d; } .accent-lime .btn-link, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lime .nav-tabs .nav-link { color: #01ff70; } .accent-lime .btn-link:hover, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lime .nav-tabs .nav-link:hover { color: #00b44e; } .accent-lime .dropdown-item:active, .accent-lime .dropdown-item.active { background-color: #01ff70; color: #1f2d3d; } .accent-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .accent-lime .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lime .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lime .custom-select:focus, .accent-lime .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lime .custom-file-input:focus ~ .custom-file-label { border-color: #81ffb8; } .accent-lime .page-item .page-link { color: #01ff70; } .accent-lime .page-item.active a, .accent-lime .page-item.active .page-link { background-color: #01ff70; border-color: #01ff70; color: #fff; } .accent-lime .page-item.disabled a, .accent-lime .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-lime .page-item .page-link:hover, .dark-mode.accent-lime .page-item .page-link:focus { color: #1bff7e; } .accent-fuchsia .btn-link, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-fuchsia .nav-tabs .nav-link { color: #f012be; } .accent-fuchsia .btn-link:hover, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-fuchsia .nav-tabs .nav-link:hover { color: #ab0b87; } .accent-fuchsia .dropdown-item:active, .accent-fuchsia .dropdown-item.active { background-color: #f012be; color: #fff; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-fuchsia .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-fuchsia .custom-select:focus, .accent-fuchsia .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-fuchsia .custom-file-input:focus ~ .custom-file-label { border-color: #f88adf; } .accent-fuchsia .page-item .page-link { color: #f012be; } .accent-fuchsia .page-item.active a, .accent-fuchsia .page-item.active .page-link { background-color: #f012be; border-color: #f012be; color: #fff; } .accent-fuchsia .page-item.disabled a, .accent-fuchsia .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-fuchsia .page-item .page-link:hover, .dark-mode.accent-fuchsia .page-item .page-link:focus { color: #f22ac5; } .accent-maroon .btn-link, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-maroon .nav-tabs .nav-link { color: #d81b60; } .accent-maroon .btn-link:hover, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-maroon .nav-tabs .nav-link:hover { color: #941342; } .accent-maroon .dropdown-item:active, .accent-maroon .dropdown-item.active { background-color: #d81b60; color: #fff; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-maroon .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-maroon .custom-select:focus, .accent-maroon .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-maroon .custom-file-input:focus ~ .custom-file-label { border-color: #f083ab; } .accent-maroon .page-item .page-link { color: #d81b60; } .accent-maroon .page-item.active a, .accent-maroon .page-item.active .page-link { background-color: #d81b60; border-color: #d81b60; color: #fff; } .accent-maroon .page-item.disabled a, .accent-maroon .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-maroon .page-item .page-link:hover, .dark-mode.accent-maroon .page-item .page-link:focus { color: #e4286d; } .accent-blue .btn-link, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-blue .nav-tabs .nav-link { color: #007bff; } .accent-blue .btn-link:hover, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-blue .nav-tabs .nav-link:hover { color: #0056b3; } .accent-blue .dropdown-item:active, .accent-blue .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-blue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-blue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-blue .custom-select:focus, .accent-blue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-blue .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-blue .page-item .page-link { color: #007bff; } .accent-blue .page-item.active a, .accent-blue .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-blue .page-item.disabled a, .accent-blue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-blue .page-item .page-link:hover, .dark-mode.accent-blue .page-item .page-link:focus { color: #1a88ff; } .accent-indigo .btn-link, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-indigo .nav-tabs .nav-link { color: #6610f2; } .accent-indigo .btn-link:hover, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-indigo .nav-tabs .nav-link:hover { color: #4709ac; } .accent-indigo .dropdown-item:active, .accent-indigo .dropdown-item.active { background-color: #6610f2; color: #fff; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-indigo .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-indigo .custom-select:focus, .accent-indigo .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-indigo .custom-file-input:focus ~ .custom-file-label { border-color: #b389f9; } .accent-indigo .page-item .page-link { color: #6610f2; } .accent-indigo .page-item.active a, .accent-indigo .page-item.active .page-link { background-color: #6610f2; border-color: #6610f2; color: #fff; } .accent-indigo .page-item.disabled a, .accent-indigo .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-indigo .page-item .page-link:hover, .dark-mode.accent-indigo .page-item .page-link:focus { color: #7528f3; } .accent-purple .btn-link, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-purple .nav-tabs .nav-link { color: #6f42c1; } .accent-purple .btn-link:hover, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-purple .nav-tabs .nav-link:hover { color: #4e2d89; } .accent-purple .dropdown-item:active, .accent-purple .dropdown-item.active { background-color: #6f42c1; color: #fff; } .accent-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .accent-purple .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-purple .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-purple .custom-select:focus, .accent-purple .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-purple .custom-file-input:focus ~ .custom-file-label { border-color: #b8a2e0; } .accent-purple .page-item .page-link { color: #6f42c1; } .accent-purple .page-item.active a, .accent-purple .page-item.active .page-link { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .accent-purple .page-item.disabled a, .accent-purple .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-purple .page-item .page-link:hover, .dark-mode.accent-purple .page-item .page-link:focus { color: #7e55c7; } .accent-pink .btn-link, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-pink .nav-tabs .nav-link { color: #e83e8c; } .accent-pink .btn-link:hover, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-pink .nav-tabs .nav-link:hover { color: #c21766; } .accent-pink .dropdown-item:active, .accent-pink .dropdown-item.active { background-color: #e83e8c; color: #fff; } .accent-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .accent-pink .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-pink .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-pink .custom-select:focus, .accent-pink .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-pink .custom-file-input:focus ~ .custom-file-label { border-color: #f6b0d0; } .accent-pink .page-item .page-link { color: #e83e8c; } .accent-pink .page-item.active a, .accent-pink .page-item.active .page-link { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .accent-pink .page-item.disabled a, .accent-pink .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-pink .page-item .page-link:hover, .dark-mode.accent-pink .page-item .page-link:focus { color: #eb559a; } .accent-red .btn-link, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-red .nav-tabs .nav-link { color: #dc3545; } .accent-red .btn-link:hover, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-red .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-red .dropdown-item:active, .accent-red .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-red .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-red .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-red .custom-select:focus, .accent-red .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-red .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-red .page-item .page-link { color: #dc3545; } .accent-red .page-item.active a, .accent-red .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-red .page-item.disabled a, .accent-red .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-red .page-item .page-link:hover, .dark-mode.accent-red .page-item .page-link:focus { color: #e04b59; } .accent-orange .btn-link, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-orange .nav-tabs .nav-link { color: #fd7e14; } .accent-orange .btn-link:hover, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-orange .nav-tabs .nav-link:hover { color: #c35a02; } .accent-orange .dropdown-item:active, .accent-orange .dropdown-item.active { background-color: #fd7e14; color: #1f2d3d; } .accent-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .accent-orange .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-orange .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-orange .custom-select:focus, .accent-orange .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-orange .custom-file-input:focus ~ .custom-file-label { border-color: #fec392; } .accent-orange .page-item .page-link { color: #fd7e14; } .accent-orange .page-item.active a, .accent-orange .page-item.active .page-link { background-color: #fd7e14; border-color: #fd7e14; color: #fff; } .accent-orange .page-item.disabled a, .accent-orange .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-orange .page-item .page-link:hover, .dark-mode.accent-orange .page-item .page-link:focus { color: #fd8c2d; } .accent-yellow .btn-link, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-yellow .nav-tabs .nav-link { color: #ffc107; } .accent-yellow .btn-link:hover, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-yellow .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-yellow .dropdown-item:active, .accent-yellow .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-yellow .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-yellow .custom-select:focus, .accent-yellow .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-yellow .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-yellow .page-item .page-link { color: #ffc107; } .accent-yellow .page-item.active a, .accent-yellow .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-yellow .page-item.disabled a, .accent-yellow .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-yellow .page-item .page-link:hover, .dark-mode.accent-yellow .page-item .page-link:focus { color: #ffc721; } .accent-green .btn-link, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-green .nav-tabs .nav-link { color: #28a745; } .accent-green .btn-link:hover, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-green .nav-tabs .nav-link:hover { color: #19692c; } .accent-green .dropdown-item:active, .accent-green .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-green .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-green .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-green .custom-select:focus, .accent-green .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-green .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-green .page-item .page-link { color: #28a745; } .accent-green .page-item.active a, .accent-green .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-green .page-item.disabled a, .accent-green .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-green .page-item .page-link:hover, .dark-mode.accent-green .page-item .page-link:focus { color: #2dbc4e; } .accent-teal .btn-link, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-teal .nav-tabs .nav-link { color: #20c997; } .accent-teal .btn-link:hover, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-teal .nav-tabs .nav-link:hover { color: #158765; } .accent-teal .dropdown-item:active, .accent-teal .dropdown-item.active { background-color: #20c997; color: #fff; } .accent-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .accent-teal .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-teal .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-teal .custom-select:focus, .accent-teal .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-teal .custom-file-input:focus ~ .custom-file-label { border-color: #7eeaca; } .accent-teal .page-item .page-link { color: #20c997; } .accent-teal .page-item.active a, .accent-teal .page-item.active .page-link { background-color: #20c997; border-color: #20c997; color: #fff; } .accent-teal .page-item.disabled a, .accent-teal .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-teal .page-item .page-link:hover, .dark-mode.accent-teal .page-item .page-link:focus { color: #26dca6; } .accent-cyan .btn-link, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-cyan .nav-tabs .nav-link { color: #17a2b8; } .accent-cyan .btn-link:hover, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-cyan .nav-tabs .nav-link:hover { color: #0f6674; } .accent-cyan .dropdown-item:active, .accent-cyan .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-cyan .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-cyan .custom-select:focus, .accent-cyan .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-cyan .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-cyan .page-item .page-link { color: #17a2b8; } .accent-cyan .page-item.active a, .accent-cyan .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-cyan .page-item.disabled a, .accent-cyan .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-cyan .page-item .page-link:hover, .dark-mode.accent-cyan .page-item .page-link:focus { color: #1ab6cf; } .accent-white .btn-link, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-white .nav-tabs .nav-link { color: #fff; } .accent-white .btn-link:hover, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-white .nav-tabs .nav-link:hover { color: #d9d9d9; } .accent-white .dropdown-item:active, .accent-white .dropdown-item.active { background-color: #fff; color: #1f2d3d; } .accent-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .accent-white .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-white .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-white .custom-select:focus, .accent-white .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-white .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-white .page-item .page-link { color: #fff; } .accent-white .page-item.active a, .accent-white .page-item.active .page-link { background-color: #fff; border-color: #fff; color: #fff; } .accent-white .page-item.disabled a, .accent-white .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-white .page-item .page-link:hover, .dark-mode.accent-white .page-item .page-link:focus { color: white; } .accent-gray .btn-link, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray .nav-tabs .nav-link { color: #6c757d; } .accent-gray .btn-link:hover, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray .nav-tabs .nav-link:hover { color: #494f54; } .accent-gray .dropdown-item:active, .accent-gray .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-gray .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray .custom-select:focus, .accent-gray .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-gray .page-item .page-link { color: #6c757d; } .accent-gray .page-item.active a, .accent-gray .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-gray .page-item.disabled a, .accent-gray .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-gray .page-item .page-link:hover, .dark-mode.accent-gray .page-item .page-link:focus { color: #78828a; } .accent-gray-dark .btn-link, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray-dark .nav-tabs .nav-link { color: #343a40; } .accent-gray-dark .btn-link:hover, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-gray-dark .dropdown-item:active, .accent-gray-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray-dark .custom-select:focus, .accent-gray-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-gray-dark .page-item .page-link { color: #343a40; } .accent-gray-dark .page-item.active a, .accent-gray-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-gray-dark .page-item.disabled a, .accent-gray-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode.accent-gray-dark .page-item .page-link:hover, .dark-mode.accent-gray-dark .page-item .page-link:focus { color: #3f474e; } [class*="accent-"] a.btn-primary { color: #fff; } [class*="accent-"] a.btn-secondary { color: #fff; } [class*="accent-"] a.btn-success { color: #fff; } [class*="accent-"] a.btn-info { color: #fff; } [class*="accent-"] a.btn-warning { color: #1f2d3d; } [class*="accent-"] a.btn-danger { color: #fff; } [class*="accent-"] a.btn-light { color: #1f2d3d; } [class*="accent-"] a.btn-dark { color: #fff; } .dark-mode .bg-light { background-color: #454d55 !important; color: #fff !important; } .dark-mode .text-black, .dark-mode .text-dark, .dark-mode .link-black, .dark-mode .link-dark { color: #ced4da !important; } .dark-mode.bg-primary { background-color: #3f6791 !important; } .dark-mode.bg-primary, .dark-mode.bg-primary > a { color: #fff !important; } .dark-mode.bg-primary.btn:hover { border-color: #304e6d; color: #ececec; } .dark-mode.bg-primary.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-primary.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-primary.btn:active, .dark-mode.bg-primary.btn.active { background-color: #304e6d !important; border-color: #2c4765; color: #fff; } .dark-mode.bg-secondary { background-color: #6c757d !important; } .dark-mode.bg-secondary, .dark-mode.bg-secondary > a { color: #fff !important; } .dark-mode.bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .dark-mode.bg-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-secondary.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-secondary.btn:active, .dark-mode.bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .dark-mode.bg-success { background-color: #00bc8c !important; } .dark-mode.bg-success, .dark-mode.bg-success > a { color: #fff !important; } .dark-mode.bg-success.btn:hover { border-color: #008966; color: #ececec; } .dark-mode.bg-success.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-success.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-success.btn:active, .dark-mode.bg-success.btn.active { background-color: #008966 !important; border-color: #007c5d; color: #fff; } .dark-mode.bg-info { background-color: #3498db !important; } .dark-mode.bg-info, .dark-mode.bg-info > a { color: #fff !important; } .dark-mode.bg-info.btn:hover { border-color: #217dbb; color: #ececec; } .dark-mode.bg-info.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-info.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-info.btn:active, .dark-mode.bg-info.btn.active { background-color: #217dbb !important; border-color: #1f76b0; color: #fff; } .dark-mode.bg-warning { background-color: #f39c12 !important; } .dark-mode.bg-warning, .dark-mode.bg-warning > a { color: #1f2d3d !important; } .dark-mode.bg-warning.btn:hover { border-color: #c87f0a; color: #121a24; } .dark-mode.bg-warning.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-warning.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-warning.btn:active, .dark-mode.bg-warning.btn.active { background-color: #c87f0a !important; border-color: #bc770a; color: #fff; } .dark-mode.bg-danger { background-color: #e74c3c !important; } .dark-mode.bg-danger, .dark-mode.bg-danger > a { color: #fff !important; } .dark-mode.bg-danger.btn:hover { border-color: #d62c1a; color: #ececec; } .dark-mode.bg-danger.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-danger.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-danger.btn:active, .dark-mode.bg-danger.btn.active { background-color: #d62c1a !important; border-color: #ca2a19; color: #fff; } .dark-mode.bg-light { background-color: #f8f9fa !important; } .dark-mode.bg-light, .dark-mode.bg-light > a { color: #1f2d3d !important; } .dark-mode.bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .dark-mode.bg-light.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-light.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-light.btn:active, .dark-mode.bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .dark-mode.bg-dark { background-color: #343a40 !important; } .dark-mode.bg-dark, .dark-mode.bg-dark > a { color: #fff !important; } .dark-mode.bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .dark-mode.bg-dark.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-dark.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-dark.btn:active, .dark-mode.bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .dark-mode.bg-lightblue { background-color: #86bad8 !important; } .dark-mode.bg-lightblue, .dark-mode.bg-lightblue > a { color: #1f2d3d !important; } .dark-mode.bg-lightblue.btn:hover { border-color: #5fa4cc; color: #121a24; } .dark-mode.bg-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-lightblue.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-lightblue.btn:active, .dark-mode.bg-lightblue.btn.active { background-color: #5fa4cc !important; border-color: #559ec9; color: #fff; } .dark-mode.bg-navy { background-color: #002c59 !important; } .dark-mode.bg-navy, .dark-mode.bg-navy > a { color: #fff !important; } .dark-mode.bg-navy.btn:hover { border-color: #001226; color: #ececec; } .dark-mode.bg-navy.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-navy.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-navy.btn:active, .dark-mode.bg-navy.btn.active { background-color: #001226 !important; border-color: #000c19; color: #fff; } .dark-mode.bg-olive { background-color: #74c8a3 !important; } .dark-mode.bg-olive, .dark-mode.bg-olive > a { color: #1f2d3d !important; } .dark-mode.bg-olive.btn:hover { border-color: #50b98a; color: #121a24; } .dark-mode.bg-olive.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-olive.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-olive.btn:active, .dark-mode.bg-olive.btn.active { background-color: #50b98a !important; border-color: #48b484; color: #fff; } .dark-mode.bg-lime { background-color: #67ffa9 !important; } .dark-mode.bg-lime, .dark-mode.bg-lime > a { color: #1f2d3d !important; } .dark-mode.bg-lime.btn:hover { border-color: #34ff8d; color: #121a24; } .dark-mode.bg-lime.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-lime.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-lime.btn:active, .dark-mode.bg-lime.btn.active { background-color: #34ff8d !important; border-color: #27ff86; color: #1f2d3d; } .dark-mode.bg-fuchsia { background-color: #f672d8 !important; } .dark-mode.bg-fuchsia, .dark-mode.bg-fuchsia > a { color: #1f2d3d !important; } .dark-mode.bg-fuchsia.btn:hover { border-color: #f342cb; color: #121a24; } .dark-mode.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-fuchsia.btn:active, .dark-mode.bg-fuchsia.btn.active { background-color: #f342cb !important; border-color: #f236c8; color: #fff; } .dark-mode.bg-maroon { background-color: #ed6c9b !important; } .dark-mode.bg-maroon, .dark-mode.bg-maroon > a { color: #1f2d3d !important; } .dark-mode.bg-maroon.btn:hover { border-color: #e73f7c; color: #121a24; } .dark-mode.bg-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-maroon.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-maroon.btn:active, .dark-mode.bg-maroon.btn.active { background-color: #e73f7c !important; border-color: #e63475; color: #fff; } .dark-mode.bg-blue { background-color: #3f6791 !important; } .dark-mode.bg-blue, .dark-mode.bg-blue > a { color: #fff !important; } .dark-mode.bg-blue.btn:hover { border-color: #304e6d; color: #ececec; } .dark-mode.bg-blue.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-blue.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-blue.btn:active, .dark-mode.bg-blue.btn.active { background-color: #304e6d !important; border-color: #2c4765; color: #fff; } .dark-mode.bg-indigo { background-color: #6610f2 !important; } .dark-mode.bg-indigo, .dark-mode.bg-indigo > a { color: #fff !important; } .dark-mode.bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .dark-mode.bg-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-indigo.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-indigo.btn:active, .dark-mode.bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .dark-mode.bg-purple { background-color: #6f42c1 !important; } .dark-mode.bg-purple, .dark-mode.bg-purple > a { color: #fff !important; } .dark-mode.bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .dark-mode.bg-purple.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-purple.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-purple.btn:active, .dark-mode.bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .dark-mode.bg-pink { background-color: #e83e8c !important; } .dark-mode.bg-pink, .dark-mode.bg-pink > a { color: #fff !important; } .dark-mode.bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .dark-mode.bg-pink.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-pink.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-pink.btn:active, .dark-mode.bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .dark-mode.bg-red { background-color: #e74c3c !important; } .dark-mode.bg-red, .dark-mode.bg-red > a { color: #fff !important; } .dark-mode.bg-red.btn:hover { border-color: #d62c1a; color: #ececec; } .dark-mode.bg-red.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-red.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-red.btn:active, .dark-mode.bg-red.btn.active { background-color: #d62c1a !important; border-color: #ca2a19; color: #fff; } .dark-mode.bg-orange { background-color: #fd7e14 !important; } .dark-mode.bg-orange, .dark-mode.bg-orange > a { color: #1f2d3d !important; } .dark-mode.bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .dark-mode.bg-orange.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-orange.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-orange.btn:active, .dark-mode.bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .dark-mode.bg-yellow { background-color: #f39c12 !important; } .dark-mode.bg-yellow, .dark-mode.bg-yellow > a { color: #1f2d3d !important; } .dark-mode.bg-yellow.btn:hover { border-color: #c87f0a; color: #121a24; } .dark-mode.bg-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-yellow.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-yellow.btn:active, .dark-mode.bg-yellow.btn.active { background-color: #c87f0a !important; border-color: #bc770a; color: #fff; } .dark-mode.bg-green { background-color: #00bc8c !important; } .dark-mode.bg-green, .dark-mode.bg-green > a { color: #fff !important; } .dark-mode.bg-green.btn:hover { border-color: #008966; color: #ececec; } .dark-mode.bg-green.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-green.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-green.btn:active, .dark-mode.bg-green.btn.active { background-color: #008966 !important; border-color: #007c5d; color: #fff; } .dark-mode.bg-teal { background-color: #20c997 !important; } .dark-mode.bg-teal, .dark-mode.bg-teal > a { color: #fff !important; } .dark-mode.bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .dark-mode.bg-teal.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-teal.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-teal.btn:active, .dark-mode.bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .dark-mode.bg-cyan { background-color: #3498db !important; } .dark-mode.bg-cyan, .dark-mode.bg-cyan > a { color: #fff !important; } .dark-mode.bg-cyan.btn:hover { border-color: #217dbb; color: #ececec; } .dark-mode.bg-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-cyan.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-cyan.btn:active, .dark-mode.bg-cyan.btn.active { background-color: #217dbb !important; border-color: #1f76b0; color: #fff; } .dark-mode.bg-white { background-color: #fff !important; } .dark-mode.bg-white, .dark-mode.bg-white > a { color: #1f2d3d !important; } .dark-mode.bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .dark-mode.bg-white.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-white.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-white.btn:active, .dark-mode.bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .dark-mode.bg-gray { background-color: #6c757d !important; } .dark-mode.bg-gray, .dark-mode.bg-gray > a { color: #fff !important; } .dark-mode.bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .dark-mode.bg-gray.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-gray.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-gray.btn:active, .dark-mode.bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .dark-mode.bg-gray-dark { background-color: #343a40 !important; } .dark-mode.bg-gray-dark, .dark-mode.bg-gray-dark > a { color: #fff !important; } .dark-mode.bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .dark-mode.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .dark-mode.bg-gray-dark.btn:active, .dark-mode.bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-primary { background: #3f6791 linear-gradient(180deg, #5c7ea2, #3f6791) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-primary.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-primary.btn:hover { background: #3f6791 linear-gradient(180deg, #526e8b, #335476) repeat-x !important; border-color: #304e6d; color: #ececec; } .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-primary.btn:active, .dark-mode .bg-gradient-primary.btn.active { background: #3f6791 linear-gradient(180deg, #4f6883, #304e6d) repeat-x !important; border-color: #2c4765; color: #fff; } .dark-mode .bg-gradient-primary.btn:disabled, .dark-mode .bg-gradient-primary.btn.disabled { background-image: none !important; border-color: #3f6791; color: #fff; } .dark-mode .bg-gradient-secondary { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-secondary.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-secondary.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-secondary.btn:active, .dark-mode .bg-gradient-secondary.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .dark-mode .bg-gradient-secondary.btn:disabled, .dark-mode .bg-gradient-secondary.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .dark-mode .bg-gradient-success { background: #00bc8c linear-gradient(180deg, #26c69d, #00bc8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-success.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-success.btn:hover { background: #00bc8c linear-gradient(180deg, #26a685, #009670) repeat-x !important; border-color: #008966; color: #ececec; } .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-success.btn:active, .dark-mode .bg-gradient-success.btn.active { background: #00bc8c linear-gradient(180deg, #269b7d, #008966) repeat-x !important; border-color: #007c5d; color: #fff; } .dark-mode .bg-gradient-success.btn:disabled, .dark-mode .bg-gradient-success.btn.disabled { background-image: none !important; border-color: #00bc8c; color: #fff; } .dark-mode .bg-gradient-info { background: #3498db linear-gradient(180deg, #52a7e0, #3498db) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-info.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-info.btn:hover { background: #3498db linear-gradient(180deg, #4497ce, #2384c6) repeat-x !important; border-color: #217dbb; color: #ececec; } .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-info.btn:active, .dark-mode .bg-gradient-info.btn.active { background: #3498db linear-gradient(180deg, #4291c5, #217dbb) repeat-x !important; border-color: #1f76b0; color: #fff; } .dark-mode .bg-gradient-info.btn:disabled, .dark-mode .bg-gradient-info.btn.disabled { background-image: none !important; border-color: #3498db; color: #fff; } .dark-mode .bg-gradient-warning { background: #f39c12 linear-gradient(180deg, #f5ab36, #f39c12) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-warning.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-warning.btn:hover { background: #f39c12 linear-gradient(180deg, #da982f, #d4860b) repeat-x !important; border-color: #c87f0a; color: #121a24; } .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-warning.btn:active, .dark-mode .bg-gradient-warning.btn.active { background: #f39c12 linear-gradient(180deg, #d0922f, #c87f0a) repeat-x !important; border-color: #bc770a; color: #fff; } .dark-mode .bg-gradient-warning.btn:disabled, .dark-mode .bg-gradient-warning.btn.disabled { background-image: none !important; border-color: #f39c12; color: #1f2d3d; } .dark-mode .bg-gradient-danger { background: #e74c3c linear-gradient(180deg, #eb6759, #e74c3c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-danger.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-danger.btn:hover { background: #e74c3c linear-gradient(180deg, #e64d3e, #e12e1c) repeat-x !important; border-color: #d62c1a; color: #ececec; } .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-danger.btn:active, .dark-mode .bg-gradient-danger.btn.active { background: #e74c3c linear-gradient(180deg, #dc4c3d, #d62c1a) repeat-x !important; border-color: #ca2a19; color: #fff; } .dark-mode .bg-gradient-danger.btn:disabled, .dark-mode .bg-gradient-danger.btn.disabled { background-image: none !important; border-color: #e74c3c; color: #fff; } .dark-mode .bg-gradient-light { background: #f8f9fa linear-gradient(180deg, #f9fafb, #f8f9fa) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-light.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-light.btn:hover { background: #f8f9fa linear-gradient(180deg, #e6eaed, #e2e6ea) repeat-x !important; border-color: #dae0e5; color: #121a24; } .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-light.btn:active, .dark-mode .bg-gradient-light.btn.active { background: #f8f9fa linear-gradient(180deg, #e0e4e9, #dae0e5) repeat-x !important; border-color: #d3d9df; color: #1f2d3d; } .dark-mode .bg-gradient-light.btn:disabled, .dark-mode .bg-gradient-light.btn.disabled { background-image: none !important; border-color: #f8f9fa; color: #1f2d3d; } .dark-mode .bg-gradient-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-dark.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-dark.btn:active, .dark-mode .bg-gradient-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-dark.btn:disabled, .dark-mode .bg-gradient-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .dark-mode .bg-gradient-lightblue { background: #86bad8 linear-gradient(180deg, #98c4de, #86bad8) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-lightblue.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-lightblue.btn:hover { background: #86bad8 linear-gradient(180deg, #7fb6d6, #69a9cf) repeat-x !important; border-color: #5fa4cc; color: #121a24; } .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-lightblue.btn:active, .dark-mode .bg-gradient-lightblue.btn.active { background: #86bad8 linear-gradient(180deg, #77b2d4, #5fa4cc) repeat-x !important; border-color: #559ec9; color: #fff; } .dark-mode .bg-gradient-lightblue.btn:disabled, .dark-mode .bg-gradient-lightblue.btn.disabled { background-image: none !important; border-color: #86bad8; color: #1f2d3d; } .dark-mode .bg-gradient-navy { background: #002c59 linear-gradient(180deg, #264b71, #002c59) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-navy.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-navy.btn:hover { background: #002c59 linear-gradient(180deg, #263b51, #001932) repeat-x !important; border-color: #001226; color: #ececec; } .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-navy.btn:active, .dark-mode .bg-gradient-navy.btn.active { background: #002c59 linear-gradient(180deg, #263646, #001226) repeat-x !important; border-color: #000c19; color: #fff; } .dark-mode .bg-gradient-navy.btn:disabled, .dark-mode .bg-gradient-navy.btn.disabled { background-image: none !important; border-color: #002c59; color: #fff; } .dark-mode .bg-gradient-olive { background: #74c8a3 linear-gradient(180deg, #89d0b0, #74c8a3) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-olive.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-olive.btn:hover { background: #74c8a3 linear-gradient(180deg, #72c7a1, #59bd90) repeat-x !important; border-color: #50b98a; color: #121a24; } .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-olive.btn:active, .dark-mode .bg-gradient-olive.btn.active { background: #74c8a3 linear-gradient(180deg, #6ac49c, #50b98a) repeat-x !important; border-color: #48b484; color: #fff; } .dark-mode .bg-gradient-olive.btn:disabled, .dark-mode .bg-gradient-olive.btn.disabled { background-image: none !important; border-color: #74c8a3; color: #1f2d3d; } .dark-mode .bg-gradient-lime { background: #67ffa9 linear-gradient(180deg, #7effb6, #67ffa9) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-lime.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-lime.btn:hover { background: #67ffa9 linear-gradient(180deg, #5dffa4, #41ff94) repeat-x !important; border-color: #34ff8d; color: #121a24; } .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-lime.btn:active, .dark-mode .bg-gradient-lime.btn.active { background: #67ffa9 linear-gradient(180deg, #52ff9e, #34ff8d) repeat-x !important; border-color: #27ff86; color: #1f2d3d; } .dark-mode .bg-gradient-lime.btn:disabled, .dark-mode .bg-gradient-lime.btn.disabled { background-image: none !important; border-color: #67ffa9; color: #1f2d3d; } .dark-mode .bg-gradient-fuchsia { background: #f672d8 linear-gradient(180deg, #f787de, #f672d8) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-fuchsia.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-fuchsia.btn:hover { background: #f672d8 linear-gradient(180deg, #f569d6, #f44ece) repeat-x !important; border-color: #f342cb; color: #121a24; } .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-fuchsia.btn:active, .dark-mode .bg-gradient-fuchsia.btn.active { background: #f672d8 linear-gradient(180deg, #f55ed3, #f342cb) repeat-x !important; border-color: #f236c8; color: #fff; } .dark-mode .bg-gradient-fuchsia.btn:disabled, .dark-mode .bg-gradient-fuchsia.btn.disabled { background-image: none !important; border-color: #f672d8; color: #1f2d3d; } .dark-mode .bg-gradient-maroon { background: #ed6c9b linear-gradient(180deg, #ef82aa, #ed6c9b) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-maroon.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-maroon.btn:hover { background: #ed6c9b linear-gradient(180deg, #ec6596, #e84a84) repeat-x !important; border-color: #e73f7c; color: #121a24; } .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-maroon.btn:active, .dark-mode .bg-gradient-maroon.btn.active { background: #ed6c9b linear-gradient(180deg, #eb5c90, #e73f7c) repeat-x !important; border-color: #e63475; color: #fff; } .dark-mode .bg-gradient-maroon.btn:disabled, .dark-mode .bg-gradient-maroon.btn.disabled { background-image: none !important; border-color: #ed6c9b; color: #1f2d3d; } .dark-mode .bg-gradient-blue { background: #3f6791 linear-gradient(180deg, #5c7ea2, #3f6791) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-blue.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-blue.btn:hover { background: #3f6791 linear-gradient(180deg, #526e8b, #335476) repeat-x !important; border-color: #304e6d; color: #ececec; } .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-blue.btn:active, .dark-mode .bg-gradient-blue.btn.active { background: #3f6791 linear-gradient(180deg, #4f6883, #304e6d) repeat-x !important; border-color: #2c4765; color: #fff; } .dark-mode .bg-gradient-blue.btn:disabled, .dark-mode .bg-gradient-blue.btn.disabled { background-image: none !important; border-color: #3f6791; color: #fff; } .dark-mode .bg-gradient-indigo { background: #6610f2 linear-gradient(180deg, #7d34f4, #6610f2) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-indigo.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-indigo.btn:hover { background: #6610f2 linear-gradient(180deg, #7030d7, #560bd0) repeat-x !important; border-color: #510bc4; color: #ececec; } .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-indigo.btn:active, .dark-mode .bg-gradient-indigo.btn.active { background: #6610f2 linear-gradient(180deg, #6b2fcd, #510bc4) repeat-x !important; border-color: #4c0ab8; color: #fff; } .dark-mode .bg-gradient-indigo.btn:disabled, .dark-mode .bg-gradient-indigo.btn.disabled { background-image: none !important; border-color: #6610f2; color: #fff; } .dark-mode .bg-gradient-purple { background: #6f42c1 linear-gradient(180deg, #855eca, #6f42c1) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-purple.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-purple.btn:hover { background: #6f42c1 linear-gradient(180deg, #7655b4, #5e37a6) repeat-x !important; border-color: #59339d; color: #ececec; } .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-purple.btn:active, .dark-mode .bg-gradient-purple.btn.active { background: #6f42c1 linear-gradient(180deg, #7252ab, #59339d) repeat-x !important; border-color: #533093; color: #fff; } .dark-mode .bg-gradient-purple.btn:disabled, .dark-mode .bg-gradient-purple.btn.disabled { background-image: none !important; border-color: #6f42c1; color: #fff; } .dark-mode .bg-gradient-pink { background: #e83e8c linear-gradient(180deg, #eb5b9d, #e83e8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-pink.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-pink.btn:hover { background: #e83e8c linear-gradient(180deg, #e83e8c, #e41c78) repeat-x !important; border-color: #d91a72; color: #ececec; } .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-pink.btn:active, .dark-mode .bg-gradient-pink.btn.active { background: #e83e8c linear-gradient(180deg, #df3c87, #d91a72) repeat-x !important; border-color: #ce196c; color: #fff; } .dark-mode .bg-gradient-pink.btn:disabled, .dark-mode .bg-gradient-pink.btn.disabled { background-image: none !important; border-color: #e83e8c; color: #fff; } .dark-mode .bg-gradient-red { background: #e74c3c linear-gradient(180deg, #eb6759, #e74c3c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-red.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-red.btn:hover { background: #e74c3c linear-gradient(180deg, #e64d3e, #e12e1c) repeat-x !important; border-color: #d62c1a; color: #ececec; } .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-red.btn:active, .dark-mode .bg-gradient-red.btn.active { background: #e74c3c linear-gradient(180deg, #dc4c3d, #d62c1a) repeat-x !important; border-color: #ca2a19; color: #fff; } .dark-mode .bg-gradient-red.btn:disabled, .dark-mode .bg-gradient-red.btn.disabled { background-image: none !important; border-color: #e74c3c; color: #fff; } .dark-mode .bg-gradient-orange { background: #fd7e14 linear-gradient(180deg, #fd9137, #fd7e14) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-orange.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-orange.btn:hover { background: #fd7e14 linear-gradient(180deg, #ec8128, #e96b02) repeat-x !important; border-color: #dc6502; color: #121a24; } .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-orange.btn:active, .dark-mode .bg-gradient-orange.btn.active { background: #fd7e14 linear-gradient(180deg, #e17c28, #dc6502) repeat-x !important; border-color: #cf5f02; color: #fff; } .dark-mode .bg-gradient-orange.btn:disabled, .dark-mode .bg-gradient-orange.btn.disabled { background-image: none !important; border-color: #fd7e14; color: #1f2d3d; } .dark-mode .bg-gradient-yellow { background: #f39c12 linear-gradient(180deg, #f5ab36, #f39c12) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-yellow.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-yellow.btn:hover { background: #f39c12 linear-gradient(180deg, #da982f, #d4860b) repeat-x !important; border-color: #c87f0a; color: #121a24; } .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-yellow.btn:active, .dark-mode .bg-gradient-yellow.btn.active { background: #f39c12 linear-gradient(180deg, #d0922f, #c87f0a) repeat-x !important; border-color: #bc770a; color: #fff; } .dark-mode .bg-gradient-yellow.btn:disabled, .dark-mode .bg-gradient-yellow.btn.disabled { background-image: none !important; border-color: #f39c12; color: #1f2d3d; } .dark-mode .bg-gradient-green { background: #00bc8c linear-gradient(180deg, #26c69d, #00bc8c) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-green.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-green.btn:hover { background: #00bc8c linear-gradient(180deg, #26a685, #009670) repeat-x !important; border-color: #008966; color: #ececec; } .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-green.btn:active, .dark-mode .bg-gradient-green.btn.active { background: #00bc8c linear-gradient(180deg, #269b7d, #008966) repeat-x !important; border-color: #007c5d; color: #fff; } .dark-mode .bg-gradient-green.btn:disabled, .dark-mode .bg-gradient-green.btn.disabled { background-image: none !important; border-color: #00bc8c; color: #fff; } .dark-mode .bg-gradient-teal { background: #20c997 linear-gradient(180deg, #41d1a7, #20c997) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-teal.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-teal.btn:hover { background: #20c997 linear-gradient(180deg, #3db592, #1ba87e) repeat-x !important; border-color: #199d76; color: #ececec; } .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-teal.btn:active, .dark-mode .bg-gradient-teal.btn.active { background: #20c997 linear-gradient(180deg, #3bac8b, #199d76) repeat-x !important; border-color: #17926e; color: #fff; } .dark-mode .bg-gradient-teal.btn:disabled, .dark-mode .bg-gradient-teal.btn.disabled { background-image: none !important; border-color: #20c997; color: #fff; } .dark-mode .bg-gradient-cyan { background: #3498db linear-gradient(180deg, #52a7e0, #3498db) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-cyan.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-cyan.btn:hover { background: #3498db linear-gradient(180deg, #4497ce, #2384c6) repeat-x !important; border-color: #217dbb; color: #ececec; } .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-cyan.btn:active, .dark-mode .bg-gradient-cyan.btn.active { background: #3498db linear-gradient(180deg, #4291c5, #217dbb) repeat-x !important; border-color: #1f76b0; color: #fff; } .dark-mode .bg-gradient-cyan.btn:disabled, .dark-mode .bg-gradient-cyan.btn.disabled { background-image: none !important; border-color: #3498db; color: #fff; } .dark-mode .bg-gradient-white { background: #fff linear-gradient(180deg, white, #fff) repeat-x !important; color: #1f2d3d; } .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-white.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-white.btn:hover { background: #fff linear-gradient(180deg, #efefef, #ececec) repeat-x !important; border-color: #e6e6e6; color: #121a24; } .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-white.btn:active, .dark-mode .bg-gradient-white.btn.active { background: #fff linear-gradient(180deg, #e9e9e9, #e6e6e6) repeat-x !important; border-color: #dfdfdf; color: #1f2d3d; } .dark-mode .bg-gradient-white.btn:disabled, .dark-mode .bg-gradient-white.btn.disabled { background-image: none !important; border-color: #fff; color: #1f2d3d; } .dark-mode .bg-gradient-gray { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-gray.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-gray.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-gray.btn:active, .dark-mode .bg-gradient-gray.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .dark-mode .bg-gradient-gray.btn:disabled, .dark-mode .bg-gradient-gray.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .dark-mode .bg-gradient-gray-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .show > .dark-mode .bg-gradient-gray-dark.btn.dropdown-toggle { background-image: none !important; } .dark-mode .bg-gradient-gray-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .dark-mode .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .dark-mode .bg-gradient-gray-dark.btn:active, .dark-mode .bg-gradient-gray-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .dark-mode .bg-gradient-gray-dark.btn:disabled, .dark-mode .bg-gradient-gray-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .dark-mode .accent-primary .btn-link, .dark-mode .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-primary .nav-tabs .nav-link { color: #3f6791; } .dark-mode .accent-primary .btn-link:hover, .dark-mode .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-primary .nav-tabs .nav-link:hover { color: #28415c; } .dark-mode .accent-primary .dropdown-item:active, .dark-mode .accent-primary .dropdown-item.active { background-color: #3f6791; color: #fff; } .dark-mode .accent-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .accent-primary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-primary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-primary .custom-select:focus, .dark-mode .accent-primary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-primary .custom-file-input:focus ~ .custom-file-label { border-color: #85a7ca; } .dark-mode .accent-primary .page-item .page-link { color: #3f6791; } .dark-mode .accent-primary .page-item.active a, .dark-mode .accent-primary .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .accent-primary .page-item.disabled a, .dark-mode .accent-primary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-primary .page-item .page-link:hover, .dark-mode .dark-mode.accent-primary .page-item .page-link:focus { color: #4774a3; } .dark-mode .accent-secondary .btn-link, .dark-mode .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-secondary .nav-tabs .nav-link { color: #6c757d; } .dark-mode .accent-secondary .btn-link:hover, .dark-mode .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-secondary .nav-tabs .nav-link:hover { color: #494f54; } .dark-mode .accent-secondary .dropdown-item:active, .dark-mode .accent-secondary .dropdown-item.active { background-color: #6c757d; color: #fff; } .dark-mode .accent-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .accent-secondary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-secondary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-secondary .custom-select:focus, .dark-mode .accent-secondary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-secondary .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .dark-mode .accent-secondary .page-item .page-link { color: #6c757d; } .dark-mode .accent-secondary .page-item.active a, .dark-mode .accent-secondary .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .accent-secondary .page-item.disabled a, .dark-mode .accent-secondary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-secondary .page-item .page-link:hover, .dark-mode .dark-mode.accent-secondary .page-item .page-link:focus { color: #78828a; } .dark-mode .accent-success .btn-link, .dark-mode .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-success .nav-tabs .nav-link { color: #00bc8c; } .dark-mode .accent-success .btn-link:hover, .dark-mode .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-success .nav-tabs .nav-link:hover { color: #007053; } .dark-mode .accent-success .dropdown-item:active, .dark-mode .accent-success .dropdown-item.active { background-color: #00bc8c; color: #fff; } .dark-mode .accent-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .accent-success .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-success .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-success .custom-select:focus, .dark-mode .accent-success .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-success .custom-file-input:focus ~ .custom-file-label { border-color: #3dffcd; } .dark-mode .accent-success .page-item .page-link { color: #00bc8c; } .dark-mode .accent-success .page-item.active a, .dark-mode .accent-success .page-item.active .page-link { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .accent-success .page-item.disabled a, .dark-mode .accent-success .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-success .page-item .page-link:hover, .dark-mode .dark-mode.accent-success .page-item .page-link:focus { color: #00d69f; } .dark-mode .accent-info .btn-link, .dark-mode .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-info .nav-tabs .nav-link { color: #3498db; } .dark-mode .accent-info .btn-link:hover, .dark-mode .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-info .nav-tabs .nav-link:hover { color: #1d6fa5; } .dark-mode .accent-info .dropdown-item:active, .dark-mode .accent-info .dropdown-item.active { background-color: #3498db; color: #fff; } .dark-mode .accent-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .accent-info .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-info .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-info .custom-select:focus, .dark-mode .accent-info .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-info .custom-file-input:focus ~ .custom-file-label { border-color: #a0cfee; } .dark-mode .accent-info .page-item .page-link { color: #3498db; } .dark-mode .accent-info .page-item.active a, .dark-mode .accent-info .page-item.active .page-link { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .accent-info .page-item.disabled a, .dark-mode .accent-info .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-info .page-item .page-link:hover, .dark-mode .dark-mode.accent-info .page-item .page-link:focus { color: #4aa3df; } .dark-mode .accent-warning .btn-link, .dark-mode .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-warning .nav-tabs .nav-link { color: #f39c12; } .dark-mode .accent-warning .btn-link:hover, .dark-mode .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-warning .nav-tabs .nav-link:hover { color: #b06f09; } .dark-mode .accent-warning .dropdown-item:active, .dark-mode .accent-warning .dropdown-item.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .accent-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .accent-warning .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-warning .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-warning .custom-select:focus, .dark-mode .accent-warning .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-warning .custom-file-input:focus ~ .custom-file-label { border-color: #f9cf8b; } .dark-mode .accent-warning .page-item .page-link { color: #f39c12; } .dark-mode .accent-warning .page-item.active a, .dark-mode .accent-warning .page-item.active .page-link { background-color: #f39c12; border-color: #f39c12; color: #fff; } .dark-mode .accent-warning .page-item.disabled a, .dark-mode .accent-warning .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-warning .page-item .page-link:hover, .dark-mode .dark-mode.accent-warning .page-item .page-link:focus { color: #f4a62a; } .dark-mode .accent-danger .btn-link, .dark-mode .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-danger .nav-tabs .nav-link { color: #e74c3c; } .dark-mode .accent-danger .btn-link:hover, .dark-mode .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-danger .nav-tabs .nav-link:hover { color: #bf2718; } .dark-mode .accent-danger .dropdown-item:active, .dark-mode .accent-danger .dropdown-item.active { background-color: #e74c3c; color: #fff; } .dark-mode .accent-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .accent-danger .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-danger .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-danger .custom-select:focus, .dark-mode .accent-danger .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-danger .custom-file-input:focus ~ .custom-file-label { border-color: #f5b4ae; } .dark-mode .accent-danger .page-item .page-link { color: #e74c3c; } .dark-mode .accent-danger .page-item.active a, .dark-mode .accent-danger .page-item.active .page-link { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .accent-danger .page-item.disabled a, .dark-mode .accent-danger .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-danger .page-item .page-link:hover, .dark-mode .dark-mode.accent-danger .page-item .page-link:focus { color: #ea6153; } .dark-mode .accent-light .btn-link, .dark-mode .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-light .nav-tabs .nav-link { color: #f8f9fa; } .dark-mode .accent-light .btn-link:hover, .dark-mode .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-light .nav-tabs .nav-link:hover { color: #cbd3da; } .dark-mode .accent-light .dropdown-item:active, .dark-mode .accent-light .dropdown-item.active { background-color: #f8f9fa; color: #1f2d3d; } .dark-mode .accent-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .dark-mode .accent-light .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-light .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-light .custom-select:focus, .dark-mode .accent-light .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-light .custom-file-input:focus ~ .custom-file-label { border-color: white; } .dark-mode .accent-light .page-item .page-link { color: #f8f9fa; } .dark-mode .accent-light .page-item.active a, .dark-mode .accent-light .page-item.active .page-link { background-color: #f8f9fa; border-color: #f8f9fa; color: #fff; } .dark-mode .accent-light .page-item.disabled a, .dark-mode .accent-light .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-light .page-item .page-link:hover, .dark-mode .dark-mode.accent-light .page-item .page-link:focus { color: white; } .dark-mode .accent-dark .btn-link, .dark-mode .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-dark .nav-tabs .nav-link { color: #343a40; } .dark-mode .accent-dark .btn-link:hover, .dark-mode .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-dark .nav-tabs .nav-link:hover { color: #121416; } .dark-mode .accent-dark .dropdown-item:active, .dark-mode .accent-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .dark-mode .accent-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .accent-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-dark .custom-select:focus, .dark-mode .accent-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .dark-mode .accent-dark .page-item .page-link { color: #343a40; } .dark-mode .accent-dark .page-item.active a, .dark-mode .accent-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .accent-dark .page-item.disabled a, .dark-mode .accent-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-dark .page-item .page-link:hover, .dark-mode .dark-mode.accent-dark .page-item .page-link:focus { color: #3f474e; } .dark-mode [class*="accent-"] a.btn-primary { color: #fff; } .dark-mode [class*="accent-"] a.btn-secondary { color: #fff; } .dark-mode [class*="accent-"] a.btn-success { color: #fff; } .dark-mode [class*="accent-"] a.btn-info { color: #fff; } .dark-mode [class*="accent-"] a.btn-warning { color: #1f2d3d; } .dark-mode [class*="accent-"] a.btn-danger { color: #fff; } .dark-mode [class*="accent-"] a.btn-light { color: #1f2d3d; } .dark-mode [class*="accent-"] a.btn-dark { color: #fff; } .dark-mode .accent-lightblue .btn-link, .dark-mode .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-lightblue .nav-tabs .nav-link { color: #86bad8; } .dark-mode .accent-lightblue .btn-link:hover, .dark-mode .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-lightblue .nav-tabs .nav-link:hover { color: #4c99c6; } .dark-mode .accent-lightblue .dropdown-item:active, .dark-mode .accent-lightblue .dropdown-item.active { background-color: #86bad8; color: #1f2d3d; } .dark-mode .accent-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #86bad8; border-color: #3c8dbc; } .dark-mode .accent-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-lightblue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-lightblue .custom-select:focus, .dark-mode .accent-lightblue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-lightblue .custom-file-input:focus ~ .custom-file-label { border-color: #e6f1f7; } .dark-mode .accent-lightblue .page-item .page-link { color: #86bad8; } .dark-mode .accent-lightblue .page-item.active a, .dark-mode .accent-lightblue .page-item.active .page-link { background-color: #86bad8; border-color: #86bad8; color: #fff; } .dark-mode .accent-lightblue .page-item.disabled a, .dark-mode .accent-lightblue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-lightblue .page-item .page-link:hover, .dark-mode .dark-mode.accent-lightblue .page-item .page-link:focus { color: #99c5de; } .dark-mode .accent-navy .btn-link, .dark-mode .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-navy .nav-tabs .nav-link { color: #002c59; } .dark-mode .accent-navy .btn-link:hover, .dark-mode .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-navy .nav-tabs .nav-link:hover { color: #00060c; } .dark-mode .accent-navy .dropdown-item:active, .dark-mode .accent-navy .dropdown-item.active { background-color: #002c59; color: #fff; } .dark-mode .accent-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #002c59; border-color: black; } .dark-mode .accent-navy .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-navy .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-navy .custom-select:focus, .dark-mode .accent-navy .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-navy .custom-file-input:focus ~ .custom-file-label { border-color: #006ad8; } .dark-mode .accent-navy .page-item .page-link { color: #002c59; } .dark-mode .accent-navy .page-item.active a, .dark-mode .accent-navy .page-item.active .page-link { background-color: #002c59; border-color: #002c59; color: #fff; } .dark-mode .accent-navy .page-item.disabled a, .dark-mode .accent-navy .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-navy .page-item .page-link:hover, .dark-mode .dark-mode.accent-navy .page-item .page-link:focus { color: #003872; } .dark-mode .accent-olive .btn-link, .dark-mode .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-olive .nav-tabs .nav-link { color: #74c8a3; } .dark-mode .accent-olive .btn-link:hover, .dark-mode .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-olive .nav-tabs .nav-link:hover { color: #44ab7d; } .dark-mode .accent-olive .dropdown-item:active, .dark-mode .accent-olive .dropdown-item.active { background-color: #74c8a3; color: #1f2d3d; } .dark-mode .accent-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #74c8a3; border-color: #3d9970; } .dark-mode .accent-olive .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-olive .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-olive .custom-select:focus, .dark-mode .accent-olive .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-olive .custom-file-input:focus ~ .custom-file-label { border-color: #cfecdf; } .dark-mode .accent-olive .page-item .page-link { color: #74c8a3; } .dark-mode .accent-olive .page-item.active a, .dark-mode .accent-olive .page-item.active .page-link { background-color: #74c8a3; border-color: #74c8a3; color: #fff; } .dark-mode .accent-olive .page-item.disabled a, .dark-mode .accent-olive .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-olive .page-item .page-link:hover, .dark-mode .dark-mode.accent-olive .page-item .page-link:focus { color: #87cfaf; } .dark-mode .accent-lime .btn-link, .dark-mode .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-lime .nav-tabs .nav-link { color: #67ffa9; } .dark-mode .accent-lime .btn-link:hover, .dark-mode .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-lime .nav-tabs .nav-link:hover { color: #1bff7e; } .dark-mode .accent-lime .dropdown-item:active, .dark-mode .accent-lime .dropdown-item.active { background-color: #67ffa9; color: #1f2d3d; } .dark-mode .accent-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #67ffa9; border-color: #01ff70; } .dark-mode .accent-lime .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-lime .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-lime .custom-select:focus, .dark-mode .accent-lime .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-lime .custom-file-input:focus ~ .custom-file-label { border-color: #e7fff1; } .dark-mode .accent-lime .page-item .page-link { color: #67ffa9; } .dark-mode .accent-lime .page-item.active a, .dark-mode .accent-lime .page-item.active .page-link { background-color: #67ffa9; border-color: #67ffa9; color: #fff; } .dark-mode .accent-lime .page-item.disabled a, .dark-mode .accent-lime .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-lime .page-item .page-link:hover, .dark-mode .dark-mode.accent-lime .page-item .page-link:focus { color: #81ffb8; } .dark-mode .accent-fuchsia .btn-link, .dark-mode .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-fuchsia .nav-tabs .nav-link { color: #f672d8; } .dark-mode .accent-fuchsia .btn-link:hover, .dark-mode .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-fuchsia .nav-tabs .nav-link:hover { color: #f22ac5; } .dark-mode .accent-fuchsia .dropdown-item:active, .dark-mode .accent-fuchsia .dropdown-item.active { background-color: #f672d8; color: #1f2d3d; } .dark-mode .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f672d8; border-color: #f012be; } .dark-mode .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-fuchsia .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-fuchsia .custom-select:focus, .dark-mode .accent-fuchsia .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-fuchsia .custom-file-input:focus ~ .custom-file-label { border-color: #feeaf9; } .dark-mode .accent-fuchsia .page-item .page-link { color: #f672d8; } .dark-mode .accent-fuchsia .page-item.active a, .dark-mode .accent-fuchsia .page-item.active .page-link { background-color: #f672d8; border-color: #f672d8; color: #fff; } .dark-mode .accent-fuchsia .page-item.disabled a, .dark-mode .accent-fuchsia .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-fuchsia .page-item .page-link:hover, .dark-mode .dark-mode.accent-fuchsia .page-item .page-link:focus { color: #f88adf; } .dark-mode .accent-maroon .btn-link, .dark-mode .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-maroon .nav-tabs .nav-link { color: #ed6c9b; } .dark-mode .accent-maroon .btn-link:hover, .dark-mode .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-maroon .nav-tabs .nav-link:hover { color: #e4286d; } .dark-mode .accent-maroon .dropdown-item:active, .dark-mode .accent-maroon .dropdown-item.active { background-color: #ed6c9b; color: #1f2d3d; } .dark-mode .accent-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #ed6c9b; border-color: #d81b60; } .dark-mode .accent-maroon .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-maroon .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-maroon .custom-select:focus, .dark-mode .accent-maroon .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-maroon .custom-file-input:focus ~ .custom-file-label { border-color: #fbdee8; } .dark-mode .accent-maroon .page-item .page-link { color: #ed6c9b; } .dark-mode .accent-maroon .page-item.active a, .dark-mode .accent-maroon .page-item.active .page-link { background-color: #ed6c9b; border-color: #ed6c9b; color: #fff; } .dark-mode .accent-maroon .page-item.disabled a, .dark-mode .accent-maroon .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-maroon .page-item .page-link:hover, .dark-mode .dark-mode.accent-maroon .page-item .page-link:focus { color: #f083ab; } .dark-mode .accent-blue .btn-link, .dark-mode .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-blue .nav-tabs .nav-link { color: #3f6791; } .dark-mode .accent-blue .btn-link:hover, .dark-mode .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-blue .nav-tabs .nav-link:hover { color: #28415c; } .dark-mode .accent-blue .dropdown-item:active, .dark-mode .accent-blue .dropdown-item.active { background-color: #3f6791; color: #fff; } .dark-mode .accent-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3f6791; border-color: #20344a; } .dark-mode .accent-blue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-blue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-blue .custom-select:focus, .dark-mode .accent-blue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-blue .custom-file-input:focus ~ .custom-file-label { border-color: #85a7ca; } .dark-mode .accent-blue .page-item .page-link { color: #3f6791; } .dark-mode .accent-blue .page-item.active a, .dark-mode .accent-blue .page-item.active .page-link { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .accent-blue .page-item.disabled a, .dark-mode .accent-blue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-blue .page-item .page-link:hover, .dark-mode .dark-mode.accent-blue .page-item .page-link:focus { color: #4774a3; } .dark-mode .accent-indigo .btn-link, .dark-mode .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-indigo .nav-tabs .nav-link { color: #6610f2; } .dark-mode .accent-indigo .btn-link:hover, .dark-mode .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-indigo .nav-tabs .nav-link:hover { color: #4709ac; } .dark-mode .accent-indigo .dropdown-item:active, .dark-mode .accent-indigo .dropdown-item.active { background-color: #6610f2; color: #fff; } .dark-mode .accent-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .dark-mode .accent-indigo .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-indigo .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-indigo .custom-select:focus, .dark-mode .accent-indigo .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-indigo .custom-file-input:focus ~ .custom-file-label { border-color: #b389f9; } .dark-mode .accent-indigo .page-item .page-link { color: #6610f2; } .dark-mode .accent-indigo .page-item.active a, .dark-mode .accent-indigo .page-item.active .page-link { background-color: #6610f2; border-color: #6610f2; color: #fff; } .dark-mode .accent-indigo .page-item.disabled a, .dark-mode .accent-indigo .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-indigo .page-item .page-link:hover, .dark-mode .dark-mode.accent-indigo .page-item .page-link:focus { color: #7528f3; } .dark-mode .accent-purple .btn-link, .dark-mode .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-purple .nav-tabs .nav-link { color: #6f42c1; } .dark-mode .accent-purple .btn-link:hover, .dark-mode .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-purple .nav-tabs .nav-link:hover { color: #4e2d89; } .dark-mode .accent-purple .dropdown-item:active, .dark-mode .accent-purple .dropdown-item.active { background-color: #6f42c1; color: #fff; } .dark-mode .accent-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .dark-mode .accent-purple .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-purple .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-purple .custom-select:focus, .dark-mode .accent-purple .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-purple .custom-file-input:focus ~ .custom-file-label { border-color: #b8a2e0; } .dark-mode .accent-purple .page-item .page-link { color: #6f42c1; } .dark-mode .accent-purple .page-item.active a, .dark-mode .accent-purple .page-item.active .page-link { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .dark-mode .accent-purple .page-item.disabled a, .dark-mode .accent-purple .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-purple .page-item .page-link:hover, .dark-mode .dark-mode.accent-purple .page-item .page-link:focus { color: #7e55c7; } .dark-mode .accent-pink .btn-link, .dark-mode .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-pink .nav-tabs .nav-link { color: #e83e8c; } .dark-mode .accent-pink .btn-link:hover, .dark-mode .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-pink .nav-tabs .nav-link:hover { color: #c21766; } .dark-mode .accent-pink .dropdown-item:active, .dark-mode .accent-pink .dropdown-item.active { background-color: #e83e8c; color: #fff; } .dark-mode .accent-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .dark-mode .accent-pink .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-pink .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-pink .custom-select:focus, .dark-mode .accent-pink .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-pink .custom-file-input:focus ~ .custom-file-label { border-color: #f6b0d0; } .dark-mode .accent-pink .page-item .page-link { color: #e83e8c; } .dark-mode .accent-pink .page-item.active a, .dark-mode .accent-pink .page-item.active .page-link { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .dark-mode .accent-pink .page-item.disabled a, .dark-mode .accent-pink .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-pink .page-item .page-link:hover, .dark-mode .dark-mode.accent-pink .page-item .page-link:focus { color: #eb559a; } .dark-mode .accent-red .btn-link, .dark-mode .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-red .nav-tabs .nav-link { color: #e74c3c; } .dark-mode .accent-red .btn-link:hover, .dark-mode .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-red .nav-tabs .nav-link:hover { color: #bf2718; } .dark-mode .accent-red .dropdown-item:active, .dark-mode .accent-red .dropdown-item.active { background-color: #e74c3c; color: #fff; } .dark-mode .accent-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #e74c3c; border-color: #a82315; } .dark-mode .accent-red .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-red .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-red .custom-select:focus, .dark-mode .accent-red .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-red .custom-file-input:focus ~ .custom-file-label { border-color: #f5b4ae; } .dark-mode .accent-red .page-item .page-link { color: #e74c3c; } .dark-mode .accent-red .page-item.active a, .dark-mode .accent-red .page-item.active .page-link { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .accent-red .page-item.disabled a, .dark-mode .accent-red .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-red .page-item .page-link:hover, .dark-mode .dark-mode.accent-red .page-item .page-link:focus { color: #ea6153; } .dark-mode .accent-orange .btn-link, .dark-mode .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-orange .nav-tabs .nav-link { color: #fd7e14; } .dark-mode .accent-orange .btn-link:hover, .dark-mode .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-orange .nav-tabs .nav-link:hover { color: #c35a02; } .dark-mode .accent-orange .dropdown-item:active, .dark-mode .accent-orange .dropdown-item.active { background-color: #fd7e14; color: #1f2d3d; } .dark-mode .accent-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .dark-mode .accent-orange .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-orange .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-orange .custom-select:focus, .dark-mode .accent-orange .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-orange .custom-file-input:focus ~ .custom-file-label { border-color: #fec392; } .dark-mode .accent-orange .page-item .page-link { color: #fd7e14; } .dark-mode .accent-orange .page-item.active a, .dark-mode .accent-orange .page-item.active .page-link { background-color: #fd7e14; border-color: #fd7e14; color: #fff; } .dark-mode .accent-orange .page-item.disabled a, .dark-mode .accent-orange .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-orange .page-item .page-link:hover, .dark-mode .dark-mode.accent-orange .page-item .page-link:focus { color: #fd8c2d; } .dark-mode .accent-yellow .btn-link, .dark-mode .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-yellow .nav-tabs .nav-link { color: #f39c12; } .dark-mode .accent-yellow .btn-link:hover, .dark-mode .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-yellow .nav-tabs .nav-link:hover { color: #b06f09; } .dark-mode .accent-yellow .dropdown-item:active, .dark-mode .accent-yellow .dropdown-item.active { background-color: #f39c12; color: #1f2d3d; } .dark-mode .accent-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #f39c12; border-color: #976008; } .dark-mode .accent-yellow .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-yellow .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-yellow .custom-select:focus, .dark-mode .accent-yellow .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-yellow .custom-file-input:focus ~ .custom-file-label { border-color: #f9cf8b; } .dark-mode .accent-yellow .page-item .page-link { color: #f39c12; } .dark-mode .accent-yellow .page-item.active a, .dark-mode .accent-yellow .page-item.active .page-link { background-color: #f39c12; border-color: #f39c12; color: #fff; } .dark-mode .accent-yellow .page-item.disabled a, .dark-mode .accent-yellow .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-yellow .page-item .page-link:hover, .dark-mode .dark-mode.accent-yellow .page-item .page-link:focus { color: #f4a62a; } .dark-mode .accent-green .btn-link, .dark-mode .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-green .nav-tabs .nav-link { color: #00bc8c; } .dark-mode .accent-green .btn-link:hover, .dark-mode .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-green .nav-tabs .nav-link:hover { color: #007053; } .dark-mode .accent-green .dropdown-item:active, .dark-mode .accent-green .dropdown-item.active { background-color: #00bc8c; color: #fff; } .dark-mode .accent-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #00bc8c; border-color: #005640; } .dark-mode .accent-green .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-green .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-green .custom-select:focus, .dark-mode .accent-green .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-green .custom-file-input:focus ~ .custom-file-label { border-color: #3dffcd; } .dark-mode .accent-green .page-item .page-link { color: #00bc8c; } .dark-mode .accent-green .page-item.active a, .dark-mode .accent-green .page-item.active .page-link { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .accent-green .page-item.disabled a, .dark-mode .accent-green .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-green .page-item .page-link:hover, .dark-mode .dark-mode.accent-green .page-item .page-link:focus { color: #00d69f; } .dark-mode .accent-teal .btn-link, .dark-mode .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-teal .nav-tabs .nav-link { color: #20c997; } .dark-mode .accent-teal .btn-link:hover, .dark-mode .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-teal .nav-tabs .nav-link:hover { color: #158765; } .dark-mode .accent-teal .dropdown-item:active, .dark-mode .accent-teal .dropdown-item.active { background-color: #20c997; color: #fff; } .dark-mode .accent-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .dark-mode .accent-teal .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-teal .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-teal .custom-select:focus, .dark-mode .accent-teal .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-teal .custom-file-input:focus ~ .custom-file-label { border-color: #7eeaca; } .dark-mode .accent-teal .page-item .page-link { color: #20c997; } .dark-mode .accent-teal .page-item.active a, .dark-mode .accent-teal .page-item.active .page-link { background-color: #20c997; border-color: #20c997; color: #fff; } .dark-mode .accent-teal .page-item.disabled a, .dark-mode .accent-teal .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-teal .page-item .page-link:hover, .dark-mode .dark-mode.accent-teal .page-item .page-link:focus { color: #26dca6; } .dark-mode .accent-cyan .btn-link, .dark-mode .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-cyan .nav-tabs .nav-link { color: #3498db; } .dark-mode .accent-cyan .btn-link:hover, .dark-mode .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-cyan .nav-tabs .nav-link:hover { color: #1d6fa5; } .dark-mode .accent-cyan .dropdown-item:active, .dark-mode .accent-cyan .dropdown-item.active { background-color: #3498db; color: #fff; } .dark-mode .accent-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #3498db; border-color: #196090; } .dark-mode .accent-cyan .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-cyan .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-cyan .custom-select:focus, .dark-mode .accent-cyan .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-cyan .custom-file-input:focus ~ .custom-file-label { border-color: #a0cfee; } .dark-mode .accent-cyan .page-item .page-link { color: #3498db; } .dark-mode .accent-cyan .page-item.active a, .dark-mode .accent-cyan .page-item.active .page-link { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .accent-cyan .page-item.disabled a, .dark-mode .accent-cyan .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-cyan .page-item .page-link:hover, .dark-mode .dark-mode.accent-cyan .page-item .page-link:focus { color: #4aa3df; } .dark-mode .accent-white .btn-link, .dark-mode .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-white .nav-tabs .nav-link { color: #fff; } .dark-mode .accent-white .btn-link:hover, .dark-mode .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-white .nav-tabs .nav-link:hover { color: #d9d9d9; } .dark-mode .accent-white .dropdown-item:active, .dark-mode .accent-white .dropdown-item.active { background-color: #fff; color: #1f2d3d; } .dark-mode .accent-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .dark-mode .accent-white .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-white .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-white .custom-select:focus, .dark-mode .accent-white .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-white .custom-file-input:focus ~ .custom-file-label { border-color: white; } .dark-mode .accent-white .page-item .page-link { color: #fff; } .dark-mode .accent-white .page-item.active a, .dark-mode .accent-white .page-item.active .page-link { background-color: #fff; border-color: #fff; color: #fff; } .dark-mode .accent-white .page-item.disabled a, .dark-mode .accent-white .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-white .page-item .page-link:hover, .dark-mode .dark-mode.accent-white .page-item .page-link:focus { color: white; } .dark-mode .accent-gray .btn-link, .dark-mode .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-gray .nav-tabs .nav-link { color: #6c757d; } .dark-mode .accent-gray .btn-link:hover, .dark-mode .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-gray .nav-tabs .nav-link:hover { color: #494f54; } .dark-mode .accent-gray .dropdown-item:active, .dark-mode .accent-gray .dropdown-item.active { background-color: #6c757d; color: #fff; } .dark-mode .accent-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .dark-mode .accent-gray .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-gray .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-gray .custom-select:focus, .dark-mode .accent-gray .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-gray .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .dark-mode .accent-gray .page-item .page-link { color: #6c757d; } .dark-mode .accent-gray .page-item.active a, .dark-mode .accent-gray .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .accent-gray .page-item.disabled a, .dark-mode .accent-gray .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-gray .page-item .page-link:hover, .dark-mode .dark-mode.accent-gray .page-item .page-link:focus { color: #78828a; } .dark-mode .accent-gray-dark .btn-link, .dark-mode .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .dark-mode .accent-gray-dark .nav-tabs .nav-link { color: #343a40; } .dark-mode .accent-gray-dark .btn-link:hover, .dark-mode .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .dark-mode .accent-gray-dark .nav-tabs .nav-link:hover { color: #121416; } .dark-mode .accent-gray-dark .dropdown-item:active, .dark-mode .accent-gray-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .dark-mode .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .dark-mode .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .dark-mode .accent-gray-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .dark-mode .accent-gray-dark .custom-select:focus, .dark-mode .accent-gray-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .dark-mode .accent-gray-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .dark-mode .accent-gray-dark .page-item .page-link { color: #343a40; } .dark-mode .accent-gray-dark .page-item.active a, .dark-mode .accent-gray-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .accent-gray-dark .page-item.disabled a, .dark-mode .accent-gray-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .dark-mode .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .dark-mode .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .dark-mode .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .dark-mode .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .dark-mode .dark-mode.accent-gray-dark .page-item .page-link:hover, .dark-mode .dark-mode.accent-gray-dark .page-item .page-link:focus { color: #3f474e; } .dark-mode .border-dark { border-color: #4b545c !important; } /*# sourceMappingURL=adminlte.core.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.extra-components.css ================================================ /*! * AdminLTE v3.2.0 * Only Extra Components * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .small-box { border-radius: 0.25rem; box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); display: block; margin-bottom: 20px; position: relative; } .small-box > .inner { padding: 10px; } .small-box > .small-box-footer { background-color: rgba(0, 0, 0, 0.1); color: rgba(255, 255, 255, 0.8); display: block; padding: 3px 0; position: relative; text-align: center; text-decoration: none; z-index: 10; } .small-box > .small-box-footer:hover { background-color: rgba(0, 0, 0, 0.15); color: #fff; } .small-box h3 { font-size: 2.2rem; font-weight: 700; margin: 0 0 10px; padding: 0; white-space: nowrap; } @media (min-width: 992px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 1.6rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 1.6rem; } } @media (min-width: 1200px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 2.2rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 2.2rem; } } .small-box p { font-size: 1rem; } .small-box p > small { color: #f8f9fa; display: block; font-size: .9rem; margin-top: 5px; } .small-box h3, .small-box p { z-index: 5; } .small-box .icon { color: rgba(0, 0, 0, 0.15); z-index: 0; } .small-box .icon > i { font-size: 90px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box .icon > i.fa, .small-box .icon > i.fas, .small-box .icon > i.far, .small-box .icon > i.fab, .small-box .icon > i.fal, .small-box .icon > i.fad, .small-box .icon > i.ion { font-size: 70px; top: 20px; } .small-box .icon svg { font-size: 70px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box:hover { text-decoration: none; } .small-box:hover .icon > i, .small-box:hover .icon > i.fa, .small-box:hover .icon > i.fas, .small-box:hover .icon > i.far, .small-box:hover .icon > i.fab, .small-box:hover .icon > i.fal, .small-box:hover .icon > i.fad, .small-box:hover .icon > i.ion { -webkit-transform: scale(1.1); transform: scale(1.1); } .small-box:hover .icon > svg { -webkit-transform: scale(1.1); transform: scale(1.1); } @media (max-width: 767.98px) { .small-box { text-align: center; } .small-box .icon { display: none; } .small-box p { font-size: 12px; } } .info-box { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; display: -ms-flexbox; display: flex; margin-bottom: 1rem; min-height: 80px; padding: .5rem; position: relative; width: 100%; } .info-box .progress { background-color: rgba(0, 0, 0, 0.125); height: 2px; margin: 5px 0; } .info-box .progress .progress-bar { background-color: #fff; } .info-box .info-box-icon { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; display: -ms-flexbox; display: flex; font-size: 1.875rem; -ms-flex-pack: center; justify-content: center; text-align: center; width: 70px; } .info-box .info-box-icon > img { max-width: 100%; } .info-box .info-box-content { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; line-height: 1.8; -ms-flex: 1; flex: 1; padding: 0 10px; overflow: hidden; } .info-box .info-box-number { display: block; margin-top: .25rem; font-weight: 700; } .info-box .progress-description, .info-box .info-box-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .info-box .info-box .bg-primary, .info-box .info-box .bg-gradient-primary { color: #fff; } .info-box .info-box .bg-primary .progress-bar, .info-box .info-box .bg-gradient-primary .progress-bar { background-color: #fff; } .info-box .info-box .bg-secondary, .info-box .info-box .bg-gradient-secondary { color: #fff; } .info-box .info-box .bg-secondary .progress-bar, .info-box .info-box .bg-gradient-secondary .progress-bar { background-color: #fff; } .info-box .info-box .bg-success, .info-box .info-box .bg-gradient-success { color: #fff; } .info-box .info-box .bg-success .progress-bar, .info-box .info-box .bg-gradient-success .progress-bar { background-color: #fff; } .info-box .info-box .bg-info, .info-box .info-box .bg-gradient-info { color: #fff; } .info-box .info-box .bg-info .progress-bar, .info-box .info-box .bg-gradient-info .progress-bar { background-color: #fff; } .info-box .info-box .bg-warning, .info-box .info-box .bg-gradient-warning { color: #1f2d3d; } .info-box .info-box .bg-warning .progress-bar, .info-box .info-box .bg-gradient-warning .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-danger, .info-box .info-box .bg-gradient-danger { color: #fff; } .info-box .info-box .bg-danger .progress-bar, .info-box .info-box .bg-gradient-danger .progress-bar { background-color: #fff; } .info-box .info-box .bg-light, .info-box .info-box .bg-gradient-light { color: #1f2d3d; } .info-box .info-box .bg-light .progress-bar, .info-box .info-box .bg-gradient-light .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-dark, .info-box .info-box .bg-gradient-dark { color: #fff; } .info-box .info-box .bg-dark .progress-bar, .info-box .info-box .bg-gradient-dark .progress-bar { background-color: #fff; } .info-box .info-box-more { display: block; } .info-box .progress-description { margin: 0; } @media (min-width: 768px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { display: none; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { display: none; } } @media (min-width: 992px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 0.75rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 0.75rem; display: block; } } @media (min-width: 1200px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 1rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 1rem; display: block; } } .dark-mode .info-box { background-color: #343a40; color: #fff; } .dark-mode .info-box .info-box .bg-primary, .dark-mode .info-box .info-box .bg-gradient-primary { color: #fff; } .dark-mode .info-box .info-box .bg-primary .progress-bar, .dark-mode .info-box .info-box .bg-gradient-primary .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-secondary, .dark-mode .info-box .info-box .bg-gradient-secondary { color: #fff; } .dark-mode .info-box .info-box .bg-secondary .progress-bar, .dark-mode .info-box .info-box .bg-gradient-secondary .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-success, .dark-mode .info-box .info-box .bg-gradient-success { color: #fff; } .dark-mode .info-box .info-box .bg-success .progress-bar, .dark-mode .info-box .info-box .bg-gradient-success .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-info, .dark-mode .info-box .info-box .bg-gradient-info { color: #fff; } .dark-mode .info-box .info-box .bg-info .progress-bar, .dark-mode .info-box .info-box .bg-gradient-info .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-warning, .dark-mode .info-box .info-box .bg-gradient-warning { color: #1f2d3d; } .dark-mode .info-box .info-box .bg-warning .progress-bar, .dark-mode .info-box .info-box .bg-gradient-warning .progress-bar { background-color: #1f2d3d; } .dark-mode .info-box .info-box .bg-danger, .dark-mode .info-box .info-box .bg-gradient-danger { color: #fff; } .dark-mode .info-box .info-box .bg-danger .progress-bar, .dark-mode .info-box .info-box .bg-gradient-danger .progress-bar { background-color: #fff; } .dark-mode .info-box .info-box .bg-light, .dark-mode .info-box .info-box .bg-gradient-light { color: #1f2d3d; } .dark-mode .info-box .info-box .bg-light .progress-bar, .dark-mode .info-box .info-box .bg-gradient-light .progress-bar { background-color: #1f2d3d; } .dark-mode .info-box .info-box .bg-dark, .dark-mode .info-box .info-box .bg-gradient-dark { color: #fff; } .dark-mode .info-box .info-box .bg-dark .progress-bar, .dark-mode .info-box .info-box .bg-gradient-dark .progress-bar { background-color: #fff; } .timeline { margin: 0 0 45px; padding: 0; position: relative; } .timeline::before { border-radius: 0.25rem; background-color: #dee2e6; bottom: 0; content: ""; left: 31px; margin: 0; position: absolute; top: 0; width: 4px; } .timeline > div { margin-bottom: 15px; margin-right: 10px; position: relative; } .timeline > div::before, .timeline > div::after { content: ""; display: table; } .timeline > div > .timeline-item { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; color: #495057; margin-left: 60px; margin-right: 15px; margin-top: 0; padding: 0; position: relative; } .timeline > div > .timeline-item > .time { color: #999; float: right; font-size: 12px; padding: 10px; } .timeline > div > .timeline-item > .timeline-header { border-bottom: 1px solid rgba(0, 0, 0, 0.125); color: #495057; font-size: 16px; line-height: 1.1; margin: 0; padding: 10px; } .timeline > div > .timeline-item > .timeline-header > a { font-weight: 600; } .timeline > div > .timeline-item > .timeline-body, .timeline > div > .timeline-item > .timeline-footer { padding: 10px; } .timeline > div > .timeline-item > .timeline-body > img { margin: 10px; } .timeline > div > .timeline-item > .timeline-body > dl, .timeline > div > .timeline-item > .timeline-body ol, .timeline > div > .timeline-item > .timeline-body ul { margin: 0; } .timeline > div > .timeline-item > .timeline-footer > a { color: #fff; } .timeline > div > .fa, .timeline > div > .fas, .timeline > div > .far, .timeline > div > .fab, .timeline > div > .fal, .timeline > div > .fad, .timeline > div > .svg-inline--fa, .timeline > div > .ion { background-color: #adb5bd; border-radius: 50%; font-size: 16px; height: 30px; left: 18px; line-height: 30px; position: absolute; text-align: center; top: 0; width: 30px; } .timeline > div > .svg-inline--fa { padding: 7px; } .timeline > .time-label > span { border-radius: 4px; background-color: #fff; display: inline-block; font-weight: 600; padding: 5px; } .timeline-inverse > div > .timeline-item { box-shadow: none; background-color: #f8f9fa; border: 1px solid #dee2e6; } .timeline-inverse > div > .timeline-item > .timeline-header { border-bottom-color: #dee2e6; } .dark-mode .timeline::before { background-color: #6c757d; } .dark-mode .timeline > div > .timeline-item { background-color: #343a40; color: #fff; border-color: #6c757d; } .dark-mode .timeline > div > .timeline-item > .timeline-header { color: #ced4da; border-color: #6c757d; } .dark-mode .timeline > div > .timeline-item > .time { color: #ced4da; } .products-list { list-style: none; margin: 0; padding: 0; } .products-list > .item { border-radius: 0.25rem; background-color: #fff; padding: 10px 0; } .products-list > .item::after { display: block; clear: both; content: ""; } .products-list .product-img { float: left; } .products-list .product-img img { height: 50px; width: 50px; } .products-list .product-info { margin-left: 60px; } .products-list .product-title { font-weight: 600; } .products-list .product-description { color: #6c757d; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .product-list-in-card > .item { border-radius: 0; border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .product-list-in-card > .item:last-of-type { border-bottom-width: 0; } .dark-mode .products-list > .item { background-color: #343a40; color: #fff; border-bottom-color: #6c757d; } .dark-mode .product-description { color: #ced4da; } .direct-chat .card-body { overflow-x: hidden; padding: 0; position: relative; } .direct-chat.chat-pane-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat.timestamp-light .direct-chat-timestamp { color: #30465f; } .direct-chat.timestamp-dark .direct-chat-timestamp { color: #cccccc; } .direct-chat-messages { -webkit-transform: translate(0, 0); transform: translate(0, 0); height: 250px; overflow: auto; padding: 10px; } .direct-chat-msg, .direct-chat-text { display: block; } .direct-chat-msg { margin-bottom: 10px; } .direct-chat-msg::after { display: block; clear: both; content: ""; } .direct-chat-messages, .direct-chat-contacts { transition: -webkit-transform .5s ease-in-out; transition: transform .5s ease-in-out; transition: transform .5s ease-in-out, -webkit-transform .5s ease-in-out; } .direct-chat-text { border-radius: 0.3rem; background-color: #d2d6de; border: 1px solid #d2d6de; color: #444; margin: 5px 0 0 50px; padding: 5px 10px; position: relative; } .direct-chat-text::after, .direct-chat-text::before { border: solid transparent; border-right-color: #d2d6de; content: " "; height: 0; pointer-events: none; position: absolute; right: 100%; top: 15px; width: 0; } .direct-chat-text::after { border-width: 5px; margin-top: -5px; } .direct-chat-text::before { border-width: 6px; margin-top: -6px; } .right .direct-chat-text { margin-left: 0; margin-right: 50px; } .right .direct-chat-text::after, .right .direct-chat-text::before { border-left-color: #d2d6de; border-right-color: transparent; left: 100%; right: auto; } .direct-chat-img { border-radius: 50%; float: left; height: 40px; width: 40px; } .right .direct-chat-img { float: right; } .direct-chat-infos { display: block; font-size: 0.875rem; margin-bottom: 2px; } .direct-chat-name { font-weight: 600; } .direct-chat-timestamp { color: #697582; } .direct-chat-contacts-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat-contacts { -webkit-transform: translate(101%, 0); transform: translate(101%, 0); background-color: #343a40; bottom: 0; color: #fff; height: 250px; overflow: auto; position: absolute; top: 0; width: 100%; } .direct-chat-contacts-light { background-color: #f8f9fa; } .direct-chat-contacts-light .contacts-list-name { color: #495057; } .direct-chat-contacts-light .contacts-list-date { color: #6c757d; } .direct-chat-contacts-light .contacts-list-msg { color: #545b62; } .contacts-list { padding-left: 0; list-style: none; } .contacts-list > li { border-bottom: 1px solid rgba(0, 0, 0, 0.2); margin: 0; padding: 10px; } .contacts-list > li::after { display: block; clear: both; content: ""; } .contacts-list > li:last-of-type { border-bottom: 0; } .contacts-list-img { border-radius: 50%; float: left; width: 40px; } .contacts-list-info { color: #fff; margin-left: 45px; } .contacts-list-name, .contacts-list-status { display: block; } .contacts-list-name { font-weight: 600; } .contacts-list-status { font-size: 0.875rem; } .contacts-list-date { color: #ced4da; font-weight: 400; } .contacts-list-msg { color: #b1bbc4; } .direct-chat-primary .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-primary .right > .direct-chat-text::after, .direct-chat-primary .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-secondary .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-secondary .right > .direct-chat-text::after, .direct-chat-secondary .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-success .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-success .right > .direct-chat-text::after, .direct-chat-success .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-info .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-info .right > .direct-chat-text::after, .direct-chat-info .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-warning .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-warning .right > .direct-chat-text::after, .direct-chat-warning .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-danger .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-danger .right > .direct-chat-text::after, .direct-chat-danger .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-light .right > .direct-chat-text { background-color: #f8f9fa; border-color: #f8f9fa; color: #1f2d3d; } .direct-chat-light .right > .direct-chat-text::after, .direct-chat-light .right > .direct-chat-text::before { border-left-color: #f8f9fa; } .direct-chat-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-dark .right > .direct-chat-text::after, .direct-chat-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .direct-chat-lightblue .right > .direct-chat-text { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .direct-chat-lightblue .right > .direct-chat-text::after, .direct-chat-lightblue .right > .direct-chat-text::before { border-left-color: #3c8dbc; } .direct-chat-navy .right > .direct-chat-text { background-color: #001f3f; border-color: #001f3f; color: #fff; } .direct-chat-navy .right > .direct-chat-text::after, .direct-chat-navy .right > .direct-chat-text::before { border-left-color: #001f3f; } .direct-chat-olive .right > .direct-chat-text { background-color: #3d9970; border-color: #3d9970; color: #fff; } .direct-chat-olive .right > .direct-chat-text::after, .direct-chat-olive .right > .direct-chat-text::before { border-left-color: #3d9970; } .direct-chat-lime .right > .direct-chat-text { background-color: #01ff70; border-color: #01ff70; color: #1f2d3d; } .direct-chat-lime .right > .direct-chat-text::after, .direct-chat-lime .right > .direct-chat-text::before { border-left-color: #01ff70; } .direct-chat-fuchsia .right > .direct-chat-text { background-color: #f012be; border-color: #f012be; color: #fff; } .direct-chat-fuchsia .right > .direct-chat-text::after, .direct-chat-fuchsia .right > .direct-chat-text::before { border-left-color: #f012be; } .direct-chat-maroon .right > .direct-chat-text { background-color: #d81b60; border-color: #d81b60; color: #fff; } .direct-chat-maroon .right > .direct-chat-text::after, .direct-chat-maroon .right > .direct-chat-text::before { border-left-color: #d81b60; } .direct-chat-blue .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-blue .right > .direct-chat-text::after, .direct-chat-blue .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-indigo .right > .direct-chat-text { background-color: #6610f2; border-color: #6610f2; color: #fff; } .direct-chat-indigo .right > .direct-chat-text::after, .direct-chat-indigo .right > .direct-chat-text::before { border-left-color: #6610f2; } .direct-chat-purple .right > .direct-chat-text { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .direct-chat-purple .right > .direct-chat-text::after, .direct-chat-purple .right > .direct-chat-text::before { border-left-color: #6f42c1; } .direct-chat-pink .right > .direct-chat-text { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .direct-chat-pink .right > .direct-chat-text::after, .direct-chat-pink .right > .direct-chat-text::before { border-left-color: #e83e8c; } .direct-chat-red .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-red .right > .direct-chat-text::after, .direct-chat-red .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-orange .right > .direct-chat-text { background-color: #fd7e14; border-color: #fd7e14; color: #1f2d3d; } .direct-chat-orange .right > .direct-chat-text::after, .direct-chat-orange .right > .direct-chat-text::before { border-left-color: #fd7e14; } .direct-chat-yellow .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-yellow .right > .direct-chat-text::after, .direct-chat-yellow .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-green .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-green .right > .direct-chat-text::after, .direct-chat-green .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-teal .right > .direct-chat-text { background-color: #20c997; border-color: #20c997; color: #fff; } .direct-chat-teal .right > .direct-chat-text::after, .direct-chat-teal .right > .direct-chat-text::before { border-left-color: #20c997; } .direct-chat-cyan .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-cyan .right > .direct-chat-text::after, .direct-chat-cyan .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-white .right > .direct-chat-text { background-color: #fff; border-color: #fff; color: #1f2d3d; } .direct-chat-white .right > .direct-chat-text::after, .direct-chat-white .right > .direct-chat-text::before { border-left-color: #fff; } .direct-chat-gray .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-gray .right > .direct-chat-text::after, .direct-chat-gray .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-gray-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-gray-dark .right > .direct-chat-text::after, .direct-chat-gray-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .dark-mode .direct-chat-text { background-color: #454d55; border-color: #4b545c; color: #fff; } .dark-mode .direct-chat-text::after, .dark-mode .direct-chat-text::before { border-right-color: #4b545c; } .dark-mode .direct-chat-timestamp { color: #adb5bd; } .dark-mode .right > .direct-chat-text::after, .dark-mode .right > .direct-chat-text::before { border-right-color: transparent; } .dark-mode .direct-chat-primary .right > .direct-chat-text { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .direct-chat-primary .right > .direct-chat-text::after, .dark-mode .direct-chat-primary .right > .direct-chat-text::before { border-left-color: #3f6791; } .dark-mode .direct-chat-secondary .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .direct-chat-secondary .right > .direct-chat-text::after, .dark-mode .direct-chat-secondary .right > .direct-chat-text::before { border-left-color: #6c757d; } .dark-mode .direct-chat-success .right > .direct-chat-text { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .direct-chat-success .right > .direct-chat-text::after, .dark-mode .direct-chat-success .right > .direct-chat-text::before { border-left-color: #00bc8c; } .dark-mode .direct-chat-info .right > .direct-chat-text { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .direct-chat-info .right > .direct-chat-text::after, .dark-mode .direct-chat-info .right > .direct-chat-text::before { border-left-color: #3498db; } .dark-mode .direct-chat-warning .right > .direct-chat-text { background-color: #f39c12; border-color: #f39c12; color: #1f2d3d; } .dark-mode .direct-chat-warning .right > .direct-chat-text::after, .dark-mode .direct-chat-warning .right > .direct-chat-text::before { border-left-color: #f39c12; } .dark-mode .direct-chat-danger .right > .direct-chat-text { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .direct-chat-danger .right > .direct-chat-text::after, .dark-mode .direct-chat-danger .right > .direct-chat-text::before { border-left-color: #e74c3c; } .dark-mode .direct-chat-light .right > .direct-chat-text { background-color: #f8f9fa; border-color: #f8f9fa; color: #1f2d3d; } .dark-mode .direct-chat-light .right > .direct-chat-text::after, .dark-mode .direct-chat-light .right > .direct-chat-text::before { border-left-color: #f8f9fa; } .dark-mode .direct-chat-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .direct-chat-dark .right > .direct-chat-text::after, .dark-mode .direct-chat-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .dark-mode .direct-chat-lightblue .right > .direct-chat-text { background-color: #86bad8; border-color: #86bad8; color: #1f2d3d; } .dark-mode .direct-chat-lightblue .right > .direct-chat-text::after, .dark-mode .direct-chat-lightblue .right > .direct-chat-text::before { border-left-color: #86bad8; } .dark-mode .direct-chat-navy .right > .direct-chat-text { background-color: #002c59; border-color: #002c59; color: #fff; } .dark-mode .direct-chat-navy .right > .direct-chat-text::after, .dark-mode .direct-chat-navy .right > .direct-chat-text::before { border-left-color: #002c59; } .dark-mode .direct-chat-olive .right > .direct-chat-text { background-color: #74c8a3; border-color: #74c8a3; color: #1f2d3d; } .dark-mode .direct-chat-olive .right > .direct-chat-text::after, .dark-mode .direct-chat-olive .right > .direct-chat-text::before { border-left-color: #74c8a3; } .dark-mode .direct-chat-lime .right > .direct-chat-text { background-color: #67ffa9; border-color: #67ffa9; color: #1f2d3d; } .dark-mode .direct-chat-lime .right > .direct-chat-text::after, .dark-mode .direct-chat-lime .right > .direct-chat-text::before { border-left-color: #67ffa9; } .dark-mode .direct-chat-fuchsia .right > .direct-chat-text { background-color: #f672d8; border-color: #f672d8; color: #1f2d3d; } .dark-mode .direct-chat-fuchsia .right > .direct-chat-text::after, .dark-mode .direct-chat-fuchsia .right > .direct-chat-text::before { border-left-color: #f672d8; } .dark-mode .direct-chat-maroon .right > .direct-chat-text { background-color: #ed6c9b; border-color: #ed6c9b; color: #1f2d3d; } .dark-mode .direct-chat-maroon .right > .direct-chat-text::after, .dark-mode .direct-chat-maroon .right > .direct-chat-text::before { border-left-color: #ed6c9b; } .dark-mode .direct-chat-blue .right > .direct-chat-text { background-color: #3f6791; border-color: #3f6791; color: #fff; } .dark-mode .direct-chat-blue .right > .direct-chat-text::after, .dark-mode .direct-chat-blue .right > .direct-chat-text::before { border-left-color: #3f6791; } .dark-mode .direct-chat-indigo .right > .direct-chat-text { background-color: #6610f2; border-color: #6610f2; color: #fff; } .dark-mode .direct-chat-indigo .right > .direct-chat-text::after, .dark-mode .direct-chat-indigo .right > .direct-chat-text::before { border-left-color: #6610f2; } .dark-mode .direct-chat-purple .right > .direct-chat-text { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .dark-mode .direct-chat-purple .right > .direct-chat-text::after, .dark-mode .direct-chat-purple .right > .direct-chat-text::before { border-left-color: #6f42c1; } .dark-mode .direct-chat-pink .right > .direct-chat-text { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .dark-mode .direct-chat-pink .right > .direct-chat-text::after, .dark-mode .direct-chat-pink .right > .direct-chat-text::before { border-left-color: #e83e8c; } .dark-mode .direct-chat-red .right > .direct-chat-text { background-color: #e74c3c; border-color: #e74c3c; color: #fff; } .dark-mode .direct-chat-red .right > .direct-chat-text::after, .dark-mode .direct-chat-red .right > .direct-chat-text::before { border-left-color: #e74c3c; } .dark-mode .direct-chat-orange .right > .direct-chat-text { background-color: #fd7e14; border-color: #fd7e14; color: #1f2d3d; } .dark-mode .direct-chat-orange .right > .direct-chat-text::after, .dark-mode .direct-chat-orange .right > .direct-chat-text::before { border-left-color: #fd7e14; } .dark-mode .direct-chat-yellow .right > .direct-chat-text { background-color: #f39c12; border-color: #f39c12; color: #1f2d3d; } .dark-mode .direct-chat-yellow .right > .direct-chat-text::after, .dark-mode .direct-chat-yellow .right > .direct-chat-text::before { border-left-color: #f39c12; } .dark-mode .direct-chat-green .right > .direct-chat-text { background-color: #00bc8c; border-color: #00bc8c; color: #fff; } .dark-mode .direct-chat-green .right > .direct-chat-text::after, .dark-mode .direct-chat-green .right > .direct-chat-text::before { border-left-color: #00bc8c; } .dark-mode .direct-chat-teal .right > .direct-chat-text { background-color: #20c997; border-color: #20c997; color: #fff; } .dark-mode .direct-chat-teal .right > .direct-chat-text::after, .dark-mode .direct-chat-teal .right > .direct-chat-text::before { border-left-color: #20c997; } .dark-mode .direct-chat-cyan .right > .direct-chat-text { background-color: #3498db; border-color: #3498db; color: #fff; } .dark-mode .direct-chat-cyan .right > .direct-chat-text::after, .dark-mode .direct-chat-cyan .right > .direct-chat-text::before { border-left-color: #3498db; } .dark-mode .direct-chat-white .right > .direct-chat-text { background-color: #fff; border-color: #fff; color: #1f2d3d; } .dark-mode .direct-chat-white .right > .direct-chat-text::after, .dark-mode .direct-chat-white .right > .direct-chat-text::before { border-left-color: #fff; } .dark-mode .direct-chat-gray .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .dark-mode .direct-chat-gray .right > .direct-chat-text::after, .dark-mode .direct-chat-gray .right > .direct-chat-text::before { border-left-color: #6c757d; } .dark-mode .direct-chat-gray-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .dark-mode .direct-chat-gray-dark .right > .direct-chat-text::after, .dark-mode .direct-chat-gray-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .users-list { padding-left: 0; list-style: none; } .users-list > li { float: left; padding: 10px; text-align: center; width: 25%; } .users-list > li img { border-radius: 50%; height: auto; max-width: 100%; } .users-list > li > a:hover, .users-list > li > a:hover .users-list-name { color: #999; } .users-list-name, .users-list-date { display: block; } .users-list-name { color: #495057; font-size: 0.875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .users-list-date { color: #748290; font-size: 12px; } .dark-mode .users-list-name { color: #ced4da; } .dark-mode .users-list-date { color: #adb5bd; } .card-widget { border: 0; position: relative; } .widget-user .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; height: 135px; padding: 1rem; text-align: center; } .widget-user .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 0; margin-top: 0; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); } .widget-user .widget-user-desc { margin-top: 0; } .widget-user .widget-user-image { left: 50%; margin-left: -45px; position: absolute; top: 80px; } .widget-user .widget-user-image > img { border: 3px solid #fff; height: auto; width: 90px; } .widget-user .card-footer { padding-top: 50px; } .widget-user-2 .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; padding: 1rem; } .widget-user-2 .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 5px; margin-top: 5px; } .widget-user-2 .widget-user-desc { margin-top: 0; } .widget-user-2 .widget-user-username, .widget-user-2 .widget-user-desc { margin-left: 75px; } .widget-user-2 .widget-user-image > img { float: left; height: auto; width: 65px; } /*# sourceMappingURL=adminlte.extra-components.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.light.css ================================================ /*! * AdminLTE v3.2.0 * Without Dark mode * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ /*! * AdminLTE v3.2.0 * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ /*! * Bootstrap v4.6.1 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --blue: #007bff; --indigo: #6610f2; --purple: #6f42c1; --pink: #e83e8c; --red: #dc3545; --orange: #fd7e14; --yellow: #ffc107; --green: #28a745; --teal: #20c997; --cyan: #17a2b8; --white: #fff; --gray: #6c757d; --gray-dark: #343a40; --primary: #007bff; --secondary: #6c757d; --success: #28a745; --info: #17a2b8; --warning: #ffc107; --danger: #dc3545; --light: #f8f9fa; --dark: #343a40; --breakpoint-xs: 0; --breakpoint-sm: 576px; --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; --font-family-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } *, *::before, *::after { box-sizing: border-box; } html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: left; background-color: #fff; } [tabindex="-1"]:focus:not(:focus-visible) { outline: 0 !important; } hr { box-sizing: content-box; height: 0; overflow: visible; } h1, h2, h3, h4, h5, h6 { margin-top: 0; margin-bottom: 0.5rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title], abbr[data-original-title] { text-decoration: underline; -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; border-bottom: 0; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: .5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small { font-size: 80%; } sub, sup { position: relative; font-size: 75%; line-height: 0; vertical-align: baseline; } sub { bottom: -.25em; } sup { top: -.5em; } a { color: #007bff; text-decoration: none; background-color: transparent; } a:hover { color: #0056b3; text-decoration: none; } a:not([href]):not([class]) { color: inherit; text-decoration: none; } a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 1em; } pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; -ms-overflow-style: scrollbar; } figure { margin: 0 0 1rem; } img { vertical-align: middle; border-style: none; } svg { overflow: hidden; vertical-align: middle; } table { border-collapse: collapse; } caption { padding-top: 0.75rem; padding-bottom: 0.75rem; color: #6c757d; text-align: left; caption-side: bottom; } th { text-align: inherit; text-align: -webkit-match-parent; } label { display: inline-block; margin-bottom: 0.5rem; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, input { overflow: visible; } button, select { text-transform: none; } [role="button"] { cursor: pointer; } select { word-wrap: normal; } button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } button:not(:disabled), [type="button"]:not(:disabled), [type="reset"]:not(:disabled), [type="submit"]:not(:disabled) { cursor: pointer; } button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { padding: 0; border-style: none; } input[type="radio"], input[type="checkbox"] { box-sizing: border-box; padding: 0; } textarea { overflow: auto; resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { display: block; width: 100%; max-width: 100%; padding: 0; margin-bottom: .5rem; font-size: 1.5rem; line-height: inherit; color: inherit; white-space: normal; } progress { vertical-align: baseline; } [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } [type="search"] { outline-offset: -2px; -webkit-appearance: none; } [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } summary { display: list-item; cursor: pointer; } template { display: none; } [hidden] { display: none !important; } h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; font-family: inherit; font-weight: 500; line-height: 1.2; color: inherit; } h1, .h1 { font-size: 2.5rem; } h2, .h2 { font-size: 2rem; } h3, .h3 { font-size: 1.75rem; } h4, .h4 { font-size: 1.5rem; } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: 6rem; font-weight: 300; line-height: 1.2; } .display-2 { font-size: 5.5rem; font-weight: 300; line-height: 1.2; } .display-3 { font-size: 4.5rem; font-weight: 300; line-height: 1.2; } .display-4 { font-size: 3.5rem; font-weight: 300; line-height: 1.2; } hr { margin-top: 1rem; margin-bottom: 1rem; border: 0; border-top: 1px solid rgba(0, 0, 0, 0.1); } small, .small { font-size: 80%; font-weight: 400; } mark, .mark { padding: 0.2em; background-color: #fcf8e3; } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 90%; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote-footer { display: block; font-size: 80%; color: #6c757d; } .blockquote-footer::before { content: "\2014\00A0"; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; border-radius: 0.25rem; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 90%; color: #6c757d; } code { font-size: 87.5%; color: #e83e8c; word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.2rem 0.4rem; font-size: 87.5%; color: #fff; background-color: #212529; border-radius: 0.2rem; box-shadow: inset 0 -0.1rem 0 rgba(0, 0, 0, 0.25); } kbd kbd { padding: 0; font-size: 100%; font-weight: 700; box-shadow: none; } pre { display: block; font-size: 87.5%; color: #212529; } pre code { font-size: inherit; color: inherit; word-break: normal; } .pre-scrollable { max-height: 340px; overflow-y: scroll; } .container, .container-fluid, .container-sm, .container-md, .container-lg, .container-xl { width: 100%; padding-right: 7.5px; padding-left: 7.5px; margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container, .container-sm { max-width: 540px; } } @media (min-width: 768px) { .container, .container-sm, .container-md { max-width: 720px; } } @media (min-width: 992px) { .container, .container-sm, .container-md, .container-lg { max-width: 960px; } } @media (min-width: 1200px) { .container, .container-sm, .container-md, .container-lg, .container-xl { max-width: 1140px; } } .row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -7.5px; margin-left: -7.5px; } .no-gutters { margin-right: 0; margin-left: 0; } .no-gutters > .col, .no-gutters > [class*="col-"] { padding-right: 0; padding-left: 0; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, .col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, .col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, .col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, .col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, .col-xl-auto { position: relative; width: 100%; padding-right: 7.5px; padding-left: 7.5px; } .col { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-first { -ms-flex-order: -1; order: -1; } .order-last { -ms-flex-order: 13; order: 13; } .order-0 { -ms-flex-order: 0; order: 0; } .order-1 { -ms-flex-order: 1; order: 1; } .order-2 { -ms-flex-order: 2; order: 2; } .order-3 { -ms-flex-order: 3; order: 3; } .order-4 { -ms-flex-order: 4; order: 4; } .order-5 { -ms-flex-order: 5; order: 5; } .order-6 { -ms-flex-order: 6; order: 6; } .order-7 { -ms-flex-order: 7; order: 7; } .order-8 { -ms-flex-order: 8; order: 8; } .order-9 { -ms-flex-order: 9; order: 9; } .order-10 { -ms-flex-order: 10; order: 10; } .order-11 { -ms-flex-order: 11; order: 11; } .order-12 { -ms-flex-order: 12; order: 12; } .offset-1 { margin-left: 8.333333%; } .offset-2 { margin-left: 16.666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.333333%; } .offset-5 { margin-left: 41.666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.333333%; } .offset-8 { margin-left: 66.666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.333333%; } .offset-11 { margin-left: 91.666667%; } @media (min-width: 576px) { .col-sm { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-sm-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-sm-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-sm-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-sm-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-sm-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-sm-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-sm-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-sm-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-sm-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-sm-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-sm-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-sm-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-sm-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-sm-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-sm-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-sm-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-sm-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-sm-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-sm-first { -ms-flex-order: -1; order: -1; } .order-sm-last { -ms-flex-order: 13; order: 13; } .order-sm-0 { -ms-flex-order: 0; order: 0; } .order-sm-1 { -ms-flex-order: 1; order: 1; } .order-sm-2 { -ms-flex-order: 2; order: 2; } .order-sm-3 { -ms-flex-order: 3; order: 3; } .order-sm-4 { -ms-flex-order: 4; order: 4; } .order-sm-5 { -ms-flex-order: 5; order: 5; } .order-sm-6 { -ms-flex-order: 6; order: 6; } .order-sm-7 { -ms-flex-order: 7; order: 7; } .order-sm-8 { -ms-flex-order: 8; order: 8; } .order-sm-9 { -ms-flex-order: 9; order: 9; } .order-sm-10 { -ms-flex-order: 10; order: 10; } .order-sm-11 { -ms-flex-order: 11; order: 11; } .order-sm-12 { -ms-flex-order: 12; order: 12; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.333333%; } .offset-sm-2 { margin-left: 16.666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.333333%; } .offset-sm-5 { margin-left: 41.666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.333333%; } .offset-sm-8 { margin-left: 66.666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.333333%; } .offset-sm-11 { margin-left: 91.666667%; } } @media (min-width: 768px) { .col-md { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-md-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-md-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-md-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-md-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-md-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-md-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-md-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-md-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-md-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-md-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-md-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-md-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-md-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-md-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-md-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-md-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-md-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-md-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-md-first { -ms-flex-order: -1; order: -1; } .order-md-last { -ms-flex-order: 13; order: 13; } .order-md-0 { -ms-flex-order: 0; order: 0; } .order-md-1 { -ms-flex-order: 1; order: 1; } .order-md-2 { -ms-flex-order: 2; order: 2; } .order-md-3 { -ms-flex-order: 3; order: 3; } .order-md-4 { -ms-flex-order: 4; order: 4; } .order-md-5 { -ms-flex-order: 5; order: 5; } .order-md-6 { -ms-flex-order: 6; order: 6; } .order-md-7 { -ms-flex-order: 7; order: 7; } .order-md-8 { -ms-flex-order: 8; order: 8; } .order-md-9 { -ms-flex-order: 9; order: 9; } .order-md-10 { -ms-flex-order: 10; order: 10; } .order-md-11 { -ms-flex-order: 11; order: 11; } .order-md-12 { -ms-flex-order: 12; order: 12; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.333333%; } .offset-md-2 { margin-left: 16.666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.333333%; } .offset-md-5 { margin-left: 41.666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.333333%; } .offset-md-8 { margin-left: 66.666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.333333%; } .offset-md-11 { margin-left: 91.666667%; } } @media (min-width: 992px) { .col-lg { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-lg-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-lg-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-lg-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-lg-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-lg-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-lg-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-lg-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-lg-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-lg-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-lg-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-lg-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-lg-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-lg-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-lg-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-lg-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-lg-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-lg-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-lg-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-lg-first { -ms-flex-order: -1; order: -1; } .order-lg-last { -ms-flex-order: 13; order: 13; } .order-lg-0 { -ms-flex-order: 0; order: 0; } .order-lg-1 { -ms-flex-order: 1; order: 1; } .order-lg-2 { -ms-flex-order: 2; order: 2; } .order-lg-3 { -ms-flex-order: 3; order: 3; } .order-lg-4 { -ms-flex-order: 4; order: 4; } .order-lg-5 { -ms-flex-order: 5; order: 5; } .order-lg-6 { -ms-flex-order: 6; order: 6; } .order-lg-7 { -ms-flex-order: 7; order: 7; } .order-lg-8 { -ms-flex-order: 8; order: 8; } .order-lg-9 { -ms-flex-order: 9; order: 9; } .order-lg-10 { -ms-flex-order: 10; order: 10; } .order-lg-11 { -ms-flex-order: 11; order: 11; } .order-lg-12 { -ms-flex-order: 12; order: 12; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.333333%; } .offset-lg-2 { margin-left: 16.666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.333333%; } .offset-lg-5 { margin-left: 41.666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.333333%; } .offset-lg-8 { margin-left: 66.666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.333333%; } .offset-lg-11 { margin-left: 91.666667%; } } @media (min-width: 1200px) { .col-xl { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; max-width: 100%; } .row-cols-xl-1 > * { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .row-cols-xl-2 > * { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .row-cols-xl-3 > * { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .row-cols-xl-4 > * { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .row-cols-xl-5 > * { -ms-flex: 0 0 20%; flex: 0 0 20%; max-width: 20%; } .row-cols-xl-6 > * { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-auto { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; max-width: 100%; } .col-xl-1 { -ms-flex: 0 0 8.333333%; flex: 0 0 8.333333%; max-width: 8.333333%; } .col-xl-2 { -ms-flex: 0 0 16.666667%; flex: 0 0 16.666667%; max-width: 16.666667%; } .col-xl-3 { -ms-flex: 0 0 25%; flex: 0 0 25%; max-width: 25%; } .col-xl-4 { -ms-flex: 0 0 33.333333%; flex: 0 0 33.333333%; max-width: 33.333333%; } .col-xl-5 { -ms-flex: 0 0 41.666667%; flex: 0 0 41.666667%; max-width: 41.666667%; } .col-xl-6 { -ms-flex: 0 0 50%; flex: 0 0 50%; max-width: 50%; } .col-xl-7 { -ms-flex: 0 0 58.333333%; flex: 0 0 58.333333%; max-width: 58.333333%; } .col-xl-8 { -ms-flex: 0 0 66.666667%; flex: 0 0 66.666667%; max-width: 66.666667%; } .col-xl-9 { -ms-flex: 0 0 75%; flex: 0 0 75%; max-width: 75%; } .col-xl-10 { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; max-width: 83.333333%; } .col-xl-11 { -ms-flex: 0 0 91.666667%; flex: 0 0 91.666667%; max-width: 91.666667%; } .col-xl-12 { -ms-flex: 0 0 100%; flex: 0 0 100%; max-width: 100%; } .order-xl-first { -ms-flex-order: -1; order: -1; } .order-xl-last { -ms-flex-order: 13; order: 13; } .order-xl-0 { -ms-flex-order: 0; order: 0; } .order-xl-1 { -ms-flex-order: 1; order: 1; } .order-xl-2 { -ms-flex-order: 2; order: 2; } .order-xl-3 { -ms-flex-order: 3; order: 3; } .order-xl-4 { -ms-flex-order: 4; order: 4; } .order-xl-5 { -ms-flex-order: 5; order: 5; } .order-xl-6 { -ms-flex-order: 6; order: 6; } .order-xl-7 { -ms-flex-order: 7; order: 7; } .order-xl-8 { -ms-flex-order: 8; order: 8; } .order-xl-9 { -ms-flex-order: 9; order: 9; } .order-xl-10 { -ms-flex-order: 10; order: 10; } .order-xl-11 { -ms-flex-order: 11; order: 11; } .order-xl-12 { -ms-flex-order: 12; order: 12; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.333333%; } .offset-xl-2 { margin-left: 16.666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.333333%; } .offset-xl-5 { margin-left: 41.666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.333333%; } .offset-xl-8 { margin-left: 66.666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.333333%; } .offset-xl-11 { margin-left: 91.666667%; } } .table { width: 100%; margin-bottom: 1rem; color: #212529; background-color: transparent; } .table th, .table td { padding: 0.75rem; vertical-align: top; border-top: 1px solid #dee2e6; } .table thead th { vertical-align: bottom; border-bottom: 2px solid #dee2e6; } .table tbody + tbody { border-top: 2px solid #dee2e6; } .table-sm th, .table-sm td { padding: 0.3rem; } .table-bordered { border: 1px solid #dee2e6; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6; } .table-bordered thead th, .table-bordered thead td { border-bottom-width: 2px; } .table-borderless th, .table-borderless td, .table-borderless thead th, .table-borderless tbody + tbody { border: 0; } .table-striped tbody tr:nth-of-type(odd) { background-color: rgba(0, 0, 0, 0.05); } .table-hover tbody tr:hover { color: #212529; background-color: rgba(0, 0, 0, 0.075); } .table-primary, .table-primary > th, .table-primary > td { background-color: #b8daff; } .table-primary th, .table-primary td, .table-primary thead th, .table-primary tbody + tbody { border-color: #7abaff; } .table-hover .table-primary:hover { background-color: #9fcdff; } .table-hover .table-primary:hover > td, .table-hover .table-primary:hover > th { background-color: #9fcdff; } .table-secondary, .table-secondary > th, .table-secondary > td { background-color: #d6d8db; } .table-secondary th, .table-secondary td, .table-secondary thead th, .table-secondary tbody + tbody { border-color: #b3b7bb; } .table-hover .table-secondary:hover { background-color: #c8cbcf; } .table-hover .table-secondary:hover > td, .table-hover .table-secondary:hover > th { background-color: #c8cbcf; } .table-success, .table-success > th, .table-success > td { background-color: #c3e6cb; } .table-success th, .table-success td, .table-success thead th, .table-success tbody + tbody { border-color: #8fd19e; } .table-hover .table-success:hover { background-color: #b1dfbb; } .table-hover .table-success:hover > td, .table-hover .table-success:hover > th { background-color: #b1dfbb; } .table-info, .table-info > th, .table-info > td { background-color: #bee5eb; } .table-info th, .table-info td, .table-info thead th, .table-info tbody + tbody { border-color: #86cfda; } .table-hover .table-info:hover { background-color: #abdde5; } .table-hover .table-info:hover > td, .table-hover .table-info:hover > th { background-color: #abdde5; } .table-warning, .table-warning > th, .table-warning > td { background-color: #ffeeba; } .table-warning th, .table-warning td, .table-warning thead th, .table-warning tbody + tbody { border-color: #ffdf7e; } .table-hover .table-warning:hover { background-color: #ffe8a1; } .table-hover .table-warning:hover > td, .table-hover .table-warning:hover > th { background-color: #ffe8a1; } .table-danger, .table-danger > th, .table-danger > td { background-color: #f5c6cb; } .table-danger th, .table-danger td, .table-danger thead th, .table-danger tbody + tbody { border-color: #ed969e; } .table-hover .table-danger:hover { background-color: #f1b0b7; } .table-hover .table-danger:hover > td, .table-hover .table-danger:hover > th { background-color: #f1b0b7; } .table-light, .table-light > th, .table-light > td { background-color: #fdfdfe; } .table-light th, .table-light td, .table-light thead th, .table-light tbody + tbody { border-color: #fbfcfc; } .table-hover .table-light:hover { background-color: #ececf6; } .table-hover .table-light:hover > td, .table-hover .table-light:hover > th { background-color: #ececf6; } .table-dark, .table-dark > th, .table-dark > td { background-color: #c6c8ca; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #95999c; } .table-hover .table-dark:hover { background-color: #b9bbbe; } .table-hover .table-dark:hover > td, .table-hover .table-dark:hover > th { background-color: #b9bbbe; } .table-active, .table-active > th, .table-active > td { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover { background-color: rgba(0, 0, 0, 0.075); } .table-hover .table-active:hover > td, .table-hover .table-active:hover > th { background-color: rgba(0, 0, 0, 0.075); } .table .thead-dark th { color: #fff; background-color: #212529; border-color: #383f45; } .table .thead-light th { color: #495057; background-color: #e9ecef; border-color: #dee2e6; } .table-dark { color: #fff; background-color: #212529; } .table-dark th, .table-dark td, .table-dark thead th { border-color: #383f45; } .table-dark.table-bordered { border: 0; } .table-dark.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.05); } .table-dark.table-hover tbody tr:hover { color: #fff; background-color: rgba(255, 255, 255, 0.075); } @media (max-width: 575.98px) { .table-responsive-sm { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-sm > .table-bordered { border: 0; } } @media (max-width: 767.98px) { .table-responsive-md { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-md > .table-bordered { border: 0; } } @media (max-width: 991.98px) { .table-responsive-lg { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-lg > .table-bordered { border: 0; } } @media (max-width: 1199.98px) { .table-responsive-xl { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive-xl > .table-bordered { border: 0; } } .table-responsive { display: block; width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-responsive > .table-bordered { border: 0; } .form-control { display: block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control::-ms-expand { background-color: transparent; border: 0; } .form-control:focus { color: #495057; background-color: #fff; border-color: #80bdff; outline: 0; box-shadow: inset 0 0 0 rgba(0, 0, 0, 0); } .form-control::-webkit-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-moz-placeholder { color: #939ba2; opacity: 1; } .form-control:-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::-ms-input-placeholder { color: #939ba2; opacity: 1; } .form-control::placeholder { color: #939ba2; opacity: 1; } .form-control:disabled, .form-control[readonly] { background-color: #e9ecef; opacity: 1; } input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control { -webkit-appearance: none; -moz-appearance: none; appearance: none; } select.form-control:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } select.form-control:focus::-ms-value { color: #495057; background-color: #fff; } .form-control-file, .form-control-range { display: block; width: 100%; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; line-height: 1.5; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; line-height: 1.5; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; font-size: 1rem; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } .form-control-sm { height: calc(1.8125rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .form-control-lg { height: calc(2.875rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } select.form-control[size], select.form-control[multiple] { height: auto; } textarea.form-control { height: auto; } .form-group { margin-bottom: 1rem; } .form-text { display: block; margin-top: 0.25rem; } .form-row { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -5px; margin-left: -5px; } .form-row > .col, .form-row > [class*="col-"] { padding-right: 5px; padding-left: 5px; } .form-check { position: relative; display: block; padding-left: 1.25rem; } .form-check-input { position: absolute; margin-top: 0.3rem; margin-left: -1.25rem; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { color: #6c757d; } .form-check-label { margin-bottom: 0; } .form-check-inline { display: -ms-inline-flexbox; display: inline-flex; -ms-flex-align: center; align-items: center; padding-left: 0; margin-right: 0.75rem; } .form-check-inline .form-check-input { position: static; margin-top: 0; margin-right: 0.3125rem; margin-left: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #28a745; } .valid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(40, 167, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .valid-tooltip, .form-row > [class*="col-"] > .valid-tooltip { left: 5px; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #28a745; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated select.form-control:valid, select.form-control.is-valid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:valid, .custom-select.is-valid { border-color: #28a745; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #28a745; } .was-validated .form-check-input:valid ~ .valid-feedback, .was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, .form-check-input.is-valid ~ .valid-tooltip { display: block; } .was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { color: #28a745; } .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { border-color: #34ce57; background-color: #34ce57; } .was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { border-color: #28a745; } .was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { border-color: #28a745; } .was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { border-color: #28a745; box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.25); } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 80%; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; left: 0; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: .1rem; font-size: 0.875rem; line-height: 1.5; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.25rem; } .form-row > .col > .invalid-tooltip, .form-row > [class*="col-"] > .invalid-tooltip { left: 5px; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-right: 2.25rem !important; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated select.form-control:invalid, select.form-control.is-invalid { padding-right: 3rem !important; background-position: right 1.5rem center; } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .custom-select:invalid, .custom-select.is-invalid { border-color: #dc3545; padding-right: calc(0.75em + 2.3125rem) !important; background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat; } .was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .was-validated .form-check-input:invalid ~ .invalid-feedback, .was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, .form-check-input.is-invalid ~ .invalid-tooltip { display: block; } .was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { color: #dc3545; } .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { border-color: #e4606d; background-color: #e4606d; } .was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { border-color: #dc3545; } .was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { border-color: #dc3545; box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.25); } .form-inline { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; } .form-inline .form-check { width: 100%; } @media (min-width: 576px) { .form-inline label { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; margin-bottom: 0; } .form-inline .form-group { display: -ms-flexbox; display: flex; -ms-flex: 0 0 auto; flex: 0 0 auto; -ms-flex-flow: row wrap; flex-flow: row wrap; -ms-flex-align: center; align-items: center; margin-bottom: 0; } .form-inline .form-control { display: inline-block; width: auto; vertical-align: middle; } .form-inline .form-control-plaintext { display: inline-block; } .form-inline .input-group, .form-inline .custom-select { width: auto; } .form-inline .form-check { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: auto; padding-left: 0; } .form-inline .form-check-input { position: relative; -ms-flex-negative: 0; flex-shrink: 0; margin-top: 0; margin-right: 0.25rem; margin-left: 0; } .form-inline .custom-control { -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; } .form-inline .custom-control-label { margin-bottom: 0; } } .btn { display: inline-block; font-weight: 400; color: #212529; text-align: center; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: transparent; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; line-height: 1.5; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: #212529; text-decoration: none; } .btn:focus, .btn.focus { outline: 0; box-shadow: none; } .btn.disabled, .btn:disabled { opacity: 0.65; box-shadow: none; } .btn:not(:disabled):not(.disabled) { cursor: pointer; } .btn:not(:disabled):not(.disabled):active, .btn:not(:disabled):not(.disabled).active { box-shadow: none; } a.btn.disabled, fieldset:disabled a.btn { pointer-events: none; } .btn-primary { color: #fff; background-color: #007bff; border-color: #007bff; box-shadow: none; } .btn-primary:hover { color: #fff; background-color: #0069d9; border-color: #0062cc; } .btn-primary:focus, .btn-primary.focus { color: #fff; background-color: #0069d9; border-color: #0062cc; box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, .show > .btn-primary.dropdown-toggle { color: #fff; background-color: #0062cc; border-color: #005cbf; } .btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(38, 143, 255, 0.5); } .btn-secondary { color: #fff; background-color: #6c757d; border-color: #6c757d; box-shadow: none; } .btn-secondary:hover { color: #fff; background-color: #5a6268; border-color: #545b62; } .btn-secondary:focus, .btn-secondary.focus { color: #fff; background-color: #5a6268; border-color: #545b62; box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, .show > .btn-secondary.dropdown-toggle { color: #fff; background-color: #545b62; border-color: #4e555b; } .btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(130, 138, 145, 0.5); } .btn-success { color: #fff; background-color: #28a745; border-color: #28a745; box-shadow: none; } .btn-success:hover { color: #fff; background-color: #218838; border-color: #1e7e34; } .btn-success:focus, .btn-success.focus { color: #fff; background-color: #218838; border-color: #1e7e34; box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-success.disabled, .btn-success:disabled { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, .show > .btn-success.dropdown-toggle { color: #fff; background-color: #1e7e34; border-color: #1c7430; } .btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(72, 180, 97, 0.5); } .btn-info { color: #fff; background-color: #17a2b8; border-color: #17a2b8; box-shadow: none; } .btn-info:hover { color: #fff; background-color: #138496; border-color: #117a8b; } .btn-info:focus, .btn-info.focus { color: #fff; background-color: #138496; border-color: #117a8b; box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-info.disabled, .btn-info:disabled { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, .show > .btn-info.dropdown-toggle { color: #fff; background-color: #117a8b; border-color: #10707f; } .btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(58, 176, 195, 0.5); } .btn-warning { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; box-shadow: none; } .btn-warning:hover { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; } .btn-warning:focus, .btn-warning.focus { color: #1f2d3d; background-color: #e0a800; border-color: #d39e00; box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-warning.disabled, .btn-warning:disabled { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, .show > .btn-warning.dropdown-toggle { color: #1f2d3d; background-color: #d39e00; border-color: #c69500; } .btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(221, 171, 15, 0.5); } .btn-danger { color: #fff; background-color: #dc3545; border-color: #dc3545; box-shadow: none; } .btn-danger:hover { color: #fff; background-color: #c82333; border-color: #bd2130; } .btn-danger:focus, .btn-danger.focus { color: #fff; background-color: #c82333; border-color: #bd2130; box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-danger.disabled, .btn-danger:disabled { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, .show > .btn-danger.dropdown-toggle { color: #fff; background-color: #bd2130; border-color: #b21f2d; } .btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(225, 83, 97, 0.5); } .btn-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; box-shadow: none; } .btn-light:hover { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; } .btn-light:focus, .btn-light.focus { color: #1f2d3d; background-color: #e2e6ea; border-color: #dae0e5; box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-light.disabled, .btn-light:disabled { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, .show > .btn-light.dropdown-toggle { color: #1f2d3d; background-color: #dae0e5; border-color: #d3d9df; } .btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(215, 218, 222, 0.5); } .btn-dark { color: #fff; background-color: #343a40; border-color: #343a40; box-shadow: none; } .btn-dark:hover { color: #fff; background-color: #23272b; border-color: #1d2124; } .btn-dark:focus, .btn-dark.focus { color: #fff; background-color: #23272b; border-color: #1d2124; box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-dark.disabled, .btn-dark:disabled { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, .show > .btn-dark.dropdown-toggle { color: #fff; background-color: #1d2124; border-color: #171a1d; } .btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(82, 88, 93, 0.5); } .btn-outline-primary { color: #007bff; border-color: #007bff; } .btn-outline-primary:hover { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:focus, .btn-outline-primary.focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-primary.disabled, .btn-outline-primary:disabled { color: #007bff; background-color: transparent; } .btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, .show > .btn-outline-primary.dropdown-toggle { color: #fff; background-color: #007bff; border-color: #007bff; } .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-primary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.5); } .btn-outline-secondary { color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:hover { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:focus, .btn-outline-secondary.focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-secondary.disabled, .btn-outline-secondary:disabled { color: #6c757d; background-color: transparent; } .btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, .show > .btn-outline-secondary.dropdown-toggle { color: #fff; background-color: #6c757d; border-color: #6c757d; } .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-secondary.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(108, 117, 125, 0.5); } .btn-outline-success { color: #28a745; border-color: #28a745; } .btn-outline-success:hover { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:focus, .btn-outline-success.focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-success.disabled, .btn-outline-success:disabled { color: #28a745; background-color: transparent; } .btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, .show > .btn-outline-success.dropdown-toggle { color: #fff; background-color: #28a745; border-color: #28a745; } .btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-success.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.5); } .btn-outline-info { color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:hover { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:focus, .btn-outline-info.focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-info.disabled, .btn-outline-info:disabled { color: #17a2b8; background-color: transparent; } .btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, .show > .btn-outline-info.dropdown-toggle { color: #fff; background-color: #17a2b8; border-color: #17a2b8; } .btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-info.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(23, 162, 184, 0.5); } .btn-outline-warning { color: #ffc107; border-color: #ffc107; } .btn-outline-warning:hover { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:focus, .btn-outline-warning.focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-warning.disabled, .btn-outline-warning:disabled { color: #ffc107; background-color: transparent; } .btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, .show > .btn-outline-warning.dropdown-toggle { color: #1f2d3d; background-color: #ffc107; border-color: #ffc107; } .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-warning.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.5); } .btn-outline-danger { color: #dc3545; border-color: #dc3545; } .btn-outline-danger:hover { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:focus, .btn-outline-danger.focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-danger.disabled, .btn-outline-danger:disabled { color: #dc3545; background-color: transparent; } .btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, .show > .btn-outline-danger.dropdown-toggle { color: #fff; background-color: #dc3545; border-color: #dc3545; } .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-danger.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.5); } .btn-outline-light { color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:hover { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:focus, .btn-outline-light.focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #f8f9fa; background-color: transparent; } .btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, .show > .btn-outline-light.dropdown-toggle { color: #1f2d3d; background-color: #f8f9fa; border-color: #f8f9fa; } .btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-light.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(248, 249, 250, 0.5); } .btn-outline-dark { color: #343a40; border-color: #343a40; } .btn-outline-dark:hover { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:focus, .btn-outline-dark.focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-outline-dark.disabled, .btn-outline-dark:disabled { color: #343a40; background-color: transparent; } .btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, .show > .btn-outline-dark.dropdown-toggle { color: #fff; background-color: #343a40; border-color: #343a40; } .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-outline-dark.dropdown-toggle:focus { box-shadow: 0 0 0 0 rgba(52, 58, 64, 0.5); } .btn-link { font-weight: 400; color: #007bff; text-decoration: none; } .btn-link:hover { color: #0056b3; text-decoration: none; } .btn-link:focus, .btn-link.focus { text-decoration: none; } .btn-link:disabled, .btn-link.disabled { color: #6c757d; pointer-events: none; } .btn-lg, .btn-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .btn-sm, .btn-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .btn-block { display: block; width: 100%; } .btn-block + .btn-block { margin-top: 0.5rem; } input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { width: 100%; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { position: relative; height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .dropup, .dropright, .dropdown, .dropleft { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { position: absolute; top: 100%; left: 0; z-index: 1000; display: none; float: left; min-width: 10rem; padding: 0.5rem 0; margin: 0.125rem 0 0; font-size: 1rem; color: #212529; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 0.25rem; box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.175); } .dropdown-menu-left { right: auto; left: 0; } .dropdown-menu-right { right: 0; left: auto; } @media (min-width: 576px) { .dropdown-menu-sm-left { right: auto; left: 0; } .dropdown-menu-sm-right { right: 0; left: auto; } } @media (min-width: 768px) { .dropdown-menu-md-left { right: auto; left: 0; } .dropdown-menu-md-right { right: 0; left: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-left { right: auto; left: 0; } .dropdown-menu-lg-right { right: 0; left: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-left { right: auto; left: 0; } .dropdown-menu-xl-right { right: 0; left: auto; } } .dropup .dropdown-menu { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 0.125rem; } .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-menu { top: 0; right: auto; left: 100%; margin-top: 0; margin-left: 0.125rem; } .dropright .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropright .dropdown-toggle:empty::after { margin-left: 0; } .dropright .dropdown-toggle::after { vertical-align: 0; } .dropleft .dropdown-menu { top: 0; right: 100%; left: auto; margin-top: 0; margin-right: 0.125rem; } .dropleft .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropleft .dropdown-toggle::after { display: none; } .dropleft .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropleft .dropdown-toggle:empty::after { margin-left: 0; } .dropleft .dropdown-toggle::before { vertical-align: 0; } .dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { right: auto; bottom: auto; } .dropdown-divider { height: 0; margin: 0.5rem 0; overflow: hidden; border-top: 1px solid #e9ecef; } .dropdown-item { display: block; width: 100%; padding: 0.25rem 1rem; clear: both; font-weight: 400; color: #212529; text-align: inherit; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: #16181b; text-decoration: none; background-color: #f8f9fa; } .dropdown-item.active, .dropdown-item:active { color: #fff; text-decoration: none; background-color: #007bff; } .dropdown-item.disabled, .dropdown-item:disabled { color: #6c757d; pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: 0.5rem 1rem; margin-bottom: 0; font-size: 0.875rem; color: #6c757d; white-space: nowrap; } .dropdown-item-text { display: block; padding: 0.25rem 1rem; color: #212529; } .btn-group, .btn-group-vertical { position: relative; display: -ms-inline-flexbox; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; } .btn-group > .btn:hover, .btn-group-vertical > .btn:hover { z-index: 1; } .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-pack: start; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) { margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:not(:first-child), .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropright .dropdown-toggle-split::after { margin-left: 0; } .dropleft .dropdown-toggle-split::before { margin-right: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group.show .dropdown-toggle { box-shadow: none; } .btn-group.show .dropdown-toggle.btn-link { box-shadow: none; } .btn-group-vertical { -ms-flex-direction: column; flex-direction: column; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: center; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .btn-group-toggle > .btn, .btn-group-toggle > .btn-group > .btn { margin-bottom: 0; } .btn-group-toggle > .btn input[type="radio"], .btn-group-toggle > .btn input[type="checkbox"], .btn-group-toggle > .btn-group > .btn input[type="radio"], .btn-group-toggle > .btn-group > .btn input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .input-group { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: stretch; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-control-plaintext, .input-group > .custom-select, .input-group > .custom-file { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; width: 1%; min-width: 0; margin-bottom: 0; } .input-group > .form-control + .form-control, .input-group > .form-control + .custom-select, .input-group > .form-control + .custom-file, .input-group > .form-control-plaintext + .form-control, .input-group > .form-control-plaintext + .custom-select, .input-group > .form-control-plaintext + .custom-file, .input-group > .custom-select + .form-control, .input-group > .custom-select + .custom-select, .input-group > .custom-select + .custom-file, .input-group > .custom-file + .form-control, .input-group > .custom-file + .custom-select, .input-group > .custom-file + .custom-file { margin-left: -1px; } .input-group > .form-control:focus, .input-group > .custom-select:focus, .input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { z-index: 3; } .input-group > .custom-file .custom-file-input:focus { z-index: 4; } .input-group > .form-control:not(:first-child), .input-group > .custom-select:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group > .custom-file { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; } .input-group > .custom-file:not(:last-child) .custom-file-label, .input-group > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .custom-file:not(:first-child) .custom-file-label { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group:not(.has-validation) > .form-control:not(:last-child), .input-group:not(.has-validation) > .custom-select:not(:last-child), .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label, .input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group.has-validation > .form-control:nth-last-child(n + 3), .input-group.has-validation > .custom-select:nth-last-child(n + 3), .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label, .input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label::after { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group-prepend, .input-group-append { display: -ms-flexbox; display: flex; } .input-group-prepend .btn, .input-group-append .btn { position: relative; z-index: 2; } .input-group-prepend .btn:focus, .input-group-append .btn:focus { z-index: 3; } .input-group-prepend .btn + .btn, .input-group-prepend .btn + .input-group-text, .input-group-prepend .input-group-text + .input-group-text, .input-group-prepend .input-group-text + .btn, .input-group-append .btn + .btn, .input-group-append .btn + .input-group-text, .input-group-append .input-group-text + .input-group-text, .input-group-append .input-group-text + .btn { margin-left: -1px; } .input-group-prepend { margin-right: -1px; } .input-group-append { margin-left: -1px; } .input-group-text { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.375rem 0.75rem; margin-bottom: 0; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.25rem; } .input-group-text input[type="radio"], .input-group-text input[type="checkbox"] { margin-top: 0; } .input-group-lg > .form-control:not(textarea), .input-group-lg > .custom-select { height: calc(2.875rem + 2px); } .input-group-lg > .form-control, .input-group-lg > .custom-select, .input-group-lg > .input-group-prepend > .input-group-text, .input-group-lg > .input-group-append > .input-group-text, .input-group-lg > .input-group-prepend > .btn, .input-group-lg > .input-group-append > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } .input-group-sm > .form-control:not(textarea), .input-group-sm > .custom-select { height: calc(1.8125rem + 2px); } .input-group-sm > .form-control, .input-group-sm > .custom-select, .input-group-sm > .input-group-prepend > .input-group-text, .input-group-sm > .input-group-append > .input-group-text, .input-group-sm > .input-group-prepend > .btn, .input-group-sm > .input-group-append > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } .input-group-lg > .custom-select, .input-group-sm > .custom-select { padding-right: 1.75rem; } .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .btn, .input-group:not(.has-validation) > .input-group-append:not(:last-child) > .input-group-text, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .btn, .input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .input-group-text, .input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .input-group-append > .btn, .input-group > .input-group-append > .input-group-text, .input-group > .input-group-prepend:not(:first-child) > .btn, .input-group > .input-group-prepend:not(:first-child) > .input-group-text, .input-group > .input-group-prepend:first-child > .btn:not(:first-child), .input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .custom-control { position: relative; z-index: 1; display: block; min-height: 1.5rem; padding-left: 1.5rem; -webkit-print-color-adjust: exact; color-adjust: exact; } .custom-control-inline { display: -ms-inline-flexbox; display: inline-flex; margin-right: 1rem; } .custom-control-input { position: absolute; left: 0; z-index: -1; width: 1rem; height: 1.25rem; opacity: 0; } .custom-control-input:checked ~ .custom-control-label::before { color: #fff; border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-control-input:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input:not(:disabled):active ~ .custom-control-label::before { color: #fff; background-color: #b3d7ff; border-color: #b3d7ff; box-shadow: none; } .custom-control-input[disabled] ~ .custom-control-label, .custom-control-input:disabled ~ .custom-control-label { color: #6c757d; } .custom-control-input[disabled] ~ .custom-control-label::before, .custom-control-input:disabled ~ .custom-control-label::before { background-color: #e9ecef; } .custom-control-label { position: relative; margin-bottom: 0; vertical-align: top; } .custom-control-label::before { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; pointer-events: none; content: ""; background-color: #dee2e6; border: #adb5bd solid 1px; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-control-label::after { position: absolute; top: 0.25rem; left: -1.5rem; display: block; width: 1rem; height: 1rem; content: ""; background: 50% / 50% 50% no-repeat; } .custom-checkbox .custom-control-label::before { border-radius: 0.25rem; } .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; box-shadow: none; } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); } .custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-radio .custom-control-label::before { border-radius: 50%; } .custom-radio .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); } .custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-switch { padding-left: 2.25rem; } .custom-switch .custom-control-label::before { left: -2.25rem; width: 1.75rem; pointer-events: all; border-radius: 0.5rem; } .custom-switch .custom-control-label::after { top: calc(0.25rem + 2px); left: calc(-2.25rem + 2px); width: calc(1rem - 4px); height: calc(1rem - 4px); background-color: #adb5bd; border-radius: 0.5rem; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-switch .custom-control-label::after { transition: none; } } .custom-switch .custom-control-input:checked ~ .custom-control-label::after { background-color: #dee2e6; -webkit-transform: translateX(0.75rem); transform: translateX(0.75rem); } .custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } .custom-select { display: inline-block; width: 100%; height: calc(2.25rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #495057; vertical-align: middle; background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-select:focus { border-color: #80bdff; outline: 0; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); } .custom-select:focus::-ms-value { color: #495057; background-color: #fff; } .custom-select[multiple], .custom-select[size]:not([size="1"]) { height: auto; padding-right: 0.75rem; background-image: none; } .custom-select:disabled { color: #6c757d; background-color: #e9ecef; } .custom-select::-ms-expand { display: none; } .custom-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #495057; } .custom-select-sm { height: calc(1.8125rem + 2px); padding-top: 0.25rem; padding-bottom: 0.25rem; padding-left: 0.5rem; font-size: 75%; } .custom-select-lg { height: calc(2.875rem + 2px); padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 1rem; font-size: 125%; } .custom-file { position: relative; display: inline-block; width: 100%; height: calc(2.25rem + 2px); margin-bottom: 0; } .custom-file-input { position: relative; z-index: 2; width: 100%; height: calc(2.25rem + 2px); margin: 0; overflow: hidden; opacity: 0; } .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; box-shadow: none; } .custom-file-input[disabled] ~ .custom-file-label, .custom-file-input:disabled ~ .custom-file-label { background-color: #e9ecef; } .custom-file-input:lang(en) ~ .custom-file-label::after { content: "Browse"; } .custom-file-input ~ .custom-file-label[data-browse]::after { content: attr(data-browse); } .custom-file-label { position: absolute; top: 0; right: 0; left: 0; z-index: 1; height: calc(2.25rem + 2px); padding: 0.375rem 0.75rem; overflow: hidden; font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; box-shadow: none; } .custom-file-label::after { position: absolute; top: 0; right: 0; bottom: 0; z-index: 3; display: block; height: 2.25rem; padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; content: "Browse"; background-color: #e9ecef; border-left: inherit; border-radius: 0 0.25rem 0.25rem 0; } .custom-range { width: 100%; height: 1rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .custom-range:focus { outline: 0; } .custom-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-range::-moz-focus-outer { border: 0; } .custom-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .custom-range::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .custom-range::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-thumb { width: 1rem; height: 1rem; margin-top: 0; margin-right: 0; margin-left: 0; background-color: #007bff; border: 0; border-radius: 1rem; box-shadow: 0 0.1rem 0.25rem rgba(0, 0, 0, 0.1); -ms-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; appearance: none; } @media (prefers-reduced-motion: reduce) { .custom-range::-ms-thumb { -ms-transition: none; transition: none; } } .custom-range::-ms-thumb:active { background-color: #b3d7ff; } .custom-range::-ms-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: transparent; border-color: transparent; border-width: 0.5rem; box-shadow: inset 0 0.25rem 0.25rem rgba(0, 0, 0, 0.1); } .custom-range::-ms-fill-lower { background-color: #dee2e6; border-radius: 1rem; } .custom-range::-ms-fill-upper { margin-right: 15px; background-color: #dee2e6; border-radius: 1rem; } .custom-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .custom-range:disabled::-webkit-slider-runnable-track { cursor: default; } .custom-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .custom-range:disabled::-moz-range-track { cursor: default; } .custom-range:disabled::-ms-thumb { background-color: #adb5bd; } .custom-control-label::before, .custom-file-label, .custom-select { transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .custom-control-label::before, .custom-file-label, .custom-select { transition: none; } } .nav { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: 0.5rem 1rem; } .nav-link:hover, .nav-link:focus { text-decoration: none; } .nav-link.disabled { color: #6c757d; pointer-events: none; cursor: default; } .nav-tabs { border-bottom: 1px solid #dee2e6; } .nav-tabs .nav-link { margin-bottom: -1px; border: 1px solid transparent; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { border-color: #e9ecef #e9ecef #dee2e6; } .nav-tabs .nav-link.disabled { color: #6c757d; background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: #495057; background-color: #fff; border-color: #dee2e6 #dee2e6 #fff; } .nav-tabs .dropdown-menu { margin-top: -1px; border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills .nav-link { border-radius: 0.25rem; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: #fff; background-color: #007bff; } .nav-fill > .nav-link, .nav-fill .nav-item { -ms-flex: 1 1 auto; flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { -ms-flex-preferred-size: 0; flex-basis: 0; -ms-flex-positive: 1; flex-grow: 1; text-align: center; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { position: relative; display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; padding: 0.5rem 0.5rem; } .navbar .container, .navbar .container-fluid, .navbar .container-sm, .navbar .container-md, .navbar .container-lg, .navbar .container-xl { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: justify; justify-content: space-between; } .navbar-brand { display: inline-block; padding-top: 0.3125rem; padding-bottom: 0.3125rem; margin-right: 0.5rem; font-size: 1.25rem; line-height: inherit; white-space: nowrap; } .navbar-brand:hover, .navbar-brand:focus { text-decoration: none; } .navbar-nav { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .nav-link { padding-right: 0; padding-left: 0; } .navbar-nav .dropdown-menu { position: static; float: none; } .navbar-text { display: inline-block; padding-top: 0.5rem; padding-bottom: 0.5rem; } .navbar-collapse { -ms-flex-preferred-size: 100%; flex-basis: 100%; -ms-flex-positive: 1; flex-grow: 1; -ms-flex-align: center; align-items: center; } .navbar-toggler { padding: 0.25rem 0.75rem; font-size: 1.25rem; line-height: 1; background-color: transparent; border: 1px solid transparent; border-radius: 0.25rem; } .navbar-toggler:hover, .navbar-toggler:focus { text-decoration: none; } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; content: ""; background: 50% / 100% 100% no-repeat; } .navbar-nav-scroll { max-height: 75vh; overflow-y: auto; } @media (max-width: 575.98px) { .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 576px) { .navbar-expand-sm { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-sm > .container, .navbar-expand-sm > .container-fluid, .navbar-expand-sm > .container-sm, .navbar-expand-sm > .container-md, .navbar-expand-sm > .container-lg, .navbar-expand-sm > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } } @media (max-width: 767.98px) { .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 768px) { .navbar-expand-md { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-md .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-md > .container, .navbar-expand-md > .container-fluid, .navbar-expand-md > .container-sm, .navbar-expand-md > .container-md, .navbar-expand-md > .container-lg, .navbar-expand-md > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } } @media (max-width: 991.98px) { .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 992px) { .navbar-expand-lg { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-lg > .container, .navbar-expand-lg > .container-fluid, .navbar-expand-lg > .container-sm, .navbar-expand-lg > .container-md, .navbar-expand-lg > .container-lg, .navbar-expand-lg > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } } @media (max-width: 1199.98px) { .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { padding-right: 0; padding-left: 0; } } @media (min-width: 1200px) { .navbar-expand-xl { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand-xl > .container, .navbar-expand-xl > .container-fluid, .navbar-expand-xl > .container-sm, .navbar-expand-xl > .container-md, .navbar-expand-xl > .container-lg, .navbar-expand-xl > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } } .navbar-expand { -ms-flex-flow: row nowrap; flex-flow: row nowrap; -ms-flex-pack: start; justify-content: flex-start; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { padding-right: 0; padding-left: 0; } .navbar-expand .navbar-nav { -ms-flex-direction: row; flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-right: 1rem; padding-left: 1rem; } .navbar-expand > .container, .navbar-expand > .container-fluid, .navbar-expand > .container-sm, .navbar-expand > .container-md, .navbar-expand > .container-lg, .navbar-expand > .container-xl { -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: -ms-flexbox !important; display: flex !important; -ms-flex-preferred-size: auto; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-light .navbar-brand { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-nav .nav-link { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { color: rgba(0, 0, 0, 0.7); } .navbar-light .navbar-nav .nav-link.disabled { color: rgba(0, 0, 0, 0.3); } .navbar-light .navbar-nav .show > .nav-link, .navbar-light .navbar-nav .active > .nav-link, .navbar-light .navbar-nav .nav-link.show, .navbar-light .navbar-nav .nav-link.active { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-toggler { color: rgba(0, 0, 0, 0.5); border-color: rgba(0, 0, 0, 0.1); } .navbar-light .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-light .navbar-text { color: rgba(0, 0, 0, 0.5); } .navbar-light .navbar-text a { color: rgba(0, 0, 0, 0.9); } .navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { color: rgba(0, 0, 0, 0.9); } .navbar-dark .navbar-brand { color: #fff; } .navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { color: #fff; } .navbar-dark .navbar-nav .nav-link { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { color: white; } .navbar-dark .navbar-nav .nav-link.disabled { color: rgba(255, 255, 255, 0.25); } .navbar-dark .navbar-nav .show > .nav-link, .navbar-dark .navbar-nav .active > .nav-link, .navbar-dark .navbar-nav .nav-link.show, .navbar-dark .navbar-nav .nav-link.active { color: #fff; } .navbar-dark .navbar-toggler { color: rgba(255, 255, 255, 0.75); border-color: rgba(255, 255, 255, 0.1); } .navbar-dark .navbar-toggler-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba%28255, 255, 255, 0.75%29' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } .navbar-dark .navbar-text { color: rgba(255, 255, 255, 0.75); } .navbar-dark .navbar-text a { color: #fff; } .navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { color: #fff; } .card { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; min-width: 0; word-wrap: break-word; background-color: #fff; background-clip: border-box; border: 0 solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { -ms-flex: 1 1 auto; flex: 1 1 auto; min-height: 1px; padding: 1.25rem; } .card-title { margin-bottom: 0.75rem; } .card-subtitle { margin-top: -0.375rem; margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link:hover { text-decoration: none; } .card-link + .card-link { margin-left: 1.25rem; } .card-header { padding: 0.75rem 1.25rem; margin-bottom: 0; background-color: rgba(0, 0, 0, 0.03); border-bottom: 0 solid rgba(0, 0, 0, 0.125); } .card-header:first-child { border-radius: calc(0.25rem - 0) calc(0.25rem - 0) 0 0; } .card-footer { padding: 0.75rem 1.25rem; background-color: rgba(0, 0, 0, 0.03); border-top: 0 solid rgba(0, 0, 0, 0.125); } .card-footer:last-child { border-radius: 0 0 calc(0.25rem - 0) calc(0.25rem - 0); } .card-header-tabs { margin-right: -0.625rem; margin-bottom: -0.75rem; margin-left: -0.625rem; border-bottom: 0; } .card-header-pills { margin-right: -0.625rem; margin-left: -0.625rem; } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: 1.25rem; border-radius: calc(0.25rem - 0); } .card-img, .card-img-top, .card-img-bottom { -ms-flex-negative: 0; flex-shrink: 0; width: 100%; } .card-img, .card-img-top { border-top-left-radius: calc(0.25rem - 0); border-top-right-radius: calc(0.25rem - 0); } .card-img, .card-img-bottom { border-bottom-right-radius: calc(0.25rem - 0); border-bottom-left-radius: calc(0.25rem - 0); } .card-deck .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-deck { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; margin-right: -7.5px; margin-left: -7.5px; } .card-deck .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-right: 7.5px; margin-bottom: 0; margin-left: 7.5px; } } .card-group > .card { margin-bottom: 7.5px; } @media (min-width: 576px) { .card-group { display: -ms-flexbox; display: flex; -ms-flex-flow: row wrap; flex-flow: row wrap; } .card-group > .card { -ms-flex: 1 0 0%; flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } } .card-columns .card { margin-bottom: 0.75rem; } @media (min-width: 576px) { .card-columns { -webkit-column-count: 3; -moz-column-count: 3; column-count: 3; -webkit-column-gap: 1.25rem; -moz-column-gap: 1.25rem; column-gap: 1.25rem; orphans: 1; widows: 1; } .card-columns .card { display: inline-block; width: 100%; } } .accordion { overflow-anchor: none; } .accordion > .card { overflow: hidden; } .accordion > .card:not(:last-of-type) { border-bottom: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .accordion > .card:not(:first-of-type) { border-top-left-radius: 0; border-top-right-radius: 0; } .accordion > .card > .card-header { border-radius: 0; margin-bottom: 0; } .breadcrumb { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 0.75rem 1rem; margin-bottom: 1rem; list-style: none; background-color: #e9ecef; border-radius: 0.25rem; } .breadcrumb-item + .breadcrumb-item { padding-left: 0.5rem; } .breadcrumb-item + .breadcrumb-item::before { float: left; padding-right: 0.5rem; color: #6c757d; content: "/"; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: underline; } .breadcrumb-item + .breadcrumb-item:hover::before { text-decoration: none; } .breadcrumb-item.active { color: #6c757d; } .pagination { display: -ms-flexbox; display: flex; padding-left: 0; list-style: none; border-radius: 0.25rem; } .page-link { position: relative; display: block; padding: 0.5rem 0.75rem; margin-left: -1px; line-height: 1.25; color: #007bff; background-color: #fff; border: 1px solid #dee2e6; } .page-link:hover { z-index: 2; color: #0056b3; text-decoration: none; background-color: #e9ecef; border-color: #dee2e6; } .page-link:focus { z-index: 3; outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; border-bottom-left-radius: 0.25rem; } .page-item:last-child .page-link { border-top-right-radius: 0.25rem; border-bottom-right-radius: 0.25rem; } .page-item.active .page-link { z-index: 3; color: #fff; background-color: #007bff; border-color: #007bff; } .page-item.disabled .page-link { color: #6c757d; pointer-events: none; cursor: auto; background-color: #fff; border-color: #dee2e6; } .pagination-lg .page-link { padding: 0.75rem 1.5rem; font-size: 1.25rem; line-height: 1.5; } .pagination-lg .page-item:first-child .page-link { border-top-left-radius: 0.3rem; border-bottom-left-radius: 0.3rem; } .pagination-lg .page-item:last-child .page-link { border-top-right-radius: 0.3rem; border-bottom-right-radius: 0.3rem; } .pagination-sm .page-link { padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; } .pagination-sm .page-item:first-child .page-link { border-top-left-radius: 0.2rem; border-bottom-left-radius: 0.2rem; } .pagination-sm .page-item:last-child .page-link { border-top-right-radius: 0.2rem; border-bottom-right-radius: 0.2rem; } .badge { display: inline-block; padding: 0.25em 0.4em; font-size: 75%; font-weight: 700; line-height: 1; text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .badge { transition: none; } } a.badge:hover, a.badge:focus { text-decoration: none; } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .badge-pill { padding-right: 0.6em; padding-left: 0.6em; border-radius: 10rem; } .badge-primary { color: #fff; background-color: #007bff; } a.badge-primary:hover, a.badge-primary:focus { color: #fff; background-color: #0062cc; } a.badge-primary:focus, a.badge-primary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); } .badge-secondary { color: #fff; background-color: #6c757d; } a.badge-secondary:hover, a.badge-secondary:focus { color: #fff; background-color: #545b62; } a.badge-secondary:focus, a.badge-secondary.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); } .badge-success { color: #fff; background-color: #28a745; } a.badge-success:hover, a.badge-success:focus { color: #fff; background-color: #1e7e34; } a.badge-success:focus, a.badge-success.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); } .badge-info { color: #fff; background-color: #17a2b8; } a.badge-info:hover, a.badge-info:focus { color: #fff; background-color: #117a8b; } a.badge-info:focus, a.badge-info.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); } .badge-warning { color: #1f2d3d; background-color: #ffc107; } a.badge-warning:hover, a.badge-warning:focus { color: #1f2d3d; background-color: #d39e00; } a.badge-warning:focus, a.badge-warning.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); } .badge-danger { color: #fff; background-color: #dc3545; } a.badge-danger:hover, a.badge-danger:focus { color: #fff; background-color: #bd2130; } a.badge-danger:focus, a.badge-danger.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); } .badge-light { color: #1f2d3d; background-color: #f8f9fa; } a.badge-light:hover, a.badge-light:focus { color: #1f2d3d; background-color: #dae0e5; } a.badge-light:focus, a.badge-light.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); } .badge-dark { color: #fff; background-color: #343a40; } a.badge-dark:hover, a.badge-dark:focus { color: #fff; background-color: #1d2124; } a.badge-dark:focus, a.badge-dark.focus { outline: 0; box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); } .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; background-color: #e9ecef; border-radius: 0.3rem; } @media (min-width: 576px) { .jumbotron { padding: 4rem 2rem; } } .jumbotron-fluid { padding-right: 0; padding-left: 0; border-radius: 0; } .alert { position: relative; padding: 0.75rem 1.25rem; margin-bottom: 1rem; border: 1px solid transparent; border-radius: 0.25rem; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 4rem; } .alert-dismissible .close, .alert-dismissible .mailbox-attachment-close { position: absolute; top: 0; right: 0; z-index: 2; padding: 0.75rem 1.25rem; color: inherit; } .alert-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-primary hr { border-top-color: #9fcdff; } .alert-primary .alert-link { color: #002752; } .alert-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-secondary hr { border-top-color: #c8cbcf; } .alert-secondary .alert-link { color: #202326; } .alert-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-success hr { border-top-color: #b1dfbb; } .alert-success .alert-link { color: #0b2e13; } .alert-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-info hr { border-top-color: #abdde5; } .alert-info .alert-link { color: #062c33; } .alert-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-warning hr { border-top-color: #ffe8a1; } .alert-warning .alert-link { color: #533f03; } .alert-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-danger hr { border-top-color: #f1b0b7; } .alert-danger .alert-link { color: #491217; } .alert-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-light hr { border-top-color: #ececf6; } .alert-light .alert-link { color: #686868; } .alert-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-dark hr { border-top-color: #b9bbbe; } .alert-dark .alert-link { color: #040505; } @-webkit-keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } @keyframes progress-bar-stripes { from { background-position: 1rem 0; } to { background-position: 0 0; } } .progress { display: -ms-flexbox; display: flex; height: 1rem; overflow: hidden; line-height: 0; font-size: 0.75rem; background-color: #e9ecef; border-radius: 0.25rem; box-shadow: inset 0 0.1rem 0.1rem rgba(0, 0, 0, 0.1); } .progress-bar { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; overflow: hidden; color: #fff; text-align: center; white-space: nowrap; background-color: #007bff; transition: width 0.6s ease; } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: 1rem 1rem; } .progress-bar-animated { -webkit-animation: 1s linear infinite progress-bar-stripes; animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { -webkit-animation: none; animation: none; } } .media { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; } .media-body { -ms-flex: 1; flex: 1; } .list-group { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; padding-left: 0; margin-bottom: 0; border-radius: 0.25rem; } .list-group-item-action { width: 100%; color: #495057; text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: #495057; text-decoration: none; background-color: #f8f9fa; } .list-group-item-action:active { color: #212529; background-color: #e9ecef; } .list-group-item { position: relative; display: block; padding: 0.75rem 1.25rem; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); } .list-group-item:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } .list-group-item:last-child { border-bottom-right-radius: inherit; border-bottom-left-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: #6c757d; pointer-events: none; background-color: #fff; } .list-group-item.active { z-index: 2; color: #fff; background-color: #007bff; border-color: #007bff; } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: -1px; border-top-width: 1px; } .list-group-horizontal { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } @media (min-width: 576px) { .list-group-horizontal-sm { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 768px) { .list-group-horizontal-md { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 992px) { .list-group-horizontal-lg { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } @media (min-width: 1200px) { .list-group-horizontal-xl { -ms-flex-direction: row; flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child { border-top-right-radius: 0.25rem; border-bottom-left-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: 1px; border-left-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: -1px; border-left-width: 1px; } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 1px; } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #004085; background-color: #b8daff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #004085; background-color: #9fcdff; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #004085; border-color: #004085; } .list-group-item-secondary { color: #383d41; background-color: #d6d8db; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #383d41; background-color: #c8cbcf; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #383d41; border-color: #383d41; } .list-group-item-success { color: #155724; background-color: #c3e6cb; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #155724; background-color: #b1dfbb; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #155724; border-color: #155724; } .list-group-item-info { color: #0c5460; background-color: #bee5eb; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #0c5460; background-color: #abdde5; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #0c5460; border-color: #0c5460; } .list-group-item-warning { color: #856404; background-color: #ffeeba; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #856404; background-color: #ffe8a1; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #856404; border-color: #856404; } .list-group-item-danger { color: #721c24; background-color: #f5c6cb; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #721c24; background-color: #f1b0b7; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #721c24; border-color: #721c24; } .list-group-item-light { color: #818182; background-color: #fdfdfe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #818182; background-color: #ececf6; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #818182; border-color: #818182; } .list-group-item-dark { color: #1b1e21; background-color: #c6c8ca; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #1b1e21; background-color: #b9bbbe; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #1b1e21; border-color: #1b1e21; } .close, .mailbox-attachment-close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover, .mailbox-attachment-close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .mailbox-attachment-close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus, .mailbox-attachment-close:not(:disabled):not(.disabled):focus { opacity: .75; } button.close, button.mailbox-attachment-close { padding: 0; background-color: transparent; border: 0; } a.close.disabled, a.disabled.mailbox-attachment-close { pointer-events: none; } .toast { -ms-flex-preferred-size: 350px; flex-basis: 350px; max-width: 350px; font-size: 0.875rem; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); opacity: 0; border-radius: 0.25rem; } .toast:not(:last-child) { margin-bottom: 0.75rem; } .toast.showing { opacity: 1; } .toast.show { display: block; opacity: 1; } .toast.hide { display: none; } .toast-header { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; padding: 0.25rem 0.75rem; color: #6c757d; background-color: rgba(255, 255, 255, 0.85); background-clip: padding-box; border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-top-left-radius: calc(0.25rem - 1px); border-top-right-radius: calc(0.25rem - 1px); } .toast-body { padding: 0.75rem; } .modal-open { overflow: hidden; } .modal-open .modal { overflow-x: hidden; overflow-y: auto; } .modal { position: fixed; top: 0; left: 0; z-index: 1050; display: none; width: 100%; height: 100%; overflow: hidden; outline: 0; } .modal-dialog { position: relative; width: auto; margin: 0.5rem; pointer-events: none; } .modal.fade .modal-dialog { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; -webkit-transform: translate(0, -50px); transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { -webkit-transform: none; transform: none; } .modal.modal-static .modal-dialog { -webkit-transform: scale(1.02); transform: scale(1.02); } .modal-dialog-scrollable { display: -ms-flexbox; display: flex; max-height: calc(100% - 1rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 1rem); overflow: hidden; } .modal-dialog-scrollable .modal-header, .modal-dialog-scrollable .modal-footer { -ms-flex-negative: 0; flex-shrink: 0; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; min-height: calc(100% - 1rem); } .modal-dialog-centered::before { display: block; height: calc(100vh - 1rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; content: ""; } .modal-dialog-centered.modal-dialog-scrollable { -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; height: 100%; } .modal-dialog-centered.modal-dialog-scrollable .modal-content { max-height: none; } .modal-dialog-centered.modal-dialog-scrollable::before { content: none; } .modal-content { position: relative; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; width: 100%; pointer-events: auto; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.5); outline: 0; } .modal-backdrop { position: fixed; top: 0; left: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: 0.5; } .modal-header { display: -ms-flexbox; display: flex; -ms-flex-align: start; align-items: flex-start; -ms-flex-pack: justify; justify-content: space-between; padding: 1rem; border-bottom: 1px solid #e9ecef; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .modal-header .close, .modal-header .mailbox-attachment-close { padding: 1rem; margin: -1rem -1rem -1rem auto; } .modal-title { margin-bottom: 0; line-height: 1.5; } .modal-body { position: relative; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: 1rem; } .modal-footer { display: -ms-flexbox; display: flex; -ms-flex-wrap: wrap; flex-wrap: wrap; -ms-flex-align: center; align-items: center; -ms-flex-pack: end; justify-content: flex-end; padding: 0.75rem; border-top: 1px solid #e9ecef; border-bottom-right-radius: calc(0.3rem - 1px); border-bottom-left-radius: calc(0.3rem - 1px); } .modal-footer > * { margin: 0.25rem; } .modal-scrollbar-measure { position: absolute; top: -9999px; width: 50px; height: 50px; overflow: scroll; } @media (min-width: 576px) { .modal-dialog { max-width: 500px; margin: 1.75rem auto; } .modal-dialog-scrollable { max-height: calc(100% - 3.5rem); } .modal-dialog-scrollable .modal-content { max-height: calc(100vh - 3.5rem); } .modal-dialog-centered { min-height: calc(100% - 3.5rem); } .modal-dialog-centered::before { height: calc(100vh - 3.5rem); height: -webkit-min-content; height: -moz-min-content; height: min-content; } .modal-content { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.5); } .modal-sm { max-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { max-width: 800px; } } @media (min-width: 1200px) { .modal-xl { max-width: 1140px; } } .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: 0.9; } .tooltip .arrow { position: absolute; display: block; width: 0.8rem; height: 0.4rem; } .tooltip .arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { padding: 0.4rem 0; } .bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { bottom: 0; } .bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { top: 0; border-width: 0.4rem 0.4rem 0; border-top-color: #000; } .bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { padding: 0 0.4rem; } .bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { left: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { right: 0; border-width: 0.4rem 0.4rem 0.4rem 0; border-right-color: #000; } .bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { padding: 0.4rem 0; } .bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { top: 0; } .bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { bottom: 0; border-width: 0 0.4rem 0.4rem; border-bottom-color: #000; } .bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { padding: 0 0.4rem; } .bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { right: 0; width: 0.4rem; height: 0.8rem; } .bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { left: 0; border-width: 0.4rem 0 0.4rem 0.4rem; border-left-color: #000; } .tooltip-inner { max-width: 200px; padding: 0.25rem 0.5rem; color: #fff; text-align: center; background-color: #000; border-radius: 0.25rem; } .popover { position: absolute; top: 0; left: 0; z-index: 1060; display: block; max-width: 276px; font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; font-size: 0.875rem; word-wrap: break-word; background-color: #fff; background-clip: padding-box; border: 1px solid rgba(0, 0, 0, 0.2); border-radius: 0.3rem; box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.2); } .popover .arrow { position: absolute; display: block; width: 1rem; height: 0.5rem; margin: 0 0.3rem; } .popover .arrow::before, .popover .arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; } .bs-popover-top, .bs-popover-auto[x-placement^="top"] { margin-bottom: 0.5rem; } .bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow { bottom: calc(-0.5rem - 1px); } .bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before { bottom: 0; border-width: 0.5rem 0.5rem 0; border-top-color: rgba(0, 0, 0, 0.25); } .bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^="top"] > .arrow::after { bottom: 1px; border-width: 0.5rem 0.5rem 0; border-top-color: #fff; } .bs-popover-right, .bs-popover-auto[x-placement^="right"] { margin-left: 0.5rem; } .bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow { left: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^="right"] > .arrow::before { left: 0; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: rgba(0, 0, 0, 0.25); } .bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^="right"] > .arrow::after { left: 1px; border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: #fff; } .bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { margin-top: 0.5rem; } .bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow { top: calc(-0.5rem - 1px); } .bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before { top: 0; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: rgba(0, 0, 0, 0.25); } .bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^="bottom"] > .arrow::after { top: 1px; border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: #fff; } .bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: 1rem; margin-left: -0.5rem; content: ""; border-bottom: 1px solid #f7f7f7; } .bs-popover-left, .bs-popover-auto[x-placement^="left"] { margin-right: 0.5rem; } .bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow { right: calc(-0.5rem - 1px); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } .bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^="left"] > .arrow::before { right: 0; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: rgba(0, 0, 0, 0.25); } .bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^="left"] > .arrow::after { right: 1px; border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: #fff; } .popover-header { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); border-top-right-radius: calc(0.3rem - 1px); } .popover-header:empty { display: none; } .popover-body { padding: 0.5rem 0.75rem; color: #212529; } .carousel { position: relative; } .carousel.pointer-event { -ms-touch-action: pan-y; touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; width: 100%; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: -webkit-transform 0.6s ease; transition: transform 0.6s ease; transition: transform 0.6s ease, -webkit-transform 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-left), .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-right), .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; -webkit-transform: none; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-left, .carousel-fade .carousel-item-prev.carousel-item-right { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-left, .carousel-fade .active.carousel-item-right { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 20px; height: 20px; background: 50% / 100% 100% no-repeat; } .carousel-control-prev-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 15; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; padding-left: 0; margin-right: 15%; margin-left: 15%; list-style: none; } .carousel-indicators li { box-sizing: content-box; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; height: 3px; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: .5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators li { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: 20px; left: 15%; z-index: 10; padding-top: 20px; padding-bottom: 20px; color: #fff; text-align: center; } @-webkit-keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes spinner-border { to { -webkit-transform: rotate(360deg); transform: rotate(360deg); } } .spinner-border { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; border: 0.25em solid currentColor; border-right-color: transparent; border-radius: 50%; -webkit-animation: .75s linear infinite spinner-border; animation: .75s linear infinite spinner-border; } .spinner-border-sm { width: 1rem; height: 1rem; border-width: 0.2em; } @-webkit-keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } @keyframes spinner-grow { 0% { -webkit-transform: scale(0); transform: scale(0); } 50% { opacity: 1; -webkit-transform: none; transform: none; } } .spinner-grow { display: inline-block; width: 2rem; height: 2rem; vertical-align: -0.125em; background-color: currentColor; border-radius: 50%; opacity: 0; -webkit-animation: .75s linear infinite spinner-grow; animation: .75s linear infinite spinner-grow; } .spinner-grow-sm { width: 1rem; height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { -webkit-animation-duration: 1.5s; animation-duration: 1.5s; } } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .bg-primary { background-color: #007bff !important; } a.bg-primary:hover, a.bg-primary:focus, button.bg-primary:hover, button.bg-primary:focus { background-color: #0062cc !important; } .bg-secondary { background-color: #6c757d !important; } a.bg-secondary:hover, a.bg-secondary:focus, button.bg-secondary:hover, button.bg-secondary:focus { background-color: #545b62 !important; } .bg-success { background-color: #28a745 !important; } a.bg-success:hover, a.bg-success:focus, button.bg-success:hover, button.bg-success:focus { background-color: #1e7e34 !important; } .bg-info { background-color: #17a2b8 !important; } a.bg-info:hover, a.bg-info:focus, button.bg-info:hover, button.bg-info:focus { background-color: #117a8b !important; } .bg-warning { background-color: #ffc107 !important; } a.bg-warning:hover, a.bg-warning:focus, button.bg-warning:hover, button.bg-warning:focus { background-color: #d39e00 !important; } .bg-danger { background-color: #dc3545 !important; } a.bg-danger:hover, a.bg-danger:focus, button.bg-danger:hover, button.bg-danger:focus { background-color: #bd2130 !important; } .bg-light { background-color: #f8f9fa !important; } a.bg-light:hover, a.bg-light:focus, button.bg-light:hover, button.bg-light:focus { background-color: #dae0e5 !important; } .bg-dark { background-color: #343a40 !important; } a.bg-dark:hover, a.bg-dark:focus, button.bg-dark:hover, button.bg-dark:focus { background-color: #1d2124 !important; } .bg-white { background-color: #fff !important; } .bg-transparent { background-color: transparent !important; } .border { border: 1px solid #dee2e6 !important; } .border-top { border-top: 1px solid #dee2e6 !important; } .border-right { border-right: 1px solid #dee2e6 !important; } .border-bottom { border-bottom: 1px solid #dee2e6 !important; } .border-left { border-left: 1px solid #dee2e6 !important; } .border-0 { border: 0 !important; } .border-top-0 { border-top: 0 !important; } .border-right-0 { border-right: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-left-0 { border-left: 0 !important; } .border-primary { border-color: #007bff !important; } .border-secondary { border-color: #6c757d !important; } .border-success { border-color: #28a745 !important; } .border-info { border-color: #17a2b8 !important; } .border-warning { border-color: #ffc107 !important; } .border-danger { border-color: #dc3545 !important; } .border-light { border-color: #f8f9fa !important; } .border-dark { border-color: #343a40 !important; } .border-white { border-color: #fff !important; } .rounded-sm { border-radius: 0.2rem !important; } .rounded { border-radius: 0.25rem !important; } .rounded-top { border-top-left-radius: 0.25rem !important; border-top-right-radius: 0.25rem !important; } .rounded-right { border-top-right-radius: 0.25rem !important; border-bottom-right-radius: 0.25rem !important; } .rounded-bottom { border-bottom-right-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-left { border-top-left-radius: 0.25rem !important; border-bottom-left-radius: 0.25rem !important; } .rounded-lg { border-radius: 0.3rem !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: 50rem !important; } .rounded-0 { border-radius: 0 !important; } .clearfix::after { display: block; clear: both; content: ""; } .d-none { display: none !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: -ms-flexbox !important; display: flex !important; } .d-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } @media (min-width: 576px) { .d-sm-none { display: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: -ms-flexbox !important; display: flex !important; } .d-sm-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 768px) { .d-md-none { display: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: -ms-flexbox !important; display: flex !important; } .d-md-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 992px) { .d-lg-none { display: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: -ms-flexbox !important; display: flex !important; } .d-lg-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media (min-width: 1200px) { .d-xl-none { display: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: -ms-flexbox !important; display: flex !important; } .d-xl-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } @media print { .d-print-none { display: none !important; } .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: -ms-flexbox !important; display: flex !important; } .d-print-inline-flex { display: -ms-inline-flexbox !important; display: inline-flex !important; } } .embed-responsive { position: relative; display: block; width: 100%; padding: 0; overflow: hidden; } .embed-responsive::before { display: block; content: ""; } .embed-responsive .embed-responsive-item, .embed-responsive iframe, .embed-responsive embed, .embed-responsive object, .embed-responsive video { position: absolute; top: 0; bottom: 0; left: 0; width: 100%; height: 100%; border: 0; } .embed-responsive-21by9::before { padding-top: 42.857143%; } .embed-responsive-16by9::before { padding-top: 56.25%; } .embed-responsive-4by3::before { padding-top: 75%; } .embed-responsive-1by1::before { padding-top: 100%; } .flex-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } @media (min-width: 576px) { .flex-sm-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-sm-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-sm-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-sm-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-sm-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-sm-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-sm-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-sm-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-sm-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-sm-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-sm-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-sm-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-sm-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-sm-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-sm-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-sm-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-sm-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-sm-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-sm-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-sm-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-sm-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-sm-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-sm-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-sm-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-sm-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-sm-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-sm-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-sm-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-sm-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-sm-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-sm-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-sm-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-sm-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 768px) { .flex-md-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-md-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-md-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-md-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-md-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-md-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-md-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-md-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-md-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-md-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-md-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-md-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-md-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-md-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-md-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-md-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-md-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-md-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-md-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-md-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-md-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-md-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-md-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-md-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-md-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-md-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-md-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-md-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-md-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-md-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-md-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-md-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-md-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-md-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 992px) { .flex-lg-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-lg-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-lg-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-lg-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-lg-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-lg-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-lg-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-lg-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-lg-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-lg-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-lg-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-lg-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-lg-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-lg-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-lg-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-lg-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-lg-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-lg-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-lg-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-lg-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-lg-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-lg-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-lg-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-lg-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-lg-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-lg-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-lg-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-lg-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-lg-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-lg-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-lg-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-lg-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-lg-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } @media (min-width: 1200px) { .flex-xl-row { -ms-flex-direction: row !important; flex-direction: row !important; } .flex-xl-column { -ms-flex-direction: column !important; flex-direction: column !important; } .flex-xl-row-reverse { -ms-flex-direction: row-reverse !important; flex-direction: row-reverse !important; } .flex-xl-column-reverse { -ms-flex-direction: column-reverse !important; flex-direction: column-reverse !important; } .flex-xl-wrap { -ms-flex-wrap: wrap !important; flex-wrap: wrap !important; } .flex-xl-nowrap { -ms-flex-wrap: nowrap !important; flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { -ms-flex-wrap: wrap-reverse !important; flex-wrap: wrap-reverse !important; } .flex-xl-fill { -ms-flex: 1 1 auto !important; flex: 1 1 auto !important; } .flex-xl-grow-0 { -ms-flex-positive: 0 !important; flex-grow: 0 !important; } .flex-xl-grow-1 { -ms-flex-positive: 1 !important; flex-grow: 1 !important; } .flex-xl-shrink-0 { -ms-flex-negative: 0 !important; flex-shrink: 0 !important; } .flex-xl-shrink-1 { -ms-flex-negative: 1 !important; flex-shrink: 1 !important; } .justify-content-xl-start { -ms-flex-pack: start !important; justify-content: flex-start !important; } .justify-content-xl-end { -ms-flex-pack: end !important; justify-content: flex-end !important; } .justify-content-xl-center { -ms-flex-pack: center !important; justify-content: center !important; } .justify-content-xl-between { -ms-flex-pack: justify !important; justify-content: space-between !important; } .justify-content-xl-around { -ms-flex-pack: distribute !important; justify-content: space-around !important; } .align-items-xl-start { -ms-flex-align: start !important; align-items: flex-start !important; } .align-items-xl-end { -ms-flex-align: end !important; align-items: flex-end !important; } .align-items-xl-center { -ms-flex-align: center !important; align-items: center !important; } .align-items-xl-baseline { -ms-flex-align: baseline !important; align-items: baseline !important; } .align-items-xl-stretch { -ms-flex-align: stretch !important; align-items: stretch !important; } .align-content-xl-start { -ms-flex-line-pack: start !important; align-content: flex-start !important; } .align-content-xl-end { -ms-flex-line-pack: end !important; align-content: flex-end !important; } .align-content-xl-center { -ms-flex-line-pack: center !important; align-content: center !important; } .align-content-xl-between { -ms-flex-line-pack: justify !important; align-content: space-between !important; } .align-content-xl-around { -ms-flex-line-pack: distribute !important; align-content: space-around !important; } .align-content-xl-stretch { -ms-flex-line-pack: stretch !important; align-content: stretch !important; } .align-self-xl-auto { -ms-flex-item-align: auto !important; align-self: auto !important; } .align-self-xl-start { -ms-flex-item-align: start !important; align-self: flex-start !important; } .align-self-xl-end { -ms-flex-item-align: end !important; align-self: flex-end !important; } .align-self-xl-center { -ms-flex-item-align: center !important; align-self: center !important; } .align-self-xl-baseline { -ms-flex-item-align: baseline !important; align-self: baseline !important; } .align-self-xl-stretch { -ms-flex-item-align: stretch !important; align-self: stretch !important; } } .float-left { float: left !important; } .float-right { float: right !important; } .float-none { float: none !important; } @media (min-width: 576px) { .float-sm-left { float: left !important; } .float-sm-right { float: right !important; } .float-sm-none { float: none !important; } } @media (min-width: 768px) { .float-md-left { float: left !important; } .float-md-right { float: right !important; } .float-md-none { float: none !important; } } @media (min-width: 992px) { .float-lg-left { float: left !important; } .float-lg-right { float: right !important; } .float-lg-none { float: none !important; } } @media (min-width: 1200px) { .float-xl-left { float: left !important; } .float-xl-right { float: right !important; } .float-xl-none { float: none !important; } } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } @supports ((position: -webkit-sticky) or (position: sticky)) { .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } } .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .sr-only-focusable:active, .sr-only-focusable:focus { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mw-100 { max-width: 100% !important; } .mh-100 { max-height: 100% !important; } .min-vw-100 { min-width: 100vw !important; } .min-vh-100 { min-height: 100vh !important; } .vw-100 { width: 100vw !important; } .vh-100 { height: 100vh !important; } .m-0 { margin: 0 !important; } .mt-0, .my-0 { margin-top: 0 !important; } .mr-0, .mx-0 { margin-right: 0 !important; } .mb-0, .my-0 { margin-bottom: 0 !important; } .ml-0, .mx-0 { margin-left: 0 !important; } .m-1 { margin: 0.25rem !important; } .mt-1, .my-1 { margin-top: 0.25rem !important; } .mr-1, .mx-1 { margin-right: 0.25rem !important; } .mb-1, .my-1 { margin-bottom: 0.25rem !important; } .ml-1, .mx-1 { margin-left: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .mt-2, .my-2 { margin-top: 0.5rem !important; } .mr-2, .mx-2 { margin-right: 0.5rem !important; } .mb-2, .my-2 { margin-bottom: 0.5rem !important; } .ml-2, .mx-2 { margin-left: 0.5rem !important; } .m-3 { margin: 1rem !important; } .mt-3, .my-3 { margin-top: 1rem !important; } .mr-3, .mx-3 { margin-right: 1rem !important; } .mb-3, .my-3 { margin-bottom: 1rem !important; } .ml-3, .mx-3 { margin-left: 1rem !important; } .m-4 { margin: 1.5rem !important; } .mt-4, .my-4 { margin-top: 1.5rem !important; } .mr-4, .mx-4 { margin-right: 1.5rem !important; } .mb-4, .my-4 { margin-bottom: 1.5rem !important; } .ml-4, .mx-4 { margin-left: 1.5rem !important; } .m-5 { margin: 3rem !important; } .mt-5, .my-5 { margin-top: 3rem !important; } .mr-5, .mx-5 { margin-right: 3rem !important; } .mb-5, .my-5 { margin-bottom: 3rem !important; } .ml-5, .mx-5 { margin-left: 3rem !important; } .p-0 { padding: 0 !important; } .pt-0, .py-0 { padding-top: 0 !important; } .pr-0, .px-0 { padding-right: 0 !important; } .pb-0, .py-0 { padding-bottom: 0 !important; } .pl-0, .px-0 { padding-left: 0 !important; } .p-1 { padding: 0.25rem !important; } .pt-1, .py-1 { padding-top: 0.25rem !important; } .pr-1, .px-1 { padding-right: 0.25rem !important; } .pb-1, .py-1 { padding-bottom: 0.25rem !important; } .pl-1, .px-1 { padding-left: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .pt-2, .py-2 { padding-top: 0.5rem !important; } .pr-2, .px-2 { padding-right: 0.5rem !important; } .pb-2, .py-2 { padding-bottom: 0.5rem !important; } .pl-2, .px-2 { padding-left: 0.5rem !important; } .p-3 { padding: 1rem !important; } .pt-3, .py-3 { padding-top: 1rem !important; } .pr-3, .px-3 { padding-right: 1rem !important; } .pb-3, .py-3 { padding-bottom: 1rem !important; } .pl-3, .px-3 { padding-left: 1rem !important; } .p-4 { padding: 1.5rem !important; } .pt-4, .py-4 { padding-top: 1.5rem !important; } .pr-4, .px-4 { padding-right: 1.5rem !important; } .pb-4, .py-4 { padding-bottom: 1.5rem !important; } .pl-4, .px-4 { padding-left: 1.5rem !important; } .p-5 { padding: 3rem !important; } .pt-5, .py-5 { padding-top: 3rem !important; } .pr-5, .px-5 { padding-right: 3rem !important; } .pb-5, .py-5 { padding-bottom: 3rem !important; } .pl-5, .px-5 { padding-left: 3rem !important; } .m-n1 { margin: -0.25rem !important; } .mt-n1, .my-n1 { margin-top: -0.25rem !important; } .mr-n1, .mx-n1 { margin-right: -0.25rem !important; } .mb-n1, .my-n1 { margin-bottom: -0.25rem !important; } .ml-n1, .mx-n1 { margin-left: -0.25rem !important; } .m-n2 { margin: -0.5rem !important; } .mt-n2, .my-n2 { margin-top: -0.5rem !important; } .mr-n2, .mx-n2 { margin-right: -0.5rem !important; } .mb-n2, .my-n2 { margin-bottom: -0.5rem !important; } .ml-n2, .mx-n2 { margin-left: -0.5rem !important; } .m-n3 { margin: -1rem !important; } .mt-n3, .my-n3 { margin-top: -1rem !important; } .mr-n3, .mx-n3 { margin-right: -1rem !important; } .mb-n3, .my-n3 { margin-bottom: -1rem !important; } .ml-n3, .mx-n3 { margin-left: -1rem !important; } .m-n4 { margin: -1.5rem !important; } .mt-n4, .my-n4 { margin-top: -1.5rem !important; } .mr-n4, .mx-n4 { margin-right: -1.5rem !important; } .mb-n4, .my-n4 { margin-bottom: -1.5rem !important; } .ml-n4, .mx-n4 { margin-left: -1.5rem !important; } .m-n5 { margin: -3rem !important; } .mt-n5, .my-n5 { margin-top: -3rem !important; } .mr-n5, .mx-n5 { margin-right: -3rem !important; } .mb-n5, .my-n5 { margin-bottom: -3rem !important; } .ml-n5, .mx-n5 { margin-left: -3rem !important; } .m-auto { margin: auto !important; } .mt-auto, .my-auto { margin-top: auto !important; } .mr-auto, .mx-auto { margin-right: auto !important; } .mb-auto, .my-auto { margin-bottom: auto !important; } .ml-auto, .mx-auto { margin-left: auto !important; } @media (min-width: 576px) { .m-sm-0 { margin: 0 !important; } .mt-sm-0, .my-sm-0 { margin-top: 0 !important; } .mr-sm-0, .mx-sm-0 { margin-right: 0 !important; } .mb-sm-0, .my-sm-0 { margin-bottom: 0 !important; } .ml-sm-0, .mx-sm-0 { margin-left: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .mt-sm-1, .my-sm-1 { margin-top: 0.25rem !important; } .mr-sm-1, .mx-sm-1 { margin-right: 0.25rem !important; } .mb-sm-1, .my-sm-1 { margin-bottom: 0.25rem !important; } .ml-sm-1, .mx-sm-1 { margin-left: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .mt-sm-2, .my-sm-2 { margin-top: 0.5rem !important; } .mr-sm-2, .mx-sm-2 { margin-right: 0.5rem !important; } .mb-sm-2, .my-sm-2 { margin-bottom: 0.5rem !important; } .ml-sm-2, .mx-sm-2 { margin-left: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .mt-sm-3, .my-sm-3 { margin-top: 1rem !important; } .mr-sm-3, .mx-sm-3 { margin-right: 1rem !important; } .mb-sm-3, .my-sm-3 { margin-bottom: 1rem !important; } .ml-sm-3, .mx-sm-3 { margin-left: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .mt-sm-4, .my-sm-4 { margin-top: 1.5rem !important; } .mr-sm-4, .mx-sm-4 { margin-right: 1.5rem !important; } .mb-sm-4, .my-sm-4 { margin-bottom: 1.5rem !important; } .ml-sm-4, .mx-sm-4 { margin-left: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .mt-sm-5, .my-sm-5 { margin-top: 3rem !important; } .mr-sm-5, .mx-sm-5 { margin-right: 3rem !important; } .mb-sm-5, .my-sm-5 { margin-bottom: 3rem !important; } .ml-sm-5, .mx-sm-5 { margin-left: 3rem !important; } .p-sm-0 { padding: 0 !important; } .pt-sm-0, .py-sm-0 { padding-top: 0 !important; } .pr-sm-0, .px-sm-0 { padding-right: 0 !important; } .pb-sm-0, .py-sm-0 { padding-bottom: 0 !important; } .pl-sm-0, .px-sm-0 { padding-left: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .pt-sm-1, .py-sm-1 { padding-top: 0.25rem !important; } .pr-sm-1, .px-sm-1 { padding-right: 0.25rem !important; } .pb-sm-1, .py-sm-1 { padding-bottom: 0.25rem !important; } .pl-sm-1, .px-sm-1 { padding-left: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .pt-sm-2, .py-sm-2 { padding-top: 0.5rem !important; } .pr-sm-2, .px-sm-2 { padding-right: 0.5rem !important; } .pb-sm-2, .py-sm-2 { padding-bottom: 0.5rem !important; } .pl-sm-2, .px-sm-2 { padding-left: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .pt-sm-3, .py-sm-3 { padding-top: 1rem !important; } .pr-sm-3, .px-sm-3 { padding-right: 1rem !important; } .pb-sm-3, .py-sm-3 { padding-bottom: 1rem !important; } .pl-sm-3, .px-sm-3 { padding-left: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .pt-sm-4, .py-sm-4 { padding-top: 1.5rem !important; } .pr-sm-4, .px-sm-4 { padding-right: 1.5rem !important; } .pb-sm-4, .py-sm-4 { padding-bottom: 1.5rem !important; } .pl-sm-4, .px-sm-4 { padding-left: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .pt-sm-5, .py-sm-5 { padding-top: 3rem !important; } .pr-sm-5, .px-sm-5 { padding-right: 3rem !important; } .pb-sm-5, .py-sm-5 { padding-bottom: 3rem !important; } .pl-sm-5, .px-sm-5 { padding-left: 3rem !important; } .m-sm-n1 { margin: -0.25rem !important; } .mt-sm-n1, .my-sm-n1 { margin-top: -0.25rem !important; } .mr-sm-n1, .mx-sm-n1 { margin-right: -0.25rem !important; } .mb-sm-n1, .my-sm-n1 { margin-bottom: -0.25rem !important; } .ml-sm-n1, .mx-sm-n1 { margin-left: -0.25rem !important; } .m-sm-n2 { margin: -0.5rem !important; } .mt-sm-n2, .my-sm-n2 { margin-top: -0.5rem !important; } .mr-sm-n2, .mx-sm-n2 { margin-right: -0.5rem !important; } .mb-sm-n2, .my-sm-n2 { margin-bottom: -0.5rem !important; } .ml-sm-n2, .mx-sm-n2 { margin-left: -0.5rem !important; } .m-sm-n3 { margin: -1rem !important; } .mt-sm-n3, .my-sm-n3 { margin-top: -1rem !important; } .mr-sm-n3, .mx-sm-n3 { margin-right: -1rem !important; } .mb-sm-n3, .my-sm-n3 { margin-bottom: -1rem !important; } .ml-sm-n3, .mx-sm-n3 { margin-left: -1rem !important; } .m-sm-n4 { margin: -1.5rem !important; } .mt-sm-n4, .my-sm-n4 { margin-top: -1.5rem !important; } .mr-sm-n4, .mx-sm-n4 { margin-right: -1.5rem !important; } .mb-sm-n4, .my-sm-n4 { margin-bottom: -1.5rem !important; } .ml-sm-n4, .mx-sm-n4 { margin-left: -1.5rem !important; } .m-sm-n5 { margin: -3rem !important; } .mt-sm-n5, .my-sm-n5 { margin-top: -3rem !important; } .mr-sm-n5, .mx-sm-n5 { margin-right: -3rem !important; } .mb-sm-n5, .my-sm-n5 { margin-bottom: -3rem !important; } .ml-sm-n5, .mx-sm-n5 { margin-left: -3rem !important; } .m-sm-auto { margin: auto !important; } .mt-sm-auto, .my-sm-auto { margin-top: auto !important; } .mr-sm-auto, .mx-sm-auto { margin-right: auto !important; } .mb-sm-auto, .my-sm-auto { margin-bottom: auto !important; } .ml-sm-auto, .mx-sm-auto { margin-left: auto !important; } } @media (min-width: 768px) { .m-md-0 { margin: 0 !important; } .mt-md-0, .my-md-0 { margin-top: 0 !important; } .mr-md-0, .mx-md-0 { margin-right: 0 !important; } .mb-md-0, .my-md-0 { margin-bottom: 0 !important; } .ml-md-0, .mx-md-0 { margin-left: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .mt-md-1, .my-md-1 { margin-top: 0.25rem !important; } .mr-md-1, .mx-md-1 { margin-right: 0.25rem !important; } .mb-md-1, .my-md-1 { margin-bottom: 0.25rem !important; } .ml-md-1, .mx-md-1 { margin-left: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .mt-md-2, .my-md-2 { margin-top: 0.5rem !important; } .mr-md-2, .mx-md-2 { margin-right: 0.5rem !important; } .mb-md-2, .my-md-2 { margin-bottom: 0.5rem !important; } .ml-md-2, .mx-md-2 { margin-left: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .mt-md-3, .my-md-3 { margin-top: 1rem !important; } .mr-md-3, .mx-md-3 { margin-right: 1rem !important; } .mb-md-3, .my-md-3 { margin-bottom: 1rem !important; } .ml-md-3, .mx-md-3 { margin-left: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .mt-md-4, .my-md-4 { margin-top: 1.5rem !important; } .mr-md-4, .mx-md-4 { margin-right: 1.5rem !important; } .mb-md-4, .my-md-4 { margin-bottom: 1.5rem !important; } .ml-md-4, .mx-md-4 { margin-left: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .mt-md-5, .my-md-5 { margin-top: 3rem !important; } .mr-md-5, .mx-md-5 { margin-right: 3rem !important; } .mb-md-5, .my-md-5 { margin-bottom: 3rem !important; } .ml-md-5, .mx-md-5 { margin-left: 3rem !important; } .p-md-0 { padding: 0 !important; } .pt-md-0, .py-md-0 { padding-top: 0 !important; } .pr-md-0, .px-md-0 { padding-right: 0 !important; } .pb-md-0, .py-md-0 { padding-bottom: 0 !important; } .pl-md-0, .px-md-0 { padding-left: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .pt-md-1, .py-md-1 { padding-top: 0.25rem !important; } .pr-md-1, .px-md-1 { padding-right: 0.25rem !important; } .pb-md-1, .py-md-1 { padding-bottom: 0.25rem !important; } .pl-md-1, .px-md-1 { padding-left: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .pt-md-2, .py-md-2 { padding-top: 0.5rem !important; } .pr-md-2, .px-md-2 { padding-right: 0.5rem !important; } .pb-md-2, .py-md-2 { padding-bottom: 0.5rem !important; } .pl-md-2, .px-md-2 { padding-left: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .pt-md-3, .py-md-3 { padding-top: 1rem !important; } .pr-md-3, .px-md-3 { padding-right: 1rem !important; } .pb-md-3, .py-md-3 { padding-bottom: 1rem !important; } .pl-md-3, .px-md-3 { padding-left: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .pt-md-4, .py-md-4 { padding-top: 1.5rem !important; } .pr-md-4, .px-md-4 { padding-right: 1.5rem !important; } .pb-md-4, .py-md-4 { padding-bottom: 1.5rem !important; } .pl-md-4, .px-md-4 { padding-left: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .pt-md-5, .py-md-5 { padding-top: 3rem !important; } .pr-md-5, .px-md-5 { padding-right: 3rem !important; } .pb-md-5, .py-md-5 { padding-bottom: 3rem !important; } .pl-md-5, .px-md-5 { padding-left: 3rem !important; } .m-md-n1 { margin: -0.25rem !important; } .mt-md-n1, .my-md-n1 { margin-top: -0.25rem !important; } .mr-md-n1, .mx-md-n1 { margin-right: -0.25rem !important; } .mb-md-n1, .my-md-n1 { margin-bottom: -0.25rem !important; } .ml-md-n1, .mx-md-n1 { margin-left: -0.25rem !important; } .m-md-n2 { margin: -0.5rem !important; } .mt-md-n2, .my-md-n2 { margin-top: -0.5rem !important; } .mr-md-n2, .mx-md-n2 { margin-right: -0.5rem !important; } .mb-md-n2, .my-md-n2 { margin-bottom: -0.5rem !important; } .ml-md-n2, .mx-md-n2 { margin-left: -0.5rem !important; } .m-md-n3 { margin: -1rem !important; } .mt-md-n3, .my-md-n3 { margin-top: -1rem !important; } .mr-md-n3, .mx-md-n3 { margin-right: -1rem !important; } .mb-md-n3, .my-md-n3 { margin-bottom: -1rem !important; } .ml-md-n3, .mx-md-n3 { margin-left: -1rem !important; } .m-md-n4 { margin: -1.5rem !important; } .mt-md-n4, .my-md-n4 { margin-top: -1.5rem !important; } .mr-md-n4, .mx-md-n4 { margin-right: -1.5rem !important; } .mb-md-n4, .my-md-n4 { margin-bottom: -1.5rem !important; } .ml-md-n4, .mx-md-n4 { margin-left: -1.5rem !important; } .m-md-n5 { margin: -3rem !important; } .mt-md-n5, .my-md-n5 { margin-top: -3rem !important; } .mr-md-n5, .mx-md-n5 { margin-right: -3rem !important; } .mb-md-n5, .my-md-n5 { margin-bottom: -3rem !important; } .ml-md-n5, .mx-md-n5 { margin-left: -3rem !important; } .m-md-auto { margin: auto !important; } .mt-md-auto, .my-md-auto { margin-top: auto !important; } .mr-md-auto, .mx-md-auto { margin-right: auto !important; } .mb-md-auto, .my-md-auto { margin-bottom: auto !important; } .ml-md-auto, .mx-md-auto { margin-left: auto !important; } } @media (min-width: 992px) { .m-lg-0 { margin: 0 !important; } .mt-lg-0, .my-lg-0 { margin-top: 0 !important; } .mr-lg-0, .mx-lg-0 { margin-right: 0 !important; } .mb-lg-0, .my-lg-0 { margin-bottom: 0 !important; } .ml-lg-0, .mx-lg-0 { margin-left: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .mt-lg-1, .my-lg-1 { margin-top: 0.25rem !important; } .mr-lg-1, .mx-lg-1 { margin-right: 0.25rem !important; } .mb-lg-1, .my-lg-1 { margin-bottom: 0.25rem !important; } .ml-lg-1, .mx-lg-1 { margin-left: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .mt-lg-2, .my-lg-2 { margin-top: 0.5rem !important; } .mr-lg-2, .mx-lg-2 { margin-right: 0.5rem !important; } .mb-lg-2, .my-lg-2 { margin-bottom: 0.5rem !important; } .ml-lg-2, .mx-lg-2 { margin-left: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .mt-lg-3, .my-lg-3 { margin-top: 1rem !important; } .mr-lg-3, .mx-lg-3 { margin-right: 1rem !important; } .mb-lg-3, .my-lg-3 { margin-bottom: 1rem !important; } .ml-lg-3, .mx-lg-3 { margin-left: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .mt-lg-4, .my-lg-4 { margin-top: 1.5rem !important; } .mr-lg-4, .mx-lg-4 { margin-right: 1.5rem !important; } .mb-lg-4, .my-lg-4 { margin-bottom: 1.5rem !important; } .ml-lg-4, .mx-lg-4 { margin-left: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .mt-lg-5, .my-lg-5 { margin-top: 3rem !important; } .mr-lg-5, .mx-lg-5 { margin-right: 3rem !important; } .mb-lg-5, .my-lg-5 { margin-bottom: 3rem !important; } .ml-lg-5, .mx-lg-5 { margin-left: 3rem !important; } .p-lg-0 { padding: 0 !important; } .pt-lg-0, .py-lg-0 { padding-top: 0 !important; } .pr-lg-0, .px-lg-0 { padding-right: 0 !important; } .pb-lg-0, .py-lg-0 { padding-bottom: 0 !important; } .pl-lg-0, .px-lg-0 { padding-left: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .pt-lg-1, .py-lg-1 { padding-top: 0.25rem !important; } .pr-lg-1, .px-lg-1 { padding-right: 0.25rem !important; } .pb-lg-1, .py-lg-1 { padding-bottom: 0.25rem !important; } .pl-lg-1, .px-lg-1 { padding-left: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .pt-lg-2, .py-lg-2 { padding-top: 0.5rem !important; } .pr-lg-2, .px-lg-2 { padding-right: 0.5rem !important; } .pb-lg-2, .py-lg-2 { padding-bottom: 0.5rem !important; } .pl-lg-2, .px-lg-2 { padding-left: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .pt-lg-3, .py-lg-3 { padding-top: 1rem !important; } .pr-lg-3, .px-lg-3 { padding-right: 1rem !important; } .pb-lg-3, .py-lg-3 { padding-bottom: 1rem !important; } .pl-lg-3, .px-lg-3 { padding-left: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .pt-lg-4, .py-lg-4 { padding-top: 1.5rem !important; } .pr-lg-4, .px-lg-4 { padding-right: 1.5rem !important; } .pb-lg-4, .py-lg-4 { padding-bottom: 1.5rem !important; } .pl-lg-4, .px-lg-4 { padding-left: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .pt-lg-5, .py-lg-5 { padding-top: 3rem !important; } .pr-lg-5, .px-lg-5 { padding-right: 3rem !important; } .pb-lg-5, .py-lg-5 { padding-bottom: 3rem !important; } .pl-lg-5, .px-lg-5 { padding-left: 3rem !important; } .m-lg-n1 { margin: -0.25rem !important; } .mt-lg-n1, .my-lg-n1 { margin-top: -0.25rem !important; } .mr-lg-n1, .mx-lg-n1 { margin-right: -0.25rem !important; } .mb-lg-n1, .my-lg-n1 { margin-bottom: -0.25rem !important; } .ml-lg-n1, .mx-lg-n1 { margin-left: -0.25rem !important; } .m-lg-n2 { margin: -0.5rem !important; } .mt-lg-n2, .my-lg-n2 { margin-top: -0.5rem !important; } .mr-lg-n2, .mx-lg-n2 { margin-right: -0.5rem !important; } .mb-lg-n2, .my-lg-n2 { margin-bottom: -0.5rem !important; } .ml-lg-n2, .mx-lg-n2 { margin-left: -0.5rem !important; } .m-lg-n3 { margin: -1rem !important; } .mt-lg-n3, .my-lg-n3 { margin-top: -1rem !important; } .mr-lg-n3, .mx-lg-n3 { margin-right: -1rem !important; } .mb-lg-n3, .my-lg-n3 { margin-bottom: -1rem !important; } .ml-lg-n3, .mx-lg-n3 { margin-left: -1rem !important; } .m-lg-n4 { margin: -1.5rem !important; } .mt-lg-n4, .my-lg-n4 { margin-top: -1.5rem !important; } .mr-lg-n4, .mx-lg-n4 { margin-right: -1.5rem !important; } .mb-lg-n4, .my-lg-n4 { margin-bottom: -1.5rem !important; } .ml-lg-n4, .mx-lg-n4 { margin-left: -1.5rem !important; } .m-lg-n5 { margin: -3rem !important; } .mt-lg-n5, .my-lg-n5 { margin-top: -3rem !important; } .mr-lg-n5, .mx-lg-n5 { margin-right: -3rem !important; } .mb-lg-n5, .my-lg-n5 { margin-bottom: -3rem !important; } .ml-lg-n5, .mx-lg-n5 { margin-left: -3rem !important; } .m-lg-auto { margin: auto !important; } .mt-lg-auto, .my-lg-auto { margin-top: auto !important; } .mr-lg-auto, .mx-lg-auto { margin-right: auto !important; } .mb-lg-auto, .my-lg-auto { margin-bottom: auto !important; } .ml-lg-auto, .mx-lg-auto { margin-left: auto !important; } } @media (min-width: 1200px) { .m-xl-0 { margin: 0 !important; } .mt-xl-0, .my-xl-0 { margin-top: 0 !important; } .mr-xl-0, .mx-xl-0 { margin-right: 0 !important; } .mb-xl-0, .my-xl-0 { margin-bottom: 0 !important; } .ml-xl-0, .mx-xl-0 { margin-left: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .mt-xl-1, .my-xl-1 { margin-top: 0.25rem !important; } .mr-xl-1, .mx-xl-1 { margin-right: 0.25rem !important; } .mb-xl-1, .my-xl-1 { margin-bottom: 0.25rem !important; } .ml-xl-1, .mx-xl-1 { margin-left: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .mt-xl-2, .my-xl-2 { margin-top: 0.5rem !important; } .mr-xl-2, .mx-xl-2 { margin-right: 0.5rem !important; } .mb-xl-2, .my-xl-2 { margin-bottom: 0.5rem !important; } .ml-xl-2, .mx-xl-2 { margin-left: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .mt-xl-3, .my-xl-3 { margin-top: 1rem !important; } .mr-xl-3, .mx-xl-3 { margin-right: 1rem !important; } .mb-xl-3, .my-xl-3 { margin-bottom: 1rem !important; } .ml-xl-3, .mx-xl-3 { margin-left: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .mt-xl-4, .my-xl-4 { margin-top: 1.5rem !important; } .mr-xl-4, .mx-xl-4 { margin-right: 1.5rem !important; } .mb-xl-4, .my-xl-4 { margin-bottom: 1.5rem !important; } .ml-xl-4, .mx-xl-4 { margin-left: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .mt-xl-5, .my-xl-5 { margin-top: 3rem !important; } .mr-xl-5, .mx-xl-5 { margin-right: 3rem !important; } .mb-xl-5, .my-xl-5 { margin-bottom: 3rem !important; } .ml-xl-5, .mx-xl-5 { margin-left: 3rem !important; } .p-xl-0 { padding: 0 !important; } .pt-xl-0, .py-xl-0 { padding-top: 0 !important; } .pr-xl-0, .px-xl-0 { padding-right: 0 !important; } .pb-xl-0, .py-xl-0 { padding-bottom: 0 !important; } .pl-xl-0, .px-xl-0 { padding-left: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .pt-xl-1, .py-xl-1 { padding-top: 0.25rem !important; } .pr-xl-1, .px-xl-1 { padding-right: 0.25rem !important; } .pb-xl-1, .py-xl-1 { padding-bottom: 0.25rem !important; } .pl-xl-1, .px-xl-1 { padding-left: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .pt-xl-2, .py-xl-2 { padding-top: 0.5rem !important; } .pr-xl-2, .px-xl-2 { padding-right: 0.5rem !important; } .pb-xl-2, .py-xl-2 { padding-bottom: 0.5rem !important; } .pl-xl-2, .px-xl-2 { padding-left: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .pt-xl-3, .py-xl-3 { padding-top: 1rem !important; } .pr-xl-3, .px-xl-3 { padding-right: 1rem !important; } .pb-xl-3, .py-xl-3 { padding-bottom: 1rem !important; } .pl-xl-3, .px-xl-3 { padding-left: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .pt-xl-4, .py-xl-4 { padding-top: 1.5rem !important; } .pr-xl-4, .px-xl-4 { padding-right: 1.5rem !important; } .pb-xl-4, .py-xl-4 { padding-bottom: 1.5rem !important; } .pl-xl-4, .px-xl-4 { padding-left: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .pt-xl-5, .py-xl-5 { padding-top: 3rem !important; } .pr-xl-5, .px-xl-5 { padding-right: 3rem !important; } .pb-xl-5, .py-xl-5 { padding-bottom: 3rem !important; } .pl-xl-5, .px-xl-5 { padding-left: 3rem !important; } .m-xl-n1 { margin: -0.25rem !important; } .mt-xl-n1, .my-xl-n1 { margin-top: -0.25rem !important; } .mr-xl-n1, .mx-xl-n1 { margin-right: -0.25rem !important; } .mb-xl-n1, .my-xl-n1 { margin-bottom: -0.25rem !important; } .ml-xl-n1, .mx-xl-n1 { margin-left: -0.25rem !important; } .m-xl-n2 { margin: -0.5rem !important; } .mt-xl-n2, .my-xl-n2 { margin-top: -0.5rem !important; } .mr-xl-n2, .mx-xl-n2 { margin-right: -0.5rem !important; } .mb-xl-n2, .my-xl-n2 { margin-bottom: -0.5rem !important; } .ml-xl-n2, .mx-xl-n2 { margin-left: -0.5rem !important; } .m-xl-n3 { margin: -1rem !important; } .mt-xl-n3, .my-xl-n3 { margin-top: -1rem !important; } .mr-xl-n3, .mx-xl-n3 { margin-right: -1rem !important; } .mb-xl-n3, .my-xl-n3 { margin-bottom: -1rem !important; } .ml-xl-n3, .mx-xl-n3 { margin-left: -1rem !important; } .m-xl-n4 { margin: -1.5rem !important; } .mt-xl-n4, .my-xl-n4 { margin-top: -1.5rem !important; } .mr-xl-n4, .mx-xl-n4 { margin-right: -1.5rem !important; } .mb-xl-n4, .my-xl-n4 { margin-bottom: -1.5rem !important; } .ml-xl-n4, .mx-xl-n4 { margin-left: -1.5rem !important; } .m-xl-n5 { margin: -3rem !important; } .mt-xl-n5, .my-xl-n5 { margin-top: -3rem !important; } .mr-xl-n5, .mx-xl-n5 { margin-right: -3rem !important; } .mb-xl-n5, .my-xl-n5 { margin-bottom: -3rem !important; } .ml-xl-n5, .mx-xl-n5 { margin-left: -3rem !important; } .m-xl-auto { margin: auto !important; } .mt-xl-auto, .my-xl-auto { margin-top: auto !important; } .mr-xl-auto, .mx-xl-auto { margin-right: auto !important; } .mb-xl-auto, .my-xl-auto { margin-bottom: auto !important; } .ml-xl-auto, .mx-xl-auto { margin-left: auto !important; } } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; pointer-events: auto; content: ""; background-color: rgba(0, 0, 0, 0); } .text-monospace { font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; } .text-justify { text-align: justify !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .text-left { text-align: left !important; } .text-right { text-align: right !important; } .text-center { text-align: center !important; } @media (min-width: 576px) { .text-sm-left { text-align: left !important; } .text-sm-right { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .text-md-left { text-align: left !important; } .text-md-right { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .text-lg-left { text-align: left !important; } .text-lg-right { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .text-xl-left { text-align: left !important; } .text-xl-right { text-align: right !important; } .text-xl-center { text-align: center !important; } } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .font-weight-light { font-weight: 300 !important; } .font-weight-lighter { font-weight: lighter !important; } .font-weight-normal { font-weight: 400 !important; } .font-weight-bold { font-weight: 700 !important; } .font-weight-bolder { font-weight: bolder !important; } .font-italic { font-style: italic !important; } .text-white { color: #fff !important; } .text-primary { color: #007bff !important; } a.text-primary:hover, a.text-primary:focus { color: #0056b3 !important; } .text-secondary { color: #6c757d !important; } a.text-secondary:hover, a.text-secondary:focus { color: #494f54 !important; } .text-success { color: #28a745 !important; } a.text-success:hover, a.text-success:focus { color: #19692c !important; } .text-info { color: #17a2b8 !important; } a.text-info:hover, a.text-info:focus { color: #0f6674 !important; } .text-warning { color: #ffc107 !important; } a.text-warning:hover, a.text-warning:focus { color: #ba8b00 !important; } .text-danger { color: #dc3545 !important; } a.text-danger:hover, a.text-danger:focus { color: #a71d2a !important; } .text-light { color: #f8f9fa !important; } a.text-light:hover, a.text-light:focus { color: #cbd3da !important; } .text-dark { color: #343a40 !important; } a.text-dark:hover, a.text-dark:focus { color: #121416 !important; } .text-body { color: #212529 !important; } .text-muted { color: #6c757d !important; } .text-black-50 { color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { color: rgba(255, 255, 255, 0.5) !important; } .text-hide { font: 0/0 a; color: transparent; text-shadow: none; background-color: transparent; border: 0; } .text-decoration-none { text-decoration: none !important; } .text-break { word-break: break-word !important; word-wrap: break-word !important; } .text-reset { color: inherit !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media print { *, *::before, *::after { text-shadow: none !important; box-shadow: none !important; } a:not(.btn) { text-decoration: underline; } abbr[title]::after { content: " (" attr(title) ")"; } pre { white-space: pre-wrap !important; } pre, blockquote { border: 1px solid #adb5bd; page-break-inside: avoid; } tr, img { page-break-inside: avoid; } p, h2, h3 { orphans: 3; widows: 3; } h2, h3 { page-break-after: avoid; } @page { size: a3; } body { min-width: 992px !important; } .container { min-width: 992px !important; } .navbar { display: none; } .badge { border: 1px solid #000; } .table { border-collapse: collapse !important; } .table td, .table th { background-color: #fff !important; } .table-bordered th, .table-bordered td { border: 1px solid #dee2e6 !important; } .table-dark { color: inherit; } .table-dark th, .table-dark td, .table-dark thead th, .table-dark tbody + tbody { border-color: #dee2e6; } .table .thead-dark th { color: inherit; border-color: #dee2e6; } } @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .animation__shake { -webkit-animation: shake 1500ms; animation: shake 1500ms; } .animation__wobble { -webkit-animation: wobble 1500ms; animation: wobble 1500ms; } .preloader { display: -ms-flexbox; display: flex; background-color: #f4f6f9; height: 100vh; width: 100%; transition: height 200ms linear; position: fixed; left: 0; top: 0; z-index: 9999; } html.scroll-smooth { scroll-behavior: smooth; } html, body, .wrapper { min-height: 100%; } .wrapper { position: relative; } .wrapper .content-wrapper { min-height: calc(100vh - calc(3.5rem + 1px) - calc(3.5rem + 1px)); } .layout-boxed .wrapper { box-shadow: 0 0 10 rgba(0, 0, 0, 0.3); } .layout-boxed .wrapper, .layout-boxed .wrapper::before { margin: 0 auto; max-width: 1250px; overflow: hidden; } .layout-boxed .wrapper .main-sidebar { left: inherit; } @supports not (-webkit-touch-callout: none) { .layout-fixed .wrapper .sidebar { height: calc(100vh - (3.5rem + 1px)); } .layout-fixed.text-sm .wrapper .sidebar { height: calc(100vh - (2.93725rem + 1px)); } } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link { height: calc(3.5rem + 1px); width: 4.6rem; } .layout-navbar-fixed.sidebar-mini.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse .wrapper .brand-link.text-sm, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse .wrapper .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed.sidebar-mini.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-md.sidebar-collapse.text-sm .wrapper .brand-link, .layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse.text-sm .wrapper .brand-link { height: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .sidebar-dark-primary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-primary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-secondary .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-secondary .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-success .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-success .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-info .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-info .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-warning .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-warning .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-danger .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-danger .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-light .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-light .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lightblue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lightblue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-navy .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-navy .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-olive .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-olive .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-lime .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-lime .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-fuchsia .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-fuchsia .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-maroon .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-maroon .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-blue .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-blue .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-indigo .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-indigo .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-purple .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-purple .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-pink .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-pink .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-red .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-red .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-orange .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-orange .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-yellow .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-yellow .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-green .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-green .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-teal .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-teal .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-cyan .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-cyan .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-white .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-white .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .sidebar-dark-gray-dark .brand-link:not([class*="navbar"]) { background-color: #343a40; } .layout-navbar-fixed .wrapper .sidebar-light-gray-dark .brand-link:not([class*="navbar"]) { background-color: #fff; } .layout-navbar-fixed .wrapper .main-header.border-bottom-0 ~ .content-wrapper { margin-top: 3.5rem; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1033; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } .layout-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-navbar-not-fixed .wrapper .sidebar, .layout-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-navbar-not-fixed .wrapper .main-header { position: static; } .layout-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } @media (min-width: 576px) { .layout-sm-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-sm-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-sm-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-sm-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-sm-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-sm-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-sm-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-sm-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-sm-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-sm-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-sm-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-sm-navbar-not-fixed .wrapper .sidebar, .layout-sm-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-sm-navbar-not-fixed .wrapper .main-header { position: static; } .layout-sm-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 768px) { .layout-md-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-md-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-md-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-md-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-md-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-md-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-md-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-md-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-md-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-md-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-md-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-md-navbar-not-fixed .wrapper .sidebar, .layout-md-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-md-navbar-not-fixed .wrapper .main-header { position: static; } .layout-md-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 992px) { .layout-lg-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-lg-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-lg-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-lg-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-lg-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-lg-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-lg-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-lg-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-lg-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-lg-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-lg-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-lg-navbar-not-fixed .wrapper .sidebar, .layout-lg-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-lg-navbar-not-fixed .wrapper .main-header { position: static; } .layout-lg-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } @media (min-width: 1200px) { .layout-xl-navbar-fixed.layout-fixed .wrapper .control-sidebar { top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header ~ .control-sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed .wrapper .sidebar { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link ~ .sidebar, .layout-xl-navbar-fixed.layout-fixed .wrapper .brand-link.text-sm ~ .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .control-sidebar { top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed.layout-fixed.text-sm .wrapper .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .control-sidebar { top: 0; } .layout-xl-navbar-fixed .wrapper a.anchor { display: block; position: relative; top: calc((3.5rem + 1px + (0.5rem * 2)) / -1); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link { height: calc(3.5rem + 1px); transition: width 0.3s ease-in-out; width: 4.6rem; } .text-sm .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link, .layout-xl-navbar-fixed .wrapper.sidebar-collapse .brand-link.text-sm { height: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper.sidebar-collapse .main-sidebar:hover .brand-link { transition: width 0.3s ease-in-out; width: 250px; } .layout-xl-navbar-fixed .wrapper .brand-link { overflow: hidden; position: fixed; top: 0; transition: width 0.3s ease-in-out; width: 250px; z-index: 1035; } .layout-xl-navbar-fixed .wrapper .content-wrapper { margin-top: calc(3.5rem + 1px); } .text-sm .layout-xl-navbar-fixed .wrapper .main-header ~ .content-wrapper, .layout-xl-navbar-fixed .wrapper .main-header.text-sm ~ .content-wrapper { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-fixed .wrapper .main-header { left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } .layout-xl-navbar-fixed.text-sm .wrapper .content-wrapper { margin-top: calc(2.93725rem + 1px); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar { margin-top: calc(calc(2.93725rem + 1px) / -1); } body:not(.layout-fixed).layout-xl-navbar-fixed.text-sm .wrapper .main-sidebar .sidebar { margin-top: calc(2.93725rem + 1px); } .layout-xl-navbar-not-fixed .wrapper .brand-link { position: static; } .layout-xl-navbar-not-fixed .wrapper .sidebar, .layout-xl-navbar-not-fixed .wrapper .content-wrapper { margin-top: 0; } .layout-xl-navbar-not-fixed .wrapper .main-header { position: static; } .layout-xl-navbar-not-fixed.layout-fixed .wrapper .sidebar { margin-top: 0; } } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-not-fixed .wrapper .main-footer { position: static; } .layout-footer-not-fixed .wrapper .content-wrapper { margin-bottom: 0; } .layout-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-footer-not-fixed .wrapper .main-footer { position: static; } @media (min-width: 576px) { .layout-sm-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-sm-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-sm-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-sm-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 768px) { .layout-md-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-md-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-md-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-md-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 992px) { .layout-lg-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-lg-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-lg-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-lg-footer-not-fixed .wrapper .main-footer { position: static; } } @media (min-width: 1200px) { .layout-xl-footer-fixed .wrapper .control-sidebar { bottom: 0; } .layout-xl-footer-fixed .wrapper .main-footer { bottom: 0; left: 0; position: fixed; right: 0; z-index: 1032; } .layout-xl-footer-fixed .wrapper .content-wrapper { padding-bottom: calc(3.5rem + 1px); } .layout-xl-footer-not-fixed .wrapper .main-footer { position: static; } } .layout-top-nav .wrapper { margin-left: 0; } .layout-top-nav .wrapper .main-header .brand-image { margin-top: -.5rem; margin-right: .2rem; height: 33px; } .layout-top-nav .wrapper .main-sidebar { bottom: inherit; height: inherit; } .layout-top-nav .wrapper .content-wrapper, .layout-top-nav .wrapper .main-header, .layout-top-nav .wrapper .main-footer { margin-left: 0; } body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .content-wrapper::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-footer::before, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header, body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) .main-header::before { margin-left: 0; } @media (min-width: 768px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, .sidebar-collapse body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (max-width: 991.98px) { body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .content-wrapper, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-footer, body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-md .content-wrapper, .sidebar-collapse .sidebar-mini-md .main-footer, .sidebar-collapse .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md .content-wrapper, .sidebar-mini-md .main-footer, .sidebar-mini-md .main-header { margin-left: 0; } } @media (min-width: 768px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: margin-left 0.3s ease-in-out; margin-left: 250px; } } @media (min-width: 768px) and (prefers-reduced-motion: reduce) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { transition: none; } } @media (min-width: 768px) { .sidebar-collapse .sidebar-mini-xs .content-wrapper, .sidebar-collapse .sidebar-mini-xs .main-footer, .sidebar-collapse .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini-xs .content-wrapper, .sidebar-mini-xs .main-footer, .sidebar-mini-xs .main-header { margin-left: 4.6rem; } } .content-wrapper { background-color: #f4f6f9; } .content-wrapper > .content { padding: 0 0.5rem; } .main-sidebar, .main-sidebar::before { transition: margin-left 0.3s ease-in-out, width 0.3s ease-in-out; width: 250px; } @media (prefers-reduced-motion: reduce) { .main-sidebar, .main-sidebar::before { transition: none; } } .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar, .sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-sidebar::before { box-shadow: none !important; } .sidebar-collapse .main-sidebar, .sidebar-collapse .main-sidebar::before { margin-left: -250px; } .sidebar-collapse .main-sidebar .nav-sidebar.nav-child-indent .nav-treeview { padding: 0; } @media (max-width: 767.98px) { .main-sidebar, .main-sidebar::before { box-shadow: none !important; margin-left: -250px; } .sidebar-open .main-sidebar, .sidebar-open .main-sidebar::before { margin-left: 0; } } body:not(.layout-fixed) .main-sidebar { height: inherit; min-height: 100%; position: absolute; top: 0; } body:not(.layout-fixed) .main-sidebar .sidebar { overflow-y: auto; } .layout-fixed .brand-link { width: 250px; } .layout-fixed .main-sidebar { bottom: 0; float: none; left: 0; position: fixed; top: 0; } .layout-fixed .control-sidebar { bottom: 0; float: none; position: fixed; top: 0; } .layout-fixed .control-sidebar .control-sidebar-content { height: calc(100vh - calc(3.5rem + 1px)); overflow-y: auto; scrollbar-width: thin; scrollbar-color: #a9a9a9 transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar { width: .5rem; height: .5rem; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-track { background-color: transparent; } .layout-fixed .control-sidebar .control-sidebar-content::-webkit-scrollbar-corner { background-color: transparent; } @supports (-webkit-touch-callout: none) { .layout-fixed .main-sidebar { height: inherit; } } .main-footer { background-color: #fff; border-top: 1px solid #dee2e6; color: #869099; padding: 1rem; } .text-sm .main-footer, .main-footer.text-sm { padding: 0.812rem; } .content-header { padding: 15px 0.5rem; } .text-sm .content-header { padding: 10px 0.5rem; } .content-header h1 { font-size: 1.8rem; margin: 0; } .text-sm .content-header h1 { font-size: 1.5rem; } .content-header .breadcrumb { background-color: transparent; line-height: 1.8rem; margin-bottom: 0; padding: 0; } .text-sm .content-header .breadcrumb { line-height: 1.5rem; } .hold-transition .content-wrapper, .hold-transition .main-header, .hold-transition .main-sidebar, .hold-transition .main-sidebar *, .hold-transition .control-sidebar, .hold-transition .control-sidebar *, .hold-transition .main-footer { transition: none !important; -webkit-animation-duration: 0s !important; animation-duration: 0s !important; } .main-header { border-bottom: 1px solid #dee2e6; z-index: 1034; } .main-header .nav-link { height: 2.5rem; position: relative; } .text-sm .main-header .nav-link, .main-header.text-sm .nav-link { height: 1.93725rem; padding: 0.35rem 1rem; } .text-sm .main-header .nav-link > .fa, .text-sm .main-header .nav-link > .fas, .text-sm .main-header .nav-link > .far, .text-sm .main-header .nav-link > .fab, .text-sm .main-header .nav-link > .fal, .text-sm .main-header .nav-link > .fad, .text-sm .main-header .nav-link > .svg-inline--fa, .text-sm .main-header .nav-link > .ion, .main-header.text-sm .nav-link > .fa, .main-header.text-sm .nav-link > .fas, .main-header.text-sm .nav-link > .far, .main-header.text-sm .nav-link > .fab, .main-header.text-sm .nav-link > .fal, .main-header.text-sm .nav-link > .fad, .main-header.text-sm .nav-link > .svg-inline--fa, .main-header.text-sm .nav-link > .ion { font-size: 0.875rem; } .main-header .navbar-nav .nav-item { margin: 0; } .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: auto; margin-top: -3px; right: 0; } @media (max-width: 575.98px) { .main-header .navbar-nav[class*="-right"] .dropdown-menu { left: 0; right: auto; } } .main-header.dropdown-legacy .dropdown-menu { top: 3rem; margin-top: 0; } .navbar-img { height: calc(calc(3.5rem + 1px) * .5); width: auto; } .navbar-badge { font-size: .6rem; font-weight: 300; padding: 2px 4px; position: absolute; right: 5px; top: 9px; } .btn-navbar { background-color: transparent; border-left-width: 0; } .form-control-navbar { border-right-width: 0; } .form-control-navbar + .input-group-append { margin-left: 0; } .form-control-navbar, .btn-navbar { transition: none; } .navbar-dark .form-control-navbar, .navbar-dark .btn-navbar { background-color: #343a40; border-color: #6c757d; } .navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(255, 255, 255, 0.6); } .navbar-dark .form-control-navbar:focus, .navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #495057; border-color: #6c757d !important; color: #ced4da; } .navbar-light .form-control-navbar, .navbar-light .btn-navbar { background-color: #dadfe4; border-color: #ced4da; } .navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-moz-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar::placeholder { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar + .input-group-append > .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-light .form-control-navbar:focus, .navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d3d9df; border-color: #c7ced5 !important; color: #ced4da; } .navbar-light .navbar-search-block .form-control-navbar:focus, .navbar-light .navbar-search-block .form-control-navbar:focus + .input-group-append .btn-navbar { color: rgba(0, 0, 0, 0.6); } .navbar-search-block { position: absolute; padding: 0 1rem; left: 0; top: 0; right: 0; bottom: 0; z-index: 10; display: none; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; background-color: initial; } .navbar-search-block.navbar-search-open { display: -ms-flexbox; display: flex; } .navbar-search-block .input-group { width: 100%; } .brand-link { display: block; font-size: 1.25rem; line-height: 1.5; padding: 0.8125rem 0.5rem; transition: width 0.3s ease-in-out; white-space: nowrap; } .brand-link:hover { color: #fff; text-decoration: none; } .text-sm .brand-link { font-size: inherit; } [class*="sidebar-dark"] .brand-link { border-bottom: 1px solid #4b545c; } [class*="sidebar-dark"] .brand-link, [class*="sidebar-dark"] .brand-link .pushmenu { color: rgba(255, 255, 255, 0.8); } [class*="sidebar-dark"] .brand-link:hover, [class*="sidebar-dark"] .brand-link .pushmenu:hover { color: #fff; } [class*="sidebar-light"] .brand-link { border-bottom: 1px solid #dee2e6; } [class*="sidebar-light"] .brand-link, [class*="sidebar-light"] .brand-link .pushmenu { color: rgba(0, 0, 0, 0.8); } [class*="sidebar-light"] .brand-link:hover, [class*="sidebar-light"] .brand-link .pushmenu:hover { color: #000; } .brand-link .pushmenu { margin-right: 0.5rem; font-size: 1rem; } .brand-link .brand-link { padding: 0; border-bottom: none; } .brand-link .brand-image { float: left; line-height: .8; margin-left: .8rem; margin-right: .5rem; margin-top: -3px; max-height: 33px; width: auto; } .brand-link .brand-image-xs { float: left; line-height: .8; margin-top: -.1rem; max-height: 33px; width: auto; } .brand-link .brand-image-xl { line-height: .8; max-height: 40px; width: auto; } .brand-link .brand-image-xl.single { margin-top: -.3rem; } .brand-link.text-sm .brand-image, .text-sm .brand-link .brand-image { height: 29px; margin-bottom: -.25rem; margin-left: .95rem; margin-top: -.25rem; } .brand-link.text-sm .brand-image-xs, .text-sm .brand-link .brand-image-xs { margin-top: -.2rem; max-height: 29px; } .brand-link.text-sm .brand-image-xl, .text-sm .brand-link .brand-image-xl { margin-top: -.225rem; max-height: 38px; } .main-sidebar { height: 100vh; overflow-y: hidden; z-index: 1038; } .main-sidebar a:-moz-focusring { border: 0; outline: none; } .sidebar { height: calc(100% - (3.5rem + 1px)); overflow-x: hidden; overflow-y: initial; padding-bottom: 0; padding-left: 0.5rem; padding-right: 0.5rem; padding-top: 0; scrollbar-color: #a9a9a9 transparent; scrollbar-width: none; } .sidebar::-webkit-scrollbar-thumb { background-color: #a9a9a9; } .sidebar::-webkit-scrollbar-track { background-color: transparent; } .sidebar::-webkit-scrollbar-corner { background-color: transparent; } .sidebar::-webkit-scrollbar { width: 0; } .sidebar:hover { scrollbar-width: thin; } .sidebar:hover::-webkit-scrollbar { width: .5rem; height: .5rem; } .brand-link.border-bottom-0 ~ .sidebar { height: calc(100% - 3.5rem); } .user-panel { position: relative; } [class*="sidebar-dark"] .user-panel { border-bottom: 1px solid #4f5962; } [class*="sidebar-light"] .user-panel { border-bottom: 1px solid #dee2e6; } .user-panel, .user-panel .info { overflow: hidden; white-space: nowrap; } .user-panel .image { display: inline-block; padding-left: 0.8rem; } .user-panel img { height: auto; width: 2.1rem; } .user-panel .info { display: inline-block; padding: 5px 5px 5px 10px; } .user-panel .status, .user-panel .dropdown-menu { font-size: 0.875rem; } .nav-sidebar .nav-item > .nav-link { margin-bottom: .2rem; } .nav-sidebar .nav-item > .nav-link .right { transition: -webkit-transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s; transition: transform ease-in-out 0.3s, -webkit-transform ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-sidebar .nav-item > .nav-link .right { transition: none; } } .nav-sidebar .nav-link > .right, .nav-sidebar .nav-link > p > .right { position: absolute; right: 1rem; top: .7rem; } .nav-sidebar .nav-link > .right i, .nav-sidebar .nav-link > .right span, .nav-sidebar .nav-link > p > .right i, .nav-sidebar .nav-link > p > .right span { margin-left: .5rem; } .nav-sidebar .nav-link > .right:nth-child(2), .nav-sidebar .nav-link > p > .right:nth-child(2) { right: 2.2rem; } .nav-sidebar .menu-open > .nav-treeview { display: block; } .nav-sidebar .menu-open > .nav-link svg.right, .nav-sidebar .menu-open > .nav-link i.right, .nav-sidebar .menu-is-opening > .nav-link svg.right, .nav-sidebar .menu-is-opening > .nav-link i.right { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .nav-sidebar > .nav-item { margin-bottom: 0; } .nav-sidebar > .nav-item .nav-icon { margin-left: .05rem; font-size: 1.2rem; margin-right: .2rem; text-align: center; width: 1.6rem; } .nav-sidebar > .nav-item .nav-icon.fa, .nav-sidebar > .nav-item .nav-icon.fas, .nav-sidebar > .nav-item .nav-icon.far, .nav-sidebar > .nav-item .nav-icon.fab, .nav-sidebar > .nav-item .nav-icon.fal, .nav-sidebar > .nav-item .nav-icon.fad, .nav-sidebar > .nav-item .nav-icon.svg-inline--fa, .nav-sidebar > .nav-item .nav-icon.ion { font-size: 1.1rem; } .nav-sidebar > .nav-item .float-right { margin-top: 3px; } .nav-sidebar .nav-treeview { display: none; list-style: none; padding: 0; } .nav-sidebar .nav-treeview > .nav-item > .nav-link > .nav-icon { width: 1.6rem; } .nav-sidebar.nav-child-indent .nav-treeview { transition: padding 0.3s ease-in-out; padding-left: 1rem; } .text-sm .nav-sidebar.nav-child-indent .nav-treeview { padding-left: .5rem; } .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .text-sm .nav-sidebar.nav-child-indent.nav-legacy .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-sidebar .nav-header { font-size: .9rem; padding: 0.5rem 0.75rem; } .nav-sidebar .nav-link p { display: inline; margin: 0; white-space: normal; } .sidebar-is-opening .sidebar .nav-sidebar .nav-link p { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } #sidebar-overlay { background-color: rgba(0, 0, 0, 0.1); bottom: 0; display: none; left: 0; position: fixed; right: 0; top: 0; z-index: 1037; } @media (max-width: 991.98px) { .sidebar-open #sidebar-overlay { display: block; } } [class*="sidebar-light-"] { background-color: #fff; } [class*="sidebar-light-"] .user-panel a:hover { color: #212529; } [class*="sidebar-light-"] .user-panel .status { background-color: rgba(0, 0, 0, 0.1); color: #343a40; } [class*="sidebar-light-"] .user-panel .status:hover, [class*="sidebar-light-"] .user-panel .status:focus, [class*="sidebar-light-"] .user-panel .status:active { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:active, [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link:focus { color: #343a40; } [class*="sidebar-light-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-light-"] .nav-sidebar > .nav-item:hover > .nav-link { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-link.active { color: #000; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-light-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-light-"] .nav-header { background-color: inherit; color: #292d32; } [class*="sidebar-light-"] .sidebar a { color: #343a40; } [class*="sidebar-light-"] .sidebar a:hover { text-decoration: none; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link { color: #777; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(0, 0, 0, 0.1); color: #000; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link.active:hover { background-color: rgba(0, 0, 0, 0.1); color: #212529; } [class*="sidebar-light-"] .nav-treeview > .nav-item > .nav-link:hover { background-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-light-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(0, 0, 0, 0.1); } [class*="sidebar-dark-"] { background-color: #343a40; } [class*="sidebar-dark-"] .user-panel a:hover { color: #fff; } [class*="sidebar-dark-"] .user-panel .status { background-color: rgba(255, 255, 255, 0.1); color: #c2c7d0; } [class*="sidebar-dark-"] .user-panel .status:hover, [class*="sidebar-dark-"] .user-panel .status:focus, [class*="sidebar-dark-"] .user-panel .status:active { background-color: rgba(247, 247, 247, 0.1); color: #fff; } [class*="sidebar-dark-"] .user-panel .dropdown-menu { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); border-color: rgba(242, 242, 242, 0.1); } [class*="sidebar-dark-"] .user-panel .dropdown-item { color: #212529; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:active { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item.menu-open > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item:hover > .nav-link, [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-link.active { color: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } [class*="sidebar-dark-"] .nav-sidebar > .nav-item > .nav-treeview { background-color: transparent; } [class*="sidebar-dark-"] .nav-header { background-color: inherit; color: #d0d4db; } [class*="sidebar-dark-"] .sidebar a { color: #c2c7d0; } [class*="sidebar-dark-"] .sidebar a:hover, [class*="sidebar-dark-"] .sidebar a:focus { text-decoration: none; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link { color: #c2c7d0; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link:focus { background-color: rgba(255, 255, 255, 0.1); color: #fff; } [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:hover, [class*="sidebar-dark-"] .nav-treeview > .nav-item > .nav-link.active:focus { background-color: rgba(255, 255, 255, 0.9); color: #343a40; } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview .nav-treeview { border-color: rgba(255, 255, 255, 0.9); } [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link, [class*="sidebar-dark-"] .nav-flat .nav-item .nav-treeview > .nav-item > .nav-link.active { border-color: rgba(255, 255, 255, 0.9); } .sidebar-dark-primary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-primary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-secondary .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-secondary .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-success .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-success .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-info .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-info .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-warning .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-warning .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-danger .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-danger .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-light .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar > .nav-item > .nav-link.active { background-color: #f8f9fa; color: #1f2d3d; } .sidebar-dark-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-light .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f8f9fa; } .sidebar-dark-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-dark-lightblue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar > .nav-item > .nav-link.active { background-color: #3c8dbc; color: #fff; } .sidebar-dark-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lightblue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3c8dbc; } .sidebar-dark-navy .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar > .nav-item > .nav-link.active { background-color: #001f3f; color: #fff; } .sidebar-dark-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-navy .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #001f3f; } .sidebar-dark-olive .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar > .nav-item > .nav-link.active { background-color: #3d9970; color: #fff; } .sidebar-dark-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-olive .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #3d9970; } .sidebar-dark-lime .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar > .nav-item > .nav-link.active { background-color: #01ff70; color: #1f2d3d; } .sidebar-dark-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-lime .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #01ff70; } .sidebar-dark-fuchsia .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar > .nav-item > .nav-link.active { background-color: #f012be; color: #fff; } .sidebar-dark-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-fuchsia .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #f012be; } .sidebar-dark-maroon .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar > .nav-item > .nav-link.active { background-color: #d81b60; color: #fff; } .sidebar-dark-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-maroon .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #d81b60; } .sidebar-dark-blue .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar > .nav-item > .nav-link.active { background-color: #007bff; color: #fff; } .sidebar-dark-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-blue .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #007bff; } .sidebar-dark-indigo .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar > .nav-item > .nav-link.active { background-color: #6610f2; color: #fff; } .sidebar-dark-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-indigo .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6610f2; } .sidebar-dark-purple .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar > .nav-item > .nav-link.active { background-color: #6f42c1; color: #fff; } .sidebar-dark-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-purple .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6f42c1; } .sidebar-dark-pink .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar > .nav-item > .nav-link.active { background-color: #e83e8c; color: #fff; } .sidebar-dark-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-pink .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #e83e8c; } .sidebar-dark-red .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar > .nav-item > .nav-link.active { background-color: #dc3545; color: #fff; } .sidebar-dark-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-red .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #dc3545; } .sidebar-dark-orange .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar > .nav-item > .nav-link.active { background-color: #fd7e14; color: #1f2d3d; } .sidebar-dark-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-orange .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fd7e14; } .sidebar-dark-yellow .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar > .nav-item > .nav-link.active { background-color: #ffc107; color: #1f2d3d; } .sidebar-dark-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-yellow .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #ffc107; } .sidebar-dark-green .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar > .nav-item > .nav-link.active { background-color: #28a745; color: #fff; } .sidebar-dark-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-green .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #28a745; } .sidebar-dark-teal .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar > .nav-item > .nav-link.active { background-color: #20c997; color: #fff; } .sidebar-dark-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-teal .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #20c997; } .sidebar-dark-cyan .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar > .nav-item > .nav-link.active { background-color: #17a2b8; color: #fff; } .sidebar-dark-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-cyan .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #17a2b8; } .sidebar-dark-white .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar > .nav-item > .nav-link.active { background-color: #fff; color: #1f2d3d; } .sidebar-dark-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-white .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #fff; } .sidebar-dark-gray .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar > .nav-item > .nav-link.active { background-color: #6c757d; color: #fff; } .sidebar-dark-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #6c757d; } .sidebar-dark-gray-dark .nav-sidebar > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar > .nav-item > .nav-link.active { background-color: #343a40; color: #fff; } .sidebar-dark-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active, .sidebar-light-gray-dark .nav-sidebar.nav-legacy > .nav-item > .nav-link.active { border-color: #343a40; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand) .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-compact.nav-sidebar.nav-child-indent:not(.nav-flat) .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .nav-flat { margin: -0.25rem -0.5rem 0; } .nav-flat .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-flat .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .nav-flat:not(.nav-child-indent) .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: .4rem; } .nav-flat.nav-child-indent .nav-treeview { padding-left: 0; } .nav-flat.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview { border-left: .2rem solid; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-icon { margin-left: .55rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-link { padding-left: calc(1rem - .2rem); } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-icon { margin-left: .35rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: .15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.15rem; } .sidebar-collapse .nav-flat.nav-child-indent .sidebar .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: -.35rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-compact.nav-sidebar .nav-treeview .nav-icon { margin-left: .4rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-icon { margin-left: .85rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-icon { margin-left: 1.15rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.45rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 1.75rem; } .sidebar-mini .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar:not(.sidebar-no-expand):hover .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon, .sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-sidebar.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-icon { margin-left: 2.05rem; } .nav-flat .nav-icon { transition: margin-left ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .nav-flat .nav-icon { transition: none; } } .nav-flat .nav-treeview .nav-icon { margin-left: -.2rem; } .nav-flat.nav-sidebar > .nav-item .nav-treeview, .nav-flat.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } .nav-flat.nav-sidebar > .nav-item .nav-treeview .nav-item > .nav-link, .nav-flat.nav-sidebar > .nav-item > .nav-treeview .nav-item > .nav-link { border-left: .2rem solid; } .nav-legacy { margin: -0.25rem -0.5rem 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link { border-radius: 0; margin-bottom: 0; } .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .55rem; } .text-sm .nav-legacy.nav-sidebar .nav-item > .nav-link > .nav-icon { margin-left: .75rem; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { background-color: inherit; border-left: 3px solid transparent; box-shadow: none; } .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.55rem - 3px); } .text-sm .nav-legacy.nav-sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } .text-sm .nav-legacy.nav-sidebar.nav-flat .nav-treeview .nav-item > .nav-link > .nav-icon { margin-left: calc(.75rem - 3px); } .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: margin-left ease-in-out 0.3s; margin-left: .6rem; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-md .nav-legacy > .nav-item .nav-link .nav-icon, .sidebar-mini-xs .nav-legacy > .nav-item .nav-link .nav-icon { transition: none; } } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview { padding-left: 1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.nav-child-indent .nav-treeview .nav-treeview { padding-left: 2rem; margin-left: -1rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview { padding-left: .5rem; } .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-md.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar.sidebar-focused .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview, .main-sidebar:hover .nav-legacy .sidebar-mini-xs.sidebar-collapse.text-sm.nav-child-indent .nav-treeview .nav-treeview { padding-left: 1rem; margin-left: -.5rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .55rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: .36rem; } .sidebar-mini.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-md.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview, .sidebar-mini-xs.sidebar-collapse .nav-legacy .sidebar.nav-child-indent .nav-treeview .nav-treeview { padding-left: 0; margin-left: 0; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link .nav-icon { margin-left: .75rem; } .sidebar-mini.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-md.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon, .sidebar-mini-xs.sidebar-collapse.text-sm .nav-legacy .sidebar > .nav-item > .nav-link.active > .nav-icon { margin-left: calc(.75rem - 3px); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(255, 255, 255, 0.05); } [class*="sidebar-dark"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #fff; } [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-dark"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #fff; } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item .nav-treeview, [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-treeview { background-color: rgba(0, 0, 0, 0.05); } [class*="sidebar-light"] .nav-legacy.nav-sidebar > .nav-item > .nav-link.active { color: #000; } [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link.active, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:focus, [class*="sidebar-light"] .nav-legacy .nav-treeview > .nav-item > .nav-link:hover { background-color: transparent; color: #000; } .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .sidebar-collapse .sidebar:not(:hover) .nav-collapse-hide-child .menu-open > .nav-treeview { max-height: 0; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-md.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar.sidebar-focused .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview, .main-sidebar:not(.sidebar-no-expand):hover .nav-collapse-hide-child .sidebar-mini-xs.sidebar-collapse .menu-open > .nav-treeview { max-height: -webkit-min-content; max-height: -moz-min-content; max-height: min-content; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; } .nav-compact .nav-link, .nav-compact .nav-header { padding-top: 0.25rem; padding-bottom: 0.25rem; } .nav-compact .nav-header:not(:first-of-type) { padding-top: 0.75rem; padding-bottom: 0.25rem; } .nav-compact .nav-link > .right, .nav-compact .nav-link > p > .right { top: .465rem; } .text-sm .nav-compact .nav-link > .right, .text-sm .nav-compact .nav-link > p > .right { top: .7rem; } [class*="sidebar-dark"] .form-control-sidebar, [class*="sidebar-dark"] .btn-sidebar { background-color: #3f474e; border: 1px solid #56606a; color: white; } [class*="sidebar-dark"] .form-control-sidebar:focus, [class*="sidebar-dark"] .btn-sidebar:focus { border: 1px solid #7a8793; } [class*="sidebar-dark"] .btn-sidebar:hover { background-color: #454d55; } [class*="sidebar-dark"] .btn-sidebar:focus { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item { background-color: #454d55; border-color: #56606a; color: #c2c7d0; } [class*="sidebar-dark"] .list-group-item:hover { background-color: #4b545c; } [class*="sidebar-dark"] .list-group-item:focus { background-color: #515a63; } [class*="sidebar-dark"] .list-group-item .search-path { color: #adb5bd; } [class*="sidebar-light"] .form-control-sidebar, [class*="sidebar-light"] .btn-sidebar { background-color: #f2f2f2; border: 1px solid #d9d9d9; color: #1f2d3d; } [class*="sidebar-light"] .form-control-sidebar:focus, [class*="sidebar-light"] .btn-sidebar:focus { border: 1px solid #b3b3b3; } [class*="sidebar-light"] .btn-sidebar:hover { background-color: #ececec; } [class*="sidebar-light"] .btn-sidebar:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item { border-color: #d9d9d9; } [class*="sidebar-light"] .list-group-item:hover { background-color: #ececec; } [class*="sidebar-light"] .list-group-item:focus { background-color: #e6e6e6; } [class*="sidebar-light"] .list-group-item .search-path { color: #6c757d; } .sidebar .form-inline .input-group { width: 100%; -ms-flex-wrap: nowrap; flex-wrap: nowrap; } .sidebar nav .form-inline { margin-bottom: .2rem; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs).sidebar-collapse .main-sidebar { margin-left: 0; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .content-wrapper, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-header, .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .main-footer { z-index: 9999; position: relative; } .layout-boxed:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) .control-sidebar { z-index: 9999; } .sidebar-collapse .form-control-sidebar, .sidebar-collapse .form-control-sidebar ~ .input-group-append, .sidebar-collapse .sidebar-search-results { display: none; } [data-widget="sidebar-search"] input[type="search"]::-ms-clear, [data-widget="sidebar-search"] input[type="search"]::-ms-reveal { display: none; width: 0; height: 0; } [data-widget="sidebar-search"] input[type="search"]::-webkit-search-cancel-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-decoration, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-button, [data-widget="sidebar-search"] input[type="search"]::-webkit-search-results-decoration { display: none; } .sidebar-search-results { position: relative; display: none; width: 100%; } .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-search-results .search-title { margin-bottom: -.1rem; } .sidebar-search-results .list-group { position: absolute; width: 100%; z-index: 1039; } .sidebar-search-results .list-group > .list-group-item { padding: 0.375rem 0.75rem; } .sidebar-search-results .list-group > .list-group-item:-moz-focusring { margin-top: 0; border-left: 1px solid transparent; border-top: 0; border-bottom: 1px solid transparent; } .sidebar-search-results .list-group > .list-group-item:first-child { margin-top: 0; border-top: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .sidebar-search-results .search-path { font-size: 80%; } .sidebar-search-open .btn, .sidebar-search-open .form-control { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } [class*="sidebar-dark"] .sidebar-custom { border-top: 1px solid #4f5962; } [class*="sidebar-light"] .sidebar-custom { border-top: 1px solid #dee2e6; } .layout-fixed.sidebar-collapse .hide-on-collapse { display: none; } .layout-fixed.sidebar-collapse:hover .hide-on-collapse { display: block; } .layout-fixed.text-sm .main-sidebar-custom .sidebar { height: calc(100% - ((2.93725rem + 3.8rem) + 1px)); } .layout-fixed.text-sm .main-sidebar-custom .sidebar-custom { height: 3.8rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom { height: -webkit-fill-available; height: -moz-available; height: -ms-stretch; height: stretch; } .layout-fixed .main-sidebar-custom .sidebar { height: calc(100% - ((3.5rem + 4rem) + 1px)); } .layout-fixed .main-sidebar-custom .sidebar-custom { height: 4rem; padding: 0.85rem 0.5rem; } .layout-fixed .main-sidebar-custom-lg .sidebar { height: calc(100% - ((3.5rem + 6rem) + 1px)); } .layout-fixed .main-sidebar-custom-lg .sidebar-custom { height: 6rem; } .layout-fixed .main-sidebar-custom-xl .sidebar { height: calc(100% - ((3.5rem + 8rem) + 1px)); } .layout-fixed .main-sidebar-custom-xl .sidebar-custom { height: 8rem; } .layout-fixed .main-sidebar-custom .pos-right, .layout-fixed .main-sidebar-custom-lg .pos-right, .layout-fixed .main-sidebar-custom-xl .pos-right { position: absolute; right: .5rem; } .sidebar-hidden .main-sidebar, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-sidebar { display: none !important; } .sidebar-hidden .content-wrapper, .sidebar-hidden .main-header, .sidebar-hidden.sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-hidden.sidebar-mini.sidebar-collapse .main-header { margin-left: 0 !important; } .logo-xs, .logo-xl { opacity: 1; position: absolute; visibility: visible; } .logo-xs.brand-image-xs, .logo-xl.brand-image-xs { left: 18px; top: 12px; } .logo-xs.brand-image-xl, .logo-xl.brand-image-xl { left: 12px; top: 6px; } .logo-xs { opacity: 0; visibility: hidden; } .logo-xs.brand-image-xl { left: 16px; top: 8px; } .brand-link.logo-switch::before { content: "\00a0"; } @media (min-width: 992px) { .sidebar-mini .nav-sidebar, .sidebar-mini .nav-sidebar > .nav-header, .sidebar-mini .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini.sidebar-collapse .content-wrapper, .sidebar-mini.sidebar-collapse .main-footer, .sidebar-mini.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar, .sidebar-mini.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 991.98px) { .sidebar-mini.sidebar-collapse .main-sidebar { box-shadow: none !important; } } @media (min-width: 768px) { .sidebar-mini-md .nav-sidebar, .sidebar-mini-md .nav-sidebar > .nav-header, .sidebar-mini-md .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-md.sidebar-collapse .content-wrapper, .sidebar-mini-md.sidebar-collapse .main-footer, .sidebar-mini-md.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-md.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-md.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-md.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar, .sidebar-mini-md.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-md.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-md.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-md.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-md.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } } @media (max-width: 767.98px) { .sidebar-mini-md.sidebar-collapse .main-sidebar { box-shadow: none !important; } } .sidebar-mini-xs .nav-sidebar, .sidebar-mini-xs .nav-sidebar > .nav-header, .sidebar-mini-xs .nav-sidebar .nav-link { white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .d-hidden-mini { display: none; } .sidebar-mini-xs.sidebar-collapse .content-wrapper, .sidebar-mini-xs.sidebar-collapse .main-footer, .sidebar-mini-xs.sidebar-collapse .main-header { margin-left: 4.6rem !important; } .sidebar-mini-xs.sidebar-collapse .nav-sidebar .nav-header { display: none; } .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p { width: 0; white-space: nowrap; } .sidebar-mini-xs.sidebar-collapse .sidebar .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .brand-text { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .logo-xs { display: inline-block; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar { overflow-x: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar, .sidebar-mini-xs.sidebar-collapse .main-sidebar::before { margin-left: 0; width: 4.6rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar .user-panel .image { float: none; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-link, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel { text-align: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel .image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel .image { float: left; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xl, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-text, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xl { display: inline-block; margin-left: 0; -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .logo-xs, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .logo-xs { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .brand-image, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .brand-image { margin-right: .5rem; } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .user-panel > .info, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .sidebar-form, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .user-panel > .info { display: block !important; -webkit-transform: translateZ(0); transform: translateZ(0); } .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand):hover .nav-sidebar > .nav-item > .nav-link > span, .sidebar-mini-xs.sidebar-collapse .main-sidebar:not(.sidebar-no-expand).sidebar-focused .nav-sidebar > .nav-item > .nav-link > span { display: inline-block !important; } .sidebar-mini-xs.sidebar-collapse .visible-sidebar-mini { display: block !important; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .main-sidebar:hover .brand-link { width: 250px; } .sidebar-mini-xs.sidebar-collapse.layout-fixed .brand-link { width: 4.6rem; } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 3rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 4rem); } .sidebar-mini .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 5rem); } .sidebar-mini .main-sidebar .nav-legacy .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-mini .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-mini .main-sidebar .nav-flat .nav-link, .sidebar-mini-md .main-sidebar .nav-flat .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-mini .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 1.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 0.5rem * 2 - 2.5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-mini .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-md .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-mini-xs .main-sidebar .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { width: calc(250px - 0.5rem * 2); transition: width ease-in-out 0.3s; } @media (prefers-reduced-motion: reduce) { .sidebar-mini .main-sidebar .nav-link, .sidebar-mini-md .main-sidebar .nav-link, .sidebar-mini-xs .main-sidebar .nav-link { transition: none; } } .sidebar-collapse.sidebar-mini .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar .sidebar-search-results { display: none; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar .nav-link { width: 3.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-legacy .nav-link { width: 4.6rem; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-treeview { padding-left: 0 !important; margin-left: 0 !important; } .sidebar-collapse.sidebar-mini .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar .nav-sidebar.nav-child-indent.nav-compact .nav-link { width: calc(4.6rem - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.hide-nav-header-on-hover) .nav-header, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.hide-nav-header-on-hover) .nav-header { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .form-control-sidebar ~ .input-group-append { display: -ms-flexbox; display: flex; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover:not(.sidebar-no-expand) .sidebar-search-open .sidebar-search-results { display: inline-block; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-link { width: calc(250px - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 1rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 3rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-legacy.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - 1rem - 4rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-link { width: calc(250px); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-flat.nav-child-indent .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .2rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-compact .nav-link { width: calc(250px - 0.5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-link { width: 250px; } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-link { width: calc(250px - .5rem); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 2); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 3); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 4); } .sidebar-collapse.sidebar-mini .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-md .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar.sidebar-focused .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link, .sidebar-collapse.sidebar-mini-xs .main-sidebar:hover .nav-child-indent.nav-legacy.nav-compact .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-treeview .nav-link { width: calc(250px - .5rem * 5); } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover { width: 4.6rem; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-header, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-header { display: none; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .brand-link, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .brand-link { width: 4.6rem !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .user-panel .image, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .user-panel .image { float: none !important; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xs, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xs { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .logo-xl, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .logo-xl { -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .nav-sidebar.nav-child-indent .nav-treeview, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .nav-sidebar.nav-child-indent .nav-treeview { padding-left: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar .nav-link p, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .brand-text, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .user-panel > .info, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar .nav-link p { margin-left: -10px; -webkit-animation-name: fadeOut; animation-name: fadeOut; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: hidden; display: inline-block; width: 0; } .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-md .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar.sidebar-focused .sidebar .nav-sidebar > .nav-item .nav-icon, .sidebar-collapse.sidebar-mini-xs .sidebar-no-expand.main-sidebar:hover .sidebar .nav-sidebar > .nav-item .nav-icon { margin-right: 0; } .nav-sidebar { position: relative; } .nav-sidebar:hover { overflow: visible; } .sidebar-form, .nav-sidebar > .nav-header { overflow: hidden; text-overflow: clip; } .nav-sidebar .nav-item > .nav-link { position: relative; } .nav-sidebar .nav-item > .nav-link > .float-right { margin-top: -7px; position: absolute; right: 10px; top: 50%; } .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: margin-left 0.3s linear, opacity 0.3s ease, visibility 0.3s ease; } @media (prefers-reduced-motion: reduce) { .sidebar .nav-link p, .main-sidebar .brand-text, .main-sidebar .logo-xs, .main-sidebar .logo-xl, .sidebar .user-panel .info { transition: none; } } html.control-sidebar-animate { overflow-x: hidden; } .control-sidebar { bottom: calc(3.5rem + 1px); position: absolute; top: calc(3.5rem + 1px); z-index: 1031; } .control-sidebar, .control-sidebar::before { bottom: calc(3.5rem + 1px); display: none; right: -250px; width: 250px; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar, .control-sidebar::before { transition: none; } } .control-sidebar::before { content: ""; display: block; position: fixed; top: 0; z-index: -1; } body.text-sm .control-sidebar { bottom: calc(2.9365rem + 1px); top: calc(2.93725rem + 1px); } .main-header.text-sm ~ .control-sidebar { top: calc(2.93725rem + 1px); } .main-footer.text-sm ~ .control-sidebar { bottom: calc(2.9365rem + 1px); } .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: margin-right 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-push-slide .content-wrapper, .control-sidebar-push-slide .main-footer { transition: none; } } .control-sidebar-open .control-sidebar { display: block !important; } .control-sidebar-open .control-sidebar, .control-sidebar-open .control-sidebar::before { right: 0; } .control-sidebar-open.control-sidebar-push .content-wrapper, .control-sidebar-open.control-sidebar-push .main-footer, .control-sidebar-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-slide-open .control-sidebar { display: block; } .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { right: 0; transition: right 0.3s ease-in-out, display 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .control-sidebar-slide-open .control-sidebar, .control-sidebar-slide-open .control-sidebar::before { transition: none; } } .control-sidebar-slide-open.control-sidebar-push .content-wrapper, .control-sidebar-slide-open.control-sidebar-push .main-footer, .control-sidebar-slide-open.control-sidebar-push-slide .content-wrapper, .control-sidebar-slide-open.control-sidebar-push-slide .main-footer { margin-right: 250px; } .control-sidebar-dark { background-color: #343a40; } .control-sidebar-dark, .control-sidebar-dark a, .control-sidebar-dark .nav-link { color: #c2c7d0; } .control-sidebar-dark a:hover { color: #fff; } .control-sidebar-dark h1, .control-sidebar-dark h2, .control-sidebar-dark h3, .control-sidebar-dark h4, .control-sidebar-dark h5, .control-sidebar-dark h6, .control-sidebar-dark label { color: #fff; } .control-sidebar-dark .nav-tabs { background-color: rgba(255, 255, 255, 0.1); border-bottom: 0; margin-bottom: 5px; } .control-sidebar-dark .nav-tabs .nav-item { margin: 0; } .control-sidebar-dark .nav-tabs .nav-link { border-radius: 0; padding: 10px 20px; position: relative; text-align: center; } .control-sidebar-dark .nav-tabs .nav-link, .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border: 0; } .control-sidebar-dark .nav-tabs .nav-link:hover, .control-sidebar-dark .nav-tabs .nav-link:active, .control-sidebar-dark .nav-tabs .nav-link:focus, .control-sidebar-dark .nav-tabs .nav-link.active { border-bottom-color: transparent; border-left-color: transparent; border-top-color: transparent; color: #fff; } .control-sidebar-dark .nav-tabs .nav-link.active { background-color: #343a40; } .control-sidebar-dark .tab-pane { padding: 10px 15px; } .control-sidebar-light { color: #4b545c; background-color: #fff; border-left: 1px solid #dee2e6; } .text-sm .dropdown-menu { font-size: 0.875rem !important; } .text-sm .dropdown-toggle::after { vertical-align: .2rem; } .dropdown-item-title { font-size: 1rem; margin: 0; } .dropdown-icon::after { margin-left: 0; } .dropdown-menu-lg { max-width: 300px; min-width: 280px; padding: 0; } .dropdown-menu-lg .dropdown-divider { margin: 0; } .dropdown-menu-lg .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-lg p { margin: 0; white-space: normal; } .dropdown-submenu { position: relative; } .dropdown-submenu > a::after { border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; float: right; margin-left: .5rem; margin-top: .5rem; } .dropdown-submenu > .dropdown-menu { left: 100%; margin-left: 0; margin-top: 0; top: 0; } .dropdown-hover:hover > .dropdown-menu, .dropdown-hover.nav-item.dropdown:hover > .dropdown-menu, .dropdown-hover .dropdown-submenu:hover > .dropdown-menu, .dropdown-hover.dropdown-submenu:hover > .dropdown-menu { display: block; } .dropdown-menu-xl { max-width: 420px; min-width: 360px; padding: 0; } .dropdown-menu-xl .dropdown-divider { margin: 0; } .dropdown-menu-xl .dropdown-item { padding: 0.5rem 1rem; } .dropdown-menu-xl p { margin: 0; white-space: normal; } .dropdown-footer, .dropdown-header { display: block; font-size: 0.875rem; padding: 0.5rem 1rem; text-align: center; } .open:not(.dropup) > .animated-dropdown-menu { -webkit-animation: flipInX 0.7s both; animation: flipInX 0.7s both; -webkit-backface-visibility: visible !important; backface-visibility: visible !important; } .navbar-custom-menu > .navbar-nav > li { position: relative; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 0; left: auto; } @media (max-width: 767.98px) { .navbar-custom-menu > .navbar-nav { float: right; } .navbar-custom-menu > .navbar-nav > li { position: static; } .navbar-custom-menu > .navbar-nav > li > .dropdown-menu { position: absolute; right: 5%; left: auto; border: 1px solid #ddd; background-color: #fff; } } .navbar-nav > .user-menu > .nav-link::after { content: none; } .navbar-nav > .user-menu > .dropdown-menu { border-top-left-radius: 0; border-top-right-radius: 0; padding: 0; width: 280px; } .navbar-nav > .user-menu > .dropdown-menu, .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header { height: 175px; padding: 10px; text-align: center; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > img { z-index: 5; height: 90px; width: 90px; border: 3px solid; border-color: transparent; border-color: rgba(255, 255, 255, 0.2); } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p { z-index: 5; font-size: 17px; margin-top: 10px; } .navbar-nav > .user-menu > .dropdown-menu > li.user-header > p > small { display: block; font-size: 12px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body { border-bottom: 1px solid #495057; border-top: 1px solid #dee2e6; padding: 15px; } .navbar-nav > .user-menu > .dropdown-menu > .user-body::after { display: block; clear: both; content: ""; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-body a { background-color: #fff !important; color: #495057 !important; } } .navbar-nav > .user-menu > .dropdown-menu > .user-footer { background-color: #f8f9fa; padding: 10px; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer::after { display: block; clear: both; content: ""; } .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default { color: #6c757d; } @media (min-width: 576px) { .navbar-nav > .user-menu > .dropdown-menu > .user-footer .btn-default:hover { background-color: #f8f9fa; } } .navbar-nav > .user-menu .user-image { border-radius: 50%; float: left; height: 2.1rem; margin-right: 10px; margin-top: -2px; width: 2.1rem; } @media (min-width: 576px) { .navbar-nav > .user-menu .user-image { float: none; line-height: 10px; margin-right: .4rem; margin-top: -8px; } } .nav-pills .nav-link { color: #6c757d; } .nav-pills .nav-link:not(.active):hover { color: #007bff; } .nav-pills .nav-item.dropdown.show .nav-link:hover { color: #fff; } .nav-tabs.flex-column { border-bottom: 0; border-right: 1px solid #dee2e6; } .nav-tabs.flex-column .nav-link { border-bottom-left-radius: 0.25rem; border-top-right-radius: 0; margin-right: -1px; } .nav-tabs.flex-column .nav-link:hover, .nav-tabs.flex-column .nav-link:focus { border-color: #e9ecef transparent #e9ecef #e9ecef; } .nav-tabs.flex-column .nav-link.active, .nav-tabs.flex-column .nav-item.show .nav-link { border-color: #dee2e6 transparent #dee2e6 #dee2e6; } .nav-tabs.flex-column.nav-tabs-right { border-left: 1px solid #dee2e6; border-right: 0; } .nav-tabs.flex-column.nav-tabs-right .nav-link { border-bottom-left-radius: 0; border-bottom-right-radius: 0.25rem; border-top-left-radius: 0; border-top-right-radius: 0.25rem; margin-left: -1px; } .nav-tabs.flex-column.nav-tabs-right .nav-link:hover, .nav-tabs.flex-column.nav-tabs-right .nav-link:focus { border-color: #e9ecef #e9ecef #e9ecef transparent; } .nav-tabs.flex-column.nav-tabs-right .nav-link.active, .nav-tabs.flex-column.nav-tabs-right .nav-item.show .nav-link { border-color: #dee2e6 #dee2e6 #dee2e6 transparent; } .navbar-no-expand { -ms-flex-direction: row; flex-direction: row; } .navbar-no-expand .nav-link { padding-left: 1rem; padding-right: 1rem; } .navbar-no-expand .dropdown-menu { position: absolute; } .navbar-light { background-color: #f8f9fa; } .navbar-dark { background-color: #343a40; border-color: #4b545c; } .navbar-primary { background-color: #007bff; color: #fff; } .navbar-primary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar, .navbar-primary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-primary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-primary.navbar-light .form-control-navbar:focus, .navbar-primary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-primary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar, .navbar-primary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-primary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-primary.navbar-dark .form-control-navbar:focus, .navbar-primary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-secondary { background-color: #6c757d; color: #fff; } .navbar-secondary.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar, .navbar-secondary.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-secondary.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-secondary.navbar-light .form-control-navbar:focus, .navbar-secondary.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-secondary.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar, .navbar-secondary.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-secondary.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-secondary.navbar-dark .form-control-navbar:focus, .navbar-secondary.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-success { background-color: #28a745; color: #fff; } .navbar-success.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar, .navbar-success.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-success.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-success.navbar-light .form-control-navbar:focus, .navbar-success.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-success.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar, .navbar-success.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-success.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-success.navbar-dark .form-control-navbar:focus, .navbar-success.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-info { background-color: #17a2b8; color: #fff; } .navbar-info.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar, .navbar-info.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-info.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-info.navbar-light .form-control-navbar:focus, .navbar-info.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-info.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar, .navbar-info.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-info.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-info.navbar-dark .form-control-navbar:focus, .navbar-info.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-warning { background-color: #ffc107; color: #1f2d3d; } .navbar-warning.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar, .navbar-warning.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-warning.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-warning.navbar-light .form-control-navbar:focus, .navbar-warning.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-warning.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar, .navbar-warning.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-warning.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-warning.navbar-dark .form-control-navbar:focus, .navbar-warning.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-danger { background-color: #dc3545; color: #fff; } .navbar-danger.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar, .navbar-danger.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-danger.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-danger.navbar-light .form-control-navbar:focus, .navbar-danger.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-danger.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar, .navbar-danger.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-danger.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-danger.navbar-dark .form-control-navbar:focus, .navbar-danger.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-lightblue { background-color: #3c8dbc; color: #fff; } .navbar-lightblue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar, .navbar-lightblue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3781ad; border-color: #317399; color: rgba(52, 58, 64, 0.8); } .navbar-lightblue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lightblue.navbar-light .form-control-navbar:focus, .navbar-lightblue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #367fa9; border-color: #317399 !important; color: #343a40; } .navbar-lightblue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar, .navbar-lightblue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #4897c5; border-color: #5ba2cb; color: rgba(255, 255, 255, 0.8); } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lightblue.navbar-dark .form-control-navbar:focus, .navbar-lightblue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #4c99c6; border-color: #5ba2cb !important; color: #fff; } .navbar-navy { background-color: #001f3f; color: #fff; } .navbar-navy.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar, .navbar-navy.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00152b; border-color: #000811; color: rgba(52, 58, 64, 0.8); } .navbar-navy.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-navy.navbar-light .form-control-navbar:focus, .navbar-navy.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #001226; border-color: #000811 !important; color: #343a40; } .navbar-navy.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar, .navbar-navy.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #002953; border-color: #00366d; color: rgba(255, 255, 255, 0.8); } .navbar-navy.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-navy.navbar-dark .form-control-navbar:focus, .navbar-navy.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #002c59; border-color: #00366d !important; color: #fff; } .navbar-olive { background-color: #3d9970; color: #fff; } .navbar-olive.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar, .navbar-olive.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #378a65; border-color: #307858; color: rgba(52, 58, 64, 0.8); } .navbar-olive.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-olive.navbar-light .form-control-navbar:focus, .navbar-olive.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #368763; border-color: #307858 !important; color: #343a40; } .navbar-olive.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar, .navbar-olive.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #43a87b; border-color: #4cb888; color: rgba(255, 255, 255, 0.8); } .navbar-olive.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-olive.navbar-dark .form-control-navbar:focus, .navbar-olive.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #44ab7d; border-color: #4cb888 !important; color: #fff; } .navbar-lime { background-color: #01ff70; color: #1f2d3d; } .navbar-lime.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar, .navbar-lime.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #00ec67; border-color: #00d25c; color: rgba(52, 58, 64, 0.8); } .navbar-lime.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-lime.navbar-light .form-control-navbar:focus, .navbar-lime.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #00e765; border-color: #00d25c !important; color: #343a40; } .navbar-lime.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar, .navbar-lime.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #15ff7b; border-color: #2fff8a; color: rgba(255, 255, 255, 0.8); } .navbar-lime.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-lime.navbar-dark .form-control-navbar:focus, .navbar-lime.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1bff7e; border-color: #2fff8a !important; color: #fff; } .navbar-fuchsia { background-color: #f012be; color: #fff; } .navbar-fuchsia.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar, .navbar-fuchsia.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df0eb0; border-color: #c70d9d; color: rgba(52, 58, 64, 0.8); } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-fuchsia.navbar-light .form-control-navbar:focus, .navbar-fuchsia.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #db0ead; border-color: #c70d9d !important; color: #343a40; } .navbar-fuchsia.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar, .navbar-fuchsia.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f125c3; border-color: #f33dca; color: rgba(255, 255, 255, 0.8); } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-fuchsia.navbar-dark .form-control-navbar:focus, .navbar-fuchsia.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f22ac5; border-color: #f33dca !important; color: #fff; } .navbar-maroon { background-color: #d81b60; color: #fff; } .navbar-maroon.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar, .navbar-maroon.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #c61958; border-color: #af164e; color: rgba(52, 58, 64, 0.8); } .navbar-maroon.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-maroon.navbar-light .form-control-navbar:focus, .navbar-maroon.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #c11856; border-color: #af164e !important; color: #343a40; } .navbar-maroon.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar, .navbar-maroon.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e4246a; border-color: #e63a79; color: rgba(255, 255, 255, 0.8); } .navbar-maroon.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-maroon.navbar-dark .form-control-navbar:focus, .navbar-maroon.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e4286d; border-color: #e63a79 !important; color: #fff; } .navbar-blue { background-color: #007bff; color: #fff; } .navbar-blue.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar, .navbar-blue.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #0071eb; border-color: #0065d1; color: rgba(52, 58, 64, 0.8); } .navbar-blue.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-blue.navbar-light .form-control-navbar:focus, .navbar-blue.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #006fe6; border-color: #0065d1 !important; color: #343a40; } .navbar-blue.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar, .navbar-blue.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1486ff; border-color: #2e93ff; color: rgba(255, 255, 255, 0.8); } .navbar-blue.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-blue.navbar-dark .form-control-navbar:focus, .navbar-blue.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1a88ff; border-color: #2e93ff !important; color: #fff; } .navbar-indigo { background-color: #6610f2; color: #fff; } .navbar-indigo.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar, .navbar-indigo.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #5d0ce1; border-color: #530bc9; color: rgba(52, 58, 64, 0.8); } .navbar-indigo.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-indigo.navbar-light .form-control-navbar:focus, .navbar-indigo.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #5b0cdd; border-color: #530bc9 !important; color: #343a40; } .navbar-indigo.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar, .navbar-indigo.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7223f3; border-color: #823cf4; color: rgba(255, 255, 255, 0.8); } .navbar-indigo.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-indigo.navbar-dark .form-control-navbar:focus, .navbar-indigo.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7528f3; border-color: #823cf4 !important; color: #fff; } .navbar-purple { background-color: #6f42c1; color: #fff; } .navbar-purple.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar, .navbar-purple.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #663bb4; border-color: #5b35a0; color: rgba(52, 58, 64, 0.8); } .navbar-purple.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-purple.navbar-light .form-control-navbar:focus, .navbar-purple.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #643ab0; border-color: #5b35a0 !important; color: #343a40; } .navbar-purple.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar, .navbar-purple.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #7b51c6; border-color: #8965cc; color: rgba(255, 255, 255, 0.8); } .navbar-purple.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-purple.navbar-dark .form-control-navbar:focus, .navbar-purple.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #7e55c7; border-color: #8965cc !important; color: #fff; } .navbar-pink { background-color: #e83e8c; color: #fff; } .navbar-pink.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar, .navbar-pink.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #e62c81; border-color: #de1a74; color: rgba(52, 58, 64, 0.8); } .navbar-pink.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-pink.navbar-light .form-control-navbar:focus, .navbar-pink.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e5277e; border-color: #de1a74 !important; color: #343a40; } .navbar-pink.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar, .navbar-pink.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ea5097; border-color: #ed67a4; color: rgba(255, 255, 255, 0.8); } .navbar-pink.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-pink.navbar-dark .form-control-navbar:focus, .navbar-pink.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #eb559a; border-color: #ed67a4 !important; color: #fff; } .navbar-red { background-color: #dc3545; color: #fff; } .navbar-red.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar, .navbar-red.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #d72536; border-color: #c22231; color: rgba(52, 58, 64, 0.8); } .navbar-red.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-red.navbar-light .form-control-navbar:focus, .navbar-red.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #d32535; border-color: #c22231 !important; color: #343a40; } .navbar-red.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar, .navbar-red.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #df4655; border-color: #e35c69; color: rgba(255, 255, 255, 0.8); } .navbar-red.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-red.navbar-dark .form-control-navbar:focus, .navbar-red.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #e04b59; border-color: #e35c69 !important; color: #fff; } .navbar-orange { background-color: #fd7e14; color: #1f2d3d; } .navbar-orange.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar, .navbar-orange.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fa7302; border-color: #e16702; color: rgba(52, 58, 64, 0.8); } .navbar-orange.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-orange.navbar-light .form-control-navbar:focus, .navbar-orange.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f57102; border-color: #e16702 !important; color: #343a40; } .navbar-orange.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar, .navbar-orange.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #fd8928; border-color: #fd9742; color: rgba(255, 255, 255, 0.8); } .navbar-orange.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-orange.navbar-dark .form-control-navbar:focus, .navbar-orange.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #fd8c2d; border-color: #fd9742 !important; color: #fff; } .navbar-yellow { background-color: #ffc107; color: #1f2d3d; } .navbar-yellow.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar, .navbar-yellow.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #f2b500; border-color: #d8a200; color: rgba(52, 58, 64, 0.8); } .navbar-yellow.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-yellow.navbar-light .form-control-navbar:focus, .navbar-yellow.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #edb100; border-color: #d8a200 !important; color: #343a40; } .navbar-yellow.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar, .navbar-yellow.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #ffc61b; border-color: #ffcc35; color: rgba(255, 255, 255, 0.8); } .navbar-yellow.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-yellow.navbar-dark .form-control-navbar:focus, .navbar-yellow.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #ffc721; border-color: #ffcc35 !important; color: #fff; } .navbar-green { background-color: #28a745; color: #fff; } .navbar-green.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar, .navbar-green.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #24973e; border-color: #1f8236; color: rgba(52, 58, 64, 0.8); } .navbar-green.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-green.navbar-light .form-control-navbar:focus, .navbar-green.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #23923d; border-color: #1f8236 !important; color: #343a40; } .navbar-green.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar, .navbar-green.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2cb74c; border-color: #31cc54; color: rgba(255, 255, 255, 0.8); } .navbar-green.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-green.navbar-dark .form-control-navbar:focus, .navbar-green.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #2dbc4e; border-color: #31cc54 !important; color: #fff; } .navbar-teal { background-color: #20c997; color: #fff; } .navbar-teal.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar, .navbar-teal.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1db78a; border-color: #1aa179; color: rgba(52, 58, 64, 0.8); } .navbar-teal.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-teal.navbar-light .form-control-navbar:focus, .navbar-teal.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1cb386; border-color: #1aa179 !important; color: #343a40; } .navbar-teal.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar, .navbar-teal.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #23dba4; border-color: #38dfae; color: rgba(255, 255, 255, 0.8); } .navbar-teal.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-teal.navbar-dark .form-control-navbar:focus, .navbar-teal.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #26dca6; border-color: #38dfae !important; color: #fff; } .navbar-cyan { background-color: #17a2b8; color: #fff; } .navbar-cyan.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar, .navbar-cyan.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #1592a6; border-color: #127e8f; color: rgba(52, 58, 64, 0.8); } .navbar-cyan.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-cyan.navbar-light .form-control-navbar:focus, .navbar-cyan.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #148ea1; border-color: #127e8f !important; color: #343a40; } .navbar-cyan.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar, .navbar-cyan.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #19b2ca; border-color: #1cc6e1; color: rgba(255, 255, 255, 0.8); } .navbar-cyan.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-cyan.navbar-dark .form-control-navbar:focus, .navbar-cyan.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #1ab6cf; border-color: #1cc6e1 !important; color: #fff; } .navbar-white { background-color: #fff; color: #1f2d3d; } .navbar-white.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar, .navbar-white.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: whitesmoke; border-color: #e8e8e8; color: rgba(52, 58, 64, 0.8); } .navbar-white.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-white.navbar-light .form-control-navbar:focus, .navbar-white.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #f2f2f2; border-color: #e8e8e8 !important; color: #343a40; } .navbar-white.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar, .navbar-white.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: white; border-color: white; color: rgba(255, 255, 255, 0.8); } .navbar-white.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-white.navbar-dark .form-control-navbar:focus, .navbar-white.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: white; border-color: white !important; color: #fff; } .navbar-gray { background-color: #6c757d; color: #fff; } .navbar-gray.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar, .navbar-gray.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #636b72; border-color: #575e64; color: rgba(52, 58, 64, 0.8); } .navbar-gray.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray.navbar-light .form-control-navbar:focus, .navbar-gray.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #60686f; border-color: #575e64 !important; color: #343a40; } .navbar-gray.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar, .navbar-gray.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #757f88; border-color: #838c94; color: rgba(255, 255, 255, 0.8); } .navbar-gray.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray.navbar-dark .form-control-navbar:focus, .navbar-gray.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #78828a; border-color: #838c94 !important; color: #fff; } .navbar-gray-dark { background-color: #343a40; color: #fff; } .navbar-gray-dark.navbar-light .form-control-navbar::-webkit-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-moz-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::-ms-input-placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar::placeholder { color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar, .navbar-gray-dark.navbar-light .form-control-navbar + .input-group-append > .btn-navbar { background-color: #2b3035; border-color: #1f2327; color: rgba(52, 58, 64, 0.8); } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-webkit-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-moz-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus:-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::-ms-input-placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus::placeholder { color: #343a40; } .navbar-gray-dark.navbar-light .form-control-navbar:focus, .navbar-gray-dark.navbar-light .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #292d32; border-color: #1f2327 !important; color: #343a40; } .navbar-gray-dark.navbar-dark .form-control-navbar::-webkit-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-moz-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::-ms-input-placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar::placeholder { color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar, .navbar-gray-dark.navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3d444b; border-color: #495159; color: rgba(255, 255, 255, 0.8); } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-webkit-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-moz-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus:-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::-ms-input-placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus::placeholder { color: #fff; } .navbar-gray-dark.navbar-dark .form-control-navbar:focus, .navbar-gray-dark.navbar-dark .form-control-navbar:focus + .input-group-append .btn-navbar { background-color: #3f474e; border-color: #495159 !important; color: #fff; } .navbar-nav-not-expanded { -ms-flex-direction: row; flex-direction: row; } .navbar-nav-not-expanded .dropdown-menu { position: absolute; } .navbar-nav-not-expanded .nav-link { padding-right: 1rem; padding-left: 1rem; } .pagination-month .page-item { justify-self: stretch; } .pagination-month .page-item .page-link { display: -ms-flexbox; display: flex; -ms-flex-align: center; align-items: center; -ms-flex-pack: center; justify-content: center; -ms-flex-direction: column; flex-direction: column; box-shadow: none; } .pagination-month .page-item:first-child .page-link, .pagination-month .page-item:last-child .page-link { height: 100%; font-size: 1.25rem; } .pagination-month .page-item .page-month { margin-bottom: 0; font-size: 1.25rem; font-weight: 700; } .pagination-month .page-item .page-year { margin-bottom: 0; } .pagination-month.pagination-lg .page-month { font-size: 1.5625rem; } .pagination-month.pagination-sm .page-month { font-size: 1rem; } .form-group.has-icon { position: relative; } .form-group.has-icon .form-control { padding-right: 35px; } .form-group.has-icon .form-icon { background-color: transparent; border: 0; cursor: pointer; font-size: 1rem; padding: 0.375rem 0.75rem; position: absolute; right: 3px; top: 0; } .btn-group-vertical .btn.btn-flat:first-of-type, .btn-group-vertical .btn.btn-flat:last-of-type { border-radius: 0; } .form-control-feedback.fa, .form-control-feedback.fas, .form-control-feedback.far, .form-control-feedback.fab, .form-control-feedback.fal, .form-control-feedback.fad, .form-control-feedback.svg-inline--fa, .form-control-feedback.ion { line-height: calc(2.25rem + 2px); } .input-lg + .form-control-feedback.fa, .input-lg + .form-control-feedback.fas, .input-lg + .form-control-feedback.far, .input-lg + .form-control-feedback.fab, .input-lg + .form-control-feedback.fal, .input-lg + .form-control-feedback.fad, .input-lg + .form-control-feedback.svg-inline--fa, .input-lg + .form-control-feedback.ion, .input-group-lg + .form-control-feedback.fa, .input-group-lg + .form-control-feedback.fas, .input-group-lg + .form-control-feedback.far, .input-group-lg + .form-control-feedback.fab, .input-group-lg + .form-control-feedback.fal, .input-group-lg + .form-control-feedback.fad, .input-group-lg + .form-control-feedback.svg-inline--fa, .input-group-lg + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .form-group-lg .form-control + .form-control-feedback.fa, .form-group-lg .form-control + .form-control-feedback.fas, .form-group-lg .form-control + .form-control-feedback.far, .form-group-lg .form-control + .form-control-feedback.fab, .form-group-lg .form-control + .form-control-feedback.fal, .form-group-lg .form-control + .form-control-feedback.fad, .form-group-lg .form-control + .form-control-feedback.svg-inline--fa, .form-group-lg .form-control + .form-control-feedback.ion { line-height: calc(2.875rem + 2px); } .input-sm + .form-control-feedback.fa, .input-sm + .form-control-feedback.fas, .input-sm + .form-control-feedback.far, .input-sm + .form-control-feedback.fab, .input-sm + .form-control-feedback.fal, .input-sm + .form-control-feedback.fad, .input-sm + .form-control-feedback.svg-inline--fa, .input-sm + .form-control-feedback.ion, .input-group-sm + .form-control-feedback.fa, .input-group-sm + .form-control-feedback.fas, .input-group-sm + .form-control-feedback.far, .input-group-sm + .form-control-feedback.fab, .input-group-sm + .form-control-feedback.fal, .input-group-sm + .form-control-feedback.fad, .input-group-sm + .form-control-feedback.svg-inline--fa, .input-group-sm + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } .form-group-sm .form-control + .form-control-feedback.fa, .form-group-sm .form-control + .form-control-feedback.fas, .form-group-sm .form-control + .form-control-feedback.far, .form-group-sm .form-control + .form-control-feedback.fab, .form-group-sm .form-control + .form-control-feedback.fal, .form-group-sm .form-control + .form-control-feedback.fad, .form-group-sm .form-control + .form-control-feedback.svg-inline--fa, .form-group-sm .form-control + .form-control-feedback.ion { line-height: calc(1.8125rem + 2px); } label:not(.form-check-label):not(.custom-file-label) { font-weight: 700; } .warning-feedback { font-size: 80%; color: #ffc107; display: none; margin-top: 0.25rem; width: 100%; } .warning-tooltip { border-radius: 0.25rem; font-size: 0.875rem; background-color: rgba(255, 193, 7, 0.9); color: #1f2d3d; display: none; line-height: 1.5; margin-top: .1rem; max-width: 100%; padding: 0.25rem 0.5rem; position: absolute; top: 100%; z-index: 5; } .form-control.is-warning { border-color: #ffc107; } .form-control.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .form-control.is-warning ~ .warning-feedback, .form-control.is-warning ~ .warning-tooltip { display: block; } textarea.form-control.is-warning { padding-right: 2.25rem; background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .custom-select.is-warning { border-color: #ffc107; } .custom-select.is-warning:focus { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-select.is-warning ~ .warning-feedback, .custom-select.is-warning ~ .warning-tooltip { display: block; } .form-control-file.is-warning ~ .warning-feedback, .form-control-file.is-warning ~ .warning-tooltip { display: block; } .form-check-input.is-warning ~ .form-check-label { color: #ffc107; } .form-check-input.is-warning ~ .warning-feedback, .form-check-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning ~ .custom-control-label { color: #ffc107; } .custom-control-input.is-warning ~ .custom-control-label::before { border-color: #ffc107; } .custom-control-input.is-warning ~ .warning-feedback, .custom-control-input.is-warning ~ .warning-tooltip { display: block; } .custom-control-input.is-warning:checked ~ .custom-control-label::before { background-color: #ffce3a; border-color: #ffce3a; } .custom-control-input.is-warning:focus ~ .custom-control-label::before { box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } .custom-control-input.is-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffc107; } .custom-file-input.is-warning ~ .custom-file-label { border-color: #ffc107; } .custom-file-input.is-warning ~ .warning-feedback, .custom-file-input.is-warning ~ .warning-tooltip { display: block; } .custom-file-input.is-warning:focus ~ .custom-file-label { border-color: #ffc107; box-shadow: 0 0 0 0 rgba(255, 193, 7, 0.25); } body.text-sm .input-group-text { font-size: 0.875rem; } .form-control.form-control-border, .custom-select.form-control-border { border-top: 0; border-left: 0; border-right: 0; border-radius: 0; box-shadow: inherit; } .form-control.form-control-border.border-width-2, .custom-select.form-control-border.border-width-2 { border-bottom-width: 2px; } .form-control.form-control-border.border-width-3, .custom-select.form-control-border.border-width-3 { border-bottom-width: 3px; } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-primary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-primary .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-primary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-primary .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-secondary .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-secondary .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-secondary .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-secondary .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-success .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-success .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-success .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-success .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-info .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-info .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-info .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-info .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-warning .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-warning .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-warning .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-warning .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-danger .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-danger .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-danger .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-danger .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-off-light .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-off-light .custom-control-input ~ .custom-control-label::after { background-color: #aeb9c5; } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .custom-switch.custom-switch-on-light .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-switch.custom-switch-on-light .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-off-lightblue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-off-lightblue .custom-control-input ~ .custom-control-label::after { background-color: #1d455b; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-switch.custom-switch-on-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-color: #acd0e5; } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-off-navy .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-off-navy .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .custom-switch.custom-switch-on-navy .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-switch.custom-switch-on-navy .custom-control-input:checked ~ .custom-control-label::after { background-color: #006ad8; } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-off-olive .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-off-olive .custom-control-input ~ .custom-control-label::after { background-color: #193e2d; } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .custom-switch.custom-switch-on-olive .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-switch.custom-switch-on-olive .custom-control-input:checked ~ .custom-control-label::after { background-color: #99d6bb; } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-off-lime .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-off-lime .custom-control-input ~ .custom-control-label::after { background-color: #008138; } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .custom-switch.custom-switch-on-lime .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-switch.custom-switch-on-lime .custom-control-input:checked ~ .custom-control-label::after { background-color: #9affc6; } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-off-fuchsia .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-off-fuchsia .custom-control-input ~ .custom-control-label::after { background-color: #7b0861; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-switch.custom-switch-on-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-color: #f9a2e5; } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-off-maroon .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-off-maroon .custom-control-input ~ .custom-control-label::after { background-color: #670d2e; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .custom-switch.custom-switch-on-maroon .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-switch.custom-switch-on-maroon .custom-control-input:checked ~ .custom-control-label::after { background-color: #f29aba; } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-off-blue .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-off-blue .custom-control-input ~ .custom-control-label::after { background-color: #003e80; } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .custom-switch.custom-switch-on-blue .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-switch.custom-switch-on-blue .custom-control-input:checked ~ .custom-control-label::after { background-color: #99caff; } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-off-indigo .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-off-indigo .custom-control-input ~ .custom-control-label::after { background-color: #33077c; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .custom-switch.custom-switch-on-indigo .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-switch.custom-switch-on-indigo .custom-control-input:checked ~ .custom-control-label::after { background-color: #c3a1fa; } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-off-purple .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-off-purple .custom-control-input ~ .custom-control-label::after { background-color: #382063; } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .custom-switch.custom-switch-on-purple .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-switch.custom-switch-on-purple .custom-control-input:checked ~ .custom-control-label::after { background-color: #c7b5e7; } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-off-pink .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-off-pink .custom-control-input ~ .custom-control-label::after { background-color: #95124e; } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .custom-switch.custom-switch-on-pink .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-switch.custom-switch-on-pink .custom-control-input:checked ~ .custom-control-label::after { background-color: #f8c7dd; } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-off-red .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-off-red .custom-control-input ~ .custom-control-label::after { background-color: #7c151f; } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .custom-switch.custom-switch-on-red .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-switch.custom-switch-on-red .custom-control-input:checked ~ .custom-control-label::after { background-color: #f3b7bd; } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-off-orange .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-off-orange .custom-control-input ~ .custom-control-label::after { background-color: #904201; } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .custom-switch.custom-switch-on-orange .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-switch.custom-switch-on-orange .custom-control-input:checked ~ .custom-control-label::after { background-color: #fed1ac; } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-off-yellow .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-off-yellow .custom-control-input ~ .custom-control-label::after { background-color: #876500; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .custom-switch.custom-switch-on-yellow .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-switch.custom-switch-on-yellow .custom-control-input:checked ~ .custom-control-label::after { background-color: #ffe7a0; } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-off-green .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-off-green .custom-control-input ~ .custom-control-label::after { background-color: #0f401b; } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .custom-switch.custom-switch-on-green .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-switch.custom-switch-on-green .custom-control-input:checked ~ .custom-control-label::after { background-color: #86e29b; } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-off-teal .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-off-teal .custom-control-input ~ .custom-control-label::after { background-color: #0e5b44; } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .custom-switch.custom-switch-on-teal .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-switch.custom-switch-on-teal .custom-control-input:checked ~ .custom-control-label::after { background-color: #94eed3; } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-off-cyan .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-off-cyan .custom-control-input ~ .custom-control-label::after { background-color: #093e47; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .custom-switch.custom-switch-on-cyan .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-switch.custom-switch-on-cyan .custom-control-input:checked ~ .custom-control-label::after { background-color: #7adeee; } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-off-white .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-off-white .custom-control-input ~ .custom-control-label::after { background-color: #bfbfbf; } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .custom-switch.custom-switch-on-white .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-switch.custom-switch-on-white .custom-control-input:checked ~ .custom-control-label::after { background-color: white; } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-off-gray .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-off-gray .custom-control-input ~ .custom-control-label::after { background-color: #313539; } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .custom-switch.custom-switch-on-gray .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-switch.custom-switch-on-gray .custom-control-input:checked ~ .custom-control-label::after { background-color: #bcc1c6; } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-off-gray-dark .custom-control-input:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-off-gray-dark .custom-control-input ~ .custom-control-label::after { background-color: black; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked:focus ~ .custom-control-label::before { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-switch.custom-switch-on-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-color: #7a8793; } .custom-range.custom-range-primary:focus { outline: none; } .custom-range.custom-range-primary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-primary::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-primary::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-primary::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-secondary:focus { outline: none; } .custom-range.custom-range-secondary:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-secondary::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-secondary::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-secondary::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-success:focus { outline: none; } .custom-range.custom-range-success:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-success::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-success::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-success::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-success::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-success::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-info:focus { outline: none; } .custom-range.custom-range-info:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-info::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-info::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-info::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-warning:focus { outline: none; } .custom-range.custom-range-warning:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-warning::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-warning::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-warning::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-danger:focus { outline: none; } .custom-range.custom-range-danger:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-danger::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-danger::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-danger::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-light:focus { outline: none; } .custom-range.custom-range-light:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(248, 249, 250, 0.25); } .custom-range.custom-range-light::-webkit-slider-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-light::-moz-range-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-light::-ms-thumb { background-color: #f8f9fa; } .custom-range.custom-range-light::-ms-thumb:active { background-color: white; } .custom-range.custom-range-dark:focus { outline: none; } .custom-range.custom-range-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-dark::-ms-thumb:active { background-color: #88939e; } .custom-range.custom-range-lightblue:focus { outline: none; } .custom-range.custom-range-lightblue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(60, 141, 188, 0.25); } .custom-range.custom-range-lightblue::-webkit-slider-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-webkit-slider-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-moz-range-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-moz-range-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-lightblue::-ms-thumb { background-color: #3c8dbc; } .custom-range.custom-range-lightblue::-ms-thumb:active { background-color: #c0dbeb; } .custom-range.custom-range-navy:focus { outline: none; } .custom-range.custom-range-navy:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 31, 63, 0.25); } .custom-range.custom-range-navy::-webkit-slider-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-webkit-slider-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-moz-range-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-moz-range-thumb:active { background-color: #0077f2; } .custom-range.custom-range-navy::-ms-thumb { background-color: #001f3f; } .custom-range.custom-range-navy::-ms-thumb:active { background-color: #0077f2; } .custom-range.custom-range-olive:focus { outline: none; } .custom-range.custom-range-olive:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(61, 153, 112, 0.25); } .custom-range.custom-range-olive::-webkit-slider-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-webkit-slider-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-moz-range-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-moz-range-thumb:active { background-color: #abdec7; } .custom-range.custom-range-olive::-ms-thumb { background-color: #3d9970; } .custom-range.custom-range-olive::-ms-thumb:active { background-color: #abdec7; } .custom-range.custom-range-lime:focus { outline: none; } .custom-range.custom-range-lime:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(1, 255, 112, 0.25); } .custom-range.custom-range-lime::-webkit-slider-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-webkit-slider-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-moz-range-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-moz-range-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-lime::-ms-thumb { background-color: #01ff70; } .custom-range.custom-range-lime::-ms-thumb:active { background-color: #b4ffd4; } .custom-range.custom-range-fuchsia:focus { outline: none; } .custom-range.custom-range-fuchsia:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(240, 18, 190, 0.25); } .custom-range.custom-range-fuchsia::-webkit-slider-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-webkit-slider-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-moz-range-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-moz-range-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-fuchsia::-ms-thumb { background-color: #f012be; } .custom-range.custom-range-fuchsia::-ms-thumb:active { background-color: #fbbaec; } .custom-range.custom-range-maroon:focus { outline: none; } .custom-range.custom-range-maroon:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(216, 27, 96, 0.25); } .custom-range.custom-range-maroon::-webkit-slider-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-webkit-slider-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-moz-range-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-moz-range-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-maroon::-ms-thumb { background-color: #d81b60; } .custom-range.custom-range-maroon::-ms-thumb:active { background-color: #f5b0c9; } .custom-range.custom-range-blue:focus { outline: none; } .custom-range.custom-range-blue:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(0, 123, 255, 0.25); } .custom-range.custom-range-blue::-webkit-slider-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-webkit-slider-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-moz-range-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-moz-range-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-blue::-ms-thumb { background-color: #007bff; } .custom-range.custom-range-blue::-ms-thumb:active { background-color: #b3d7ff; } .custom-range.custom-range-indigo:focus { outline: none; } .custom-range.custom-range-indigo:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(102, 16, 242, 0.25); } .custom-range.custom-range-indigo::-webkit-slider-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-webkit-slider-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-moz-range-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-moz-range-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-indigo::-ms-thumb { background-color: #6610f2; } .custom-range.custom-range-indigo::-ms-thumb:active { background-color: #d2b9fb; } .custom-range.custom-range-purple:focus { outline: none; } .custom-range.custom-range-purple:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(111, 66, 193, 0.25); } .custom-range.custom-range-purple::-webkit-slider-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-webkit-slider-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-moz-range-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-moz-range-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-purple::-ms-thumb { background-color: #6f42c1; } .custom-range.custom-range-purple::-ms-thumb:active { background-color: #d5c8ed; } .custom-range.custom-range-pink:focus { outline: none; } .custom-range.custom-range-pink:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(232, 62, 140, 0.25); } .custom-range.custom-range-pink::-webkit-slider-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-webkit-slider-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-moz-range-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-moz-range-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-pink::-ms-thumb { background-color: #e83e8c; } .custom-range.custom-range-pink::-ms-thumb:active { background-color: #fbddeb; } .custom-range.custom-range-red:focus { outline: none; } .custom-range.custom-range-red:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(220, 53, 69, 0.25); } .custom-range.custom-range-red::-webkit-slider-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-webkit-slider-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-moz-range-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-moz-range-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-red::-ms-thumb { background-color: #dc3545; } .custom-range.custom-range-red::-ms-thumb:active { background-color: #f6cdd1; } .custom-range.custom-range-orange:focus { outline: none; } .custom-range.custom-range-orange:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(253, 126, 20, 0.25); } .custom-range.custom-range-orange::-webkit-slider-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-webkit-slider-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-moz-range-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-moz-range-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-orange::-ms-thumb { background-color: #fd7e14; } .custom-range.custom-range-orange::-ms-thumb:active { background-color: #ffdfc5; } .custom-range.custom-range-yellow:focus { outline: none; } .custom-range.custom-range-yellow:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 193, 7, 0.25); } .custom-range.custom-range-yellow::-webkit-slider-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-webkit-slider-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-moz-range-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-moz-range-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-yellow::-ms-thumb { background-color: #ffc107; } .custom-range.custom-range-yellow::-ms-thumb:active { background-color: #ffeeba; } .custom-range.custom-range-green:focus { outline: none; } .custom-range.custom-range-green:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(40, 167, 69, 0.25); } .custom-range.custom-range-green::-webkit-slider-thumb { background-color: #28a745; } .custom-range.custom-range-green::-webkit-slider-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-moz-range-thumb { background-color: #28a745; } .custom-range.custom-range-green::-moz-range-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-green::-ms-thumb { background-color: #28a745; } .custom-range.custom-range-green::-ms-thumb:active { background-color: #9be7ac; } .custom-range.custom-range-teal:focus { outline: none; } .custom-range.custom-range-teal:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(32, 201, 151, 0.25); } .custom-range.custom-range-teal::-webkit-slider-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-webkit-slider-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-moz-range-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-moz-range-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-teal::-ms-thumb { background-color: #20c997; } .custom-range.custom-range-teal::-ms-thumb:active { background-color: #aaf1dc; } .custom-range.custom-range-cyan:focus { outline: none; } .custom-range.custom-range-cyan:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(23, 162, 184, 0.25); } .custom-range.custom-range-cyan::-webkit-slider-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-webkit-slider-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-moz-range-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-moz-range-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-cyan::-ms-thumb { background-color: #17a2b8; } .custom-range.custom-range-cyan::-ms-thumb:active { background-color: #90e4f1; } .custom-range.custom-range-white:focus { outline: none; } .custom-range.custom-range-white:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(255, 255, 255, 0.25); } .custom-range.custom-range-white::-webkit-slider-thumb { background-color: #fff; } .custom-range.custom-range-white::-webkit-slider-thumb:active { background-color: white; } .custom-range.custom-range-white::-moz-range-thumb { background-color: #fff; } .custom-range.custom-range-white::-moz-range-thumb:active { background-color: white; } .custom-range.custom-range-white::-ms-thumb { background-color: #fff; } .custom-range.custom-range-white::-ms-thumb:active { background-color: white; } .custom-range.custom-range-gray:focus { outline: none; } .custom-range.custom-range-gray:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(108, 117, 125, 0.25); } .custom-range.custom-range-gray::-webkit-slider-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-webkit-slider-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-moz-range-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-moz-range-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray::-ms-thumb { background-color: #6c757d; } .custom-range.custom-range-gray::-ms-thumb:active { background-color: #caced1; } .custom-range.custom-range-gray-dark:focus { outline: none; } .custom-range.custom-range-gray-dark:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark:focus::-ms-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 2px rgba(52, 58, 64, 0.25); } .custom-range.custom-range-gray-dark::-webkit-slider-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-webkit-slider-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-moz-range-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-moz-range-thumb:active { background-color: #88939e; } .custom-range.custom-range-gray-dark::-ms-thumb { background-color: #343a40; } .custom-range.custom-range-gray-dark::-ms-thumb:active { background-color: #88939e; } .custom-control-input-primary:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-primary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-primary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-primary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-primary:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-primary:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-secondary:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-secondary.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-secondary:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-secondary:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-secondary:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-success:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-success.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-success.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-success:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-success:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-success:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-info:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-info.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-info.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-info:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-info:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-info:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-warning:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-warning.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-warning.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-warning:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-warning:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-warning:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-danger:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-danger.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-danger.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-danger:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-danger:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-danger:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-light:checked ~ .custom-control-label::before { border-color: #f8f9fa; background-color: #f8f9fa; } .custom-control-input-light.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f8f9fa' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-light.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f8f9fa'/%3E%3C/svg%3E") !important; } .custom-control-input-light:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(248, 249, 250, 0.25); } .custom-control-input-light:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-light:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-lightblue:checked ~ .custom-control-label::before { border-color: #3c8dbc; background-color: #3c8dbc; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233c8dbc' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233c8dbc'/%3E%3C/svg%3E") !important; } .custom-control-input-lightblue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(60, 141, 188, 0.25); } .custom-control-input-lightblue:focus:not(:checked) ~ .custom-control-label::before { border-color: #99c5de; } .custom-control-input-lightblue:not(:disabled):active ~ .custom-control-label::before { background-color: #c0dbeb; border-color: #c0dbeb; } .custom-control-input-navy:checked ~ .custom-control-label::before { border-color: #001f3f; background-color: #001f3f; } .custom-control-input-navy.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23001f3f' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-navy.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23001f3f'/%3E%3C/svg%3E") !important; } .custom-control-input-navy:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 31, 63, 0.25); } .custom-control-input-navy:focus:not(:checked) ~ .custom-control-label::before { border-color: #005ebf; } .custom-control-input-navy:not(:disabled):active ~ .custom-control-label::before { background-color: #0077f2; border-color: #0077f2; } .custom-control-input-olive:checked ~ .custom-control-label::before { border-color: #3d9970; background-color: #3d9970; } .custom-control-input-olive.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%233d9970' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-olive.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%233d9970'/%3E%3C/svg%3E") !important; } .custom-control-input-olive:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(61, 153, 112, 0.25); } .custom-control-input-olive:focus:not(:checked) ~ .custom-control-label::before { border-color: #87cfaf; } .custom-control-input-olive:not(:disabled):active ~ .custom-control-label::before { background-color: #abdec7; border-color: #abdec7; } .custom-control-input-lime:checked ~ .custom-control-label::before { border-color: #01ff70; background-color: #01ff70; } .custom-control-input-lime.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2301ff70' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-lime.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2301ff70'/%3E%3C/svg%3E") !important; } .custom-control-input-lime:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(1, 255, 112, 0.25); } .custom-control-input-lime:focus:not(:checked) ~ .custom-control-label::before { border-color: #81ffb8; } .custom-control-input-lime:not(:disabled):active ~ .custom-control-label::before { background-color: #b4ffd4; border-color: #b4ffd4; } .custom-control-input-fuchsia:checked ~ .custom-control-label::before { border-color: #f012be; background-color: #f012be; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23f012be' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23f012be'/%3E%3C/svg%3E") !important; } .custom-control-input-fuchsia:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(240, 18, 190, 0.25); } .custom-control-input-fuchsia:focus:not(:checked) ~ .custom-control-label::before { border-color: #f88adf; } .custom-control-input-fuchsia:not(:disabled):active ~ .custom-control-label::before { background-color: #fbbaec; border-color: #fbbaec; } .custom-control-input-maroon:checked ~ .custom-control-label::before { border-color: #d81b60; background-color: #d81b60; } .custom-control-input-maroon.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23d81b60' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23d81b60'/%3E%3C/svg%3E") !important; } .custom-control-input-maroon:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(216, 27, 96, 0.25); } .custom-control-input-maroon:focus:not(:checked) ~ .custom-control-label::before { border-color: #f083ab; } .custom-control-input-maroon:not(:disabled):active ~ .custom-control-label::before { background-color: #f5b0c9; border-color: #f5b0c9; } .custom-control-input-blue:checked ~ .custom-control-label::before { border-color: #007bff; background-color: #007bff; } .custom-control-input-blue.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23007bff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-blue.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23007bff'/%3E%3C/svg%3E") !important; } .custom-control-input-blue:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-control-input-blue:focus:not(:checked) ~ .custom-control-label::before { border-color: #80bdff; } .custom-control-input-blue:not(:disabled):active ~ .custom-control-label::before { background-color: #b3d7ff; border-color: #b3d7ff; } .custom-control-input-indigo:checked ~ .custom-control-label::before { border-color: #6610f2; background-color: #6610f2; } .custom-control-input-indigo.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236610f2' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236610f2'/%3E%3C/svg%3E") !important; } .custom-control-input-indigo:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(102, 16, 242, 0.25); } .custom-control-input-indigo:focus:not(:checked) ~ .custom-control-label::before { border-color: #b389f9; } .custom-control-input-indigo:not(:disabled):active ~ .custom-control-label::before { background-color: #d2b9fb; border-color: #d2b9fb; } .custom-control-input-purple:checked ~ .custom-control-label::before { border-color: #6f42c1; background-color: #6f42c1; } .custom-control-input-purple.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236f42c1' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-purple.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236f42c1'/%3E%3C/svg%3E") !important; } .custom-control-input-purple:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(111, 66, 193, 0.25); } .custom-control-input-purple:focus:not(:checked) ~ .custom-control-label::before { border-color: #b8a2e0; } .custom-control-input-purple:not(:disabled):active ~ .custom-control-label::before { background-color: #d5c8ed; border-color: #d5c8ed; } .custom-control-input-pink:checked ~ .custom-control-label::before { border-color: #e83e8c; background-color: #e83e8c; } .custom-control-input-pink.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23e83e8c' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-pink.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23e83e8c'/%3E%3C/svg%3E") !important; } .custom-control-input-pink:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(232, 62, 140, 0.25); } .custom-control-input-pink:focus:not(:checked) ~ .custom-control-label::before { border-color: #f6b0d0; } .custom-control-input-pink:not(:disabled):active ~ .custom-control-label::before { background-color: #fbddeb; border-color: #fbddeb; } .custom-control-input-red:checked ~ .custom-control-label::before { border-color: #dc3545; background-color: #dc3545; } .custom-control-input-red.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23dc3545' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-red.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23dc3545'/%3E%3C/svg%3E") !important; } .custom-control-input-red:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .custom-control-input-red:focus:not(:checked) ~ .custom-control-label::before { border-color: #efa2a9; } .custom-control-input-red:not(:disabled):active ~ .custom-control-label::before { background-color: #f6cdd1; border-color: #f6cdd1; } .custom-control-input-orange:checked ~ .custom-control-label::before { border-color: #fd7e14; background-color: #fd7e14; } .custom-control-input-orange.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fd7e14' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-orange.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fd7e14'/%3E%3C/svg%3E") !important; } .custom-control-input-orange:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(253, 126, 20, 0.25); } .custom-control-input-orange:focus:not(:checked) ~ .custom-control-label::before { border-color: #fec392; } .custom-control-input-orange:not(:disabled):active ~ .custom-control-label::before { background-color: #ffdfc5; border-color: #ffdfc5; } .custom-control-input-yellow:checked ~ .custom-control-label::before { border-color: #ffc107; background-color: #ffc107; } .custom-control-input-yellow.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23ffc107' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23ffc107'/%3E%3C/svg%3E") !important; } .custom-control-input-yellow:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 193, 7, 0.25); } .custom-control-input-yellow:focus:not(:checked) ~ .custom-control-label::before { border-color: #ffe187; } .custom-control-input-yellow:not(:disabled):active ~ .custom-control-label::before { background-color: #ffeeba; border-color: #ffeeba; } .custom-control-input-green:checked ~ .custom-control-label::before { border-color: #28a745; background-color: #28a745; } .custom-control-input-green.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-green.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2328a745'/%3E%3C/svg%3E") !important; } .custom-control-input-green:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .custom-control-input-green:focus:not(:checked) ~ .custom-control-label::before { border-color: #71dd8a; } .custom-control-input-green:not(:disabled):active ~ .custom-control-label::before { background-color: #9be7ac; border-color: #9be7ac; } .custom-control-input-teal:checked ~ .custom-control-label::before { border-color: #20c997; background-color: #20c997; } .custom-control-input-teal.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2320c997' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-teal.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2320c997'/%3E%3C/svg%3E") !important; } .custom-control-input-teal:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(32, 201, 151, 0.25); } .custom-control-input-teal:focus:not(:checked) ~ .custom-control-label::before { border-color: #7eeaca; } .custom-control-input-teal:not(:disabled):active ~ .custom-control-label::before { background-color: #aaf1dc; border-color: #aaf1dc; } .custom-control-input-cyan:checked ~ .custom-control-label::before { border-color: #17a2b8; background-color: #17a2b8; } .custom-control-input-cyan.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2317a2b8' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%2317a2b8'/%3E%3C/svg%3E") !important; } .custom-control-input-cyan:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(23, 162, 184, 0.25); } .custom-control-input-cyan:focus:not(:checked) ~ .custom-control-label::before { border-color: #63d9ec; } .custom-control-input-cyan:not(:disabled):active ~ .custom-control-label::before { background-color: #90e4f1; border-color: #90e4f1; } .custom-control-input-white:checked ~ .custom-control-label::before { border-color: #fff; background-color: #fff; } .custom-control-input-white.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-white.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E") !important; } .custom-control-input-white:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(255, 255, 255, 0.25); } .custom-control-input-white:focus:not(:checked) ~ .custom-control-label::before { border-color: white; } .custom-control-input-white:not(:disabled):active ~ .custom-control-label::before { background-color: white; border-color: white; } .custom-control-input-gray:checked ~ .custom-control-label::before { border-color: #6c757d; background-color: #6c757d; } .custom-control-input-gray.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%236c757d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%236c757d'/%3E%3C/svg%3E") !important; } .custom-control-input-gray:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(108, 117, 125, 0.25); } .custom-control-input-gray:focus:not(:checked) ~ .custom-control-label::before { border-color: #afb5ba; } .custom-control-input-gray:not(:disabled):active ~ .custom-control-label::before { background-color: #caced1; border-color: #caced1; } .custom-control-input-gray-dark:checked ~ .custom-control-label::before { border-color: #343a40; background-color: #343a40; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="checkbox"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23343a40' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark.custom-control-input-outline:checked[type="radio"] ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23343a40'/%3E%3C/svg%3E") !important; } .custom-control-input-gray-dark:focus ~ .custom-control-label::before { box-shadow: inset 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0.2rem rgba(52, 58, 64, 0.25); } .custom-control-input-gray-dark:focus:not(:checked) ~ .custom-control-label::before { border-color: #6d7a86; } .custom-control-input-gray-dark:not(:disabled):active ~ .custom-control-label::before { background-color: #88939e; border-color: #88939e; } .custom-control-input-outline ~ .custom-control-label::before { background-color: transparent !important; box-shadow: none; } .custom-control-input-outline:checked ~ .custom-control-label::before { background-color: transparent; } .navbar-dark .btn-navbar, .navbar-dark .form-control-navbar { background-color: #3f474e; border: 1px solid #56606a; color: white; } .navbar-dark .btn-navbar:hover { background-color: #454d55; } .navbar-dark .btn-navbar:focus { background-color: #4b545c; } .navbar-dark .form-control-navbar + .input-group-prepend > .btn-navbar, .navbar-dark .form-control-navbar + .input-group-append > .btn-navbar { background-color: #3f474e; color: #fff; border: 1px solid #56606a; border-left: none; } .progress { box-shadow: none; border-radius: 1px; } .progress.vertical { display: inline-block; height: 200px; margin-right: 10px; position: relative; width: 30px; } .progress.vertical > .progress-bar { bottom: 0; position: absolute; width: 100%; } .progress.vertical.sm, .progress.vertical.progress-sm { width: 20px; } .progress.vertical.xs, .progress.vertical.progress-xs { width: 10px; } .progress.vertical.xxs, .progress.vertical.progress-xxs { width: 3px; } .progress-group { margin-bottom: 0.5rem; } .progress-sm { height: 10px; } .progress-xs { height: 7px; } .progress-xxs { height: 3px; } .table tr > td .progress { margin: 0; } .card-primary:not(.card-outline) > .card-header { background-color: #007bff; } .card-primary:not(.card-outline) > .card-header, .card-primary:not(.card-outline) > .card-header a { color: #fff; } .card-primary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-primary.card-outline { border-top: 3px solid #007bff; } .card-primary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-primary.card-outline-tabs > .card-header a.active, .card-primary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-primary > .card-header .btn-tool, .bg-gradient-primary > .card-header .btn-tool, .card-primary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-primary > .card-header .btn-tool:hover, .bg-gradient-primary > .card-header .btn-tool:hover, .card-primary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget .table td, .card.bg-primary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-primary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-primary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-primary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-primary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-secondary:not(.card-outline) > .card-header { background-color: #6c757d; } .card-secondary:not(.card-outline) > .card-header, .card-secondary:not(.card-outline) > .card-header a { color: #fff; } .card-secondary:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-secondary.card-outline { border-top: 3px solid #6c757d; } .card-secondary.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-secondary.card-outline-tabs > .card-header a.active, .card-secondary.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-secondary > .card-header .btn-tool, .bg-gradient-secondary > .card-header .btn-tool, .card-secondary:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-secondary > .card-header .btn-tool:hover, .bg-gradient-secondary > .card-header .btn-tool:hover, .card-secondary:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-secondary .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-secondary .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-secondary .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-secondary .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-success:not(.card-outline) > .card-header { background-color: #28a745; } .card-success:not(.card-outline) > .card-header, .card-success:not(.card-outline) > .card-header a { color: #fff; } .card-success:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-success.card-outline { border-top: 3px solid #28a745; } .card-success.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-success.card-outline-tabs > .card-header a.active, .card-success.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-success > .card-header .btn-tool, .bg-gradient-success > .card-header .btn-tool, .card-success:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-success > .card-header .btn-tool:hover, .bg-gradient-success > .card-header .btn-tool:hover, .card-success:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget .table td, .card.bg-success .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-success .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-success .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-success .bootstrap-datetimepicker-widget table td.active, .card.bg-success .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-success .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-info:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-info:not(.card-outline) > .card-header, .card-info:not(.card-outline) > .card-header a { color: #fff; } .card-info:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-info.card-outline { border-top: 3px solid #17a2b8; } .card-info.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-info.card-outline-tabs > .card-header a.active, .card-info.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-info > .card-header .btn-tool, .bg-gradient-info > .card-header .btn-tool, .card-info:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-info > .card-header .btn-tool:hover, .bg-gradient-info > .card-header .btn-tool:hover, .card-info:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget .table td, .card.bg-info .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-info .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-info .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-info .bootstrap-datetimepicker-widget table td.active, .card.bg-info .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-info .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-warning:not(.card-outline) > .card-header { background-color: #ffc107; } .card-warning:not(.card-outline) > .card-header, .card-warning:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-warning:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-warning.card-outline { border-top: 3px solid #ffc107; } .card-warning.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-warning.card-outline-tabs > .card-header a.active, .card-warning.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-warning > .card-header .btn-tool, .bg-gradient-warning > .card-header .btn-tool, .card-warning:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-warning > .card-header .btn-tool:hover, .bg-gradient-warning > .card-header .btn-tool:hover, .card-warning:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget .table td, .card.bg-warning .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-warning .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-warning .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-warning .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-warning .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-danger:not(.card-outline) > .card-header { background-color: #dc3545; } .card-danger:not(.card-outline) > .card-header, .card-danger:not(.card-outline) > .card-header a { color: #fff; } .card-danger:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-danger.card-outline { border-top: 3px solid #dc3545; } .card-danger.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-danger.card-outline-tabs > .card-header a.active, .card-danger.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-danger > .card-header .btn-tool, .bg-gradient-danger > .card-header .btn-tool, .card-danger:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-danger > .card-header .btn-tool:hover, .bg-gradient-danger > .card-header .btn-tool:hover, .card-danger:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget .table td, .card.bg-danger .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-danger .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-danger .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-danger .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-danger .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-light:not(.card-outline) > .card-header { background-color: #f8f9fa; } .card-light:not(.card-outline) > .card-header, .card-light:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-light:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-light.card-outline { border-top: 3px solid #f8f9fa; } .card-light.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-light.card-outline-tabs > .card-header a.active, .card-light.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f8f9fa; } .bg-light > .card-header .btn-tool, .bg-gradient-light > .card-header .btn-tool, .card-light:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-light > .card-header .btn-tool:hover, .bg-gradient-light > .card-header .btn-tool:hover, .card-light:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget .table td, .card.bg-light .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-light .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-light .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e0e5e9; color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-light .bootstrap-datetimepicker-widget table td.active, .card.bg-light .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-light .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-dark:not(.card-outline) > .card-header, .card-dark:not(.card-outline) > .card-header a { color: #fff; } .card-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-dark.card-outline { border-top: 3px solid #343a40; } .card-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-dark.card-outline-tabs > .card-header a.active, .card-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-dark > .card-header .btn-tool, .bg-gradient-dark > .card-header .btn-tool, .card-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-dark > .card-header .btn-tool:hover, .bg-gradient-dark > .card-header .btn-tool:hover, .card-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget .table td, .card.bg-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card-lightblue:not(.card-outline) > .card-header { background-color: #3c8dbc; } .card-lightblue:not(.card-outline) > .card-header, .card-lightblue:not(.card-outline) > .card-header a { color: #fff; } .card-lightblue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lightblue.card-outline { border-top: 3px solid #3c8dbc; } .card-lightblue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lightblue.card-outline-tabs > .card-header a.active, .card-lightblue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3c8dbc; } .bg-lightblue > .card-header .btn-tool, .bg-gradient-lightblue > .card-header .btn-tool, .card-lightblue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-lightblue > .card-header .btn-tool:hover, .bg-gradient-lightblue > .card-header .btn-tool:hover, .card-lightblue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-lightblue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #32769d; color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-lightblue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lightblue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #5fa4cc; color: #fff; } .card-navy:not(.card-outline) > .card-header { background-color: #001f3f; } .card-navy:not(.card-outline) > .card-header, .card-navy:not(.card-outline) > .card-header a { color: #fff; } .card-navy:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-navy.card-outline { border-top: 3px solid #001f3f; } .card-navy.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-navy.card-outline-tabs > .card-header a.active, .card-navy.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #001f3f; } .bg-navy > .card-header .btn-tool, .bg-gradient-navy > .card-header .btn-tool, .card-navy:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-navy > .card-header .btn-tool:hover, .bg-gradient-navy > .card-header .btn-tool:hover, .card-navy:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget .table td, .card.bg-navy .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-navy .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-navy .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.second:hover { background-color: #000b16; color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-navy .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-navy .bootstrap-datetimepicker-widget table td.active:hover { background-color: #003872; color: #fff; } .card-olive:not(.card-outline) > .card-header { background-color: #3d9970; } .card-olive:not(.card-outline) > .card-header, .card-olive:not(.card-outline) > .card-header a { color: #fff; } .card-olive:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-olive.card-outline { border-top: 3px solid #3d9970; } .card-olive.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-olive.card-outline-tabs > .card-header a.active, .card-olive.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #3d9970; } .bg-olive > .card-header .btn-tool, .bg-gradient-olive > .card-header .btn-tool, .card-olive:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-olive > .card-header .btn-tool:hover, .bg-gradient-olive > .card-header .btn-tool:hover, .card-olive:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget .table td, .card.bg-olive .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-olive .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-olive .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.second:hover { background-color: #317c5b; color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-olive .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-olive .bootstrap-datetimepicker-widget table td.active:hover { background-color: #50b98a; color: #fff; } .card-lime:not(.card-outline) > .card-header { background-color: #01ff70; } .card-lime:not(.card-outline) > .card-header, .card-lime:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-lime:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-lime.card-outline { border-top: 3px solid #01ff70; } .card-lime.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-lime.card-outline-tabs > .card-header a.active, .card-lime.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #01ff70; } .bg-lime > .card-header .btn-tool, .bg-gradient-lime > .card-header .btn-tool, .card-lime:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-lime > .card-header .btn-tool:hover, .bg-gradient-lime > .card-header .btn-tool:hover, .card-lime:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget .table td, .card.bg-lime .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-lime .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-lime .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.second:hover { background-color: #00d75e; color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-lime .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-lime .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ff8d; color: #1f2d3d; } .card-fuchsia:not(.card-outline) > .card-header { background-color: #f012be; } .card-fuchsia:not(.card-outline) > .card-header, .card-fuchsia:not(.card-outline) > .card-header a { color: #fff; } .card-fuchsia:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-fuchsia.card-outline { border-top: 3px solid #f012be; } .card-fuchsia.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-fuchsia.card-outline-tabs > .card-header a.active, .card-fuchsia.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #f012be; } .bg-fuchsia > .card-header .btn-tool, .bg-gradient-fuchsia > .card-header .btn-tool, .card-fuchsia:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-fuchsia > .card-header .btn-tool:hover, .bg-gradient-fuchsia > .card-header .btn-tool:hover, .card-fuchsia:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-fuchsia .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.second:hover { background-color: #cc0da1; color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-fuchsia .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-fuchsia .bootstrap-datetimepicker-widget table td.active:hover { background-color: #f342cb; color: #fff; } .card-maroon:not(.card-outline) > .card-header { background-color: #d81b60; } .card-maroon:not(.card-outline) > .card-header, .card-maroon:not(.card-outline) > .card-header a { color: #fff; } .card-maroon:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-maroon.card-outline { border-top: 3px solid #d81b60; } .card-maroon.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-maroon.card-outline-tabs > .card-header a.active, .card-maroon.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #d81b60; } .bg-maroon > .card-header .btn-tool, .bg-gradient-maroon > .card-header .btn-tool, .card-maroon:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-maroon > .card-header .btn-tool:hover, .bg-gradient-maroon > .card-header .btn-tool:hover, .card-maroon:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-maroon .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-maroon .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.second:hover { background-color: #b41650; color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-maroon .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-maroon .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e73f7c; color: #fff; } .card-blue:not(.card-outline) > .card-header { background-color: #007bff; } .card-blue:not(.card-outline) > .card-header, .card-blue:not(.card-outline) > .card-header a { color: #fff; } .card-blue:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-blue.card-outline { border-top: 3px solid #007bff; } .card-blue.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-blue.card-outline-tabs > .card-header a.active, .card-blue.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #007bff; } .bg-blue > .card-header .btn-tool, .bg-gradient-blue > .card-header .btn-tool, .card-blue:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-blue > .card-header .btn-tool:hover, .bg-gradient-blue > .card-header .btn-tool:hover, .card-blue:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget .table td, .card.bg-blue .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-blue .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-blue .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.second:hover { background-color: #0067d6; color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-blue .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-blue .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3395ff; color: #fff; } .card-indigo:not(.card-outline) > .card-header { background-color: #6610f2; } .card-indigo:not(.card-outline) > .card-header, .card-indigo:not(.card-outline) > .card-header a { color: #fff; } .card-indigo:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-indigo.card-outline { border-top: 3px solid #6610f2; } .card-indigo.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-indigo.card-outline-tabs > .card-header a.active, .card-indigo.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6610f2; } .bg-indigo > .card-header .btn-tool, .bg-gradient-indigo > .card-header .btn-tool, .card-indigo:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-indigo > .card-header .btn-tool:hover, .bg-gradient-indigo > .card-header .btn-tool:hover, .card-indigo:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-indigo .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-indigo .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.second:hover { background-color: #550bce; color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-indigo .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-indigo .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8540f5; color: #fff; } .card-purple:not(.card-outline) > .card-header { background-color: #6f42c1; } .card-purple:not(.card-outline) > .card-header, .card-purple:not(.card-outline) > .card-header a { color: #fff; } .card-purple:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-purple.card-outline { border-top: 3px solid #6f42c1; } .card-purple.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-purple.card-outline-tabs > .card-header a.active, .card-purple.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6f42c1; } .bg-purple > .card-header .btn-tool, .bg-gradient-purple > .card-header .btn-tool, .card-purple:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-purple > .card-header .btn-tool:hover, .bg-gradient-purple > .card-header .btn-tool:hover, .card-purple:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget .table td, .card.bg-purple .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-purple .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-purple .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.second:hover { background-color: #5d36a4; color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-purple .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-purple .bootstrap-datetimepicker-widget table td.active:hover { background-color: #8c68ce; color: #fff; } .card-pink:not(.card-outline) > .card-header { background-color: #e83e8c; } .card-pink:not(.card-outline) > .card-header, .card-pink:not(.card-outline) > .card-header a { color: #fff; } .card-pink:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-pink.card-outline { border-top: 3px solid #e83e8c; } .card-pink.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-pink.card-outline-tabs > .card-header a.active, .card-pink.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #e83e8c; } .bg-pink > .card-header .btn-tool, .bg-gradient-pink > .card-header .btn-tool, .card-pink:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-pink > .card-header .btn-tool:hover, .bg-gradient-pink > .card-header .btn-tool:hover, .card-pink:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget .table td, .card.bg-pink .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-pink .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-pink .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e21b76; color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-pink .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-pink .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ed6ca7; color: #fff; } .card-red:not(.card-outline) > .card-header { background-color: #dc3545; } .card-red:not(.card-outline) > .card-header, .card-red:not(.card-outline) > .card-header a { color: #fff; } .card-red:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-red.card-outline { border-top: 3px solid #dc3545; } .card-red.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-red.card-outline-tabs > .card-header a.active, .card-red.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #dc3545; } .bg-red > .card-header .btn-tool, .bg-gradient-red > .card-header .btn-tool, .card-red:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-red > .card-header .btn-tool:hover, .bg-gradient-red > .card-header .btn-tool:hover, .card-red:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget .table td, .card.bg-red .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-red .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-red .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.second:hover { background-color: #c62232; color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-red .bootstrap-datetimepicker-widget table td.active, .card.bg-red .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-red .bootstrap-datetimepicker-widget table td.active:hover { background-color: #e4606d; color: #fff; } .card-orange:not(.card-outline) > .card-header { background-color: #fd7e14; } .card-orange:not(.card-outline) > .card-header, .card-orange:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-orange:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-orange.card-outline { border-top: 3px solid #fd7e14; } .card-orange.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-orange.card-outline-tabs > .card-header a.active, .card-orange.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fd7e14; } .bg-orange > .card-header .btn-tool, .bg-gradient-orange > .card-header .btn-tool, .card-orange:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-orange > .card-header .btn-tool:hover, .bg-gradient-orange > .card-header .btn-tool:hover, .card-orange:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget .table td, .card.bg-orange .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-orange .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-orange .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.second:hover { background-color: #e66a02; color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-orange .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-orange .bootstrap-datetimepicker-widget table td.active:hover { background-color: #fd9a47; color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header { background-color: #ffc107; } .card-yellow:not(.card-outline) > .card-header, .card-yellow:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-yellow:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-yellow.card-outline { border-top: 3px solid #ffc107; } .card-yellow.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-yellow.card-outline-tabs > .card-header a.active, .card-yellow.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #ffc107; } .bg-yellow > .card-header .btn-tool, .bg-gradient-yellow > .card-header .btn-tool, .card-yellow:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-yellow > .card-header .btn-tool:hover, .bg-gradient-yellow > .card-header .btn-tool:hover, .card-yellow:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-yellow .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-yellow .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.second:hover { background-color: #dda600; color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-yellow .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-yellow .bootstrap-datetimepicker-widget table td.active:hover { background-color: #ffce3a; color: #1f2d3d; } .card-green:not(.card-outline) > .card-header { background-color: #28a745; } .card-green:not(.card-outline) > .card-header, .card-green:not(.card-outline) > .card-header a { color: #fff; } .card-green:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-green.card-outline { border-top: 3px solid #28a745; } .card-green.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-green.card-outline-tabs > .card-header a.active, .card-green.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #28a745; } .bg-green > .card-header .btn-tool, .bg-gradient-green > .card-header .btn-tool, .card-green:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-green > .card-header .btn-tool:hover, .bg-gradient-green > .card-header .btn-tool:hover, .card-green:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget .table td, .card.bg-green .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-green .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-green .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.second:hover { background-color: #208637; color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-green .bootstrap-datetimepicker-widget table td.active, .card.bg-green .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-green .bootstrap-datetimepicker-widget table td.active:hover { background-color: #34ce57; color: #fff; } .card-teal:not(.card-outline) > .card-header { background-color: #20c997; } .card-teal:not(.card-outline) > .card-header, .card-teal:not(.card-outline) > .card-header a { color: #fff; } .card-teal:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-teal.card-outline { border-top: 3px solid #20c997; } .card-teal.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-teal.card-outline-tabs > .card-header a.active, .card-teal.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #20c997; } .bg-teal > .card-header .btn-tool, .bg-gradient-teal > .card-header .btn-tool, .card-teal:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-teal > .card-header .btn-tool:hover, .bg-gradient-teal > .card-header .btn-tool:hover, .card-teal:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget .table td, .card.bg-teal .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-teal .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-teal .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.second:hover { background-color: #1aa67d; color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-teal .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-teal .bootstrap-datetimepicker-widget table td.active:hover { background-color: #3ce0af; color: #fff; } .card-cyan:not(.card-outline) > .card-header { background-color: #17a2b8; } .card-cyan:not(.card-outline) > .card-header, .card-cyan:not(.card-outline) > .card-header a { color: #fff; } .card-cyan:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-cyan.card-outline { border-top: 3px solid #17a2b8; } .card-cyan.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-cyan.card-outline-tabs > .card-header a.active, .card-cyan.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #17a2b8; } .bg-cyan > .card-header .btn-tool, .bg-gradient-cyan > .card-header .btn-tool, .card-cyan:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-cyan > .card-header .btn-tool:hover, .bg-gradient-cyan > .card-header .btn-tool:hover, .card-cyan:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-cyan .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-cyan .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.second:hover { background-color: #128294; color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-cyan .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-cyan .bootstrap-datetimepicker-widget table td.active:hover { background-color: #1fc8e3; color: #fff; } .card-white:not(.card-outline) > .card-header { background-color: #fff; } .card-white:not(.card-outline) > .card-header, .card-white:not(.card-outline) > .card-header a { color: #1f2d3d; } .card-white:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-white.card-outline { border-top: 3px solid #fff; } .card-white.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-white.card-outline-tabs > .card-header a.active, .card-white.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #fff; } .bg-white > .card-header .btn-tool, .bg-gradient-white > .card-header .btn-tool, .card-white:not(.card-outline) > .card-header .btn-tool { color: rgba(31, 45, 61, 0.8); } .bg-white > .card-header .btn-tool:hover, .bg-gradient-white > .card-header .btn-tool:hover, .card-white:not(.card-outline) > .card-header .btn-tool:hover { color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget .table td, .card.bg-white .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-white .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-white .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.second:hover { background-color: #ebebeb; color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #1f2d3d; } .card.bg-white .bootstrap-datetimepicker-widget table td.active, .card.bg-white .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-white .bootstrap-datetimepicker-widget table td.active:hover { background-color: white; color: #1f2d3d; } .card-gray:not(.card-outline) > .card-header { background-color: #6c757d; } .card-gray:not(.card-outline) > .card-header, .card-gray:not(.card-outline) > .card-header a { color: #fff; } .card-gray:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray.card-outline { border-top: 3px solid #6c757d; } .card-gray.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray.card-outline-tabs > .card-header a.active, .card-gray.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #6c757d; } .bg-gray > .card-header .btn-tool, .bg-gradient-gray > .card-header .btn-tool, .card-gray:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray > .card-header .btn-tool:hover, .bg-gradient-gray > .card-header .btn-tool:hover, .card-gray:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gray .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.second:hover { background-color: #596167; color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gray .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray .bootstrap-datetimepicker-widget table td.active:hover { background-color: #868e96; color: #fff; } .card-gray-dark:not(.card-outline) > .card-header { background-color: #343a40; } .card-gray-dark:not(.card-outline) > .card-header, .card-gray-dark:not(.card-outline) > .card-header a { color: #fff; } .card-gray-dark:not(.card-outline) > .card-header a.active { color: #1f2d3d; } .card-gray-dark.card-outline { border-top: 3px solid #343a40; } .card-gray-dark.card-outline-tabs > .card-header a:hover { border-top: 3px solid #dee2e6; } .card-gray-dark.card-outline-tabs > .card-header a.active, .card-gray-dark.card-outline-tabs > .card-header a.active:hover { border-top: 3px solid #343a40; } .bg-gray-dark > .card-header .btn-tool, .bg-gradient-gray-dark > .card-header .btn-tool, .card-gray-dark:not(.card-outline) > .card-header .btn-tool { color: rgba(255, 255, 255, 0.8); } .bg-gray-dark > .card-header .btn-tool:hover, .bg-gradient-gray-dark > .card-header .btn-tool:hover, .card-gray-dark:not(.card-outline) > .card-header .btn-tool:hover { color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gray-dark .bootstrap-datetimepicker-widget .table th, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table td, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget .table th { border: none; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.second:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table thead tr:first-child th:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.day:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.hour:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.minute:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.second:hover { background-color: #222629; color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.today::before, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.today::before { border-bottom-color: #fff; } .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gray-dark .bootstrap-datetimepicker-widget table td.active:hover, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active, .card.bg-gradient-gray-dark .bootstrap-datetimepicker-widget table td.active:hover { background-color: #4b545c; color: #fff; } .card { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); margin-bottom: 1rem; } .card.bg-dark .card-header { border-color: #383f45; } .card.bg-dark, .card.bg-dark .card-body { color: #fff; } .card.maximized-card { height: 100% !important; left: 0; max-height: 100% !important; max-width: 100% !important; position: fixed; top: 0; width: 100% !important; z-index: 1040; } .card.maximized-card.was-collapsed .card-body { display: block !important; } .card.maximized-card .card-body { overflow: auto; } .card.maximized-card [data-card-widgett="collapse"] { display: none; } .card.maximized-card .card-header, .card.maximized-card .card-footer { border-radius: 0 !important; } .card.collapsed-card .card-body, .card.collapsed-card .card-footer { display: none; } .card .nav.flex-column:not(.nav-sidebar) > li { border-bottom: 1px solid rgba(0, 0, 0, 0.125); margin: 0; } .card .nav.flex-column:not(.nav-sidebar) > li:last-of-type { border-bottom: 0; } .card.height-control .card-body { max-height: 300px; overflow: auto; } .card .border-right { border-right: 1px solid rgba(0, 0, 0, 0.125); } .card .border-left { border-left: 1px solid rgba(0, 0, 0, 0.125); } .card.card-tabs:not(.card-outline) > .card-header { border-bottom: 0; } .card.card-tabs:not(.card-outline) > .card-header .nav-item:first-child .nav-link { border-left-color: transparent; } .card.card-tabs.card-outline .nav-item { border-bottom: 0; } .card.card-tabs.card-outline .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-tabs .card-tools { margin: .3rem .5rem; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } .card.card-outline-tabs { border-top: 0; } .card.card-outline-tabs .card-header .nav-item:first-child .nav-link { border-left: 0; margin-left: 0; } .card.card-outline-tabs .card-header a { border-top: 3px solid transparent; } .card.card-outline-tabs .card-header a:hover { border-top: 3px solid #dee2e6; } .card.card-outline-tabs .card-header a.active:hover { margin-top: 0; } .card.card-outline-tabs .card-tools { margin: .5rem .5rem .3rem; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs { border-bottom: 0; } .card.card-outline-tabs:not(.expanding-card).collapsed-card .card-header .nav-tabs .nav-item { margin-bottom: 0; } .card.card-outline-tabs.expanding-card .card-header .nav-tabs .nav-item { margin-bottom: -1px; } html.maximized-card { overflow: hidden; } .card-header::after, .card-body::after, .card-footer::after { display: block; clear: both; content: ""; } .card-header { background-color: transparent; border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 0.75rem 1.25rem; position: relative; border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; } .collapsed-card .card-header { border-bottom: 0; } .card-header > .card-tools { float: right; margin-right: -0.625rem; } .card-header > .card-tools .input-group, .card-header > .card-tools .nav, .card-header > .card-tools .pagination { margin-bottom: -0.3rem; margin-top: -0.3rem; } .card-header > .card-tools [data-toggle="tooltip"] { position: relative; } .card-title { float: left; font-size: 1.1rem; font-weight: 400; margin: 0; } .card-text { clear: both; } .btn-tool { background-color: transparent; color: #adb5bd; font-size: 0.875rem; margin: -0.75rem 0; padding: .25rem .5rem; } .btn-group.show .btn-tool, .btn-tool:hover { color: #495057; } .show .btn-tool, .btn-tool:focus { box-shadow: none !important; } .text-sm .card-title { font-size: 1rem; } .text-sm .nav-link { padding: 0.4rem 0.8rem; } .card-body > .table { margin-bottom: 0; } .card-body > .table > thead > tr > th, .card-body > .table > thead > tr > td { border-top-width: 0; } .card-body .fc { margin-top: 5px; } .card-body .full-width-chart { margin: -19px; } .card-body.p-0 .full-width-chart { margin: -9px; } .chart-legend { padding-left: 0; list-style: none; margin: 10px 0; } @media (max-width: 576px) { .chart-legend > li { float: left; margin-right: 10px; } } .card-comments { background-color: #f8f9fa; } .card-comments .card-comment { border-bottom: 1px solid #e9ecef; padding: 8px 0; } .card-comments .card-comment::after { display: block; clear: both; content: ""; } .card-comments .card-comment:last-of-type { border-bottom: 0; } .card-comments .card-comment:first-of-type { padding-top: 0; } .card-comments .card-comment img { height: 1.875rem; width: 1.875rem; float: left; } .card-comments .comment-text { color: #78838e; margin-left: 40px; } .card-comments .username { color: #495057; display: block; font-weight: 600; } .card-comments .text-muted { font-size: 12px; font-weight: 400; } .todo-list { list-style: none; margin: 0; overflow: auto; padding: 0; } .todo-list > li { border-radius: 2px; background-color: #f8f9fa; border-left: 2px solid #e9ecef; color: #495057; margin-bottom: 2px; padding: 10px; } .todo-list > li:last-of-type { margin-bottom: 0; } .todo-list > li > input[type="checkbox"] { margin: 0 10px 0 5px; } .todo-list > li .text { display: inline-block; font-weight: 600; margin-left: 5px; } .todo-list > li .badge { font-size: .7rem; margin-left: 10px; } .todo-list > li .tools { color: #dc3545; display: none; float: right; } .todo-list > li .tools > .fa, .todo-list > li .tools > .fas, .todo-list > li .tools > .far, .todo-list > li .tools > .fab, .todo-list > li .tools > .fal, .todo-list > li .tools > .fad, .todo-list > li .tools > .svg-inline--fa, .todo-list > li .tools > .ion { cursor: pointer; margin-right: 5px; } .todo-list > li:hover .tools { display: inline-block; } .todo-list > li.done { color: #697582; } .todo-list > li.done .text { font-weight: 500; text-decoration: line-through; } .todo-list > li.done .badge { background-color: #adb5bd !important; } .todo-list .primary { border-left-color: #007bff; } .todo-list .secondary { border-left-color: #6c757d; } .todo-list .success { border-left-color: #28a745; } .todo-list .info { border-left-color: #17a2b8; } .todo-list .warning { border-left-color: #ffc107; } .todo-list .danger { border-left-color: #dc3545; } .todo-list .light { border-left-color: #f8f9fa; } .todo-list .dark { border-left-color: #343a40; } .todo-list .lightblue { border-left-color: #3c8dbc; } .todo-list .navy { border-left-color: #001f3f; } .todo-list .olive { border-left-color: #3d9970; } .todo-list .lime { border-left-color: #01ff70; } .todo-list .fuchsia { border-left-color: #f012be; } .todo-list .maroon { border-left-color: #d81b60; } .todo-list .blue { border-left-color: #007bff; } .todo-list .indigo { border-left-color: #6610f2; } .todo-list .purple { border-left-color: #6f42c1; } .todo-list .pink { border-left-color: #e83e8c; } .todo-list .red { border-left-color: #dc3545; } .todo-list .orange { border-left-color: #fd7e14; } .todo-list .yellow { border-left-color: #ffc107; } .todo-list .green { border-left-color: #28a745; } .todo-list .teal { border-left-color: #20c997; } .todo-list .cyan { border-left-color: #17a2b8; } .todo-list .white { border-left-color: #fff; } .todo-list .gray { border-left-color: #6c757d; } .todo-list .gray-dark { border-left-color: #343a40; } .todo-list .handle { cursor: move; display: inline-block; margin: 0 5px; } .card-input { max-width: 200px; } .card-default .nav-item:first-child .nav-link { border-left: 0; } .modal-dialog .overlay { display: -ms-flexbox; display: flex; position: absolute; left: 0; top: 0; bottom: 0; right: 0; margin: -1px; z-index: 1052; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; background-color: rgba(0, 0, 0, 0.7); color: #666f76; border-radius: 0.3rem; } .modal-content.bg-warning .modal-header, .modal-content.bg-warning .modal-footer { border-color: #343a40; } .modal-content.bg-primary .close, .modal-content.bg-primary .mailbox-attachment-close, .modal-content.bg-secondary .close, .modal-content.bg-secondary .mailbox-attachment-close, .modal-content.bg-info .close, .modal-content.bg-info .mailbox-attachment-close, .modal-content.bg-danger .close, .modal-content.bg-danger .mailbox-attachment-close, .modal-content.bg-success .close, .modal-content.bg-success .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toasts-top-right { position: absolute; right: 0; top: 0; z-index: 1040; } .toasts-top-right.fixed { position: fixed; } .toasts-top-left { left: 0; position: absolute; top: 0; z-index: 1040; } .toasts-top-left.fixed { position: fixed; } .toasts-bottom-right { bottom: 0; position: absolute; right: 0; z-index: 1040; } .toasts-bottom-right.fixed { position: fixed; } .toasts-bottom-left { bottom: 0; left: 0; position: absolute; z-index: 1040; } .toasts-bottom-left.fixed { position: fixed; } .toast.bg-primary { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-primary .close, .toast.bg-primary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-primary .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-secondary { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-secondary .close, .toast.bg-secondary .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-secondary .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-success { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-success .close, .toast.bg-success .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-success .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-info { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-info .close, .toast.bg-info .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-info .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-warning { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-warning .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-danger { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-danger .close, .toast.bg-danger .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-danger .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-light { background-color: rgba(248, 249, 250, 0.9) !important; } .toast.bg-light .toast-header { background-color: rgba(248, 249, 250, 0.85); color: #1f2d3d; } .toast.bg-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-dark .close, .toast.bg-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .toast.bg-lightblue { background-color: rgba(60, 141, 188, 0.9) !important; } .toast.bg-lightblue .close, .toast.bg-lightblue .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-lightblue .toast-header { background-color: rgba(60, 141, 188, 0.85); color: #fff; } .toast.bg-navy { background-color: rgba(0, 31, 63, 0.9) !important; } .toast.bg-navy .close, .toast.bg-navy .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-navy .toast-header { background-color: rgba(0, 31, 63, 0.85); color: #fff; } .toast.bg-olive { background-color: rgba(61, 153, 112, 0.9) !important; } .toast.bg-olive .close, .toast.bg-olive .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-olive .toast-header { background-color: rgba(61, 153, 112, 0.85); color: #fff; } .toast.bg-lime { background-color: rgba(1, 255, 112, 0.9) !important; } .toast.bg-lime .toast-header { background-color: rgba(1, 255, 112, 0.85); color: #1f2d3d; } .toast.bg-fuchsia { background-color: rgba(240, 18, 190, 0.9) !important; } .toast.bg-fuchsia .close, .toast.bg-fuchsia .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-fuchsia .toast-header { background-color: rgba(240, 18, 190, 0.85); color: #fff; } .toast.bg-maroon { background-color: rgba(216, 27, 96, 0.9) !important; } .toast.bg-maroon .close, .toast.bg-maroon .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-maroon .toast-header { background-color: rgba(216, 27, 96, 0.85); color: #fff; } .toast.bg-blue { background-color: rgba(0, 123, 255, 0.9) !important; } .toast.bg-blue .close, .toast.bg-blue .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-blue .toast-header { background-color: rgba(0, 123, 255, 0.85); color: #fff; } .toast.bg-indigo { background-color: rgba(102, 16, 242, 0.9) !important; } .toast.bg-indigo .close, .toast.bg-indigo .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-indigo .toast-header { background-color: rgba(102, 16, 242, 0.85); color: #fff; } .toast.bg-purple { background-color: rgba(111, 66, 193, 0.9) !important; } .toast.bg-purple .close, .toast.bg-purple .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-purple .toast-header { background-color: rgba(111, 66, 193, 0.85); color: #fff; } .toast.bg-pink { background-color: rgba(232, 62, 140, 0.9) !important; } .toast.bg-pink .close, .toast.bg-pink .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-pink .toast-header { background-color: rgba(232, 62, 140, 0.85); color: #fff; } .toast.bg-red { background-color: rgba(220, 53, 69, 0.9) !important; } .toast.bg-red .close, .toast.bg-red .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-red .toast-header { background-color: rgba(220, 53, 69, 0.85); color: #fff; } .toast.bg-orange { background-color: rgba(253, 126, 20, 0.9) !important; } .toast.bg-orange .toast-header { background-color: rgba(253, 126, 20, 0.85); color: #1f2d3d; } .toast.bg-yellow { background-color: rgba(255, 193, 7, 0.9) !important; } .toast.bg-yellow .toast-header { background-color: rgba(255, 193, 7, 0.85); color: #1f2d3d; } .toast.bg-green { background-color: rgba(40, 167, 69, 0.9) !important; } .toast.bg-green .close, .toast.bg-green .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-green .toast-header { background-color: rgba(40, 167, 69, 0.85); color: #fff; } .toast.bg-teal { background-color: rgba(32, 201, 151, 0.9) !important; } .toast.bg-teal .close, .toast.bg-teal .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-teal .toast-header { background-color: rgba(32, 201, 151, 0.85); color: #fff; } .toast.bg-cyan { background-color: rgba(23, 162, 184, 0.9) !important; } .toast.bg-cyan .close, .toast.bg-cyan .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-cyan .toast-header { background-color: rgba(23, 162, 184, 0.85); color: #fff; } .toast.bg-white { background-color: rgba(255, 255, 255, 0.9) !important; } .toast.bg-white .toast-header { background-color: rgba(255, 255, 255, 0.85); color: #1f2d3d; } .toast.bg-gray { background-color: rgba(108, 117, 125, 0.9) !important; } .toast.bg-gray .close, .toast.bg-gray .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray .toast-header { background-color: rgba(108, 117, 125, 0.85); color: #fff; } .toast.bg-gray-dark { background-color: rgba(52, 58, 64, 0.9) !important; } .toast.bg-gray-dark .close, .toast.bg-gray-dark .mailbox-attachment-close { color: #fff; text-shadow: 0 1px 0 #000; } .toast.bg-gray-dark .toast-header { background-color: rgba(52, 58, 64, 0.85); color: #fff; } .btn.disabled, .btn:disabled { cursor: not-allowed; } .btn.btn-flat { border-radius: 0; border-width: 1px; box-shadow: none; } .btn.btn-file { overflow: hidden; position: relative; } .btn.btn-file > input[type="file"] { background-color: #fff; cursor: inherit; display: block; font-size: 100px; min-height: 100%; min-width: 100%; opacity: 0; outline: none; position: absolute; right: 0; text-align: right; top: 0; } .text-sm .btn { font-size: 0.875rem !important; } .btn-default { background-color: #f8f9fa; border-color: #ddd; color: #444; } .btn-default:hover, .btn-default:active, .btn-default.hover { background-color: #e9ecef; color: #2b2b2b; } .btn-default.disabled, .btn-default:disabled { color: #444; background-color: #f8f9fa; } .btn-outline-light { color: #bdc6d0; border-color: #bdc6d0; } .btn-outline-light.disabled, .btn-outline-light:disabled { color: #bdc6d0; border-color: #bdc6d0; } .btn-app { border-radius: 3px; background-color: #f8f9fa; border: 1px solid #ddd; color: #6c757d; font-size: 12px; height: 60px; margin: 0 0 10px 10px; min-width: 80px; padding: 15px 5px; position: relative; text-align: center; } .btn-app > .fa, .btn-app > .fas, .btn-app > .far, .btn-app > .fab, .btn-app > .fal, .btn-app > .fad, .btn-app > .svg-inline--fa, .btn-app > .ion { display: block; font-size: 20px; } .btn-app > .svg-inline--fa { margin: 0 auto; } .btn-app:hover { background-color: #f8f9fa; border-color: #aaaaaa; color: #444; } .btn-app:active, .btn-app:focus { box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); } .btn-app > .badge { font-size: 10px; font-weight: 400; position: absolute; right: -10px; top: -3px; } .btn-xs { padding: 0.125rem 0.25rem; font-size: 0.75rem; line-height: 1.5; border-radius: 0.15rem; } .callout { border-radius: 0.25rem; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); background-color: #fff; border-left: 5px solid #e9ecef; margin-bottom: 1rem; padding: 1rem; } .callout a { color: #495057; text-decoration: underline; } .callout a:hover { color: #e9ecef; } .callout p:last-child { margin-bottom: 0; } .callout.callout-danger { border-left-color: #bd2130; } .callout.callout-warning { border-left-color: #d39e00; } .callout.callout-info { border-left-color: #117a8b; } .callout.callout-success { border-left-color: #1e7e34; } .alert .icon { margin-right: 10px; } .alert .close, .alert .mailbox-attachment-close { color: #000; opacity: .2; } .alert .close:hover, .alert .mailbox-attachment-close:hover { opacity: .5; } .alert a { color: #fff; text-decoration: underline; } .alert-primary { color: #fff; background-color: #007bff; border-color: #006fe6; } .alert-default-primary { color: #004085; background-color: #cce5ff; border-color: #b8daff; } .alert-default-primary hr { border-top-color: #9fcdff; } .alert-default-primary .alert-link { color: #002752; } .alert-secondary { color: #fff; background-color: #6c757d; border-color: #60686f; } .alert-default-secondary { color: #383d41; background-color: #e2e3e5; border-color: #d6d8db; } .alert-default-secondary hr { border-top-color: #c8cbcf; } .alert-default-secondary .alert-link { color: #202326; } .alert-success { color: #fff; background-color: #28a745; border-color: #23923d; } .alert-default-success { color: #155724; background-color: #d4edda; border-color: #c3e6cb; } .alert-default-success hr { border-top-color: #b1dfbb; } .alert-default-success .alert-link { color: #0b2e13; } .alert-info { color: #fff; background-color: #17a2b8; border-color: #148ea1; } .alert-default-info { color: #0c5460; background-color: #d1ecf1; border-color: #bee5eb; } .alert-default-info hr { border-top-color: #abdde5; } .alert-default-info .alert-link { color: #062c33; } .alert-warning { color: #1f2d3d; background-color: #ffc107; border-color: #edb100; } .alert-default-warning { color: #856404; background-color: #fff3cd; border-color: #ffeeba; } .alert-default-warning hr { border-top-color: #ffe8a1; } .alert-default-warning .alert-link { color: #533f03; } .alert-danger { color: #fff; background-color: #dc3545; border-color: #d32535; } .alert-default-danger { color: #721c24; background-color: #f8d7da; border-color: #f5c6cb; } .alert-default-danger hr { border-top-color: #f1b0b7; } .alert-default-danger .alert-link { color: #491217; } .alert-light { color: #1f2d3d; background-color: #f8f9fa; border-color: #e9ecef; } .alert-default-light { color: #818182; background-color: #fefefe; border-color: #fdfdfe; } .alert-default-light hr { border-top-color: #ececf6; } .alert-default-light .alert-link { color: #686868; } .alert-dark { color: #fff; background-color: #343a40; border-color: #292d32; } .alert-default-dark { color: #1b1e21; background-color: #d6d8d9; border-color: #c6c8ca; } .alert-default-dark hr { border-top-color: #b9bbbe; } .alert-default-dark .alert-link { color: #040505; } .table:not(.table-dark) { color: inherit; } .table.table-head-fixed thead tr:nth-child(1) th { background-color: #fff; border-bottom: 0; box-shadow: inset 0 1px 0 #dee2e6, inset 0 -1px 0 #dee2e6; position: -webkit-sticky; position: sticky; top: 0; z-index: 10; } .table.table-head-fixed.table-dark thead tr:nth-child(1) th { background-color: #212529; box-shadow: inset 0 1px 0 #383f45, inset 0 -1px 0 #383f45; } .table.no-border, .table.no-border td, .table.no-border th { border: 0; } .table.text-center, .table.text-center td, .table.text-center th { text-align: center; } .table.table-valign-middle thead > tr > th, .table.table-valign-middle thead > tr > td, .table.table-valign-middle tbody > tr > th, .table.table-valign-middle tbody > tr > td { vertical-align: middle; } .card-body.p-0 .table thead > tr > th:first-of-type, .card-body.p-0 .table thead > tr > td:first-of-type, .card-body.p-0 .table tfoot > tr > th:first-of-type, .card-body.p-0 .table tfoot > tr > td:first-of-type, .card-body.p-0 .table tbody > tr > th:first-of-type, .card-body.p-0 .table tbody > tr > td:first-of-type { padding-left: 1.5rem; } .card-body.p-0 .table thead > tr > th:last-of-type, .card-body.p-0 .table thead > tr > td:last-of-type, .card-body.p-0 .table tfoot > tr > th:last-of-type, .card-body.p-0 .table tfoot > tr > td:last-of-type, .card-body.p-0 .table tbody > tr > th:last-of-type, .card-body.p-0 .table tbody > tr > td:last-of-type { padding-right: 1.5rem; } .table-hover tbody tr.expandable-body:hover { background-color: inherit !important; } [data-widget="expandable-table"] { cursor: pointer; } [data-widget="expandable-table"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [data-widget="expandable-table"][aria-expanded="true"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } [aria-expanded="true"] { cursor: pointer; } [aria-expanded="true"] i.expandable-table-caret { transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="right"] { -webkit-transform: rotate(90deg); transform: rotate(90deg); } [aria-expanded="true"] [data-widget="expandable-table"] i.expandable-table-caret[class*="left"] { -webkit-transform: rotate(-90deg); transform: rotate(-90deg); } .expandable-body > td { padding: 0 !important; width: 100%; } .expandable-body > td > div, .expandable-body > td > p { padding: 0.75rem; } .expandable-body .table { width: calc(100% - 0.75rem); margin: 0 0 0 0.75rem; } .expandable-body .table tr:first-child td, .expandable-body .table tr:first-child th { border-top: none; } .carousel-control-prev .carousel-control-custom-icon { margin-left: -20px; } .carousel-control-next .carousel-control-custom-icon { margin-right: 20px; } .carousel-control-custom-icon > .fa, .carousel-control-custom-icon > .fas, .carousel-control-custom-icon > .far, .carousel-control-custom-icon > .fab, .carousel-control-custom-icon > .fal, .carousel-control-custom-icon > .fad, .carousel-control-custom-icon > .svg-inline--fa, .carousel-control-custom-icon > .ion { display: inline-block; font-size: 40px; margin-top: -20px; position: absolute; top: 50%; z-index: 5; } .close, .mailbox-attachment-close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover, .mailbox-attachment-close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .mailbox-attachment-close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus, .mailbox-attachment-close:not(:disabled):not(.disabled):focus { opacity: .75; } .close:focus, .mailbox-attachment-close:focus { outline: none; } button.close, button.mailbox-attachment-close { padding: 0; background-color: transparent; border: 0; } a.close.disabled, a.disabled.mailbox-attachment-close { pointer-events: none; } .small-box { border-radius: 0.25rem; box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); display: block; margin-bottom: 20px; position: relative; } .small-box > .inner { padding: 10px; } .small-box > .small-box-footer { background-color: rgba(0, 0, 0, 0.1); color: rgba(255, 255, 255, 0.8); display: block; padding: 3px 0; position: relative; text-align: center; text-decoration: none; z-index: 10; } .small-box > .small-box-footer:hover { background-color: rgba(0, 0, 0, 0.15); color: #fff; } .small-box h3 { font-size: 2.2rem; font-weight: 700; margin: 0 0 10px; padding: 0; white-space: nowrap; } @media (min-width: 992px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 1.6rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 1.6rem; } } @media (min-width: 1200px) { .col-xl-2 .small-box h3, .col-lg-2 .small-box h3, .col-md-2 .small-box h3 { font-size: 2.2rem; } .col-xl-3 .small-box h3, .col-lg-3 .small-box h3, .col-md-3 .small-box h3 { font-size: 2.2rem; } } .small-box p { font-size: 1rem; } .small-box p > small { color: #f8f9fa; display: block; font-size: .9rem; margin-top: 5px; } .small-box h3, .small-box p { z-index: 5; } .small-box .icon { color: rgba(0, 0, 0, 0.15); z-index: 0; } .small-box .icon > i { font-size: 90px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box .icon > i.fa, .small-box .icon > i.fas, .small-box .icon > i.far, .small-box .icon > i.fab, .small-box .icon > i.fal, .small-box .icon > i.fad, .small-box .icon > i.ion { font-size: 70px; top: 20px; } .small-box .icon svg { font-size: 70px; position: absolute; right: 15px; top: 15px; transition: -webkit-transform 0.3s linear; transition: transform 0.3s linear; transition: transform 0.3s linear, -webkit-transform 0.3s linear; } .small-box:hover { text-decoration: none; } .small-box:hover .icon > i, .small-box:hover .icon > i.fa, .small-box:hover .icon > i.fas, .small-box:hover .icon > i.far, .small-box:hover .icon > i.fab, .small-box:hover .icon > i.fal, .small-box:hover .icon > i.fad, .small-box:hover .icon > i.ion { -webkit-transform: scale(1.1); transform: scale(1.1); } .small-box:hover .icon > svg { -webkit-transform: scale(1.1); transform: scale(1.1); } @media (max-width: 767.98px) { .small-box { text-align: center; } .small-box .icon { display: none; } .small-box p { font-size: 12px; } } .info-box { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; display: -ms-flexbox; display: flex; margin-bottom: 1rem; min-height: 80px; padding: .5rem; position: relative; width: 100%; } .info-box .progress { background-color: rgba(0, 0, 0, 0.125); height: 2px; margin: 5px 0; } .info-box .progress .progress-bar { background-color: #fff; } .info-box .info-box-icon { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; display: -ms-flexbox; display: flex; font-size: 1.875rem; -ms-flex-pack: center; justify-content: center; text-align: center; width: 70px; } .info-box .info-box-icon > img { max-width: 100%; } .info-box .info-box-content { display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; -ms-flex-pack: center; justify-content: center; line-height: 1.8; -ms-flex: 1; flex: 1; padding: 0 10px; overflow: hidden; } .info-box .info-box-number { display: block; margin-top: .25rem; font-weight: 700; } .info-box .progress-description, .info-box .info-box-text { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .info-box .info-box .bg-primary, .info-box .info-box .bg-gradient-primary { color: #fff; } .info-box .info-box .bg-primary .progress-bar, .info-box .info-box .bg-gradient-primary .progress-bar { background-color: #fff; } .info-box .info-box .bg-secondary, .info-box .info-box .bg-gradient-secondary { color: #fff; } .info-box .info-box .bg-secondary .progress-bar, .info-box .info-box .bg-gradient-secondary .progress-bar { background-color: #fff; } .info-box .info-box .bg-success, .info-box .info-box .bg-gradient-success { color: #fff; } .info-box .info-box .bg-success .progress-bar, .info-box .info-box .bg-gradient-success .progress-bar { background-color: #fff; } .info-box .info-box .bg-info, .info-box .info-box .bg-gradient-info { color: #fff; } .info-box .info-box .bg-info .progress-bar, .info-box .info-box .bg-gradient-info .progress-bar { background-color: #fff; } .info-box .info-box .bg-warning, .info-box .info-box .bg-gradient-warning { color: #1f2d3d; } .info-box .info-box .bg-warning .progress-bar, .info-box .info-box .bg-gradient-warning .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-danger, .info-box .info-box .bg-gradient-danger { color: #fff; } .info-box .info-box .bg-danger .progress-bar, .info-box .info-box .bg-gradient-danger .progress-bar { background-color: #fff; } .info-box .info-box .bg-light, .info-box .info-box .bg-gradient-light { color: #1f2d3d; } .info-box .info-box .bg-light .progress-bar, .info-box .info-box .bg-gradient-light .progress-bar { background-color: #1f2d3d; } .info-box .info-box .bg-dark, .info-box .info-box .bg-gradient-dark { color: #fff; } .info-box .info-box .bg-dark .progress-bar, .info-box .info-box .bg-gradient-dark .progress-bar { background-color: #fff; } .info-box .info-box-more { display: block; } .info-box .progress-description { margin: 0; } @media (min-width: 768px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { display: none; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { display: none; } } @media (min-width: 992px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 0.75rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 0.75rem; display: block; } } @media (min-width: 1200px) { .col-xl-2 .info-box .progress-description, .col-lg-2 .info-box .progress-description, .col-md-2 .info-box .progress-description { font-size: 1rem; display: block; } .col-xl-3 .info-box .progress-description, .col-lg-3 .info-box .progress-description, .col-md-3 .info-box .progress-description { font-size: 1rem; display: block; } } .timeline { margin: 0 0 45px; padding: 0; position: relative; } .timeline::before { border-radius: 0.25rem; background-color: #dee2e6; bottom: 0; content: ""; left: 31px; margin: 0; position: absolute; top: 0; width: 4px; } .timeline > div { margin-bottom: 15px; margin-right: 10px; position: relative; } .timeline > div::before, .timeline > div::after { content: ""; display: table; } .timeline > div > .timeline-item { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; background-color: #fff; color: #495057; margin-left: 60px; margin-right: 15px; margin-top: 0; padding: 0; position: relative; } .timeline > div > .timeline-item > .time { color: #999; float: right; font-size: 12px; padding: 10px; } .timeline > div > .timeline-item > .timeline-header { border-bottom: 1px solid rgba(0, 0, 0, 0.125); color: #495057; font-size: 16px; line-height: 1.1; margin: 0; padding: 10px; } .timeline > div > .timeline-item > .timeline-header > a { font-weight: 600; } .timeline > div > .timeline-item > .timeline-body, .timeline > div > .timeline-item > .timeline-footer { padding: 10px; } .timeline > div > .timeline-item > .timeline-body > img { margin: 10px; } .timeline > div > .timeline-item > .timeline-body > dl, .timeline > div > .timeline-item > .timeline-body ol, .timeline > div > .timeline-item > .timeline-body ul { margin: 0; } .timeline > div > .timeline-item > .timeline-footer > a { color: #fff; } .timeline > div > .fa, .timeline > div > .fas, .timeline > div > .far, .timeline > div > .fab, .timeline > div > .fal, .timeline > div > .fad, .timeline > div > .svg-inline--fa, .timeline > div > .ion { background-color: #adb5bd; border-radius: 50%; font-size: 16px; height: 30px; left: 18px; line-height: 30px; position: absolute; text-align: center; top: 0; width: 30px; } .timeline > div > .svg-inline--fa { padding: 7px; } .timeline > .time-label > span { border-radius: 4px; background-color: #fff; display: inline-block; font-weight: 600; padding: 5px; } .timeline-inverse > div > .timeline-item { box-shadow: none; background-color: #f8f9fa; border: 1px solid #dee2e6; } .timeline-inverse > div > .timeline-item > .timeline-header { border-bottom-color: #dee2e6; } .products-list { list-style: none; margin: 0; padding: 0; } .products-list > .item { border-radius: 0.25rem; background-color: #fff; padding: 10px 0; } .products-list > .item::after { display: block; clear: both; content: ""; } .products-list .product-img { float: left; } .products-list .product-img img { height: 50px; width: 50px; } .products-list .product-info { margin-left: 60px; } .products-list .product-title { font-weight: 600; } .products-list .product-description { color: #6c757d; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .product-list-in-card > .item { border-radius: 0; border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .product-list-in-card > .item:last-of-type { border-bottom-width: 0; } .direct-chat .card-body { overflow-x: hidden; padding: 0; position: relative; } .direct-chat.chat-pane-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat.timestamp-light .direct-chat-timestamp { color: #30465f; } .direct-chat.timestamp-dark .direct-chat-timestamp { color: #cccccc; } .direct-chat-messages { -webkit-transform: translate(0, 0); transform: translate(0, 0); height: 250px; overflow: auto; padding: 10px; } .direct-chat-msg, .direct-chat-text { display: block; } .direct-chat-msg { margin-bottom: 10px; } .direct-chat-msg::after { display: block; clear: both; content: ""; } .direct-chat-messages, .direct-chat-contacts { transition: -webkit-transform .5s ease-in-out; transition: transform .5s ease-in-out; transition: transform .5s ease-in-out, -webkit-transform .5s ease-in-out; } .direct-chat-text { border-radius: 0.3rem; background-color: #d2d6de; border: 1px solid #d2d6de; color: #444; margin: 5px 0 0 50px; padding: 5px 10px; position: relative; } .direct-chat-text::after, .direct-chat-text::before { border: solid transparent; border-right-color: #d2d6de; content: " "; height: 0; pointer-events: none; position: absolute; right: 100%; top: 15px; width: 0; } .direct-chat-text::after { border-width: 5px; margin-top: -5px; } .direct-chat-text::before { border-width: 6px; margin-top: -6px; } .right .direct-chat-text { margin-left: 0; margin-right: 50px; } .right .direct-chat-text::after, .right .direct-chat-text::before { border-left-color: #d2d6de; border-right-color: transparent; left: 100%; right: auto; } .direct-chat-img { border-radius: 50%; float: left; height: 40px; width: 40px; } .right .direct-chat-img { float: right; } .direct-chat-infos { display: block; font-size: 0.875rem; margin-bottom: 2px; } .direct-chat-name { font-weight: 600; } .direct-chat-timestamp { color: #697582; } .direct-chat-contacts-open .direct-chat-contacts { -webkit-transform: translate(0, 0); transform: translate(0, 0); } .direct-chat-contacts { -webkit-transform: translate(101%, 0); transform: translate(101%, 0); background-color: #343a40; bottom: 0; color: #fff; height: 250px; overflow: auto; position: absolute; top: 0; width: 100%; } .direct-chat-contacts-light { background-color: #f8f9fa; } .direct-chat-contacts-light .contacts-list-name { color: #495057; } .direct-chat-contacts-light .contacts-list-date { color: #6c757d; } .direct-chat-contacts-light .contacts-list-msg { color: #545b62; } .contacts-list { padding-left: 0; list-style: none; } .contacts-list > li { border-bottom: 1px solid rgba(0, 0, 0, 0.2); margin: 0; padding: 10px; } .contacts-list > li::after { display: block; clear: both; content: ""; } .contacts-list > li:last-of-type { border-bottom: 0; } .contacts-list-img { border-radius: 50%; float: left; width: 40px; } .contacts-list-info { color: #fff; margin-left: 45px; } .contacts-list-name, .contacts-list-status { display: block; } .contacts-list-name { font-weight: 600; } .contacts-list-status { font-size: 0.875rem; } .contacts-list-date { color: #ced4da; font-weight: 400; } .contacts-list-msg { color: #b1bbc4; } .direct-chat-primary .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-primary .right > .direct-chat-text::after, .direct-chat-primary .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-secondary .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-secondary .right > .direct-chat-text::after, .direct-chat-secondary .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-success .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-success .right > .direct-chat-text::after, .direct-chat-success .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-info .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-info .right > .direct-chat-text::after, .direct-chat-info .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-warning .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-warning .right > .direct-chat-text::after, .direct-chat-warning .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-danger .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-danger .right > .direct-chat-text::after, .direct-chat-danger .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-light .right > .direct-chat-text { background-color: #f8f9fa; border-color: #f8f9fa; color: #1f2d3d; } .direct-chat-light .right > .direct-chat-text::after, .direct-chat-light .right > .direct-chat-text::before { border-left-color: #f8f9fa; } .direct-chat-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-dark .right > .direct-chat-text::after, .direct-chat-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .direct-chat-lightblue .right > .direct-chat-text { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .direct-chat-lightblue .right > .direct-chat-text::after, .direct-chat-lightblue .right > .direct-chat-text::before { border-left-color: #3c8dbc; } .direct-chat-navy .right > .direct-chat-text { background-color: #001f3f; border-color: #001f3f; color: #fff; } .direct-chat-navy .right > .direct-chat-text::after, .direct-chat-navy .right > .direct-chat-text::before { border-left-color: #001f3f; } .direct-chat-olive .right > .direct-chat-text { background-color: #3d9970; border-color: #3d9970; color: #fff; } .direct-chat-olive .right > .direct-chat-text::after, .direct-chat-olive .right > .direct-chat-text::before { border-left-color: #3d9970; } .direct-chat-lime .right > .direct-chat-text { background-color: #01ff70; border-color: #01ff70; color: #1f2d3d; } .direct-chat-lime .right > .direct-chat-text::after, .direct-chat-lime .right > .direct-chat-text::before { border-left-color: #01ff70; } .direct-chat-fuchsia .right > .direct-chat-text { background-color: #f012be; border-color: #f012be; color: #fff; } .direct-chat-fuchsia .right > .direct-chat-text::after, .direct-chat-fuchsia .right > .direct-chat-text::before { border-left-color: #f012be; } .direct-chat-maroon .right > .direct-chat-text { background-color: #d81b60; border-color: #d81b60; color: #fff; } .direct-chat-maroon .right > .direct-chat-text::after, .direct-chat-maroon .right > .direct-chat-text::before { border-left-color: #d81b60; } .direct-chat-blue .right > .direct-chat-text { background-color: #007bff; border-color: #007bff; color: #fff; } .direct-chat-blue .right > .direct-chat-text::after, .direct-chat-blue .right > .direct-chat-text::before { border-left-color: #007bff; } .direct-chat-indigo .right > .direct-chat-text { background-color: #6610f2; border-color: #6610f2; color: #fff; } .direct-chat-indigo .right > .direct-chat-text::after, .direct-chat-indigo .right > .direct-chat-text::before { border-left-color: #6610f2; } .direct-chat-purple .right > .direct-chat-text { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .direct-chat-purple .right > .direct-chat-text::after, .direct-chat-purple .right > .direct-chat-text::before { border-left-color: #6f42c1; } .direct-chat-pink .right > .direct-chat-text { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .direct-chat-pink .right > .direct-chat-text::after, .direct-chat-pink .right > .direct-chat-text::before { border-left-color: #e83e8c; } .direct-chat-red .right > .direct-chat-text { background-color: #dc3545; border-color: #dc3545; color: #fff; } .direct-chat-red .right > .direct-chat-text::after, .direct-chat-red .right > .direct-chat-text::before { border-left-color: #dc3545; } .direct-chat-orange .right > .direct-chat-text { background-color: #fd7e14; border-color: #fd7e14; color: #1f2d3d; } .direct-chat-orange .right > .direct-chat-text::after, .direct-chat-orange .right > .direct-chat-text::before { border-left-color: #fd7e14; } .direct-chat-yellow .right > .direct-chat-text { background-color: #ffc107; border-color: #ffc107; color: #1f2d3d; } .direct-chat-yellow .right > .direct-chat-text::after, .direct-chat-yellow .right > .direct-chat-text::before { border-left-color: #ffc107; } .direct-chat-green .right > .direct-chat-text { background-color: #28a745; border-color: #28a745; color: #fff; } .direct-chat-green .right > .direct-chat-text::after, .direct-chat-green .right > .direct-chat-text::before { border-left-color: #28a745; } .direct-chat-teal .right > .direct-chat-text { background-color: #20c997; border-color: #20c997; color: #fff; } .direct-chat-teal .right > .direct-chat-text::after, .direct-chat-teal .right > .direct-chat-text::before { border-left-color: #20c997; } .direct-chat-cyan .right > .direct-chat-text { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .direct-chat-cyan .right > .direct-chat-text::after, .direct-chat-cyan .right > .direct-chat-text::before { border-left-color: #17a2b8; } .direct-chat-white .right > .direct-chat-text { background-color: #fff; border-color: #fff; color: #1f2d3d; } .direct-chat-white .right > .direct-chat-text::after, .direct-chat-white .right > .direct-chat-text::before { border-left-color: #fff; } .direct-chat-gray .right > .direct-chat-text { background-color: #6c757d; border-color: #6c757d; color: #fff; } .direct-chat-gray .right > .direct-chat-text::after, .direct-chat-gray .right > .direct-chat-text::before { border-left-color: #6c757d; } .direct-chat-gray-dark .right > .direct-chat-text { background-color: #343a40; border-color: #343a40; color: #fff; } .direct-chat-gray-dark .right > .direct-chat-text::after, .direct-chat-gray-dark .right > .direct-chat-text::before { border-left-color: #343a40; } .users-list { padding-left: 0; list-style: none; } .users-list > li { float: left; padding: 10px; text-align: center; width: 25%; } .users-list > li img { border-radius: 50%; height: auto; max-width: 100%; } .users-list > li > a:hover, .users-list > li > a:hover .users-list-name { color: #999; } .users-list-name, .users-list-date { display: block; } .users-list-name { color: #495057; font-size: 0.875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .users-list-date { color: #748290; font-size: 12px; } .card-widget { border: 0; position: relative; } .widget-user .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; height: 135px; padding: 1rem; text-align: center; } .widget-user .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 0; margin-top: 0; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); } .widget-user .widget-user-desc { margin-top: 0; } .widget-user .widget-user-image { left: 50%; margin-left: -45px; position: absolute; top: 80px; } .widget-user .widget-user-image > img { border: 3px solid #fff; height: auto; width: 90px; } .widget-user .card-footer { padding-top: 50px; } .widget-user-2 .widget-user-header { border-top-left-radius: 0.25rem; border-top-right-radius: 0.25rem; padding: 1rem; } .widget-user-2 .widget-user-username { font-size: 25px; font-weight: 300; margin-bottom: 5px; margin-top: 5px; } .widget-user-2 .widget-user-desc { margin-top: 0; } .widget-user-2 .widget-user-username, .widget-user-2 .widget-user-desc { margin-left: 75px; } .widget-user-2 .widget-user-image > img { float: left; height: auto; width: 65px; } .mailbox-messages > .table { margin: 0; } .mailbox-controls { padding: 5px; } .mailbox-controls.with-border { border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .mailbox-read-info { border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 10px; } .mailbox-read-info h3 { font-size: 20px; margin: 0; } .mailbox-read-info h5 { margin: 0; padding: 5px 0 0; } .mailbox-read-time { color: #999; font-size: 13px; } .mailbox-read-message { padding: 10px; } .mailbox-attachments { padding-left: 0; list-style: none; } .mailbox-attachments li { border: 1px solid #eee; float: left; margin-bottom: 10px; margin-right: 10px; width: 200px; } .mailbox-attachment-name { color: #666; font-weight: 700; } .mailbox-attachment-icon, .mailbox-attachment-info, .mailbox-attachment-size { display: block; } .mailbox-attachment-info { background-color: #f8f9fa; padding: 10px; } .mailbox-attachment-size { color: #999; font-size: 12px; } .mailbox-attachment-size > span { display: inline-block; padding-top: .75rem; } .mailbox-attachment-icon { color: #666; font-size: 65px; max-height: 132.5px; padding: 20px 10px; text-align: center; } .mailbox-attachment-icon.has-img { padding: 0; } .mailbox-attachment-icon.has-img > img { height: auto; max-width: 100%; } .lockscreen { background-color: #e9ecef; } .lockscreen .lockscreen-name { font-weight: 600; text-align: center; } .lockscreen-logo { font-size: 35px; font-weight: 300; margin-bottom: 25px; text-align: center; } .lockscreen-logo a { color: #495057; } .lockscreen-wrapper { margin: 0 auto; margin-top: 10%; max-width: 400px; } .lockscreen-item { border-radius: 4px; background-color: #fff; margin: 10px auto 30px; padding: 0; position: relative; width: 290px; } .lockscreen-image { border-radius: 50%; background-color: #fff; left: -10px; padding: 5px; position: absolute; top: -25px; z-index: 10; } .lockscreen-image > img { border-radius: 50%; height: 70px; width: 70px; } .lockscreen-credentials { margin-left: 70px; } .lockscreen-credentials .form-control { border: 0; } .lockscreen-credentials .btn { background-color: #fff; border: 0; padding: 0 10px; } .lockscreen-footer { margin-top: 10px; } .login-logo, .register-logo { font-size: 2.1rem; font-weight: 300; margin-bottom: .9rem; text-align: center; } .login-logo a, .register-logo a { color: #495057; } .login-page, .register-page { -ms-flex-align: center; align-items: center; background-color: #e9ecef; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; height: 100vh; -ms-flex-pack: center; justify-content: center; } .login-box, .register-box { width: 360px; } @media (max-width: 576px) { .login-box, .register-box { margin-top: .5rem; width: 90%; } } .login-box .card, .register-box .card { margin-bottom: 0; } .login-card-body, .register-card-body { background-color: #fff; border-top: 0; color: #666; padding: 20px; } .login-card-body .input-group .form-control, .register-card-body .input-group .form-control { border-right: 0; } .login-card-body .input-group .form-control:focus, .register-card-body .input-group .form-control:focus { box-shadow: none; } .login-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text { border-color: #80bdff; } .login-card-body .input-group .form-control.is-valid:focus, .register-card-body .input-group .form-control.is-valid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text { border-color: #28a745; } .login-card-body .input-group .form-control.is-invalid:focus, .register-card-body .input-group .form-control.is-invalid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text { border-color: #dc3545; } .login-card-body .input-group .input-group-text, .register-card-body .input-group .input-group-text { background-color: transparent; border-bottom-right-radius: 0.25rem; border-left: 0; border-top-right-radius: 0.25rem; color: #777; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .login-box-msg, .register-box-msg { margin: 0; padding: 0 20px 20px; text-align: center; } .social-auth-links { margin: 10px 0; } .error-page { margin: 20px auto 0; width: 600px; } @media (max-width: 767.98px) { .error-page { width: 100%; } } .error-page > .headline { float: left; font-size: 100px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .headline { float: none; text-align: center; } } .error-page > .error-content { display: block; margin-left: 190px; } @media (max-width: 767.98px) { .error-page > .error-content { margin-left: 0; } } .error-page > .error-content > h3 { font-size: 25px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .error-content > h3 { text-align: center; } } .invoice { background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); position: relative; } .invoice-title { margin-top: 0; } .profile-user-img { border: 3px solid #adb5bd; margin: 0 auto; padding: 3px; width: 100px; } .profile-username { font-size: 21px; margin-top: 5px; } .post { border-bottom: 1px solid #adb5bd; color: #666; margin-bottom: 15px; padding-bottom: 15px; } .post:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; } .post .user-block { margin-bottom: 15px; width: 100%; } .post .row { width: 100%; } .product-image { max-width: 100%; height: auto; width: 100%; } .product-image-thumbs { -ms-flex-align: stretch; align-items: stretch; display: -ms-flexbox; display: flex; margin-top: 2rem; } .product-image-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); border-radius: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; display: -ms-flexbox; display: flex; margin-right: 1rem; max-width: 7rem; padding: 0.5rem; } .product-image-thumb img { max-width: 100%; height: auto; -ms-flex-item-align: center; align-self: center; } .product-image-thumb:hover { opacity: .5; } .product-share a { margin-right: .5rem; } .projects td { vertical-align: middle; } .projects .list-inline { margin-bottom: 0; } .projects img.table-avatar, .projects .table-avatar img { border-radius: 50%; display: inline; width: 2.5rem; } .projects .project-state { text-align: center; } body.iframe-mode .main-sidebar { display: none; } body.iframe-mode .content-wrapper { margin-left: 0 !important; margin-top: 0 !important; padding-bottom: 0 !important; } body.iframe-mode .main-header, body.iframe-mode .main-footer { display: none; } body.iframe-mode-fullscreen { overflow: hidden; } body.iframe-mode-fullscreen.layout-navbar-fixed .wrapper .content-wrapper { margin-top: 0 !important; } .content-wrapper { height: 100%; } .content-wrapper.iframe-mode .btn-iframe-close { color: #dc3545; position: absolute; line-height: 1; right: .125rem; top: .125rem; z-index: 10; visibility: hidden; } .content-wrapper.iframe-mode .btn-iframe-close:hover, .content-wrapper.iframe-mode .btn-iframe-close:focus { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .navbar-nav { overflow-y: auto; width: 100%; } .content-wrapper.iframe-mode .navbar-nav .nav-link { white-space: nowrap; } .content-wrapper.iframe-mode .navbar-nav .nav-item { position: relative; } .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .tab-content { position: relative; } .content-wrapper.iframe-mode .tab-pane + .tab-empty { display: none; } .content-wrapper.iframe-mode .tab-empty { width: 100%; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; } .content-wrapper.iframe-mode .tab-loading { position: absolute; top: 0; left: 0; width: 100%; display: none; background-color: #f4f6f9; } .content-wrapper.iframe-mode .tab-loading > div { display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; width: 100%; height: 100%; } .content-wrapper.iframe-mode iframe { border: 0; width: 100%; height: 100%; margin-bottom: -8px; } .content-wrapper.iframe-mode iframe .content-wrapper { padding-bottom: 0 !important; } body.iframe-mode-fullscreen .content-wrapper.iframe-mode { position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin-left: 0 !important; height: 100%; min-height: 100%; z-index: 1048; } .permanent-btn-iframe-close .btn-iframe-close { -webkit-animation: none !important; animation: none !important; visibility: visible !important; opacity: 1; } .content-wrapper.kanban { height: 1px; } .content-wrapper.kanban .content { height: 100%; overflow-x: auto; overflow-y: hidden; } .content-wrapper.kanban .content .container, .content-wrapper.kanban .content .container-fluid, .content-wrapper.kanban .content .container-sm, .content-wrapper.kanban .content .container-md, .content-wrapper.kanban .content .container-lg, .content-wrapper.kanban .content .container-xl { width: -webkit-max-content; width: -moz-max-content; width: max-content; display: -ms-flexbox; display: flex; -ms-flex-align: stretch; align-items: stretch; } .content-wrapper.kanban .content-header + .content { height: calc(100% - ((2 * 15px) + (1.8rem * 1.2))); } .content-wrapper.kanban .card .card-body { padding: .5rem; } .content-wrapper.kanban .card.card-row { width: 340px; display: inline-block; margin: 0 .5rem; } .content-wrapper.kanban .card.card-row:first-child { margin-left: 0; } .content-wrapper.kanban .card.card-row .card-body { height: calc(100% - (12px + (1.8rem * 1.2) + .5rem)); overflow-y: auto; } .content-wrapper.kanban .card.card-row .card:last-child { margin-bottom: 0; border-bottom-width: 1px; } .content-wrapper.kanban .card.card-row .card .card-header { padding: .5rem .75rem; } .content-wrapper.kanban .card.card-row .card .card-body { padding: .75rem; } .content-wrapper.kanban .btn-tool.btn-link { text-decoration: underline; padding-left: 0; padding-right: 0; } .fc-button { background: #f8f9fa; background-image: none; border-bottom-color: #ddd; border-color: #ddd; color: #495057; } .fc-button:hover, .fc-button:active, .fc-button.hover { background-color: #e9e9e9; } .fc-header-title h2 { color: #666; font-size: 15px; line-height: 1.6em; margin-left: 10px; } .fc-header-right { padding-right: 10px; } .fc-header-left { padding-left: 10px; } .fc-widget-header { background: #fafafa; } .fc-grid { border: 0; width: 100%; } .fc-widget-header:first-of-type, .fc-widget-content:first-of-type { border-left: 0; border-right: 0; } .fc-widget-header:last-of-type, .fc-widget-content:last-of-type { border-right: 0; } .fc-toolbar, .fc-toolbar.fc-header-toolbar { margin: 0; padding: 1rem; } @media (max-width: 575.98px) { .fc-toolbar { -ms-flex-direction: column; flex-direction: column; } .fc-toolbar .fc-left { -ms-flex-order: 1; order: 1; margin-bottom: .5rem; } .fc-toolbar .fc-center { -ms-flex-order: 0; order: 0; margin-bottom: .375rem; } .fc-toolbar .fc-right { -ms-flex-order: 2; order: 2; } } .fc-day-number { font-size: 20px; font-weight: 300; padding-right: 10px; } .fc-color-picker { list-style: none; margin: 0; padding: 0; } .fc-color-picker > li { float: left; font-size: 30px; line-height: 30px; margin-right: 5px; } .fc-color-picker > li .fa, .fc-color-picker > li .fas, .fc-color-picker > li .far, .fc-color-picker > li .fab, .fc-color-picker > li .fal, .fc-color-picker > li .fad, .fc-color-picker > li .svg-inline--fa, .fc-color-picker > li .ion { transition: -webkit-transform linear .3s; transition: transform linear .3s; transition: transform linear .3s, -webkit-transform linear .3s; } .fc-color-picker > li .fa:hover, .fc-color-picker > li .fas:hover, .fc-color-picker > li .far:hover, .fc-color-picker > li .fab:hover, .fc-color-picker > li .fal:hover, .fc-color-picker > li .fad:hover, .fc-color-picker > li .svg-inline--fa:hover, .fc-color-picker > li .ion:hover { -webkit-transform: rotate(30deg); transform: rotate(30deg); } #add-new-event { transition: all linear .3s; } .external-event { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; cursor: move; font-weight: 700; margin-bottom: 4px; padding: 5px 10px; } .external-event:hover { box-shadow: inset 0 0 90px rgba(0, 0, 0, 0.2); } .select2-container--default .select2-selection--single { border: 1px solid #ced4da; padding: 0.46875rem 0.75rem; height: calc(2.25rem + 2px); } .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-dropdown { border: 1px solid #ced4da; } .select2-container--default .select2-results__option { padding: 6px 12px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .select2-container--default .select2-selection--single .select2-selection__rendered { padding-left: 0; height: auto; margin-top: -3px; } .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__rendered { padding-right: 6px; padding-left: 20px; } .select2-container--default .select2-selection--single .select2-selection__arrow { height: 31px; right: 6px; } .select2-container--default .select2-selection--single .select2-selection__arrow b { margin-top: 0; } .select2-container--default .select2-dropdown .select2-search__field, .select2-container--default .select2-search--inline .select2-search__field { border: 1px solid #ced4da; } .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-search--inline .select2-search__field:focus { outline: none; border: 1px solid #80bdff; } .select2-container--default .select2-dropdown.select2-dropdown--below { border-top: 0; } .select2-container--default .select2-dropdown.select2-dropdown--above { border-bottom: 0; } .select2-container--default .select2-results__option[aria-disabled='true'] { color: #6c757d; } .select2-container--default .select2-results__option[aria-selected='true'] { background-color: #dee2e6; } .select2-container--default .select2-results__option[aria-selected='true'], .select2-container--default .select2-results__option[aria-selected='true']:hover { color: #1f2d3d; } .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-selection--multiple { border: 1px solid #ced4da; min-height: calc(2.25rem + 2px); } .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.375rem 0.375rem; margin-bottom: -0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { width: 100%; margin-left: 0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline .select2-search__field { width: 100% !important; } .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { border: 0; margin-top: 6px; } .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; padding: 0 10px; margin-top: .31rem; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); float: right; margin-left: 5px; margin-right: -2px; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .text-sm .select2-container--default .select2-selection--multiple .select2-search.select2-search--inline .select2-search__field, .select2-container--default .select2-selection--multiple.text-sm .select2-search.select2-search--inline .select2-search__field { margin-top: 8px; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__choice, .select2-container--default .select2-selection--multiple.text-sm .select2-selection__choice { margin-top: .4rem; } .select2-container--default.select2-container--focus .select2-selection--single, .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-container--default.select2-container--focus .select2-search__field { border: 0; } .select2-container--default .select2-selection--single .select2-selection__rendered li { padding-right: 10px; } .input-group-prepend ~ .select2-container--default .select2-selection { border-bottom-left-radius: 0; border-top-left-radius: 0; } .input-group > .select2-container--default:not(:last-child) .select2-selection { border-bottom-right-radius: 0; border-top-right-radius: 0; } .select2-container--bootstrap4.select2-container--focus .select2-selection { box-shadow: none; } select.form-control-sm ~ .select2-container--default { font-size: 75%; } .text-sm .select2-container--default .select2-selection--single, select.form-control-sm ~ .select2-container--default .select2-selection--single { height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--single .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__rendered { margin-top: -.4rem; } .text-sm .select2-container--default .select2-selection--single .select2-selection__arrow, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__arrow { top: -.12rem; } .text-sm .select2-container--default .select2-selection--multiple, select.form-control-sm ~ .select2-container--default .select2-selection--multiple { min-height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.25rem 0.25rem; margin-top: -0.1rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { margin-left: 0.25rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { margin-top: 6px; } .maximized-card .select2-dropdown { z-index: 9999; } .select2-primary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-primary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-primary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-search--inline .select2-search__field:focus, .select2-primary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-primary .select2-results__option--highlighted, .select2-primary .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected]:hover, .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple:focus, .select2-primary .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-primary.select2-container--focus .select2-selection--multiple, .select2-primary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-secondary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-secondary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-secondary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-search--inline .select2-search__field:focus, .select2-secondary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-secondary .select2-results__option--highlighted, .select2-secondary .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected]:hover, .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple:focus, .select2-secondary .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-secondary.select2-container--focus .select2-selection--multiple, .select2-secondary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-success + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-success + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-success.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-search--inline .select2-search__field:focus, .select2-success .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-success .select2-results__option--highlighted, .select2-success .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected]:hover, .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple:focus, .select2-success .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-success.select2-container--focus .select2-selection--multiple, .select2-success .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-info + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-info + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-info.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-search--inline .select2-search__field:focus, .select2-info .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-info .select2-results__option--highlighted, .select2-info .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected]:hover, .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple:focus, .select2-info .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-info.select2-container--focus .select2-selection--multiple, .select2-info .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-warning + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-warning + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-warning.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-search--inline .select2-search__field:focus, .select2-warning .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-warning .select2-results__option--highlighted, .select2-warning .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected]:hover, .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple:focus, .select2-warning .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-warning.select2-container--focus .select2-selection--multiple, .select2-warning .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-danger + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-danger + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-danger.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-search--inline .select2-search__field:focus, .select2-danger .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-danger .select2-results__option--highlighted, .select2-danger .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected]:hover, .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple:focus, .select2-danger .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-danger.select2-container--focus .select2-selection--multiple, .select2-danger .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-light + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-light + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-light.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-search--inline .select2-search__field:focus, .select2-light .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-light .select2-results__option--highlighted, .select2-light .select2-container--default .select2-results__option--highlighted { background-color: #f8f9fa; color: #1f2d3d; } .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected]:hover, .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eff1f4; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple:focus, .select2-light .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f8f9fa; border-color: #e9ecef; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-light.select2-container--focus .select2-selection--multiple, .select2-light .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-search--inline .select2-search__field:focus, .select2-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-dark .select2-results__option--highlighted, .select2-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple:focus, .select2-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-dark.select2-container--focus .select2-selection--multiple, .select2-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .select2-lightblue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #99c5de; } .select2-lightblue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #99c5de; } .select2-container--default .select2-lightblue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-search--inline .select2-search__field:focus, .select2-lightblue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #99c5de; } .select2-container--default .select2-lightblue .select2-results__option--highlighted, .select2-lightblue .select2-container--default .select2-results__option--highlighted { background-color: #3c8dbc; color: #fff; } .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected]:hover, .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3884b0; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple:focus, .select2-lightblue .select2-container--default .select2-selection--multiple:focus { border-color: #99c5de; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3c8dbc; border-color: #367fa9; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-lightblue.select2-container--focus .select2-selection--multiple, .select2-lightblue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #99c5de; } .select2-navy + .select2-container--default.select2-container--open .select2-selection--single { border-color: #005ebf; } .select2-navy + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #005ebf; } .select2-container--default .select2-navy.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-search--inline .select2-search__field:focus, .select2-navy .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #005ebf; } .select2-container--default .select2-navy .select2-results__option--highlighted, .select2-navy .select2-container--default .select2-results__option--highlighted { background-color: #001f3f; color: #fff; } .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected]:hover, .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #001730; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple:focus, .select2-navy .select2-container--default .select2-selection--multiple:focus { border-color: #005ebf; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #001f3f; border-color: #001226; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-navy.select2-container--focus .select2-selection--multiple, .select2-navy .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #005ebf; } .select2-olive + .select2-container--default.select2-container--open .select2-selection--single { border-color: #87cfaf; } .select2-olive + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #87cfaf; } .select2-container--default .select2-olive.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-search--inline .select2-search__field:focus, .select2-olive .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #87cfaf; } .select2-container--default .select2-olive .select2-results__option--highlighted, .select2-olive .select2-container--default .select2-results__option--highlighted { background-color: #3d9970; color: #fff; } .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected]:hover, .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #398e68; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple:focus, .select2-olive .select2-container--default .select2-selection--multiple:focus { border-color: #87cfaf; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3d9970; border-color: #368763; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-olive.select2-container--focus .select2-selection--multiple, .select2-olive .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #87cfaf; } .select2-lime + .select2-container--default.select2-container--open .select2-selection--single { border-color: #81ffb8; } .select2-lime + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #81ffb8; } .select2-container--default .select2-lime.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-search--inline .select2-search__field:focus, .select2-lime .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #81ffb8; } .select2-container--default .select2-lime .select2-results__option--highlighted, .select2-lime .select2-container--default .select2-results__option--highlighted { background-color: #01ff70; color: #1f2d3d; } .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected]:hover, .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00f169; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple:focus, .select2-lime .select2-container--default .select2-selection--multiple:focus { border-color: #81ffb8; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #01ff70; border-color: #00e765; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-lime.select2-container--focus .select2-selection--multiple, .select2-lime .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #81ffb8; } .select2-fuchsia + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f88adf; } .select2-fuchsia + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f88adf; } .select2-container--default .select2-fuchsia.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-search--inline .select2-search__field:focus, .select2-fuchsia .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f88adf; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted, .select2-fuchsia .select2-container--default .select2-results__option--highlighted { background-color: #f012be; color: #fff; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected]:hover, .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e40eb4; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple:focus, .select2-fuchsia .select2-container--default .select2-selection--multiple:focus { border-color: #f88adf; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f012be; border-color: #db0ead; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-fuchsia.select2-container--focus .select2-selection--multiple, .select2-fuchsia .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f88adf; } .select2-maroon + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f083ab; } .select2-maroon + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f083ab; } .select2-container--default .select2-maroon.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-search--inline .select2-search__field:focus, .select2-maroon .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f083ab; } .select2-container--default .select2-maroon .select2-results__option--highlighted, .select2-maroon .select2-container--default .select2-results__option--highlighted { background-color: #d81b60; color: #fff; } .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected]:hover, .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ca195a; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple:focus, .select2-maroon .select2-container--default .select2-selection--multiple:focus { border-color: #f083ab; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #d81b60; border-color: #c11856; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-maroon.select2-container--focus .select2-selection--multiple, .select2-maroon .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f083ab; } .select2-blue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-blue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-blue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-search--inline .select2-search__field:focus, .select2-blue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-blue .select2-results__option--highlighted, .select2-blue .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected]:hover, .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple:focus, .select2-blue .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-blue.select2-container--focus .select2-selection--multiple, .select2-blue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-indigo + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b389f9; } .select2-indigo + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b389f9; } .select2-container--default .select2-indigo.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-search--inline .select2-search__field:focus, .select2-indigo .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b389f9; } .select2-container--default .select2-indigo .select2-results__option--highlighted, .select2-indigo .select2-container--default .select2-results__option--highlighted { background-color: #6610f2; color: #fff; } .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected]:hover, .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #5f0de6; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple:focus, .select2-indigo .select2-container--default .select2-selection--multiple:focus { border-color: #b389f9; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6610f2; border-color: #5b0cdd; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-indigo.select2-container--focus .select2-selection--multiple, .select2-indigo .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b389f9; } .select2-purple + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b8a2e0; } .select2-purple + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b8a2e0; } .select2-container--default .select2-purple.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-search--inline .select2-search__field:focus, .select2-purple .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b8a2e0; } .select2-container--default .select2-purple .select2-results__option--highlighted, .select2-purple .select2-container--default .select2-results__option--highlighted { background-color: #6f42c1; color: #fff; } .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected]:hover, .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #683cb8; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple:focus, .select2-purple .select2-container--default .select2-selection--multiple:focus { border-color: #b8a2e0; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6f42c1; border-color: #643ab0; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-purple.select2-container--focus .select2-selection--multiple, .select2-purple .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b8a2e0; } .select2-pink + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f6b0d0; } .select2-pink + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f6b0d0; } .select2-container--default .select2-pink.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-search--inline .select2-search__field:focus, .select2-pink .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f6b0d0; } .select2-container--default .select2-pink .select2-results__option--highlighted, .select2-pink .select2-container--default .select2-results__option--highlighted { background-color: #e83e8c; color: #fff; } .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected]:hover, .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e63084; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple:focus, .select2-pink .select2-container--default .select2-selection--multiple:focus { border-color: #f6b0d0; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e83e8c; border-color: #e5277e; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-pink.select2-container--focus .select2-selection--multiple, .select2-pink .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f6b0d0; } .select2-red + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-red + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-red.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-search--inline .select2-search__field:focus, .select2-red .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-red .select2-results__option--highlighted, .select2-red .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected]:hover, .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple:focus, .select2-red .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-red.select2-container--focus .select2-selection--multiple, .select2-red .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-orange + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fec392; } .select2-orange + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fec392; } .select2-container--default .select2-orange.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-search--inline .select2-search__field:focus, .select2-orange .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fec392; } .select2-container--default .select2-orange .select2-results__option--highlighted, .select2-orange .select2-container--default .select2-results__option--highlighted { background-color: #fd7e14; color: #1f2d3d; } .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected]:hover, .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #fd7605; color: #fff; } .select2-container--default .select2-orange .select2-selection--multiple:focus, .select2-orange .select2-container--default .select2-selection--multiple:focus { border-color: #fec392; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fd7e14; border-color: #f57102; color: #1f2d3d; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-orange.select2-container--focus .select2-selection--multiple, .select2-orange .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fec392; } .select2-yellow + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-yellow + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-yellow.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-search--inline .select2-search__field:focus, .select2-yellow .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-yellow .select2-results__option--highlighted, .select2-yellow .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected]:hover, .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple:focus, .select2-yellow .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-yellow.select2-container--focus .select2-selection--multiple, .select2-yellow .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-green + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-green + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-green.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-search--inline .select2-search__field:focus, .select2-green .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-green .select2-results__option--highlighted, .select2-green .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected]:hover, .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple:focus, .select2-green .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-green.select2-container--focus .select2-selection--multiple, .select2-green .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-teal + .select2-container--default.select2-container--open .select2-selection--single { border-color: #7eeaca; } .select2-teal + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #7eeaca; } .select2-container--default .select2-teal.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-search--inline .select2-search__field:focus, .select2-teal .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #7eeaca; } .select2-container--default .select2-teal .select2-results__option--highlighted, .select2-teal .select2-container--default .select2-results__option--highlighted { background-color: #20c997; color: #fff; } .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected]:hover, .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1ebc8d; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple:focus, .select2-teal .select2-container--default .select2-selection--multiple:focus { border-color: #7eeaca; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #20c997; border-color: #1cb386; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-teal.select2-container--focus .select2-selection--multiple, .select2-teal .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #7eeaca; } .select2-cyan + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-cyan + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-cyan.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-search--inline .select2-search__field:focus, .select2-cyan .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-cyan .select2-results__option--highlighted, .select2-cyan .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected]:hover, .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple:focus, .select2-cyan .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-cyan.select2-container--focus .select2-selection--multiple, .select2-cyan .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-white + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-white + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-white.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-search--inline .select2-search__field:focus, .select2-white .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-white .select2-results__option--highlighted, .select2-white .select2-container--default .select2-results__option--highlighted { background-color: #fff; color: #1f2d3d; } .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected]:hover, .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7f7f7; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple:focus, .select2-white .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border-color: #f2f2f2; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-white.select2-container--focus .select2-selection--multiple, .select2-white .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-gray + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-gray + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-gray.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-search--inline .select2-search__field:focus, .select2-gray .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-gray .select2-results__option--highlighted, .select2-gray .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected]:hover, .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple:focus, .select2-gray .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray.select2-container--focus .select2-selection--multiple, .select2-gray .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-gray-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-gray-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-gray-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-search--inline .select2-search__field:focus, .select2-gray-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted, .select2-gray-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple:focus, .select2-gray-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray-dark.select2-container--focus .select2-selection--multiple, .select2-gray-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .slider .tooltip.in { opacity: 0.9; } .slider.slider-vertical { height: 100%; } .slider.slider-horizontal { width: 100%; } .slider-primary .slider .slider-selection { background: #007bff; } .slider-secondary .slider .slider-selection { background: #6c757d; } .slider-success .slider .slider-selection { background: #28a745; } .slider-info .slider .slider-selection { background: #17a2b8; } .slider-warning .slider .slider-selection { background: #ffc107; } .slider-danger .slider .slider-selection { background: #dc3545; } .slider-light .slider .slider-selection { background: #f8f9fa; } .slider-dark .slider .slider-selection { background: #343a40; } .slider-lightblue .slider .slider-selection { background: #3c8dbc; } .slider-navy .slider .slider-selection { background: #001f3f; } .slider-olive .slider .slider-selection { background: #3d9970; } .slider-lime .slider .slider-selection { background: #01ff70; } .slider-fuchsia .slider .slider-selection { background: #f012be; } .slider-maroon .slider .slider-selection { background: #d81b60; } .slider-blue .slider .slider-selection { background: #007bff; } .slider-indigo .slider .slider-selection { background: #6610f2; } .slider-purple .slider .slider-selection { background: #6f42c1; } .slider-pink .slider .slider-selection { background: #e83e8c; } .slider-red .slider .slider-selection { background: #dc3545; } .slider-orange .slider .slider-selection { background: #fd7e14; } .slider-yellow .slider .slider-selection { background: #ffc107; } .slider-green .slider .slider-selection { background: #28a745; } .slider-teal .slider .slider-selection { background: #20c997; } .slider-cyan .slider .slider-selection { background: #17a2b8; } .slider-white .slider .slider-selection { background: #fff; } .slider-gray .slider .slider-selection { background: #6c757d; } .slider-gray-dark .slider .slider-selection { background: #343a40; } .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:checked + label::before, .icheck-primary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:checked + label::before, .icheck-secondary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-success > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:checked + label::before, .icheck-success > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-info > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:checked + label::before, .icheck-info > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:checked + label::before, .icheck-warning > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:checked + label::before, .icheck-danger > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-light > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:checked + label::before, .icheck-light > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f8f9fa; border-color: #f8f9fa; } .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:checked + label::before, .icheck-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:checked + label::before, .icheck-lightblue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3c8dbc; border-color: #3c8dbc; } .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:checked + label::before, .icheck-navy > input:first-child:checked + input[type="hidden"] + label::before { background-color: #001f3f; border-color: #001f3f; } .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:checked + label::before, .icheck-olive > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3d9970; border-color: #3d9970; } .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:checked + label::before, .icheck-lime > input:first-child:checked + input[type="hidden"] + label::before { background-color: #01ff70; border-color: #01ff70; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:checked + label::before, .icheck-fuchsia > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f012be; border-color: #f012be; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:checked + label::before, .icheck-maroon > input:first-child:checked + input[type="hidden"] + label::before { background-color: #d81b60; border-color: #d81b60; } .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:checked + label::before, .icheck-blue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:checked + label::before, .icheck-indigo > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6610f2; border-color: #6610f2; } .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:checked + label::before, .icheck-purple > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6f42c1; border-color: #6f42c1; } .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:checked + label::before, .icheck-pink > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e83e8c; border-color: #e83e8c; } .icheck-red > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:checked + label::before, .icheck-red > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:checked + label::before, .icheck-orange > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fd7e14; border-color: #fd7e14; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:checked + label::before, .icheck-yellow > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-green > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:checked + label::before, .icheck-green > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:checked + label::before, .icheck-teal > input:first-child:checked + input[type="hidden"] + label::before { background-color: #20c997; border-color: #20c997; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:checked + label::before, .icheck-cyan > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-white > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:checked + label::before, .icheck-white > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fff; border-color: #fff; } .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:checked + label::before, .icheck-gray > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:checked + label::before, .icheck-gray-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .mapael .map { position: relative; } .mapael .mapTooltip { font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; border-radius: 0.25rem; font-size: 0.875rem; background-color: #000; color: #fff; display: block; max-width: 200px; padding: 0.25rem 0.5rem; position: absolute; text-align: center; word-wrap: break-word; z-index: 1070; } .mapael .myLegend { background-color: #f8f9fa; border: 1px solid #adb5bd; padding: 10px; width: 600px; } .mapael .zoomButton { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; cursor: pointer; font-weight: 700; height: 16px; left: 10px; line-height: 14px; padding-left: 1px; position: absolute; text-align: center; top: 0; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; width: 16px; } .mapael .zoomButton:hover, .mapael .zoomButton:active, .mapael .zoomButton.hover { background-color: #e9ecef; color: #2b2b2b; } .mapael .zoomReset { line-height: 12px; top: 10px; } .mapael .zoomIn { top: 30px; } .mapael .zoomOut { top: 50px; } .jqvmap-zoomin, .jqvmap-zoomout { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; height: 15px; width: 15px; padding: 1px 2px; } .jqvmap-zoomin:hover, .jqvmap-zoomin:active, .jqvmap-zoomin.hover, .jqvmap-zoomout:hover, .jqvmap-zoomout:active, .jqvmap-zoomout.hover { background-color: #e9ecef; color: #2b2b2b; } .swal2-icon.swal2-info { border-color: ligthen(#17a2b8, 20%); color: #17a2b8; } .swal2-icon.swal2-warning { border-color: ligthen(#ffc107, 20%); color: #ffc107; } .swal2-icon.swal2-error { border-color: ligthen(#dc3545, 20%); color: #dc3545; } .swal2-icon.swal2-question { border-color: ligthen(#6c757d, 20%); color: #6c757d; } .swal2-icon.swal2-success { border-color: ligthen(#28a745, 20%); color: #28a745; } .swal2-icon.swal2-success .swal2-success-ring { border-color: ligthen(#28a745, 20%); } .swal2-icon.swal2-success [class^='swal2-success-line'] { background-color: #28a745; } #toast-container .toast { background-color: #007bff; } #toast-container .toast-success { background-color: #28a745; } #toast-container .toast-error { background-color: #dc3545; } #toast-container .toast-info { background-color: #17a2b8; } #toast-container .toast-warning { background-color: #ffc107; } .toast-bottom-full-width .toast, .toast-top-full-width .toast { max-width: inherit; } .pace { z-index: 1048; } .pace .pace-progress { z-index: 1049; } .pace .pace-activity { z-index: 1050; } .pace-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace { background: #fff; } .pace-barber-shop-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-primary .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-primary .pace .pace-activity { background: #007bff; } .pace-center-atom-primary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-primary .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-primary .pace-activity { border-color: #007bff; } .pace-center-atom-primary .pace-activity::after, .pace-center-atom-primary .pace-activity::before { border-color: #007bff; } .pace-center-circle-primary .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-primary .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-primary .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-primary .pace { background: #fff; border-color: #007bff; } .pace-center-simple-primary .pace .pace-progress { background: #007bff; } .pace-material-primary .pace { color: #007bff; } .pace-corner-indicator-primary .pace .pace-activity { background: #007bff; } .pace-corner-indicator-primary .pace .pace-activity::after, .pace-corner-indicator-primary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-primary .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-primary .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-primary .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-primary .pace .pace-progress { background: #007bff; } .pace-flash-primary .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-primary .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-primary .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-primary .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-primary .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-primary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-primary .pace-progress { color: #007bff; } .pace-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace { background: #fff; } .pace-barber-shop-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-secondary .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-secondary .pace .pace-activity { background: #6c757d; } .pace-center-atom-secondary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-secondary .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-secondary .pace-activity { border-color: #6c757d; } .pace-center-atom-secondary .pace-activity::after, .pace-center-atom-secondary .pace-activity::before { border-color: #6c757d; } .pace-center-circle-secondary .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-secondary .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-secondary .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-secondary .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-secondary .pace .pace-progress { background: #6c757d; } .pace-material-secondary .pace { color: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity::after, .pace-corner-indicator-secondary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-secondary .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-secondary .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-secondary .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-secondary .pace .pace-progress { background: #6c757d; } .pace-flash-secondary .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-secondary .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-secondary .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-secondary .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-secondary .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-secondary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-secondary .pace-progress { color: #6c757d; } .pace-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace { background: #fff; } .pace-barber-shop-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-success .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-success .pace .pace-activity { background: #28a745; } .pace-center-atom-success .pace-progress { height: 100px; width: 80px; } .pace-center-atom-success .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-success .pace-activity { border-color: #28a745; } .pace-center-atom-success .pace-activity::after, .pace-center-atom-success .pace-activity::before { border-color: #28a745; } .pace-center-circle-success .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-success .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-success .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-success .pace { background: #fff; border-color: #28a745; } .pace-center-simple-success .pace .pace-progress { background: #28a745; } .pace-material-success .pace { color: #28a745; } .pace-corner-indicator-success .pace .pace-activity { background: #28a745; } .pace-corner-indicator-success .pace .pace-activity::after, .pace-corner-indicator-success .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-success .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-success .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-success .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-success .pace .pace-progress { background: #28a745; } .pace-flash-success .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-success .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-success .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-success .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-success .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-success .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-success .pace-progress { color: #28a745; } .pace-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace { background: #fff; } .pace-barber-shop-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-info .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-info .pace .pace-activity { background: #17a2b8; } .pace-center-atom-info .pace-progress { height: 100px; width: 80px; } .pace-center-atom-info .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-info .pace-activity { border-color: #17a2b8; } .pace-center-atom-info .pace-activity::after, .pace-center-atom-info .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-info .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-info .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-info .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-info .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-info .pace .pace-progress { background: #17a2b8; } .pace-material-info .pace { color: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity::after, .pace-corner-indicator-info .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-info .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-info .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-info .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-info .pace .pace-progress { background: #17a2b8; } .pace-flash-info .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-info .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-info .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-info .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-info .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-info .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-info .pace-progress { color: #17a2b8; } .pace-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace { background: #1f2d3d; } .pace-barber-shop-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-warning .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-warning .pace .pace-activity { background: #ffc107; } .pace-center-atom-warning .pace-progress { height: 100px; width: 80px; } .pace-center-atom-warning .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-warning .pace-activity { border-color: #ffc107; } .pace-center-atom-warning .pace-activity::after, .pace-center-atom-warning .pace-activity::before { border-color: #ffc107; } .pace-center-circle-warning .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-warning .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-warning .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-warning .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-warning .pace .pace-progress { background: #ffc107; } .pace-material-warning .pace { color: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity::after, .pace-corner-indicator-warning .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-warning .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-warning .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-warning .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-warning .pace .pace-progress { background: #ffc107; } .pace-flash-warning .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-warning .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-warning .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-warning .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-warning .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-warning .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-warning .pace-progress { color: #ffc107; } .pace-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace { background: #fff; } .pace-barber-shop-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-danger .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-danger .pace .pace-activity { background: #dc3545; } .pace-center-atom-danger .pace-progress { height: 100px; width: 80px; } .pace-center-atom-danger .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-danger .pace-activity { border-color: #dc3545; } .pace-center-atom-danger .pace-activity::after, .pace-center-atom-danger .pace-activity::before { border-color: #dc3545; } .pace-center-circle-danger .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-danger .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-danger .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-danger .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-danger .pace .pace-progress { background: #dc3545; } .pace-material-danger .pace { color: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity::after, .pace-corner-indicator-danger .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-danger .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-danger .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-danger .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-danger .pace .pace-progress { background: #dc3545; } .pace-flash-danger .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-danger .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-danger .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-danger .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-danger .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-danger .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-danger .pace-progress { color: #dc3545; } .pace-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace { background: #1f2d3d; } .pace-barber-shop-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-light .pace .pace-progress::after { color: rgba(248, 249, 250, 0.2); } .pace-bounce-light .pace .pace-activity { background: #f8f9fa; } .pace-center-atom-light .pace-progress { height: 100px; width: 80px; } .pace-center-atom-light .pace-progress::before { background: #f8f9fa; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-light .pace-activity { border-color: #f8f9fa; } .pace-center-atom-light .pace-activity::after, .pace-center-atom-light .pace-activity::before { border-color: #f8f9fa; } .pace-center-circle-light .pace .pace-progress { background: rgba(248, 249, 250, 0.8); color: #1f2d3d; } .pace-center-radar-light .pace .pace-activity { border-color: #f8f9fa transparent transparent; } .pace-center-radar-light .pace .pace-activity::before { border-color: #f8f9fa transparent transparent; } .pace-center-simple-light .pace { background: #1f2d3d; border-color: #f8f9fa; } .pace-center-simple-light .pace .pace-progress { background: #f8f9fa; } .pace-material-light .pace { color: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity { background: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity::after, .pace-corner-indicator-light .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-light .pace .pace-activity::before { border-right-color: rgba(248, 249, 250, 0.2); border-left-color: rgba(248, 249, 250, 0.2); } .pace-corner-indicator-light .pace .pace-activity::after { border-top-color: rgba(248, 249, 250, 0.2); border-bottom-color: rgba(248, 249, 250, 0.2); } .pace-fill-left-light .pace .pace-progress { background-color: rgba(248, 249, 250, 0.2); } .pace-flash-light .pace .pace-progress { background: #f8f9fa; } .pace-flash-light .pace .pace-progress-inner { box-shadow: 0 0 10px #f8f9fa, 0 0 5px #f8f9fa; } .pace-flash-light .pace .pace-activity { border-top-color: #f8f9fa; border-left-color: #f8f9fa; } .pace-loading-bar-light .pace .pace-progress { background: #f8f9fa; color: #f8f9fa; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-light .pace .pace-activity { box-shadow: inset 0 0 0 2px #f8f9fa, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-light .pace .pace-progress { background-color: #f8f9fa; box-shadow: inset -1px 0 #f8f9fa, inset 0 -1px #f8f9fa, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-light .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-light .pace-progress { color: #f8f9fa; } .pace-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace { background: #fff; } .pace-barber-shop-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-dark .pace-activity { border-color: #343a40; } .pace-center-atom-dark .pace-activity::after, .pace-center-atom-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-dark .pace .pace-progress { background: #343a40; } .pace-material-dark .pace { color: #343a40; } .pace-corner-indicator-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-dark .pace .pace-activity::after, .pace-corner-indicator-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-dark .pace .pace-progress { background: #343a40; } .pace-flash-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-dark .pace-progress { color: #343a40; } .pace-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace { background: #fff; } .pace-barber-shop-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lightblue .pace .pace-progress::after { color: rgba(60, 141, 188, 0.2); } .pace-bounce-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-center-atom-lightblue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lightblue .pace-progress::before { background: #3c8dbc; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lightblue .pace-activity { border-color: #3c8dbc; } .pace-center-atom-lightblue .pace-activity::after, .pace-center-atom-lightblue .pace-activity::before { border-color: #3c8dbc; } .pace-center-circle-lightblue .pace .pace-progress { background: rgba(60, 141, 188, 0.8); color: #fff; } .pace-center-radar-lightblue .pace .pace-activity { border-color: #3c8dbc transparent transparent; } .pace-center-radar-lightblue .pace .pace-activity::before { border-color: #3c8dbc transparent transparent; } .pace-center-simple-lightblue .pace { background: #fff; border-color: #3c8dbc; } .pace-center-simple-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-material-lightblue .pace { color: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity::after, .pace-corner-indicator-lightblue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-lightblue .pace .pace-activity::before { border-right-color: rgba(60, 141, 188, 0.2); border-left-color: rgba(60, 141, 188, 0.2); } .pace-corner-indicator-lightblue .pace .pace-activity::after { border-top-color: rgba(60, 141, 188, 0.2); border-bottom-color: rgba(60, 141, 188, 0.2); } .pace-fill-left-lightblue .pace .pace-progress { background-color: rgba(60, 141, 188, 0.2); } .pace-flash-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-flash-lightblue .pace .pace-progress-inner { box-shadow: 0 0 10px #3c8dbc, 0 0 5px #3c8dbc; } .pace-flash-lightblue .pace .pace-activity { border-top-color: #3c8dbc; border-left-color: #3c8dbc; } .pace-loading-bar-lightblue .pace .pace-progress { background: #3c8dbc; color: #3c8dbc; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-lightblue .pace .pace-activity { box-shadow: inset 0 0 0 2px #3c8dbc, inset 0 0 0 7px #fff; } .pace-mac-osx-lightblue .pace .pace-progress { background-color: #3c8dbc; box-shadow: inset -1px 0 #3c8dbc, inset 0 -1px #3c8dbc, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-lightblue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-lightblue .pace-progress { color: #3c8dbc; } .pace-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace { background: #fff; } .pace-barber-shop-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-navy .pace .pace-progress::after { color: rgba(0, 31, 63, 0.2); } .pace-bounce-navy .pace .pace-activity { background: #001f3f; } .pace-center-atom-navy .pace-progress { height: 100px; width: 80px; } .pace-center-atom-navy .pace-progress::before { background: #001f3f; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-navy .pace-activity { border-color: #001f3f; } .pace-center-atom-navy .pace-activity::after, .pace-center-atom-navy .pace-activity::before { border-color: #001f3f; } .pace-center-circle-navy .pace .pace-progress { background: rgba(0, 31, 63, 0.8); color: #fff; } .pace-center-radar-navy .pace .pace-activity { border-color: #001f3f transparent transparent; } .pace-center-radar-navy .pace .pace-activity::before { border-color: #001f3f transparent transparent; } .pace-center-simple-navy .pace { background: #fff; border-color: #001f3f; } .pace-center-simple-navy .pace .pace-progress { background: #001f3f; } .pace-material-navy .pace { color: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity { background: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity::after, .pace-corner-indicator-navy .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-navy .pace .pace-activity::before { border-right-color: rgba(0, 31, 63, 0.2); border-left-color: rgba(0, 31, 63, 0.2); } .pace-corner-indicator-navy .pace .pace-activity::after { border-top-color: rgba(0, 31, 63, 0.2); border-bottom-color: rgba(0, 31, 63, 0.2); } .pace-fill-left-navy .pace .pace-progress { background-color: rgba(0, 31, 63, 0.2); } .pace-flash-navy .pace .pace-progress { background: #001f3f; } .pace-flash-navy .pace .pace-progress-inner { box-shadow: 0 0 10px #001f3f, 0 0 5px #001f3f; } .pace-flash-navy .pace .pace-activity { border-top-color: #001f3f; border-left-color: #001f3f; } .pace-loading-bar-navy .pace .pace-progress { background: #001f3f; color: #001f3f; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-navy .pace .pace-activity { box-shadow: inset 0 0 0 2px #001f3f, inset 0 0 0 7px #fff; } .pace-mac-osx-navy .pace .pace-progress { background-color: #001f3f; box-shadow: inset -1px 0 #001f3f, inset 0 -1px #001f3f, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-navy .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-navy .pace-progress { color: #001f3f; } .pace-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace { background: #fff; } .pace-barber-shop-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-olive .pace .pace-progress::after { color: rgba(61, 153, 112, 0.2); } .pace-bounce-olive .pace .pace-activity { background: #3d9970; } .pace-center-atom-olive .pace-progress { height: 100px; width: 80px; } .pace-center-atom-olive .pace-progress::before { background: #3d9970; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-olive .pace-activity { border-color: #3d9970; } .pace-center-atom-olive .pace-activity::after, .pace-center-atom-olive .pace-activity::before { border-color: #3d9970; } .pace-center-circle-olive .pace .pace-progress { background: rgba(61, 153, 112, 0.8); color: #fff; } .pace-center-radar-olive .pace .pace-activity { border-color: #3d9970 transparent transparent; } .pace-center-radar-olive .pace .pace-activity::before { border-color: #3d9970 transparent transparent; } .pace-center-simple-olive .pace { background: #fff; border-color: #3d9970; } .pace-center-simple-olive .pace .pace-progress { background: #3d9970; } .pace-material-olive .pace { color: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity { background: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity::after, .pace-corner-indicator-olive .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-olive .pace .pace-activity::before { border-right-color: rgba(61, 153, 112, 0.2); border-left-color: rgba(61, 153, 112, 0.2); } .pace-corner-indicator-olive .pace .pace-activity::after { border-top-color: rgba(61, 153, 112, 0.2); border-bottom-color: rgba(61, 153, 112, 0.2); } .pace-fill-left-olive .pace .pace-progress { background-color: rgba(61, 153, 112, 0.2); } .pace-flash-olive .pace .pace-progress { background: #3d9970; } .pace-flash-olive .pace .pace-progress-inner { box-shadow: 0 0 10px #3d9970, 0 0 5px #3d9970; } .pace-flash-olive .pace .pace-activity { border-top-color: #3d9970; border-left-color: #3d9970; } .pace-loading-bar-olive .pace .pace-progress { background: #3d9970; color: #3d9970; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-olive .pace .pace-activity { box-shadow: inset 0 0 0 2px #3d9970, inset 0 0 0 7px #fff; } .pace-mac-osx-olive .pace .pace-progress { background-color: #3d9970; box-shadow: inset -1px 0 #3d9970, inset 0 -1px #3d9970, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-olive .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-olive .pace-progress { color: #3d9970; } .pace-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace { background: #1f2d3d; } .pace-barber-shop-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lime .pace .pace-progress::after { color: rgba(1, 255, 112, 0.2); } .pace-bounce-lime .pace .pace-activity { background: #01ff70; } .pace-center-atom-lime .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lime .pace-progress::before { background: #01ff70; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lime .pace-activity { border-color: #01ff70; } .pace-center-atom-lime .pace-activity::after, .pace-center-atom-lime .pace-activity::before { border-color: #01ff70; } .pace-center-circle-lime .pace .pace-progress { background: rgba(1, 255, 112, 0.8); color: #1f2d3d; } .pace-center-radar-lime .pace .pace-activity { border-color: #01ff70 transparent transparent; } .pace-center-radar-lime .pace .pace-activity::before { border-color: #01ff70 transparent transparent; } .pace-center-simple-lime .pace { background: #1f2d3d; border-color: #01ff70; } .pace-center-simple-lime .pace .pace-progress { background: #01ff70; } .pace-material-lime .pace { color: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity { background: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity::after, .pace-corner-indicator-lime .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-lime .pace .pace-activity::before { border-right-color: rgba(1, 255, 112, 0.2); border-left-color: rgba(1, 255, 112, 0.2); } .pace-corner-indicator-lime .pace .pace-activity::after { border-top-color: rgba(1, 255, 112, 0.2); border-bottom-color: rgba(1, 255, 112, 0.2); } .pace-fill-left-lime .pace .pace-progress { background-color: rgba(1, 255, 112, 0.2); } .pace-flash-lime .pace .pace-progress { background: #01ff70; } .pace-flash-lime .pace .pace-progress-inner { box-shadow: 0 0 10px #01ff70, 0 0 5px #01ff70; } .pace-flash-lime .pace .pace-activity { border-top-color: #01ff70; border-left-color: #01ff70; } .pace-loading-bar-lime .pace .pace-progress { background: #01ff70; color: #01ff70; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-lime .pace .pace-activity { box-shadow: inset 0 0 0 2px #01ff70, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-lime .pace .pace-progress { background-color: #01ff70; box-shadow: inset -1px 0 #01ff70, inset 0 -1px #01ff70, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-lime .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-lime .pace-progress { color: #01ff70; } .pace-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace { background: #fff; } .pace-barber-shop-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-fuchsia .pace .pace-progress::after { color: rgba(240, 18, 190, 0.2); } .pace-bounce-fuchsia .pace .pace-activity { background: #f012be; } .pace-center-atom-fuchsia .pace-progress { height: 100px; width: 80px; } .pace-center-atom-fuchsia .pace-progress::before { background: #f012be; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-fuchsia .pace-activity { border-color: #f012be; } .pace-center-atom-fuchsia .pace-activity::after, .pace-center-atom-fuchsia .pace-activity::before { border-color: #f012be; } .pace-center-circle-fuchsia .pace .pace-progress { background: rgba(240, 18, 190, 0.8); color: #fff; } .pace-center-radar-fuchsia .pace .pace-activity { border-color: #f012be transparent transparent; } .pace-center-radar-fuchsia .pace .pace-activity::before { border-color: #f012be transparent transparent; } .pace-center-simple-fuchsia .pace { background: #fff; border-color: #f012be; } .pace-center-simple-fuchsia .pace .pace-progress { background: #f012be; } .pace-material-fuchsia .pace { color: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity { background: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity::after, .pace-corner-indicator-fuchsia .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-fuchsia .pace .pace-activity::before { border-right-color: rgba(240, 18, 190, 0.2); border-left-color: rgba(240, 18, 190, 0.2); } .pace-corner-indicator-fuchsia .pace .pace-activity::after { border-top-color: rgba(240, 18, 190, 0.2); border-bottom-color: rgba(240, 18, 190, 0.2); } .pace-fill-left-fuchsia .pace .pace-progress { background-color: rgba(240, 18, 190, 0.2); } .pace-flash-fuchsia .pace .pace-progress { background: #f012be; } .pace-flash-fuchsia .pace .pace-progress-inner { box-shadow: 0 0 10px #f012be, 0 0 5px #f012be; } .pace-flash-fuchsia .pace .pace-activity { border-top-color: #f012be; border-left-color: #f012be; } .pace-loading-bar-fuchsia .pace .pace-progress { background: #f012be; color: #f012be; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-fuchsia .pace .pace-activity { box-shadow: inset 0 0 0 2px #f012be, inset 0 0 0 7px #fff; } .pace-mac-osx-fuchsia .pace .pace-progress { background-color: #f012be; box-shadow: inset -1px 0 #f012be, inset 0 -1px #f012be, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-fuchsia .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-fuchsia .pace-progress { color: #f012be; } .pace-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace { background: #fff; } .pace-barber-shop-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-maroon .pace .pace-progress::after { color: rgba(216, 27, 96, 0.2); } .pace-bounce-maroon .pace .pace-activity { background: #d81b60; } .pace-center-atom-maroon .pace-progress { height: 100px; width: 80px; } .pace-center-atom-maroon .pace-progress::before { background: #d81b60; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-maroon .pace-activity { border-color: #d81b60; } .pace-center-atom-maroon .pace-activity::after, .pace-center-atom-maroon .pace-activity::before { border-color: #d81b60; } .pace-center-circle-maroon .pace .pace-progress { background: rgba(216, 27, 96, 0.8); color: #fff; } .pace-center-radar-maroon .pace .pace-activity { border-color: #d81b60 transparent transparent; } .pace-center-radar-maroon .pace .pace-activity::before { border-color: #d81b60 transparent transparent; } .pace-center-simple-maroon .pace { background: #fff; border-color: #d81b60; } .pace-center-simple-maroon .pace .pace-progress { background: #d81b60; } .pace-material-maroon .pace { color: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity { background: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity::after, .pace-corner-indicator-maroon .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-maroon .pace .pace-activity::before { border-right-color: rgba(216, 27, 96, 0.2); border-left-color: rgba(216, 27, 96, 0.2); } .pace-corner-indicator-maroon .pace .pace-activity::after { border-top-color: rgba(216, 27, 96, 0.2); border-bottom-color: rgba(216, 27, 96, 0.2); } .pace-fill-left-maroon .pace .pace-progress { background-color: rgba(216, 27, 96, 0.2); } .pace-flash-maroon .pace .pace-progress { background: #d81b60; } .pace-flash-maroon .pace .pace-progress-inner { box-shadow: 0 0 10px #d81b60, 0 0 5px #d81b60; } .pace-flash-maroon .pace .pace-activity { border-top-color: #d81b60; border-left-color: #d81b60; } .pace-loading-bar-maroon .pace .pace-progress { background: #d81b60; color: #d81b60; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-maroon .pace .pace-activity { box-shadow: inset 0 0 0 2px #d81b60, inset 0 0 0 7px #fff; } .pace-mac-osx-maroon .pace .pace-progress { background-color: #d81b60; box-shadow: inset -1px 0 #d81b60, inset 0 -1px #d81b60, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-maroon .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-maroon .pace-progress { color: #d81b60; } .pace-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace { background: #fff; } .pace-barber-shop-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-blue .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-blue .pace .pace-activity { background: #007bff; } .pace-center-atom-blue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-blue .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-blue .pace-activity { border-color: #007bff; } .pace-center-atom-blue .pace-activity::after, .pace-center-atom-blue .pace-activity::before { border-color: #007bff; } .pace-center-circle-blue .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-blue .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-blue .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-blue .pace { background: #fff; border-color: #007bff; } .pace-center-simple-blue .pace .pace-progress { background: #007bff; } .pace-material-blue .pace { color: #007bff; } .pace-corner-indicator-blue .pace .pace-activity { background: #007bff; } .pace-corner-indicator-blue .pace .pace-activity::after, .pace-corner-indicator-blue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-blue .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-blue .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-blue .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-blue .pace .pace-progress { background: #007bff; } .pace-flash-blue .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-blue .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-blue .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-blue .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-blue .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-blue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-blue .pace-progress { color: #007bff; } .pace-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace { background: #fff; } .pace-barber-shop-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-indigo .pace .pace-progress::after { color: rgba(102, 16, 242, 0.2); } .pace-bounce-indigo .pace .pace-activity { background: #6610f2; } .pace-center-atom-indigo .pace-progress { height: 100px; width: 80px; } .pace-center-atom-indigo .pace-progress::before { background: #6610f2; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-indigo .pace-activity { border-color: #6610f2; } .pace-center-atom-indigo .pace-activity::after, .pace-center-atom-indigo .pace-activity::before { border-color: #6610f2; } .pace-center-circle-indigo .pace .pace-progress { background: rgba(102, 16, 242, 0.8); color: #fff; } .pace-center-radar-indigo .pace .pace-activity { border-color: #6610f2 transparent transparent; } .pace-center-radar-indigo .pace .pace-activity::before { border-color: #6610f2 transparent transparent; } .pace-center-simple-indigo .pace { background: #fff; border-color: #6610f2; } .pace-center-simple-indigo .pace .pace-progress { background: #6610f2; } .pace-material-indigo .pace { color: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity { background: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity::after, .pace-corner-indicator-indigo .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-indigo .pace .pace-activity::before { border-right-color: rgba(102, 16, 242, 0.2); border-left-color: rgba(102, 16, 242, 0.2); } .pace-corner-indicator-indigo .pace .pace-activity::after { border-top-color: rgba(102, 16, 242, 0.2); border-bottom-color: rgba(102, 16, 242, 0.2); } .pace-fill-left-indigo .pace .pace-progress { background-color: rgba(102, 16, 242, 0.2); } .pace-flash-indigo .pace .pace-progress { background: #6610f2; } .pace-flash-indigo .pace .pace-progress-inner { box-shadow: 0 0 10px #6610f2, 0 0 5px #6610f2; } .pace-flash-indigo .pace .pace-activity { border-top-color: #6610f2; border-left-color: #6610f2; } .pace-loading-bar-indigo .pace .pace-progress { background: #6610f2; color: #6610f2; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-indigo .pace .pace-activity { box-shadow: inset 0 0 0 2px #6610f2, inset 0 0 0 7px #fff; } .pace-mac-osx-indigo .pace .pace-progress { background-color: #6610f2; box-shadow: inset -1px 0 #6610f2, inset 0 -1px #6610f2, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-indigo .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-indigo .pace-progress { color: #6610f2; } .pace-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace { background: #fff; } .pace-barber-shop-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-purple .pace .pace-progress::after { color: rgba(111, 66, 193, 0.2); } .pace-bounce-purple .pace .pace-activity { background: #6f42c1; } .pace-center-atom-purple .pace-progress { height: 100px; width: 80px; } .pace-center-atom-purple .pace-progress::before { background: #6f42c1; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-purple .pace-activity { border-color: #6f42c1; } .pace-center-atom-purple .pace-activity::after, .pace-center-atom-purple .pace-activity::before { border-color: #6f42c1; } .pace-center-circle-purple .pace .pace-progress { background: rgba(111, 66, 193, 0.8); color: #fff; } .pace-center-radar-purple .pace .pace-activity { border-color: #6f42c1 transparent transparent; } .pace-center-radar-purple .pace .pace-activity::before { border-color: #6f42c1 transparent transparent; } .pace-center-simple-purple .pace { background: #fff; border-color: #6f42c1; } .pace-center-simple-purple .pace .pace-progress { background: #6f42c1; } .pace-material-purple .pace { color: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity { background: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity::after, .pace-corner-indicator-purple .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-purple .pace .pace-activity::before { border-right-color: rgba(111, 66, 193, 0.2); border-left-color: rgba(111, 66, 193, 0.2); } .pace-corner-indicator-purple .pace .pace-activity::after { border-top-color: rgba(111, 66, 193, 0.2); border-bottom-color: rgba(111, 66, 193, 0.2); } .pace-fill-left-purple .pace .pace-progress { background-color: rgba(111, 66, 193, 0.2); } .pace-flash-purple .pace .pace-progress { background: #6f42c1; } .pace-flash-purple .pace .pace-progress-inner { box-shadow: 0 0 10px #6f42c1, 0 0 5px #6f42c1; } .pace-flash-purple .pace .pace-activity { border-top-color: #6f42c1; border-left-color: #6f42c1; } .pace-loading-bar-purple .pace .pace-progress { background: #6f42c1; color: #6f42c1; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-purple .pace .pace-activity { box-shadow: inset 0 0 0 2px #6f42c1, inset 0 0 0 7px #fff; } .pace-mac-osx-purple .pace .pace-progress { background-color: #6f42c1; box-shadow: inset -1px 0 #6f42c1, inset 0 -1px #6f42c1, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-purple .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-purple .pace-progress { color: #6f42c1; } .pace-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace { background: #fff; } .pace-barber-shop-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-pink .pace .pace-progress::after { color: rgba(232, 62, 140, 0.2); } .pace-bounce-pink .pace .pace-activity { background: #e83e8c; } .pace-center-atom-pink .pace-progress { height: 100px; width: 80px; } .pace-center-atom-pink .pace-progress::before { background: #e83e8c; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-pink .pace-activity { border-color: #e83e8c; } .pace-center-atom-pink .pace-activity::after, .pace-center-atom-pink .pace-activity::before { border-color: #e83e8c; } .pace-center-circle-pink .pace .pace-progress { background: rgba(232, 62, 140, 0.8); color: #fff; } .pace-center-radar-pink .pace .pace-activity { border-color: #e83e8c transparent transparent; } .pace-center-radar-pink .pace .pace-activity::before { border-color: #e83e8c transparent transparent; } .pace-center-simple-pink .pace { background: #fff; border-color: #e83e8c; } .pace-center-simple-pink .pace .pace-progress { background: #e83e8c; } .pace-material-pink .pace { color: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity { background: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity::after, .pace-corner-indicator-pink .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-pink .pace .pace-activity::before { border-right-color: rgba(232, 62, 140, 0.2); border-left-color: rgba(232, 62, 140, 0.2); } .pace-corner-indicator-pink .pace .pace-activity::after { border-top-color: rgba(232, 62, 140, 0.2); border-bottom-color: rgba(232, 62, 140, 0.2); } .pace-fill-left-pink .pace .pace-progress { background-color: rgba(232, 62, 140, 0.2); } .pace-flash-pink .pace .pace-progress { background: #e83e8c; } .pace-flash-pink .pace .pace-progress-inner { box-shadow: 0 0 10px #e83e8c, 0 0 5px #e83e8c; } .pace-flash-pink .pace .pace-activity { border-top-color: #e83e8c; border-left-color: #e83e8c; } .pace-loading-bar-pink .pace .pace-progress { background: #e83e8c; color: #e83e8c; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-pink .pace .pace-activity { box-shadow: inset 0 0 0 2px #e83e8c, inset 0 0 0 7px #fff; } .pace-mac-osx-pink .pace .pace-progress { background-color: #e83e8c; box-shadow: inset -1px 0 #e83e8c, inset 0 -1px #e83e8c, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-pink .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-pink .pace-progress { color: #e83e8c; } .pace-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace { background: #fff; } .pace-barber-shop-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-red .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-red .pace .pace-activity { background: #dc3545; } .pace-center-atom-red .pace-progress { height: 100px; width: 80px; } .pace-center-atom-red .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-red .pace-activity { border-color: #dc3545; } .pace-center-atom-red .pace-activity::after, .pace-center-atom-red .pace-activity::before { border-color: #dc3545; } .pace-center-circle-red .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-red .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-red .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-red .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-red .pace .pace-progress { background: #dc3545; } .pace-material-red .pace { color: #dc3545; } .pace-corner-indicator-red .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-red .pace .pace-activity::after, .pace-corner-indicator-red .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-red .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-red .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-red .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-red .pace .pace-progress { background: #dc3545; } .pace-flash-red .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-red .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-red .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-red .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-red .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-red .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-red .pace-progress { color: #dc3545; } .pace-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace { background: #1f2d3d; } .pace-barber-shop-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-orange .pace .pace-progress::after { color: rgba(253, 126, 20, 0.2); } .pace-bounce-orange .pace .pace-activity { background: #fd7e14; } .pace-center-atom-orange .pace-progress { height: 100px; width: 80px; } .pace-center-atom-orange .pace-progress::before { background: #fd7e14; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-orange .pace-activity { border-color: #fd7e14; } .pace-center-atom-orange .pace-activity::after, .pace-center-atom-orange .pace-activity::before { border-color: #fd7e14; } .pace-center-circle-orange .pace .pace-progress { background: rgba(253, 126, 20, 0.8); color: #1f2d3d; } .pace-center-radar-orange .pace .pace-activity { border-color: #fd7e14 transparent transparent; } .pace-center-radar-orange .pace .pace-activity::before { border-color: #fd7e14 transparent transparent; } .pace-center-simple-orange .pace { background: #1f2d3d; border-color: #fd7e14; } .pace-center-simple-orange .pace .pace-progress { background: #fd7e14; } .pace-material-orange .pace { color: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity { background: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity::after, .pace-corner-indicator-orange .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-orange .pace .pace-activity::before { border-right-color: rgba(253, 126, 20, 0.2); border-left-color: rgba(253, 126, 20, 0.2); } .pace-corner-indicator-orange .pace .pace-activity::after { border-top-color: rgba(253, 126, 20, 0.2); border-bottom-color: rgba(253, 126, 20, 0.2); } .pace-fill-left-orange .pace .pace-progress { background-color: rgba(253, 126, 20, 0.2); } .pace-flash-orange .pace .pace-progress { background: #fd7e14; } .pace-flash-orange .pace .pace-progress-inner { box-shadow: 0 0 10px #fd7e14, 0 0 5px #fd7e14; } .pace-flash-orange .pace .pace-activity { border-top-color: #fd7e14; border-left-color: #fd7e14; } .pace-loading-bar-orange .pace .pace-progress { background: #fd7e14; color: #fd7e14; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-orange .pace .pace-activity { box-shadow: inset 0 0 0 2px #fd7e14, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-orange .pace .pace-progress { background-color: #fd7e14; box-shadow: inset -1px 0 #fd7e14, inset 0 -1px #fd7e14, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-orange .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-orange .pace-progress { color: #fd7e14; } .pace-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace { background: #1f2d3d; } .pace-barber-shop-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-yellow .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-yellow .pace .pace-activity { background: #ffc107; } .pace-center-atom-yellow .pace-progress { height: 100px; width: 80px; } .pace-center-atom-yellow .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-yellow .pace-activity { border-color: #ffc107; } .pace-center-atom-yellow .pace-activity::after, .pace-center-atom-yellow .pace-activity::before { border-color: #ffc107; } .pace-center-circle-yellow .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-yellow .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-yellow .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-yellow .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-yellow .pace .pace-progress { background: #ffc107; } .pace-material-yellow .pace { color: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity::after, .pace-corner-indicator-yellow .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-yellow .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-yellow .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-yellow .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-yellow .pace .pace-progress { background: #ffc107; } .pace-flash-yellow .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-yellow .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-yellow .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-yellow .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-yellow .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-yellow .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-yellow .pace-progress { color: #ffc107; } .pace-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace { background: #fff; } .pace-barber-shop-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-green .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-green .pace .pace-activity { background: #28a745; } .pace-center-atom-green .pace-progress { height: 100px; width: 80px; } .pace-center-atom-green .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-green .pace-activity { border-color: #28a745; } .pace-center-atom-green .pace-activity::after, .pace-center-atom-green .pace-activity::before { border-color: #28a745; } .pace-center-circle-green .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-green .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-green .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-green .pace { background: #fff; border-color: #28a745; } .pace-center-simple-green .pace .pace-progress { background: #28a745; } .pace-material-green .pace { color: #28a745; } .pace-corner-indicator-green .pace .pace-activity { background: #28a745; } .pace-corner-indicator-green .pace .pace-activity::after, .pace-corner-indicator-green .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-green .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-green .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-green .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-green .pace .pace-progress { background: #28a745; } .pace-flash-green .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-green .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-green .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-green .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-green .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-green .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-green .pace-progress { color: #28a745; } .pace-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace { background: #fff; } .pace-barber-shop-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-teal .pace .pace-progress::after { color: rgba(32, 201, 151, 0.2); } .pace-bounce-teal .pace .pace-activity { background: #20c997; } .pace-center-atom-teal .pace-progress { height: 100px; width: 80px; } .pace-center-atom-teal .pace-progress::before { background: #20c997; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-teal .pace-activity { border-color: #20c997; } .pace-center-atom-teal .pace-activity::after, .pace-center-atom-teal .pace-activity::before { border-color: #20c997; } .pace-center-circle-teal .pace .pace-progress { background: rgba(32, 201, 151, 0.8); color: #fff; } .pace-center-radar-teal .pace .pace-activity { border-color: #20c997 transparent transparent; } .pace-center-radar-teal .pace .pace-activity::before { border-color: #20c997 transparent transparent; } .pace-center-simple-teal .pace { background: #fff; border-color: #20c997; } .pace-center-simple-teal .pace .pace-progress { background: #20c997; } .pace-material-teal .pace { color: #20c997; } .pace-corner-indicator-teal .pace .pace-activity { background: #20c997; } .pace-corner-indicator-teal .pace .pace-activity::after, .pace-corner-indicator-teal .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-teal .pace .pace-activity::before { border-right-color: rgba(32, 201, 151, 0.2); border-left-color: rgba(32, 201, 151, 0.2); } .pace-corner-indicator-teal .pace .pace-activity::after { border-top-color: rgba(32, 201, 151, 0.2); border-bottom-color: rgba(32, 201, 151, 0.2); } .pace-fill-left-teal .pace .pace-progress { background-color: rgba(32, 201, 151, 0.2); } .pace-flash-teal .pace .pace-progress { background: #20c997; } .pace-flash-teal .pace .pace-progress-inner { box-shadow: 0 0 10px #20c997, 0 0 5px #20c997; } .pace-flash-teal .pace .pace-activity { border-top-color: #20c997; border-left-color: #20c997; } .pace-loading-bar-teal .pace .pace-progress { background: #20c997; color: #20c997; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-teal .pace .pace-activity { box-shadow: inset 0 0 0 2px #20c997, inset 0 0 0 7px #fff; } .pace-mac-osx-teal .pace .pace-progress { background-color: #20c997; box-shadow: inset -1px 0 #20c997, inset 0 -1px #20c997, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-teal .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-teal .pace-progress { color: #20c997; } .pace-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace { background: #fff; } .pace-barber-shop-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-cyan .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-cyan .pace .pace-activity { background: #17a2b8; } .pace-center-atom-cyan .pace-progress { height: 100px; width: 80px; } .pace-center-atom-cyan .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-cyan .pace-activity { border-color: #17a2b8; } .pace-center-atom-cyan .pace-activity::after, .pace-center-atom-cyan .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-cyan .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-cyan .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-cyan .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-cyan .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-cyan .pace .pace-progress { background: #17a2b8; } .pace-material-cyan .pace { color: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity::after, .pace-corner-indicator-cyan .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-cyan .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-cyan .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-cyan .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-cyan .pace .pace-progress { background: #17a2b8; } .pace-flash-cyan .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-cyan .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-cyan .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-cyan .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-cyan .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-cyan .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-cyan .pace-progress { color: #17a2b8; } .pace-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace { background: #1f2d3d; } .pace-barber-shop-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-white .pace .pace-progress::after { color: rgba(255, 255, 255, 0.2); } .pace-bounce-white .pace .pace-activity { background: #fff; } .pace-center-atom-white .pace-progress { height: 100px; width: 80px; } .pace-center-atom-white .pace-progress::before { background: #fff; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-white .pace-activity { border-color: #fff; } .pace-center-atom-white .pace-activity::after, .pace-center-atom-white .pace-activity::before { border-color: #fff; } .pace-center-circle-white .pace .pace-progress { background: rgba(255, 255, 255, 0.8); color: #1f2d3d; } .pace-center-radar-white .pace .pace-activity { border-color: #fff transparent transparent; } .pace-center-radar-white .pace .pace-activity::before { border-color: #fff transparent transparent; } .pace-center-simple-white .pace { background: #1f2d3d; border-color: #fff; } .pace-center-simple-white .pace .pace-progress { background: #fff; } .pace-material-white .pace { color: #fff; } .pace-corner-indicator-white .pace .pace-activity { background: #fff; } .pace-corner-indicator-white .pace .pace-activity::after, .pace-corner-indicator-white .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-white .pace .pace-activity::before { border-right-color: rgba(255, 255, 255, 0.2); border-left-color: rgba(255, 255, 255, 0.2); } .pace-corner-indicator-white .pace .pace-activity::after { border-top-color: rgba(255, 255, 255, 0.2); border-bottom-color: rgba(255, 255, 255, 0.2); } .pace-fill-left-white .pace .pace-progress { background-color: rgba(255, 255, 255, 0.2); } .pace-flash-white .pace .pace-progress { background: #fff; } .pace-flash-white .pace .pace-progress-inner { box-shadow: 0 0 10px #fff, 0 0 5px #fff; } .pace-flash-white .pace .pace-activity { border-top-color: #fff; border-left-color: #fff; } .pace-loading-bar-white .pace .pace-progress { background: #fff; color: #fff; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-white .pace .pace-activity { box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-white .pace .pace-progress { background-color: #fff; box-shadow: inset -1px 0 #fff, inset 0 -1px #fff, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-white .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-white .pace-progress { color: #fff; } .pace-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace { background: #fff; } .pace-barber-shop-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-gray .pace .pace-activity { background: #6c757d; } .pace-center-atom-gray .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray .pace-activity { border-color: #6c757d; } .pace-center-atom-gray .pace-activity::after, .pace-center-atom-gray .pace-activity::before { border-color: #6c757d; } .pace-center-circle-gray .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-gray .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-gray .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-gray .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-gray .pace .pace-progress { background: #6c757d; } .pace-material-gray .pace { color: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity::after, .pace-corner-indicator-gray .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-gray .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-gray .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-gray .pace .pace-progress { background: #6c757d; } .pace-flash-gray .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-gray .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-gray .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-gray .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray .pace-progress { color: #6c757d; } .pace-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace { background: #fff; } .pace-barber-shop-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-gray-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-gray-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray-dark .pace-activity { border-color: #343a40; } .pace-center-atom-gray-dark .pace-activity::after, .pace-center-atom-gray-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-gray-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-gray-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-gray-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-gray-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-gray-dark .pace .pace-progress { background: #343a40; } .pace-material-gray-dark .pace { color: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity::after, .pace-corner-indicator-gray-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-gray-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-gray-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-gray-dark .pace .pace-progress { background: #343a40; } .pace-flash-gray-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-gray-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-gray-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-gray-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray-dark .pace-progress { color: #343a40; } /** * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. * * @version v3.4 (MODDED) * @homepage https://bttstrp.github.io/bootstrap-switch * @author Mattia Larentis (http://larentis.eu) * @license MIT */ .bootstrap-switch { border: 1px solid #ced4da; border-radius: 0.25rem; cursor: pointer; direction: ltr; display: inline-block; line-height: .5rem; overflow: hidden; position: relative; text-align: left; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; vertical-align: middle; z-index: 0; } .bootstrap-switch .bootstrap-switch-container { border-radius: 0.25rem; display: inline-block; top: 0; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .bootstrap-switch:focus-within { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off, .bootstrap-switch .bootstrap-switch-label { box-sizing: border-box; cursor: pointer; display: table-cell; font-size: 1rem; font-weight: 500; line-height: 1.2rem; padding: .25rem .5rem; vertical-align: middle; } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off { text-align: center; z-index: 1; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default { background: #e9ecef; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-secondary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-secondary { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-light, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-light { background: #f8f9fa; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lightblue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lightblue { background: #3c8dbc; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-navy, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-navy { background: #001f3f; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-olive, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-olive { background: #3d9970; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lime, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lime { background: #01ff70; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-fuchsia, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-fuchsia { background: #f012be; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-maroon, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-maroon { background: #d81b60; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-indigo, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-indigo { background: #6610f2; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-purple, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-purple { background: #6f42c1; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-pink, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-pink { background: #e83e8c; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange { background: #fd7e14; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-yellow, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-yellow { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-teal, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-teal { background: #20c997; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-cyan, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-cyan { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-white, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-white { background: #fff; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .bootstrap-switch .bootstrap-switch-handle-off { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch input[type='radio'], .bootstrap-switch input[type='checkbox'] { filter: alpha(opacity=0); left: 0; margin: 0; opacity: 0; position: absolute; top: 0; visibility: hidden; z-index: -1; } .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .1rem .3rem; } .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .2rem .4rem; } .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label { font-size: 1.25rem; line-height: 1.3333333rem; padding: .3rem .5rem; } .bootstrap-switch.bootstrap-switch-disabled, .bootstrap-switch.bootstrap-switch-readonly, .bootstrap-switch.bootstrap-switch-indeterminate { cursor: default; } .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label { cursor: default; filter: alpha(opacity=50); opacity: .5; } .bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container { transition: margin-left .5s; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on { border-radius: 0 0.1rem 0.1rem 0; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off { border-radius: 0.1rem 0 0 0.1rem; } .bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .jqstooltip { height: auto !important; padding: 5px !important; width: auto !important; } .connectedSortable { min-height: 100px; } .ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .sort-highlight { background: #f8f9fa; border: 1px dashed #dee2e6; margin-bottom: 10px; } .chart { overflow: hidden; position: relative; } .border-transparent { border-color: transparent !important; } .description-block { display: block; margin: 10px 0; text-align: center; } .description-block.margin-bottom { margin-bottom: 25px; } .description-block > .description-header { font-size: 16px; font-weight: 600; margin: 0; padding: 0; } .description-block > .description-text { text-transform: uppercase; } .description-block .description-icon { font-size: 16px; } .list-group-unbordered > .list-group-item { border-left: 0; border-radius: 0; border-right: 0; padding-left: 0; padding-right: 0; } .list-header { color: #6c757d; font-size: 15px; font-weight: 700; padding: 10px 4px; } .list-seperator { background-color: rgba(0, 0, 0, 0.125); height: 1px; margin: 15px 0 9px; } .list-link > a { color: #6c757d; padding: 4px; } .list-link > a:hover { color: #212529; } .user-block { float: left; } .user-block img { float: left; height: 40px; width: 40px; } .user-block .username, .user-block .description, .user-block .comment { display: block; margin-left: 50px; } .user-block .username { font-size: 16px; font-weight: 600; margin-top: -1px; } .user-block .description { color: #6c757d; font-size: 13px; margin-top: -3px; } .user-block.user-block-sm img { width: 1.875rem; height: 1.875rem; } .user-block.user-block-sm .username, .user-block.user-block-sm .description, .user-block.user-block-sm .comment { margin-left: 40px; } .user-block.user-block-sm .username { font-size: 14px; } .img-sm, .img-md, .img-lg { float: left; } .img-sm { height: 1.875rem; width: 1.875rem; } .img-sm + .img-push { margin-left: 2.5rem; } .img-md { width: 3.75rem; height: 3.75rem; } .img-md + .img-push { margin-left: 4.375rem; } .img-lg { width: 6.25rem; height: 6.25rem; } .img-lg + .img-push { margin-left: 6.875rem; } .img-bordered { border: 3px solid #adb5bd; padding: 3px; } .img-bordered-sm { border: 2px solid #adb5bd; padding: 2px; } .img-rounded { border-radius: 0.25rem; } .img-circle { border-radius: 50%; } .img-size-64, .img-size-50, .img-size-32 { height: auto; } .img-size-64 { width: 64px; } .img-size-50 { width: 50px; } .img-size-32 { width: 32px; } .size-32, .size-40, .size-50 { display: block; text-align: center; } .size-32 { height: 32px; line-height: 32px; width: 32px; } .size-40 { height: 40px; line-height: 40px; width: 40px; } .size-50 { height: 50px; line-height: 50px; width: 50px; } .attachment-block { background-color: #f8f9fa; border: 1px solid rgba(0, 0, 0, 0.125); margin-bottom: 10px; padding: 5px; } .attachment-block .attachment-img { float: left; height: auto; max-height: 100px; max-width: 100px; } .attachment-block .attachment-pushed { margin-left: 110px; } .attachment-block .attachment-heading { margin: 0; } .attachment-block .attachment-text { color: #495057; } .card > .overlay, .card > .loading-img, .overlay-wrapper > .overlay, .overlay-wrapper > .loading-img, .info-box > .overlay, .info-box > .loading-img, .small-box > .overlay, .small-box > .loading-img { height: 100%; left: 0; position: absolute; top: 0; width: 100%; } .card .overlay, .overlay-wrapper .overlay, .info-box .overlay, .small-box .overlay { border-radius: 0.25rem; -ms-flex-align: center; align-items: center; background-color: rgba(255, 255, 255, 0.7); display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; z-index: 50; } .card .overlay > .fa, .card .overlay > .fas, .card .overlay > .far, .card .overlay > .fab, .card .overlay > .fal, .card .overlay > .fad, .card .overlay > .svg-inline--fa, .card .overlay > .ion, .overlay-wrapper .overlay > .fa, .overlay-wrapper .overlay > .fas, .overlay-wrapper .overlay > .far, .overlay-wrapper .overlay > .fab, .overlay-wrapper .overlay > .fal, .overlay-wrapper .overlay > .fad, .overlay-wrapper .overlay > .svg-inline--fa, .overlay-wrapper .overlay > .ion, .info-box .overlay > .fa, .info-box .overlay > .fas, .info-box .overlay > .far, .info-box .overlay > .fab, .info-box .overlay > .fal, .info-box .overlay > .fad, .info-box .overlay > .svg-inline--fa, .info-box .overlay > .ion, .small-box .overlay > .fa, .small-box .overlay > .fas, .small-box .overlay > .far, .small-box .overlay > .fab, .small-box .overlay > .fal, .small-box .overlay > .fad, .small-box .overlay > .svg-inline--fa, .small-box .overlay > .ion { color: #343a40; } .card .overlay.dark, .overlay-wrapper .overlay.dark, .info-box .overlay.dark, .small-box .overlay.dark { background-color: rgba(0, 0, 0, 0.5); } .card .overlay.dark > .fa, .card .overlay.dark > .fas, .card .overlay.dark > .far, .card .overlay.dark > .fab, .card .overlay.dark > .fal, .card .overlay.dark > .fad, .card .overlay.dark > .svg-inline--fa, .card .overlay.dark > .ion, .overlay-wrapper .overlay.dark > .fa, .overlay-wrapper .overlay.dark > .fas, .overlay-wrapper .overlay.dark > .far, .overlay-wrapper .overlay.dark > .fab, .overlay-wrapper .overlay.dark > .fal, .overlay-wrapper .overlay.dark > .fad, .overlay-wrapper .overlay.dark > .svg-inline--fa, .overlay-wrapper .overlay.dark > .ion, .info-box .overlay.dark > .fa, .info-box .overlay.dark > .fas, .info-box .overlay.dark > .far, .info-box .overlay.dark > .fab, .info-box .overlay.dark > .fal, .info-box .overlay.dark > .fad, .info-box .overlay.dark > .svg-inline--fa, .info-box .overlay.dark > .ion, .small-box .overlay.dark > .fa, .small-box .overlay.dark > .fas, .small-box .overlay.dark > .far, .small-box .overlay.dark > .fab, .small-box .overlay.dark > .fal, .small-box .overlay.dark > .fad, .small-box .overlay.dark > .svg-inline--fa, .small-box .overlay.dark > .ion { color: #ced4da; } .tab-pane > .overlay-wrapper { position: relative; } .tab-pane > .overlay-wrapper > .overlay { border-top-left-radius: 0; border-top-right-radius: 0; -ms-flex-direction: column; flex-direction: column; margin-top: -1.25rem; margin-left: -1.25rem; height: calc(100% + 2 * 1.25rem); width: calc(100% + 2 * 1.25rem); } .tab-pane > .overlay-wrapper > .overlay.dark { color: #fff; } .ribbon-wrapper { height: 70px; overflow: hidden; position: absolute; right: -2px; top: -2px; width: 70px; z-index: 10; } .ribbon-wrapper.ribbon-lg { height: 120px; width: 120px; } .ribbon-wrapper.ribbon-lg .ribbon { right: 0; top: 26px; width: 160px; } .ribbon-wrapper.ribbon-xl { height: 180px; width: 180px; } .ribbon-wrapper.ribbon-xl .ribbon { right: 4px; top: 47px; width: 240px; } .ribbon-wrapper .ribbon { box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); font-size: 0.8rem; line-height: 100%; padding: 0.375rem 0; position: relative; right: -2px; text-align: center; text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4); text-transform: uppercase; top: 10px; -webkit-transform: rotate(45deg); transform: rotate(45deg); width: 90px; } .ribbon-wrapper .ribbon::before, .ribbon-wrapper .ribbon::after { border-left: 3px solid transparent; border-right: 3px solid transparent; border-top: 3px solid #9e9e9e; bottom: -3px; content: ""; position: absolute; } .ribbon-wrapper .ribbon::before { left: 0; } .ribbon-wrapper .ribbon::after { right: 0; } .back-to-top { bottom: 1.25rem; position: fixed; right: 1.25rem; z-index: 1032; } .back-to-top:focus { box-shadow: none; } pre { padding: .75rem; } blockquote { background-color: #fff; border-left: 0.7rem solid #007bff; margin: 1.5em .7rem; padding: .5em .7rem; } .box blockquote { background-color: #e9ecef; } blockquote p:last-child { margin-bottom: 0; } blockquote h1, blockquote h2, blockquote h3, blockquote h4, blockquote h5, blockquote h6 { color: #007bff; font-size: 1.25rem; font-weight: 600; } blockquote.quote-primary { border-color: #007bff; } blockquote.quote-primary h1, blockquote.quote-primary h2, blockquote.quote-primary h3, blockquote.quote-primary h4, blockquote.quote-primary h5, blockquote.quote-primary h6 { color: #007bff; } blockquote.quote-secondary { border-color: #6c757d; } blockquote.quote-secondary h1, blockquote.quote-secondary h2, blockquote.quote-secondary h3, blockquote.quote-secondary h4, blockquote.quote-secondary h5, blockquote.quote-secondary h6 { color: #6c757d; } blockquote.quote-success { border-color: #28a745; } blockquote.quote-success h1, blockquote.quote-success h2, blockquote.quote-success h3, blockquote.quote-success h4, blockquote.quote-success h5, blockquote.quote-success h6 { color: #28a745; } blockquote.quote-info { border-color: #17a2b8; } blockquote.quote-info h1, blockquote.quote-info h2, blockquote.quote-info h3, blockquote.quote-info h4, blockquote.quote-info h5, blockquote.quote-info h6 { color: #17a2b8; } blockquote.quote-warning { border-color: #ffc107; } blockquote.quote-warning h1, blockquote.quote-warning h2, blockquote.quote-warning h3, blockquote.quote-warning h4, blockquote.quote-warning h5, blockquote.quote-warning h6 { color: #ffc107; } blockquote.quote-danger { border-color: #dc3545; } blockquote.quote-danger h1, blockquote.quote-danger h2, blockquote.quote-danger h3, blockquote.quote-danger h4, blockquote.quote-danger h5, blockquote.quote-danger h6 { color: #dc3545; } blockquote.quote-light { border-color: #f8f9fa; } blockquote.quote-light h1, blockquote.quote-light h2, blockquote.quote-light h3, blockquote.quote-light h4, blockquote.quote-light h5, blockquote.quote-light h6 { color: #f8f9fa; } blockquote.quote-dark { border-color: #343a40; } blockquote.quote-dark h1, blockquote.quote-dark h2, blockquote.quote-dark h3, blockquote.quote-dark h4, blockquote.quote-dark h5, blockquote.quote-dark h6 { color: #343a40; } blockquote.quote-lightblue { border-color: #3c8dbc; } blockquote.quote-lightblue h1, blockquote.quote-lightblue h2, blockquote.quote-lightblue h3, blockquote.quote-lightblue h4, blockquote.quote-lightblue h5, blockquote.quote-lightblue h6 { color: #3c8dbc; } blockquote.quote-navy { border-color: #001f3f; } blockquote.quote-navy h1, blockquote.quote-navy h2, blockquote.quote-navy h3, blockquote.quote-navy h4, blockquote.quote-navy h5, blockquote.quote-navy h6 { color: #001f3f; } blockquote.quote-olive { border-color: #3d9970; } blockquote.quote-olive h1, blockquote.quote-olive h2, blockquote.quote-olive h3, blockquote.quote-olive h4, blockquote.quote-olive h5, blockquote.quote-olive h6 { color: #3d9970; } blockquote.quote-lime { border-color: #01ff70; } blockquote.quote-lime h1, blockquote.quote-lime h2, blockquote.quote-lime h3, blockquote.quote-lime h4, blockquote.quote-lime h5, blockquote.quote-lime h6 { color: #01ff70; } blockquote.quote-fuchsia { border-color: #f012be; } blockquote.quote-fuchsia h1, blockquote.quote-fuchsia h2, blockquote.quote-fuchsia h3, blockquote.quote-fuchsia h4, blockquote.quote-fuchsia h5, blockquote.quote-fuchsia h6 { color: #f012be; } blockquote.quote-maroon { border-color: #d81b60; } blockquote.quote-maroon h1, blockquote.quote-maroon h2, blockquote.quote-maroon h3, blockquote.quote-maroon h4, blockquote.quote-maroon h5, blockquote.quote-maroon h6 { color: #d81b60; } blockquote.quote-blue { border-color: #007bff; } blockquote.quote-blue h1, blockquote.quote-blue h2, blockquote.quote-blue h3, blockquote.quote-blue h4, blockquote.quote-blue h5, blockquote.quote-blue h6 { color: #007bff; } blockquote.quote-indigo { border-color: #6610f2; } blockquote.quote-indigo h1, blockquote.quote-indigo h2, blockquote.quote-indigo h3, blockquote.quote-indigo h4, blockquote.quote-indigo h5, blockquote.quote-indigo h6 { color: #6610f2; } blockquote.quote-purple { border-color: #6f42c1; } blockquote.quote-purple h1, blockquote.quote-purple h2, blockquote.quote-purple h3, blockquote.quote-purple h4, blockquote.quote-purple h5, blockquote.quote-purple h6 { color: #6f42c1; } blockquote.quote-pink { border-color: #e83e8c; } blockquote.quote-pink h1, blockquote.quote-pink h2, blockquote.quote-pink h3, blockquote.quote-pink h4, blockquote.quote-pink h5, blockquote.quote-pink h6 { color: #e83e8c; } blockquote.quote-red { border-color: #dc3545; } blockquote.quote-red h1, blockquote.quote-red h2, blockquote.quote-red h3, blockquote.quote-red h4, blockquote.quote-red h5, blockquote.quote-red h6 { color: #dc3545; } blockquote.quote-orange { border-color: #fd7e14; } blockquote.quote-orange h1, blockquote.quote-orange h2, blockquote.quote-orange h3, blockquote.quote-orange h4, blockquote.quote-orange h5, blockquote.quote-orange h6 { color: #fd7e14; } blockquote.quote-yellow { border-color: #ffc107; } blockquote.quote-yellow h1, blockquote.quote-yellow h2, blockquote.quote-yellow h3, blockquote.quote-yellow h4, blockquote.quote-yellow h5, blockquote.quote-yellow h6 { color: #ffc107; } blockquote.quote-green { border-color: #28a745; } blockquote.quote-green h1, blockquote.quote-green h2, blockquote.quote-green h3, blockquote.quote-green h4, blockquote.quote-green h5, blockquote.quote-green h6 { color: #28a745; } blockquote.quote-teal { border-color: #20c997; } blockquote.quote-teal h1, blockquote.quote-teal h2, blockquote.quote-teal h3, blockquote.quote-teal h4, blockquote.quote-teal h5, blockquote.quote-teal h6 { color: #20c997; } blockquote.quote-cyan { border-color: #17a2b8; } blockquote.quote-cyan h1, blockquote.quote-cyan h2, blockquote.quote-cyan h3, blockquote.quote-cyan h4, blockquote.quote-cyan h5, blockquote.quote-cyan h6 { color: #17a2b8; } blockquote.quote-white { border-color: #fff; } blockquote.quote-white h1, blockquote.quote-white h2, blockquote.quote-white h3, blockquote.quote-white h4, blockquote.quote-white h5, blockquote.quote-white h6 { color: #fff; } blockquote.quote-gray { border-color: #6c757d; } blockquote.quote-gray h1, blockquote.quote-gray h2, blockquote.quote-gray h3, blockquote.quote-gray h4, blockquote.quote-gray h5, blockquote.quote-gray h6 { color: #6c757d; } blockquote.quote-gray-dark { border-color: #343a40; } blockquote.quote-gray-dark h1, blockquote.quote-gray-dark h2, blockquote.quote-gray-dark h3, blockquote.quote-gray-dark h4, blockquote.quote-gray-dark h5, blockquote.quote-gray-dark h6 { color: #343a40; } .tab-custom-content { border-top: 1px solid #dee2e6; margin-top: .5rem; padding-top: .5rem; } .nav + .tab-custom-content { border-top: none; border-bottom: 1px solid #dee2e6; margin-top: 0; margin-bottom: .5rem; padding-bottom: .5rem; } .badge-btn { border-radius: 0.15rem; font-size: 0.75rem; font-weight: 400; padding: 0.25rem 0.5rem; } .badge-btn.badge-pill { padding: .375rem .6rem; } @media print { .no-print, .main-sidebar, .main-header, .content-header { display: none !important; } .content-wrapper, .main-footer { -webkit-transform: translate(0, 0); transform: translate(0, 0); margin-left: 0 !important; min-height: 0 !important; } .layout-fixed .content-wrapper { padding-top: 0 !important; } .invoice { border: 0; margin: 0; padding: 0; width: 100%; } .invoice-col { float: left; width: 33.3333333%; } .table-responsive { overflow: auto; } .table-responsive > .table tr th, .table-responsive > .table tr td { white-space: normal !important; } } .text-bold, .text-bold.table td, .text-bold.table th { font-weight: 700; } .text-xs { font-size: 0.75rem !important; } .text-sm { font-size: 0.875rem !important; } .text-md { font-size: 1rem !important; } .text-lg { font-size: 1.25rem !important; } .text-xl { font-size: 2rem !important; } .text-lightblue { color: #3c8dbc !important; } .text-navy { color: #001f3f !important; } .text-olive { color: #3d9970 !important; } .text-lime { color: #01ff70 !important; } .text-fuchsia { color: #f012be !important; } .text-maroon { color: #d81b60 !important; } .text-blue { color: #007bff !important; } .text-indigo { color: #6610f2 !important; } .text-purple { color: #6f42c1 !important; } .text-pink { color: #e83e8c !important; } .text-red { color: #dc3545 !important; } .text-orange { color: #fd7e14 !important; } .text-yellow { color: #ffc107 !important; } .text-green { color: #28a745 !important; } .text-teal { color: #20c997 !important; } .text-cyan { color: #17a2b8 !important; } .text-white { color: #fff !important; } .text-gray { color: #6c757d !important; } .text-gray-dark { color: #343a40 !important; } .elevation-0 { box-shadow: none !important; } .elevation-1 { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important; } .elevation-2 { box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-3 { box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23) !important; } .elevation-4 { box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22) !important; } .elevation-5 { box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22) !important; } .bg-primary { background-color: #007bff !important; } .bg-primary, .bg-primary > a { color: #fff !important; } .bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .bg-primary.btn:not(:disabled):not(.disabled):active, .bg-primary.btn:not(:disabled):not(.disabled).active, .bg-primary.btn:active, .bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-secondary { background-color: #6c757d !important; } .bg-secondary, .bg-secondary > a { color: #fff !important; } .bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .bg-secondary.btn:not(:disabled):not(.disabled):active, .bg-secondary.btn:not(:disabled):not(.disabled).active, .bg-secondary.btn:active, .bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-success { background-color: #28a745 !important; } .bg-success, .bg-success > a { color: #fff !important; } .bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-success.btn:not(:disabled):not(.disabled):active, .bg-success.btn:not(:disabled):not(.disabled).active, .bg-success.btn:active, .bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-info { background-color: #17a2b8 !important; } .bg-info, .bg-info > a { color: #fff !important; } .bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .bg-info.btn:not(:disabled):not(.disabled):active, .bg-info.btn:not(:disabled):not(.disabled).active, .bg-info.btn:active, .bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-warning { background-color: #ffc107 !important; } .bg-warning, .bg-warning > a { color: #1f2d3d !important; } .bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .bg-warning.btn:not(:disabled):not(.disabled):active, .bg-warning.btn:not(:disabled):not(.disabled).active, .bg-warning.btn:active, .bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-danger { background-color: #dc3545 !important; } .bg-danger, .bg-danger > a { color: #fff !important; } .bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .bg-danger.btn:not(:disabled):not(.disabled):active, .bg-danger.btn:not(:disabled):not(.disabled).active, .bg-danger.btn:active, .bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-light { background-color: #f8f9fa !important; } .bg-light, .bg-light > a { color: #1f2d3d !important; } .bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .bg-light.btn:not(:disabled):not(.disabled):active, .bg-light.btn:not(:disabled):not(.disabled).active, .bg-light.btn:active, .bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .bg-dark { background-color: #343a40 !important; } .bg-dark, .bg-dark > a { color: #fff !important; } .bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-dark.btn:not(:disabled):not(.disabled):active, .bg-dark.btn:not(:disabled):not(.disabled).active, .bg-dark.btn:active, .bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .bg-lightblue { background-color: #3c8dbc !important; } .bg-lightblue, .bg-lightblue > a { color: #fff !important; } .bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .bg-lightblue.btn:not(:disabled):not(.disabled):active, .bg-lightblue.btn:not(:disabled):not(.disabled).active, .bg-lightblue.btn:active, .bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .bg-navy { background-color: #001f3f !important; } .bg-navy, .bg-navy > a { color: #fff !important; } .bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .bg-navy.btn:not(:disabled):not(.disabled):active, .bg-navy.btn:not(:disabled):not(.disabled).active, .bg-navy.btn:active, .bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .bg-olive { background-color: #3d9970 !important; } .bg-olive, .bg-olive > a { color: #fff !important; } .bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .bg-olive.btn:not(:disabled):not(.disabled):active, .bg-olive.btn:not(:disabled):not(.disabled).active, .bg-olive.btn:active, .bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .bg-lime { background-color: #01ff70 !important; } .bg-lime, .bg-lime > a { color: #1f2d3d !important; } .bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .bg-lime.btn:not(:disabled):not(.disabled):active, .bg-lime.btn:not(:disabled):not(.disabled).active, .bg-lime.btn:active, .bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .bg-fuchsia { background-color: #f012be !important; } .bg-fuchsia, .bg-fuchsia > a { color: #fff !important; } .bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .bg-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-fuchsia.btn:active, .bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .bg-maroon { background-color: #d81b60 !important; } .bg-maroon, .bg-maroon > a { color: #fff !important; } .bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .bg-maroon.btn:not(:disabled):not(.disabled):active, .bg-maroon.btn:not(:disabled):not(.disabled).active, .bg-maroon.btn:active, .bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .bg-blue { background-color: #007bff !important; } .bg-blue, .bg-blue > a { color: #fff !important; } .bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .bg-blue.btn:not(:disabled):not(.disabled):active, .bg-blue.btn:not(:disabled):not(.disabled).active, .bg-blue.btn:active, .bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .bg-indigo { background-color: #6610f2 !important; } .bg-indigo, .bg-indigo > a { color: #fff !important; } .bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .bg-indigo.btn:not(:disabled):not(.disabled):active, .bg-indigo.btn:not(:disabled):not(.disabled).active, .bg-indigo.btn:active, .bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .bg-purple { background-color: #6f42c1 !important; } .bg-purple, .bg-purple > a { color: #fff !important; } .bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .bg-purple.btn:not(:disabled):not(.disabled):active, .bg-purple.btn:not(:disabled):not(.disabled).active, .bg-purple.btn:active, .bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .bg-pink { background-color: #e83e8c !important; } .bg-pink, .bg-pink > a { color: #fff !important; } .bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .bg-pink.btn:not(:disabled):not(.disabled):active, .bg-pink.btn:not(:disabled):not(.disabled).active, .bg-pink.btn:active, .bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .bg-red { background-color: #dc3545 !important; } .bg-red, .bg-red > a { color: #fff !important; } .bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .bg-red.btn:not(:disabled):not(.disabled):active, .bg-red.btn:not(:disabled):not(.disabled).active, .bg-red.btn:active, .bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .bg-orange { background-color: #fd7e14 !important; } .bg-orange, .bg-orange > a { color: #1f2d3d !important; } .bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .bg-orange.btn:not(:disabled):not(.disabled):active, .bg-orange.btn:not(:disabled):not(.disabled).active, .bg-orange.btn:active, .bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .bg-yellow { background-color: #ffc107 !important; } .bg-yellow, .bg-yellow > a { color: #1f2d3d !important; } .bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .bg-yellow.btn:not(:disabled):not(.disabled):active, .bg-yellow.btn:not(:disabled):not(.disabled).active, .bg-yellow.btn:active, .bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .bg-green { background-color: #28a745 !important; } .bg-green, .bg-green > a { color: #fff !important; } .bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .bg-green.btn:not(:disabled):not(.disabled):active, .bg-green.btn:not(:disabled):not(.disabled).active, .bg-green.btn:active, .bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .bg-teal { background-color: #20c997 !important; } .bg-teal, .bg-teal > a { color: #fff !important; } .bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .bg-teal.btn:not(:disabled):not(.disabled):active, .bg-teal.btn:not(:disabled):not(.disabled).active, .bg-teal.btn:active, .bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .bg-cyan { background-color: #17a2b8 !important; } .bg-cyan, .bg-cyan > a { color: #fff !important; } .bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .bg-cyan.btn:not(:disabled):not(.disabled):active, .bg-cyan.btn:not(:disabled):not(.disabled).active, .bg-cyan.btn:active, .bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .bg-white { background-color: #fff !important; } .bg-white, .bg-white > a { color: #1f2d3d !important; } .bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .bg-white.btn:not(:disabled):not(.disabled):active, .bg-white.btn:not(:disabled):not(.disabled).active, .bg-white.btn:active, .bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gray { background-color: #6c757d !important; } .bg-gray, .bg-gray > a { color: #fff !important; } .bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .bg-gray.btn:not(:disabled):not(.disabled):active, .bg-gray.btn:not(:disabled):not(.disabled).active, .bg-gray.btn:active, .bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .bg-gray-dark { background-color: #343a40 !important; } .bg-gray-dark, .bg-gray-dark > a { color: #fff !important; } .bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .bg-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gray-dark.btn:active, .bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } @media print { .table td.bg-primary, .table th.bg-primary { background-color: #007bff !important; } .table td.bg-primary, .table td.bg-primary > a, .table th.bg-primary, .table th.bg-primary > a { color: #fff !important; } .table td.bg-primary.btn:hover, .table th.bg-primary.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-primary.btn:not(:disabled):not(.disabled):active, .table td.bg-primary.btn:not(:disabled):not(.disabled).active, .table td.bg-primary.btn:active, .table td.bg-primary.btn.active, .table th.bg-primary.btn:not(:disabled):not(.disabled):active, .table th.bg-primary.btn:not(:disabled):not(.disabled).active, .table th.bg-primary.btn:active, .table th.bg-primary.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-secondary, .table th.bg-secondary { background-color: #6c757d !important; } .table td.bg-secondary, .table td.bg-secondary > a, .table th.bg-secondary, .table th.bg-secondary > a { color: #fff !important; } .table td.bg-secondary.btn:hover, .table th.bg-secondary.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-secondary.btn:not(:disabled):not(.disabled):active, .table td.bg-secondary.btn:not(:disabled):not(.disabled).active, .table td.bg-secondary.btn:active, .table td.bg-secondary.btn.active, .table th.bg-secondary.btn:not(:disabled):not(.disabled):active, .table th.bg-secondary.btn:not(:disabled):not(.disabled).active, .table th.bg-secondary.btn:active, .table th.bg-secondary.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-success, .table th.bg-success { background-color: #28a745 !important; } .table td.bg-success, .table td.bg-success > a, .table th.bg-success, .table th.bg-success > a { color: #fff !important; } .table td.bg-success.btn:hover, .table th.bg-success.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-success.btn:not(:disabled):not(.disabled):active, .table td.bg-success.btn:not(:disabled):not(.disabled).active, .table td.bg-success.btn:active, .table td.bg-success.btn.active, .table th.bg-success.btn:not(:disabled):not(.disabled):active, .table th.bg-success.btn:not(:disabled):not(.disabled).active, .table th.bg-success.btn:active, .table th.bg-success.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-info, .table th.bg-info { background-color: #17a2b8 !important; } .table td.bg-info, .table td.bg-info > a, .table th.bg-info, .table th.bg-info > a { color: #fff !important; } .table td.bg-info.btn:hover, .table th.bg-info.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-info.btn:not(:disabled):not(.disabled):active, .table td.bg-info.btn:not(:disabled):not(.disabled).active, .table td.bg-info.btn:active, .table td.bg-info.btn.active, .table th.bg-info.btn:not(:disabled):not(.disabled):active, .table th.bg-info.btn:not(:disabled):not(.disabled).active, .table th.bg-info.btn:active, .table th.bg-info.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-warning, .table th.bg-warning { background-color: #ffc107 !important; } .table td.bg-warning, .table td.bg-warning > a, .table th.bg-warning, .table th.bg-warning > a { color: #1f2d3d !important; } .table td.bg-warning.btn:hover, .table th.bg-warning.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-warning.btn:not(:disabled):not(.disabled):active, .table td.bg-warning.btn:not(:disabled):not(.disabled).active, .table td.bg-warning.btn:active, .table td.bg-warning.btn.active, .table th.bg-warning.btn:not(:disabled):not(.disabled):active, .table th.bg-warning.btn:not(:disabled):not(.disabled).active, .table th.bg-warning.btn:active, .table th.bg-warning.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-danger, .table th.bg-danger { background-color: #dc3545 !important; } .table td.bg-danger, .table td.bg-danger > a, .table th.bg-danger, .table th.bg-danger > a { color: #fff !important; } .table td.bg-danger.btn:hover, .table th.bg-danger.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-danger.btn:not(:disabled):not(.disabled):active, .table td.bg-danger.btn:not(:disabled):not(.disabled).active, .table td.bg-danger.btn:active, .table td.bg-danger.btn.active, .table th.bg-danger.btn:not(:disabled):not(.disabled):active, .table th.bg-danger.btn:not(:disabled):not(.disabled).active, .table th.bg-danger.btn:active, .table th.bg-danger.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-light, .table th.bg-light { background-color: #f8f9fa !important; } .table td.bg-light, .table td.bg-light > a, .table th.bg-light, .table th.bg-light > a { color: #1f2d3d !important; } .table td.bg-light.btn:hover, .table th.bg-light.btn:hover { border-color: #dae0e5; color: #121a24; } .table td.bg-light.btn:not(:disabled):not(.disabled):active, .table td.bg-light.btn:not(:disabled):not(.disabled).active, .table td.bg-light.btn:active, .table td.bg-light.btn.active, .table th.bg-light.btn:not(:disabled):not(.disabled):active, .table th.bg-light.btn:not(:disabled):not(.disabled).active, .table th.bg-light.btn:active, .table th.bg-light.btn.active { background-color: #dae0e5 !important; border-color: #d3d9df; color: #1f2d3d; } .table td.bg-dark, .table th.bg-dark { background-color: #343a40 !important; } .table td.bg-dark, .table td.bg-dark > a, .table th.bg-dark, .table th.bg-dark > a { color: #fff !important; } .table td.bg-dark.btn:hover, .table th.bg-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-dark.btn:active, .table td.bg-dark.btn.active, .table th.bg-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-dark.btn:active, .table th.bg-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } .table td.bg-lightblue, .table th.bg-lightblue { background-color: #3c8dbc !important; } .table td.bg-lightblue, .table td.bg-lightblue > a, .table th.bg-lightblue, .table th.bg-lightblue > a { color: #fff !important; } .table td.bg-lightblue.btn:hover, .table th.bg-lightblue.btn:hover { border-color: #307095; color: #ececec; } .table td.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table td.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table td.bg-lightblue.btn:active, .table td.bg-lightblue.btn.active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled):active, .table th.bg-lightblue.btn:not(:disabled):not(.disabled).active, .table th.bg-lightblue.btn:active, .table th.bg-lightblue.btn.active { background-color: #307095 !important; border-color: #2d698c; color: #fff; } .table td.bg-navy, .table th.bg-navy { background-color: #001f3f !important; } .table td.bg-navy, .table td.bg-navy > a, .table th.bg-navy, .table th.bg-navy > a { color: #fff !important; } .table td.bg-navy.btn:hover, .table th.bg-navy.btn:hover { border-color: #00060c; color: #ececec; } .table td.bg-navy.btn:not(:disabled):not(.disabled):active, .table td.bg-navy.btn:not(:disabled):not(.disabled).active, .table td.bg-navy.btn:active, .table td.bg-navy.btn.active, .table th.bg-navy.btn:not(:disabled):not(.disabled):active, .table th.bg-navy.btn:not(:disabled):not(.disabled).active, .table th.bg-navy.btn:active, .table th.bg-navy.btn.active { background-color: #00060c !important; border-color: black; color: #fff; } .table td.bg-olive, .table th.bg-olive { background-color: #3d9970 !important; } .table td.bg-olive, .table td.bg-olive > a, .table th.bg-olive, .table th.bg-olive > a { color: #fff !important; } .table td.bg-olive.btn:hover, .table th.bg-olive.btn:hover { border-color: #2e7555; color: #ececec; } .table td.bg-olive.btn:not(:disabled):not(.disabled):active, .table td.bg-olive.btn:not(:disabled):not(.disabled).active, .table td.bg-olive.btn:active, .table td.bg-olive.btn.active, .table th.bg-olive.btn:not(:disabled):not(.disabled):active, .table th.bg-olive.btn:not(:disabled):not(.disabled).active, .table th.bg-olive.btn:active, .table th.bg-olive.btn.active { background-color: #2e7555 !important; border-color: #2b6b4f; color: #fff; } .table td.bg-lime, .table th.bg-lime { background-color: #01ff70 !important; } .table td.bg-lime, .table td.bg-lime > a, .table th.bg-lime, .table th.bg-lime > a { color: #1f2d3d !important; } .table td.bg-lime.btn:hover, .table th.bg-lime.btn:hover { border-color: #00cd5a; color: #121a24; } .table td.bg-lime.btn:not(:disabled):not(.disabled):active, .table td.bg-lime.btn:not(:disabled):not(.disabled).active, .table td.bg-lime.btn:active, .table td.bg-lime.btn.active, .table th.bg-lime.btn:not(:disabled):not(.disabled):active, .table th.bg-lime.btn:not(:disabled):not(.disabled).active, .table th.bg-lime.btn:active, .table th.bg-lime.btn.active { background-color: #00cd5a !important; border-color: #00c054; color: #fff; } .table td.bg-fuchsia, .table th.bg-fuchsia { background-color: #f012be !important; } .table td.bg-fuchsia, .table td.bg-fuchsia > a, .table th.bg-fuchsia, .table th.bg-fuchsia > a { color: #fff !important; } .table td.bg-fuchsia.btn:hover, .table th.bg-fuchsia.btn:hover { border-color: #c30c9a; color: #ececec; } .table td.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table td.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table td.bg-fuchsia.btn:active, .table td.bg-fuchsia.btn.active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled):active, .table th.bg-fuchsia.btn:not(:disabled):not(.disabled).active, .table th.bg-fuchsia.btn:active, .table th.bg-fuchsia.btn.active { background-color: #c30c9a !important; border-color: #b70c90; color: #fff; } .table td.bg-maroon, .table th.bg-maroon { background-color: #d81b60 !important; } .table td.bg-maroon, .table td.bg-maroon > a, .table th.bg-maroon, .table th.bg-maroon > a { color: #fff !important; } .table td.bg-maroon.btn:hover, .table th.bg-maroon.btn:hover { border-color: #ab154c; color: #ececec; } .table td.bg-maroon.btn:not(:disabled):not(.disabled):active, .table td.bg-maroon.btn:not(:disabled):not(.disabled).active, .table td.bg-maroon.btn:active, .table td.bg-maroon.btn.active, .table th.bg-maroon.btn:not(:disabled):not(.disabled):active, .table th.bg-maroon.btn:not(:disabled):not(.disabled).active, .table th.bg-maroon.btn:active, .table th.bg-maroon.btn.active { background-color: #ab154c !important; border-color: #9f1447; color: #fff; } .table td.bg-blue, .table th.bg-blue { background-color: #007bff !important; } .table td.bg-blue, .table td.bg-blue > a, .table th.bg-blue, .table th.bg-blue > a { color: #fff !important; } .table td.bg-blue.btn:hover, .table th.bg-blue.btn:hover { border-color: #0062cc; color: #ececec; } .table td.bg-blue.btn:not(:disabled):not(.disabled):active, .table td.bg-blue.btn:not(:disabled):not(.disabled).active, .table td.bg-blue.btn:active, .table td.bg-blue.btn.active, .table th.bg-blue.btn:not(:disabled):not(.disabled):active, .table th.bg-blue.btn:not(:disabled):not(.disabled).active, .table th.bg-blue.btn:active, .table th.bg-blue.btn.active { background-color: #0062cc !important; border-color: #005cbf; color: #fff; } .table td.bg-indigo, .table th.bg-indigo { background-color: #6610f2 !important; } .table td.bg-indigo, .table td.bg-indigo > a, .table th.bg-indigo, .table th.bg-indigo > a { color: #fff !important; } .table td.bg-indigo.btn:hover, .table th.bg-indigo.btn:hover { border-color: #510bc4; color: #ececec; } .table td.bg-indigo.btn:not(:disabled):not(.disabled):active, .table td.bg-indigo.btn:not(:disabled):not(.disabled).active, .table td.bg-indigo.btn:active, .table td.bg-indigo.btn.active, .table th.bg-indigo.btn:not(:disabled):not(.disabled):active, .table th.bg-indigo.btn:not(:disabled):not(.disabled).active, .table th.bg-indigo.btn:active, .table th.bg-indigo.btn.active { background-color: #510bc4 !important; border-color: #4c0ab8; color: #fff; } .table td.bg-purple, .table th.bg-purple { background-color: #6f42c1 !important; } .table td.bg-purple, .table td.bg-purple > a, .table th.bg-purple, .table th.bg-purple > a { color: #fff !important; } .table td.bg-purple.btn:hover, .table th.bg-purple.btn:hover { border-color: #59339d; color: #ececec; } .table td.bg-purple.btn:not(:disabled):not(.disabled):active, .table td.bg-purple.btn:not(:disabled):not(.disabled).active, .table td.bg-purple.btn:active, .table td.bg-purple.btn.active, .table th.bg-purple.btn:not(:disabled):not(.disabled):active, .table th.bg-purple.btn:not(:disabled):not(.disabled).active, .table th.bg-purple.btn:active, .table th.bg-purple.btn.active { background-color: #59339d !important; border-color: #533093; color: #fff; } .table td.bg-pink, .table th.bg-pink { background-color: #e83e8c !important; } .table td.bg-pink, .table td.bg-pink > a, .table th.bg-pink, .table th.bg-pink > a { color: #fff !important; } .table td.bg-pink.btn:hover, .table th.bg-pink.btn:hover { border-color: #d91a72; color: #ececec; } .table td.bg-pink.btn:not(:disabled):not(.disabled):active, .table td.bg-pink.btn:not(:disabled):not(.disabled).active, .table td.bg-pink.btn:active, .table td.bg-pink.btn.active, .table th.bg-pink.btn:not(:disabled):not(.disabled):active, .table th.bg-pink.btn:not(:disabled):not(.disabled).active, .table th.bg-pink.btn:active, .table th.bg-pink.btn.active { background-color: #d91a72 !important; border-color: #ce196c; color: #fff; } .table td.bg-red, .table th.bg-red { background-color: #dc3545 !important; } .table td.bg-red, .table td.bg-red > a, .table th.bg-red, .table th.bg-red > a { color: #fff !important; } .table td.bg-red.btn:hover, .table th.bg-red.btn:hover { border-color: #bd2130; color: #ececec; } .table td.bg-red.btn:not(:disabled):not(.disabled):active, .table td.bg-red.btn:not(:disabled):not(.disabled).active, .table td.bg-red.btn:active, .table td.bg-red.btn.active, .table th.bg-red.btn:not(:disabled):not(.disabled):active, .table th.bg-red.btn:not(:disabled):not(.disabled).active, .table th.bg-red.btn:active, .table th.bg-red.btn.active { background-color: #bd2130 !important; border-color: #b21f2d; color: #fff; } .table td.bg-orange, .table th.bg-orange { background-color: #fd7e14 !important; } .table td.bg-orange, .table td.bg-orange > a, .table th.bg-orange, .table th.bg-orange > a { color: #1f2d3d !important; } .table td.bg-orange.btn:hover, .table th.bg-orange.btn:hover { border-color: #dc6502; color: #121a24; } .table td.bg-orange.btn:not(:disabled):not(.disabled):active, .table td.bg-orange.btn:not(:disabled):not(.disabled).active, .table td.bg-orange.btn:active, .table td.bg-orange.btn.active, .table th.bg-orange.btn:not(:disabled):not(.disabled):active, .table th.bg-orange.btn:not(:disabled):not(.disabled).active, .table th.bg-orange.btn:active, .table th.bg-orange.btn.active { background-color: #dc6502 !important; border-color: #cf5f02; color: #fff; } .table td.bg-yellow, .table th.bg-yellow { background-color: #ffc107 !important; } .table td.bg-yellow, .table td.bg-yellow > a, .table th.bg-yellow, .table th.bg-yellow > a { color: #1f2d3d !important; } .table td.bg-yellow.btn:hover, .table th.bg-yellow.btn:hover { border-color: #d39e00; color: #121a24; } .table td.bg-yellow.btn:not(:disabled):not(.disabled):active, .table td.bg-yellow.btn:not(:disabled):not(.disabled).active, .table td.bg-yellow.btn:active, .table td.bg-yellow.btn.active, .table th.bg-yellow.btn:not(:disabled):not(.disabled):active, .table th.bg-yellow.btn:not(:disabled):not(.disabled).active, .table th.bg-yellow.btn:active, .table th.bg-yellow.btn.active { background-color: #d39e00 !important; border-color: #c69500; color: #1f2d3d; } .table td.bg-green, .table th.bg-green { background-color: #28a745 !important; } .table td.bg-green, .table td.bg-green > a, .table th.bg-green, .table th.bg-green > a { color: #fff !important; } .table td.bg-green.btn:hover, .table th.bg-green.btn:hover { border-color: #1e7e34; color: #ececec; } .table td.bg-green.btn:not(:disabled):not(.disabled):active, .table td.bg-green.btn:not(:disabled):not(.disabled).active, .table td.bg-green.btn:active, .table td.bg-green.btn.active, .table th.bg-green.btn:not(:disabled):not(.disabled):active, .table th.bg-green.btn:not(:disabled):not(.disabled).active, .table th.bg-green.btn:active, .table th.bg-green.btn.active { background-color: #1e7e34 !important; border-color: #1c7430; color: #fff; } .table td.bg-teal, .table th.bg-teal { background-color: #20c997 !important; } .table td.bg-teal, .table td.bg-teal > a, .table th.bg-teal, .table th.bg-teal > a { color: #fff !important; } .table td.bg-teal.btn:hover, .table th.bg-teal.btn:hover { border-color: #199d76; color: #ececec; } .table td.bg-teal.btn:not(:disabled):not(.disabled):active, .table td.bg-teal.btn:not(:disabled):not(.disabled).active, .table td.bg-teal.btn:active, .table td.bg-teal.btn.active, .table th.bg-teal.btn:not(:disabled):not(.disabled):active, .table th.bg-teal.btn:not(:disabled):not(.disabled).active, .table th.bg-teal.btn:active, .table th.bg-teal.btn.active { background-color: #199d76 !important; border-color: #17926e; color: #fff; } .table td.bg-cyan, .table th.bg-cyan { background-color: #17a2b8 !important; } .table td.bg-cyan, .table td.bg-cyan > a, .table th.bg-cyan, .table th.bg-cyan > a { color: #fff !important; } .table td.bg-cyan.btn:hover, .table th.bg-cyan.btn:hover { border-color: #117a8b; color: #ececec; } .table td.bg-cyan.btn:not(:disabled):not(.disabled):active, .table td.bg-cyan.btn:not(:disabled):not(.disabled).active, .table td.bg-cyan.btn:active, .table td.bg-cyan.btn.active, .table th.bg-cyan.btn:not(:disabled):not(.disabled):active, .table th.bg-cyan.btn:not(:disabled):not(.disabled).active, .table th.bg-cyan.btn:active, .table th.bg-cyan.btn.active { background-color: #117a8b !important; border-color: #10707f; color: #fff; } .table td.bg-white, .table th.bg-white { background-color: #fff !important; } .table td.bg-white, .table td.bg-white > a, .table th.bg-white, .table th.bg-white > a { color: #1f2d3d !important; } .table td.bg-white.btn:hover, .table th.bg-white.btn:hover { border-color: #e6e6e6; color: #121a24; } .table td.bg-white.btn:not(:disabled):not(.disabled):active, .table td.bg-white.btn:not(:disabled):not(.disabled).active, .table td.bg-white.btn:active, .table td.bg-white.btn.active, .table th.bg-white.btn:not(:disabled):not(.disabled):active, .table th.bg-white.btn:not(:disabled):not(.disabled).active, .table th.bg-white.btn:active, .table th.bg-white.btn.active { background-color: #e6e6e6 !important; border-color: #dfdfdf; color: #1f2d3d; } .table td.bg-gray, .table th.bg-gray { background-color: #6c757d !important; } .table td.bg-gray, .table td.bg-gray > a, .table th.bg-gray, .table th.bg-gray > a { color: #fff !important; } .table td.bg-gray.btn:hover, .table th.bg-gray.btn:hover { border-color: #545b62; color: #ececec; } .table td.bg-gray.btn:not(:disabled):not(.disabled):active, .table td.bg-gray.btn:not(:disabled):not(.disabled).active, .table td.bg-gray.btn:active, .table td.bg-gray.btn.active, .table th.bg-gray.btn:not(:disabled):not(.disabled):active, .table th.bg-gray.btn:not(:disabled):not(.disabled).active, .table th.bg-gray.btn:active, .table th.bg-gray.btn.active { background-color: #545b62 !important; border-color: #4e555b; color: #fff; } .table td.bg-gray-dark, .table th.bg-gray-dark { background-color: #343a40 !important; } .table td.bg-gray-dark, .table td.bg-gray-dark > a, .table th.bg-gray-dark, .table th.bg-gray-dark > a { color: #fff !important; } .table td.bg-gray-dark.btn:hover, .table th.bg-gray-dark.btn:hover { border-color: #1d2124; color: #ececec; } .table td.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table td.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table td.bg-gray-dark.btn:active, .table td.bg-gray-dark.btn.active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled):active, .table th.bg-gray-dark.btn:not(:disabled):not(.disabled).active, .table th.bg-gray-dark.btn:active, .table th.bg-gray-dark.btn.active { background-color: #1d2124 !important; border-color: #171a1d; color: #fff; } } .bg-gray { background-color: #adb5bd; color: #1f2d3d; } .bg-gray-light { background-color: #f2f4f5; color: #1f2d3d !important; } .bg-black { background-color: #000; color: #fff !important; } .bg-white { background-color: #fff; color: #1f2d3d !important; } .bg-gradient-primary { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-primary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-primary.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-primary.btn:not(:disabled):not(.disabled):active, .bg-gradient-primary.btn:not(:disabled):not(.disabled).active, .bg-gradient-primary.btn:active, .bg-gradient-primary.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-primary.btn:disabled, .bg-gradient-primary.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-secondary { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-secondary.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-secondary.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-secondary.btn:not(:disabled):not(.disabled):active, .bg-gradient-secondary.btn:not(:disabled):not(.disabled).active, .bg-gradient-secondary.btn:active, .bg-gradient-secondary.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-secondary.btn:disabled, .bg-gradient-secondary.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-success { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-success.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-success.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-success.btn:not(:disabled):not(.disabled):active, .bg-gradient-success.btn:not(:disabled):not(.disabled).active, .bg-gradient-success.btn:active, .bg-gradient-success.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-success.btn:disabled, .bg-gradient-success.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-info { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-info.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-info.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-info.btn:not(:disabled):not(.disabled):active, .bg-gradient-info.btn:not(:disabled):not(.disabled).active, .bg-gradient-info.btn:active, .bg-gradient-info.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-info.btn:disabled, .bg-gradient-info.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-warning { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-warning.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-warning.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-warning.btn:not(:disabled):not(.disabled):active, .bg-gradient-warning.btn:not(:disabled):not(.disabled).active, .bg-gradient-warning.btn:active, .bg-gradient-warning.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-warning.btn:disabled, .bg-gradient-warning.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-danger { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-danger.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-danger.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-danger.btn:not(:disabled):not(.disabled):active, .bg-gradient-danger.btn:not(:disabled):not(.disabled).active, .bg-gradient-danger.btn:active, .bg-gradient-danger.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-danger.btn:disabled, .bg-gradient-danger.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-light { background: #f8f9fa linear-gradient(180deg, #f9fafb, #f8f9fa) repeat-x !important; color: #1f2d3d; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-light.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-light.btn:hover { background: #f8f9fa linear-gradient(180deg, #e6eaed, #e2e6ea) repeat-x !important; border-color: #dae0e5; color: #121a24; } .bg-gradient-light.btn:not(:disabled):not(.disabled):active, .bg-gradient-light.btn:not(:disabled):not(.disabled).active, .bg-gradient-light.btn:active, .bg-gradient-light.btn.active { background: #f8f9fa linear-gradient(180deg, #e0e4e9, #dae0e5) repeat-x !important; border-color: #d3d9df; color: #1f2d3d; } .bg-gradient-light.btn:disabled, .bg-gradient-light.btn.disabled { background-image: none !important; border-color: #f8f9fa; color: #1f2d3d; } .bg-gradient-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-dark.btn:active, .bg-gradient-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-dark.btn:disabled, .bg-gradient-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } .bg-gradient-lightblue { background: #3c8dbc linear-gradient(180deg, #599ec6, #3c8dbc) repeat-x !important; color: #fff; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lightblue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lightblue.btn:hover { background: #3c8dbc linear-gradient(180deg, #518cad, #33779f) repeat-x !important; border-color: #307095; color: #ececec; } .bg-gradient-lightblue.btn:not(:disabled):not(.disabled):active, .bg-gradient-lightblue.btn:not(:disabled):not(.disabled).active, .bg-gradient-lightblue.btn:active, .bg-gradient-lightblue.btn.active { background: #3c8dbc linear-gradient(180deg, #4f85a5, #307095) repeat-x !important; border-color: #2d698c; color: #fff; } .bg-gradient-lightblue.btn:disabled, .bg-gradient-lightblue.btn.disabled { background-image: none !important; border-color: #3c8dbc; color: #fff; } .bg-gradient-navy { background: #001f3f linear-gradient(180deg, #26415c, #001f3f) repeat-x !important; color: #fff; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-navy.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-navy.btn:hover { background: #001f3f linear-gradient(180deg, #26313b, #000c19) repeat-x !important; border-color: #00060c; color: #ececec; } .bg-gradient-navy.btn:not(:disabled):not(.disabled):active, .bg-gradient-navy.btn:not(:disabled):not(.disabled).active, .bg-gradient-navy.btn:active, .bg-gradient-navy.btn.active { background: #001f3f linear-gradient(180deg, #262b30, #00060c) repeat-x !important; border-color: black; color: #fff; } .bg-gradient-navy.btn:disabled, .bg-gradient-navy.btn.disabled { background-image: none !important; border-color: #001f3f; color: #fff; } .bg-gradient-olive { background: #3d9970 linear-gradient(180deg, #5aa885, #3d9970) repeat-x !important; color: #fff; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-olive.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-olive.btn:hover { background: #3d9970 linear-gradient(180deg, #519174, #327e5c) repeat-x !important; border-color: #2e7555; color: #ececec; } .bg-gradient-olive.btn:not(:disabled):not(.disabled):active, .bg-gradient-olive.btn:not(:disabled):not(.disabled).active, .bg-gradient-olive.btn:active, .bg-gradient-olive.btn.active { background: #3d9970 linear-gradient(180deg, #4e896f, #2e7555) repeat-x !important; border-color: #2b6b4f; color: #fff; } .bg-gradient-olive.btn:disabled, .bg-gradient-olive.btn.disabled { background-image: none !important; border-color: #3d9970; color: #fff; } .bg-gradient-lime { background: #01ff70 linear-gradient(180deg, #27ff85, #01ff70) repeat-x !important; color: #1f2d3d; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-lime.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-lime.btn:hover { background: #01ff70 linear-gradient(180deg, #26df77, #00da5f) repeat-x !important; border-color: #00cd5a; color: #121a24; } .bg-gradient-lime.btn:not(:disabled):not(.disabled):active, .bg-gradient-lime.btn:not(:disabled):not(.disabled).active, .bg-gradient-lime.btn:active, .bg-gradient-lime.btn.active { background: #01ff70 linear-gradient(180deg, #26d572, #00cd5a) repeat-x !important; border-color: #00c054; color: #fff; } .bg-gradient-lime.btn:disabled, .bg-gradient-lime.btn.disabled { background-image: none !important; border-color: #01ff70; color: #1f2d3d; } .bg-gradient-fuchsia { background: #f012be linear-gradient(180deg, #f236c8, #f012be) repeat-x !important; color: #fff; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-fuchsia.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-fuchsia.btn:hover { background: #f012be linear-gradient(180deg, #d631b1, #cf0da3) repeat-x !important; border-color: #c30c9a; color: #ececec; } .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled):active, .bg-gradient-fuchsia.btn:not(:disabled):not(.disabled).active, .bg-gradient-fuchsia.btn:active, .bg-gradient-fuchsia.btn.active { background: #f012be linear-gradient(180deg, #cc31a9, #c30c9a) repeat-x !important; border-color: #b70c90; color: #fff; } .bg-gradient-fuchsia.btn:disabled, .bg-gradient-fuchsia.btn.disabled { background-image: none !important; border-color: #f012be; color: #fff; } .bg-gradient-maroon { background: #d81b60 linear-gradient(180deg, #de3d78, #d81b60) repeat-x !important; color: #fff; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-maroon.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-maroon.btn:hover { background: #d81b60 linear-gradient(180deg, #c13a6b, #b61751) repeat-x !important; border-color: #ab154c; color: #ececec; } .bg-gradient-maroon.btn:not(:disabled):not(.disabled):active, .bg-gradient-maroon.btn:not(:disabled):not(.disabled).active, .bg-gradient-maroon.btn:active, .bg-gradient-maroon.btn.active { background: #d81b60 linear-gradient(180deg, #b73867, #ab154c) repeat-x !important; border-color: #9f1447; color: #fff; } .bg-gradient-maroon.btn:disabled, .bg-gradient-maroon.btn.disabled { background-image: none !important; border-color: #d81b60; color: #fff; } .bg-gradient-blue { background: #007bff linear-gradient(180deg, #268fff, #007bff) repeat-x !important; color: #fff; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-blue.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-blue.btn:hover { background: #007bff linear-gradient(180deg, #267fde, #0069d9) repeat-x !important; border-color: #0062cc; color: #ececec; } .bg-gradient-blue.btn:not(:disabled):not(.disabled):active, .bg-gradient-blue.btn:not(:disabled):not(.disabled).active, .bg-gradient-blue.btn:active, .bg-gradient-blue.btn.active { background: #007bff linear-gradient(180deg, #267ad4, #0062cc) repeat-x !important; border-color: #005cbf; color: #fff; } .bg-gradient-blue.btn:disabled, .bg-gradient-blue.btn.disabled { background-image: none !important; border-color: #007bff; color: #fff; } .bg-gradient-indigo { background: #6610f2 linear-gradient(180deg, #7d34f4, #6610f2) repeat-x !important; color: #fff; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-indigo.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-indigo.btn:hover { background: #6610f2 linear-gradient(180deg, #7030d7, #560bd0) repeat-x !important; border-color: #510bc4; color: #ececec; } .bg-gradient-indigo.btn:not(:disabled):not(.disabled):active, .bg-gradient-indigo.btn:not(:disabled):not(.disabled).active, .bg-gradient-indigo.btn:active, .bg-gradient-indigo.btn.active { background: #6610f2 linear-gradient(180deg, #6b2fcd, #510bc4) repeat-x !important; border-color: #4c0ab8; color: #fff; } .bg-gradient-indigo.btn:disabled, .bg-gradient-indigo.btn.disabled { background-image: none !important; border-color: #6610f2; color: #fff; } .bg-gradient-purple { background: #6f42c1 linear-gradient(180deg, #855eca, #6f42c1) repeat-x !important; color: #fff; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-purple.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-purple.btn:hover { background: #6f42c1 linear-gradient(180deg, #7655b4, #5e37a6) repeat-x !important; border-color: #59339d; color: #ececec; } .bg-gradient-purple.btn:not(:disabled):not(.disabled):active, .bg-gradient-purple.btn:not(:disabled):not(.disabled).active, .bg-gradient-purple.btn:active, .bg-gradient-purple.btn.active { background: #6f42c1 linear-gradient(180deg, #7252ab, #59339d) repeat-x !important; border-color: #533093; color: #fff; } .bg-gradient-purple.btn:disabled, .bg-gradient-purple.btn.disabled { background-image: none !important; border-color: #6f42c1; color: #fff; } .bg-gradient-pink { background: #e83e8c linear-gradient(180deg, #eb5b9d, #e83e8c) repeat-x !important; color: #fff; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-pink.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-pink.btn:hover { background: #e83e8c linear-gradient(180deg, #e83e8c, #e41c78) repeat-x !important; border-color: #d91a72; color: #ececec; } .bg-gradient-pink.btn:not(:disabled):not(.disabled):active, .bg-gradient-pink.btn:not(:disabled):not(.disabled).active, .bg-gradient-pink.btn:active, .bg-gradient-pink.btn.active { background: #e83e8c linear-gradient(180deg, #df3c87, #d91a72) repeat-x !important; border-color: #ce196c; color: #fff; } .bg-gradient-pink.btn:disabled, .bg-gradient-pink.btn.disabled { background-image: none !important; border-color: #e83e8c; color: #fff; } .bg-gradient-red { background: #dc3545 linear-gradient(180deg, #e15361, #dc3545) repeat-x !important; color: #fff; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-red.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-red.btn:hover { background: #dc3545 linear-gradient(180deg, #d04451, #c82333) repeat-x !important; border-color: #bd2130; color: #ececec; } .bg-gradient-red.btn:not(:disabled):not(.disabled):active, .bg-gradient-red.btn:not(:disabled):not(.disabled).active, .bg-gradient-red.btn:active, .bg-gradient-red.btn.active { background: #dc3545 linear-gradient(180deg, #c7424f, #bd2130) repeat-x !important; border-color: #b21f2d; color: #fff; } .bg-gradient-red.btn:disabled, .bg-gradient-red.btn.disabled { background-image: none !important; border-color: #dc3545; color: #fff; } .bg-gradient-orange { background: #fd7e14 linear-gradient(180deg, #fd9137, #fd7e14) repeat-x !important; color: #1f2d3d; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-orange.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-orange.btn:hover { background: #fd7e14 linear-gradient(180deg, #ec8128, #e96b02) repeat-x !important; border-color: #dc6502; color: #121a24; } .bg-gradient-orange.btn:not(:disabled):not(.disabled):active, .bg-gradient-orange.btn:not(:disabled):not(.disabled).active, .bg-gradient-orange.btn:active, .bg-gradient-orange.btn.active { background: #fd7e14 linear-gradient(180deg, #e17c28, #dc6502) repeat-x !important; border-color: #cf5f02; color: #fff; } .bg-gradient-orange.btn:disabled, .bg-gradient-orange.btn.disabled { background-image: none !important; border-color: #fd7e14; color: #1f2d3d; } .bg-gradient-yellow { background: #ffc107 linear-gradient(180deg, #ffca2c, #ffc107) repeat-x !important; color: #1f2d3d; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-yellow.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-yellow.btn:hover { background: #ffc107 linear-gradient(180deg, #e4b526, #e0a800) repeat-x !important; border-color: #d39e00; color: #121a24; } .bg-gradient-yellow.btn:not(:disabled):not(.disabled):active, .bg-gradient-yellow.btn:not(:disabled):not(.disabled).active, .bg-gradient-yellow.btn:active, .bg-gradient-yellow.btn.active { background: #ffc107 linear-gradient(180deg, #daad26, #d39e00) repeat-x !important; border-color: #c69500; color: #1f2d3d; } .bg-gradient-yellow.btn:disabled, .bg-gradient-yellow.btn.disabled { background-image: none !important; border-color: #ffc107; color: #1f2d3d; } .bg-gradient-green { background: #28a745 linear-gradient(180deg, #48b461, #28a745) repeat-x !important; color: #fff; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-green.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-green.btn:hover { background: #28a745 linear-gradient(180deg, #429a56, #218838) repeat-x !important; border-color: #1e7e34; color: #ececec; } .bg-gradient-green.btn:not(:disabled):not(.disabled):active, .bg-gradient-green.btn:not(:disabled):not(.disabled).active, .bg-gradient-green.btn:active, .bg-gradient-green.btn.active { background: #28a745 linear-gradient(180deg, #409152, #1e7e34) repeat-x !important; border-color: #1c7430; color: #fff; } .bg-gradient-green.btn:disabled, .bg-gradient-green.btn.disabled { background-image: none !important; border-color: #28a745; color: #fff; } .bg-gradient-teal { background: #20c997 linear-gradient(180deg, #41d1a7, #20c997) repeat-x !important; color: #fff; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-teal.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-teal.btn:hover { background: #20c997 linear-gradient(180deg, #3db592, #1ba87e) repeat-x !important; border-color: #199d76; color: #ececec; } .bg-gradient-teal.btn:not(:disabled):not(.disabled):active, .bg-gradient-teal.btn:not(:disabled):not(.disabled).active, .bg-gradient-teal.btn:active, .bg-gradient-teal.btn.active { background: #20c997 linear-gradient(180deg, #3bac8b, #199d76) repeat-x !important; border-color: #17926e; color: #fff; } .bg-gradient-teal.btn:disabled, .bg-gradient-teal.btn.disabled { background-image: none !important; border-color: #20c997; color: #fff; } .bg-gradient-cyan { background: #17a2b8 linear-gradient(180deg, #3ab0c3, #17a2b8) repeat-x !important; color: #fff; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-cyan.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-cyan.btn:hover { background: #17a2b8 linear-gradient(180deg, #3697a6, #138496) repeat-x !important; border-color: #117a8b; color: #ececec; } .bg-gradient-cyan.btn:not(:disabled):not(.disabled):active, .bg-gradient-cyan.btn:not(:disabled):not(.disabled).active, .bg-gradient-cyan.btn:active, .bg-gradient-cyan.btn.active { background: #17a2b8 linear-gradient(180deg, #358e9c, #117a8b) repeat-x !important; border-color: #10707f; color: #fff; } .bg-gradient-cyan.btn:disabled, .bg-gradient-cyan.btn.disabled { background-image: none !important; border-color: #17a2b8; color: #fff; } .bg-gradient-white { background: #fff linear-gradient(180deg, white, #fff) repeat-x !important; color: #1f2d3d; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-white.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-white.btn:hover { background: #fff linear-gradient(180deg, #efefef, #ececec) repeat-x !important; border-color: #e6e6e6; color: #121a24; } .bg-gradient-white.btn:not(:disabled):not(.disabled):active, .bg-gradient-white.btn:not(:disabled):not(.disabled).active, .bg-gradient-white.btn:active, .bg-gradient-white.btn.active { background: #fff linear-gradient(180deg, #e9e9e9, #e6e6e6) repeat-x !important; border-color: #dfdfdf; color: #1f2d3d; } .bg-gradient-white.btn:disabled, .bg-gradient-white.btn.disabled { background-image: none !important; border-color: #fff; color: #1f2d3d; } .bg-gradient-gray { background: #6c757d linear-gradient(180deg, #828a91, #6c757d) repeat-x !important; color: #fff; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray.btn:hover { background: #6c757d linear-gradient(180deg, #73797f, #5a6268) repeat-x !important; border-color: #545b62; color: #ececec; } .bg-gradient-gray.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray.btn:active, .bg-gradient-gray.btn.active { background: #6c757d linear-gradient(180deg, #6e7479, #545b62) repeat-x !important; border-color: #4e555b; color: #fff; } .bg-gradient-gray.btn:disabled, .bg-gradient-gray.btn.disabled { background-image: none !important; border-color: #6c757d; color: #fff; } .bg-gradient-gray-dark { background: #343a40 linear-gradient(180deg, #52585d, #343a40) repeat-x !important; color: #fff; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .show > .bg-gradient-gray-dark.btn.dropdown-toggle { background-image: none !important; } .bg-gradient-gray-dark.btn:hover { background: #343a40 linear-gradient(180deg, #44474b, #23272b) repeat-x !important; border-color: #1d2124; color: #ececec; } .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled):active, .bg-gradient-gray-dark.btn:not(:disabled):not(.disabled).active, .bg-gradient-gray-dark.btn:active, .bg-gradient-gray-dark.btn.active { background: #343a40 linear-gradient(180deg, #3f4245, #1d2124) repeat-x !important; border-color: #171a1d; color: #fff; } .bg-gradient-gray-dark.btn:disabled, .bg-gradient-gray-dark.btn.disabled { background-image: none !important; border-color: #343a40; color: #fff; } [class^="bg-"].disabled { opacity: .65; } a.text-muted:hover { color: #007bff !important; } .link-muted { color: #5d6974; } .link-muted:hover, .link-muted:focus { color: #464f58; } .link-black { color: #6c757d; } .link-black:hover, .link-black:focus { color: #e6e8ea; } .accent-primary .btn-link, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-primary .nav-tabs .nav-link { color: #007bff; } .accent-primary .btn-link:hover, .accent-primary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-primary .nav-tabs .nav-link:hover { color: #0056b3; } .accent-primary .dropdown-item:active, .accent-primary .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-primary .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-primary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-primary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-primary .custom-select:focus, .accent-primary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-primary .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-primary .page-item .page-link { color: #007bff; } .accent-primary .page-item.active a, .accent-primary .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-primary .page-item.disabled a, .accent-primary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-primary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-primary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-secondary .btn-link, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-secondary .nav-tabs .nav-link { color: #6c757d; } .accent-secondary .btn-link:hover, .accent-secondary a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-secondary .nav-tabs .nav-link:hover { color: #494f54; } .accent-secondary .dropdown-item:active, .accent-secondary .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-secondary .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-secondary .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-secondary .custom-select:focus, .accent-secondary .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-secondary .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-secondary .page-item .page-link { color: #6c757d; } .accent-secondary .page-item.active a, .accent-secondary .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-secondary .page-item.disabled a, .accent-secondary .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-secondary [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-secondary [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-success .btn-link, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-success .nav-tabs .nav-link { color: #28a745; } .accent-success .btn-link:hover, .accent-success a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-success .nav-tabs .nav-link:hover { color: #19692c; } .accent-success .dropdown-item:active, .accent-success .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-success .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-success .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-success .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-success .custom-select:focus, .accent-success .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-success .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-success .page-item .page-link { color: #28a745; } .accent-success .page-item.active a, .accent-success .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-success .page-item.disabled a, .accent-success .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-success [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-success [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-info .btn-link, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-info .nav-tabs .nav-link { color: #17a2b8; } .accent-info .btn-link:hover, .accent-info a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-info .nav-tabs .nav-link:hover { color: #0f6674; } .accent-info .dropdown-item:active, .accent-info .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-info .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-info .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-info .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-info .custom-select:focus, .accent-info .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-info .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-info .page-item .page-link { color: #17a2b8; } .accent-info .page-item.active a, .accent-info .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-info .page-item.disabled a, .accent-info .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-info [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-info [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-warning .btn-link, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-warning .nav-tabs .nav-link { color: #ffc107; } .accent-warning .btn-link:hover, .accent-warning a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-warning .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-warning .dropdown-item:active, .accent-warning .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-warning .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-warning .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-warning .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-warning .custom-select:focus, .accent-warning .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-warning .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-warning .page-item .page-link { color: #ffc107; } .accent-warning .page-item.active a, .accent-warning .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-warning .page-item.disabled a, .accent-warning .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-warning [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-warning [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-danger .btn-link, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-danger .nav-tabs .nav-link { color: #dc3545; } .accent-danger .btn-link:hover, .accent-danger a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-danger .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-danger .dropdown-item:active, .accent-danger .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-danger .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-danger .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-danger .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-danger .custom-select:focus, .accent-danger .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-danger .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-danger .page-item .page-link { color: #dc3545; } .accent-danger .page-item.active a, .accent-danger .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-danger .page-item.disabled a, .accent-danger .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-danger [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-danger [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-light .btn-link, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-light .nav-tabs .nav-link { color: #f8f9fa; } .accent-light .btn-link:hover, .accent-light a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-light .nav-tabs .nav-link:hover { color: #cbd3da; } .accent-light .dropdown-item:active, .accent-light .dropdown-item.active { background-color: #f8f9fa; color: #1f2d3d; } .accent-light .custom-control-input:checked ~ .custom-control-label::before { background-color: #f8f9fa; border-color: #bdc6d0; } .accent-light .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-light .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-light .custom-select:focus, .accent-light .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-light .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-light .page-item .page-link { color: #f8f9fa; } .accent-light .page-item.active a, .accent-light .page-item.active .page-link { background-color: #f8f9fa; border-color: #f8f9fa; color: #fff; } .accent-light .page-item.disabled a, .accent-light .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-light [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-light [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-dark .btn-link, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-dark .nav-tabs .nav-link { color: #343a40; } .accent-dark .btn-link:hover, .accent-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-dark .dropdown-item:active, .accent-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-dark .custom-select:focus, .accent-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-dark .page-item .page-link { color: #343a40; } .accent-dark .page-item.active a, .accent-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-dark .page-item.disabled a, .accent-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-lightblue .btn-link, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lightblue .nav-tabs .nav-link { color: #3c8dbc; } .accent-lightblue .btn-link:hover, .accent-lightblue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lightblue .nav-tabs .nav-link:hover { color: #296282; } .accent-lightblue .dropdown-item:active, .accent-lightblue .dropdown-item.active { background-color: #3c8dbc; color: #fff; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::before { background-color: #3c8dbc; border-color: #23536f; } .accent-lightblue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lightblue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lightblue .custom-select:focus, .accent-lightblue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lightblue .custom-file-input:focus ~ .custom-file-label { border-color: #99c5de; } .accent-lightblue .page-item .page-link { color: #3c8dbc; } .accent-lightblue .page-item.active a, .accent-lightblue .page-item.active .page-link { background-color: #3c8dbc; border-color: #3c8dbc; color: #fff; } .accent-lightblue .page-item.disabled a, .accent-lightblue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lightblue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lightblue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-navy .btn-link, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-navy .nav-tabs .nav-link { color: #001f3f; } .accent-navy .btn-link:hover, .accent-navy a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-navy .nav-tabs .nav-link:hover { color: black; } .accent-navy .dropdown-item:active, .accent-navy .dropdown-item.active { background-color: #001f3f; color: #fff; } .accent-navy .custom-control-input:checked ~ .custom-control-label::before { background-color: #001f3f; border-color: black; } .accent-navy .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-navy .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-navy .custom-select:focus, .accent-navy .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-navy .custom-file-input:focus ~ .custom-file-label { border-color: #005ebf; } .accent-navy .page-item .page-link { color: #001f3f; } .accent-navy .page-item.active a, .accent-navy .page-item.active .page-link { background-color: #001f3f; border-color: #001f3f; color: #fff; } .accent-navy .page-item.disabled a, .accent-navy .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-navy [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-navy [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-olive .btn-link, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-olive .nav-tabs .nav-link { color: #3d9970; } .accent-olive .btn-link:hover, .accent-olive a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-olive .nav-tabs .nav-link:hover { color: #276248; } .accent-olive .dropdown-item:active, .accent-olive .dropdown-item.active { background-color: #3d9970; color: #fff; } .accent-olive .custom-control-input:checked ~ .custom-control-label::before { background-color: #3d9970; border-color: #20503b; } .accent-olive .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-olive .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-olive .custom-select:focus, .accent-olive .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-olive .custom-file-input:focus ~ .custom-file-label { border-color: #87cfaf; } .accent-olive .page-item .page-link { color: #3d9970; } .accent-olive .page-item.active a, .accent-olive .page-item.active .page-link { background-color: #3d9970; border-color: #3d9970; color: #fff; } .accent-olive .page-item.disabled a, .accent-olive .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-olive [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-olive [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-lime .btn-link, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-lime .nav-tabs .nav-link { color: #01ff70; } .accent-lime .btn-link:hover, .accent-lime a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-lime .nav-tabs .nav-link:hover { color: #00b44e; } .accent-lime .dropdown-item:active, .accent-lime .dropdown-item.active { background-color: #01ff70; color: #1f2d3d; } .accent-lime .custom-control-input:checked ~ .custom-control-label::before { background-color: #01ff70; border-color: #009a43; } .accent-lime .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-lime .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-lime .custom-select:focus, .accent-lime .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-lime .custom-file-input:focus ~ .custom-file-label { border-color: #81ffb8; } .accent-lime .page-item .page-link { color: #01ff70; } .accent-lime .page-item.active a, .accent-lime .page-item.active .page-link { background-color: #01ff70; border-color: #01ff70; color: #fff; } .accent-lime .page-item.disabled a, .accent-lime .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-lime [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-lime [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-fuchsia .btn-link, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-fuchsia .nav-tabs .nav-link { color: #f012be; } .accent-fuchsia .btn-link:hover, .accent-fuchsia a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-fuchsia .nav-tabs .nav-link:hover { color: #ab0b87; } .accent-fuchsia .dropdown-item:active, .accent-fuchsia .dropdown-item.active { background-color: #f012be; color: #fff; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::before { background-color: #f012be; border-color: #930974; } .accent-fuchsia .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-fuchsia .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-fuchsia .custom-select:focus, .accent-fuchsia .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-fuchsia .custom-file-input:focus ~ .custom-file-label { border-color: #f88adf; } .accent-fuchsia .page-item .page-link { color: #f012be; } .accent-fuchsia .page-item.active a, .accent-fuchsia .page-item.active .page-link { background-color: #f012be; border-color: #f012be; color: #fff; } .accent-fuchsia .page-item.disabled a, .accent-fuchsia .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-fuchsia [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-fuchsia [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-maroon .btn-link, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-maroon .nav-tabs .nav-link { color: #d81b60; } .accent-maroon .btn-link:hover, .accent-maroon a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-maroon .nav-tabs .nav-link:hover { color: #941342; } .accent-maroon .dropdown-item:active, .accent-maroon .dropdown-item.active { background-color: #d81b60; color: #fff; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::before { background-color: #d81b60; border-color: #7d1038; } .accent-maroon .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-maroon .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-maroon .custom-select:focus, .accent-maroon .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-maroon .custom-file-input:focus ~ .custom-file-label { border-color: #f083ab; } .accent-maroon .page-item .page-link { color: #d81b60; } .accent-maroon .page-item.active a, .accent-maroon .page-item.active .page-link { background-color: #d81b60; border-color: #d81b60; color: #fff; } .accent-maroon .page-item.disabled a, .accent-maroon .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-maroon [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-maroon [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-blue .btn-link, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-blue .nav-tabs .nav-link { color: #007bff; } .accent-blue .btn-link:hover, .accent-blue a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-blue .nav-tabs .nav-link:hover { color: #0056b3; } .accent-blue .dropdown-item:active, .accent-blue .dropdown-item.active { background-color: #007bff; color: #fff; } .accent-blue .custom-control-input:checked ~ .custom-control-label::before { background-color: #007bff; border-color: #004a99; } .accent-blue .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-blue .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-blue .custom-select:focus, .accent-blue .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-blue .custom-file-input:focus ~ .custom-file-label { border-color: #80bdff; } .accent-blue .page-item .page-link { color: #007bff; } .accent-blue .page-item.active a, .accent-blue .page-item.active .page-link { background-color: #007bff; border-color: #007bff; color: #fff; } .accent-blue .page-item.disabled a, .accent-blue .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-blue [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-blue [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-indigo .btn-link, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-indigo .nav-tabs .nav-link { color: #6610f2; } .accent-indigo .btn-link:hover, .accent-indigo a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-indigo .nav-tabs .nav-link:hover { color: #4709ac; } .accent-indigo .dropdown-item:active, .accent-indigo .dropdown-item.active { background-color: #6610f2; color: #fff; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::before { background-color: #6610f2; border-color: #3d0894; } .accent-indigo .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-indigo .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-indigo .custom-select:focus, .accent-indigo .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-indigo .custom-file-input:focus ~ .custom-file-label { border-color: #b389f9; } .accent-indigo .page-item .page-link { color: #6610f2; } .accent-indigo .page-item.active a, .accent-indigo .page-item.active .page-link { background-color: #6610f2; border-color: #6610f2; color: #fff; } .accent-indigo .page-item.disabled a, .accent-indigo .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-indigo [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-indigo [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-purple .btn-link, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-purple .nav-tabs .nav-link { color: #6f42c1; } .accent-purple .btn-link:hover, .accent-purple a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-purple .nav-tabs .nav-link:hover { color: #4e2d89; } .accent-purple .dropdown-item:active, .accent-purple .dropdown-item.active { background-color: #6f42c1; color: #fff; } .accent-purple .custom-control-input:checked ~ .custom-control-label::before { background-color: #6f42c1; border-color: #432776; } .accent-purple .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-purple .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-purple .custom-select:focus, .accent-purple .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-purple .custom-file-input:focus ~ .custom-file-label { border-color: #b8a2e0; } .accent-purple .page-item .page-link { color: #6f42c1; } .accent-purple .page-item.active a, .accent-purple .page-item.active .page-link { background-color: #6f42c1; border-color: #6f42c1; color: #fff; } .accent-purple .page-item.disabled a, .accent-purple .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-purple [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-purple [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-pink .btn-link, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-pink .nav-tabs .nav-link { color: #e83e8c; } .accent-pink .btn-link:hover, .accent-pink a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-pink .nav-tabs .nav-link:hover { color: #c21766; } .accent-pink .dropdown-item:active, .accent-pink .dropdown-item.active { background-color: #e83e8c; color: #fff; } .accent-pink .custom-control-input:checked ~ .custom-control-label::before { background-color: #e83e8c; border-color: #ac145a; } .accent-pink .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-pink .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-pink .custom-select:focus, .accent-pink .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-pink .custom-file-input:focus ~ .custom-file-label { border-color: #f6b0d0; } .accent-pink .page-item .page-link { color: #e83e8c; } .accent-pink .page-item.active a, .accent-pink .page-item.active .page-link { background-color: #e83e8c; border-color: #e83e8c; color: #fff; } .accent-pink .page-item.disabled a, .accent-pink .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-pink [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-pink [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-red .btn-link, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-red .nav-tabs .nav-link { color: #dc3545; } .accent-red .btn-link:hover, .accent-red a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-red .nav-tabs .nav-link:hover { color: #a71d2a; } .accent-red .dropdown-item:active, .accent-red .dropdown-item.active { background-color: #dc3545; color: #fff; } .accent-red .custom-control-input:checked ~ .custom-control-label::before { background-color: #dc3545; border-color: #921925; } .accent-red .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-red .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-red .custom-select:focus, .accent-red .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-red .custom-file-input:focus ~ .custom-file-label { border-color: #efa2a9; } .accent-red .page-item .page-link { color: #dc3545; } .accent-red .page-item.active a, .accent-red .page-item.active .page-link { background-color: #dc3545; border-color: #dc3545; color: #fff; } .accent-red .page-item.disabled a, .accent-red .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-red [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-red [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-orange .btn-link, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-orange .nav-tabs .nav-link { color: #fd7e14; } .accent-orange .btn-link:hover, .accent-orange a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-orange .nav-tabs .nav-link:hover { color: #c35a02; } .accent-orange .dropdown-item:active, .accent-orange .dropdown-item.active { background-color: #fd7e14; color: #1f2d3d; } .accent-orange .custom-control-input:checked ~ .custom-control-label::before { background-color: #fd7e14; border-color: #aa4e01; } .accent-orange .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-orange .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-orange .custom-select:focus, .accent-orange .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-orange .custom-file-input:focus ~ .custom-file-label { border-color: #fec392; } .accent-orange .page-item .page-link { color: #fd7e14; } .accent-orange .page-item.active a, .accent-orange .page-item.active .page-link { background-color: #fd7e14; border-color: #fd7e14; color: #fff; } .accent-orange .page-item.disabled a, .accent-orange .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-orange [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-orange [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-yellow .btn-link, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-yellow .nav-tabs .nav-link { color: #ffc107; } .accent-yellow .btn-link:hover, .accent-yellow a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-yellow .nav-tabs .nav-link:hover { color: #ba8b00; } .accent-yellow .dropdown-item:active, .accent-yellow .dropdown-item.active { background-color: #ffc107; color: #1f2d3d; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::before { background-color: #ffc107; border-color: #a07800; } .accent-yellow .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-yellow .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-yellow .custom-select:focus, .accent-yellow .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-yellow .custom-file-input:focus ~ .custom-file-label { border-color: #ffe187; } .accent-yellow .page-item .page-link { color: #ffc107; } .accent-yellow .page-item.active a, .accent-yellow .page-item.active .page-link { background-color: #ffc107; border-color: #ffc107; color: #fff; } .accent-yellow .page-item.disabled a, .accent-yellow .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-yellow [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-yellow [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-green .btn-link, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-green .nav-tabs .nav-link { color: #28a745; } .accent-green .btn-link:hover, .accent-green a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-green .nav-tabs .nav-link:hover { color: #19692c; } .accent-green .dropdown-item:active, .accent-green .dropdown-item.active { background-color: #28a745; color: #fff; } .accent-green .custom-control-input:checked ~ .custom-control-label::before { background-color: #28a745; border-color: #145523; } .accent-green .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-green .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-green .custom-select:focus, .accent-green .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-green .custom-file-input:focus ~ .custom-file-label { border-color: #71dd8a; } .accent-green .page-item .page-link { color: #28a745; } .accent-green .page-item.active a, .accent-green .page-item.active .page-link { background-color: #28a745; border-color: #28a745; color: #fff; } .accent-green .page-item.disabled a, .accent-green .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-green [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-green [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-teal .btn-link, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-teal .nav-tabs .nav-link { color: #20c997; } .accent-teal .btn-link:hover, .accent-teal a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-teal .nav-tabs .nav-link:hover { color: #158765; } .accent-teal .dropdown-item:active, .accent-teal .dropdown-item.active { background-color: #20c997; color: #fff; } .accent-teal .custom-control-input:checked ~ .custom-control-label::before { background-color: #20c997; border-color: #127155; } .accent-teal .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-teal .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-teal .custom-select:focus, .accent-teal .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-teal .custom-file-input:focus ~ .custom-file-label { border-color: #7eeaca; } .accent-teal .page-item .page-link { color: #20c997; } .accent-teal .page-item.active a, .accent-teal .page-item.active .page-link { background-color: #20c997; border-color: #20c997; color: #fff; } .accent-teal .page-item.disabled a, .accent-teal .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-teal [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-teal [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-cyan .btn-link, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-cyan .nav-tabs .nav-link { color: #17a2b8; } .accent-cyan .btn-link:hover, .accent-cyan a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-cyan .nav-tabs .nav-link:hover { color: #0f6674; } .accent-cyan .dropdown-item:active, .accent-cyan .dropdown-item.active { background-color: #17a2b8; color: #fff; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::before { background-color: #17a2b8; border-color: #0c525d; } .accent-cyan .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-cyan .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-cyan .custom-select:focus, .accent-cyan .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-cyan .custom-file-input:focus ~ .custom-file-label { border-color: #63d9ec; } .accent-cyan .page-item .page-link { color: #17a2b8; } .accent-cyan .page-item.active a, .accent-cyan .page-item.active .page-link { background-color: #17a2b8; border-color: #17a2b8; color: #fff; } .accent-cyan .page-item.disabled a, .accent-cyan .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-cyan [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-cyan [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-white .btn-link, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-white .nav-tabs .nav-link { color: #fff; } .accent-white .btn-link:hover, .accent-white a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-white .nav-tabs .nav-link:hover { color: #d9d9d9; } .accent-white .dropdown-item:active, .accent-white .dropdown-item.active { background-color: #fff; color: #1f2d3d; } .accent-white .custom-control-input:checked ~ .custom-control-label::before { background-color: #fff; border-color: #cccccc; } .accent-white .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%231f2d3d' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-white .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-white .custom-select:focus, .accent-white .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-white .custom-file-input:focus ~ .custom-file-label { border-color: white; } .accent-white .page-item .page-link { color: #fff; } .accent-white .page-item.active a, .accent-white .page-item.active .page-link { background-color: #fff; border-color: #fff; color: #fff; } .accent-white .page-item.disabled a, .accent-white .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-white [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-white [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-gray .btn-link, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray .nav-tabs .nav-link { color: #6c757d; } .accent-gray .btn-link:hover, .accent-gray a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray .nav-tabs .nav-link:hover { color: #494f54; } .accent-gray .dropdown-item:active, .accent-gray .dropdown-item.active { background-color: #6c757d; color: #fff; } .accent-gray .custom-control-input:checked ~ .custom-control-label::before { background-color: #6c757d; border-color: #3d4246; } .accent-gray .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray .custom-select:focus, .accent-gray .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray .custom-file-input:focus ~ .custom-file-label { border-color: #afb5ba; } .accent-gray .page-item .page-link { color: #6c757d; } .accent-gray .page-item.active a, .accent-gray .page-item.active .page-link { background-color: #6c757d; border-color: #6c757d; color: #fff; } .accent-gray .page-item.disabled a, .accent-gray .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } .accent-gray-dark .btn-link, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn), .accent-gray-dark .nav-tabs .nav-link { color: #343a40; } .accent-gray-dark .btn-link:hover, .accent-gray-dark a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):not(.page-link):not(.badge):not(.btn):hover, .accent-gray-dark .nav-tabs .nav-link:hover { color: #121416; } .accent-gray-dark .dropdown-item:active, .accent-gray-dark .dropdown-item.active { background-color: #343a40; color: #fff; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::before { background-color: #343a40; border-color: #060708; } .accent-gray-dark .custom-control-input:checked ~ .custom-control-label::after { background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); } .accent-gray-dark .form-control:focus:not(.is-invalid):not(.is-warning):not(.is-valid), .accent-gray-dark .custom-select:focus, .accent-gray-dark .custom-control-input:focus:not(:checked) ~ .custom-control-label::before, .accent-gray-dark .custom-file-input:focus ~ .custom-file-label { border-color: #6d7a86; } .accent-gray-dark .page-item .page-link { color: #343a40; } .accent-gray-dark .page-item.active a, .accent-gray-dark .page-item.active .page-link { background-color: #343a40; border-color: #343a40; color: #fff; } .accent-gray-dark .page-item.disabled a, .accent-gray-dark .page-item.disabled .page-link { background-color: #fff; border-color: #dee2e6; color: #6c757d; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #c2c7d0; } .accent-gray-dark [class*="sidebar-dark-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #fff; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link) { color: #343a40; } .accent-gray-dark [class*="sidebar-light-"] .sidebar a:not(.dropdown-item):not(.btn-app):not(.nav-link):not(.brand-link):hover { color: #212529; } [class*="accent-"] a.btn-primary { color: #fff; } [class*="accent-"] a.btn-secondary { color: #fff; } [class*="accent-"] a.btn-success { color: #fff; } [class*="accent-"] a.btn-info { color: #fff; } [class*="accent-"] a.btn-warning { color: #1f2d3d; } [class*="accent-"] a.btn-danger { color: #fff; } [class*="accent-"] a.btn-light { color: #1f2d3d; } [class*="accent-"] a.btn-dark { color: #fff; } /*# sourceMappingURL=adminlte.light.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.pages.css ================================================ /*! * AdminLTE v3.2.0 * Only Pages * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ .close, .mailbox-attachment-close { float: right; font-size: 1.5rem; font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; opacity: .5; } .close:hover, .mailbox-attachment-close:hover { color: #000; text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .mailbox-attachment-close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus, .mailbox-attachment-close:not(:disabled):not(.disabled):focus { opacity: .75; } button.close, button.mailbox-attachment-close { padding: 0; background-color: transparent; border: 0; } a.close.disabled, a.disabled.mailbox-attachment-close { pointer-events: none; } @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .mailbox-messages > .table { margin: 0; } .mailbox-controls { padding: 5px; } .mailbox-controls.with-border { border-bottom: 1px solid rgba(0, 0, 0, 0.125); } .mailbox-read-info { border-bottom: 1px solid rgba(0, 0, 0, 0.125); padding: 10px; } .mailbox-read-info h3 { font-size: 20px; margin: 0; } .mailbox-read-info h5 { margin: 0; padding: 5px 0 0; } .mailbox-read-time { color: #999; font-size: 13px; } .mailbox-read-message { padding: 10px; } .mailbox-attachments { padding-left: 0; list-style: none; } .mailbox-attachments li { border: 1px solid #eee; float: left; margin-bottom: 10px; margin-right: 10px; width: 200px; } .mailbox-attachment-name { color: #666; font-weight: 700; } .mailbox-attachment-icon, .mailbox-attachment-info, .mailbox-attachment-size { display: block; } .mailbox-attachment-info { background-color: #f8f9fa; padding: 10px; } .mailbox-attachment-size { color: #999; font-size: 12px; } .mailbox-attachment-size > span { display: inline-block; padding-top: .75rem; } .mailbox-attachment-icon { color: #666; font-size: 65px; max-height: 132.5px; padding: 20px 10px; text-align: center; } .mailbox-attachment-icon.has-img { padding: 0; } .mailbox-attachment-icon.has-img > img { height: auto; max-width: 100%; } .lockscreen { background-color: #e9ecef; } .lockscreen .lockscreen-name { font-weight: 600; text-align: center; } .lockscreen-logo { font-size: 35px; font-weight: 300; margin-bottom: 25px; text-align: center; } .lockscreen-logo a { color: #495057; } .lockscreen-wrapper { margin: 0 auto; margin-top: 10%; max-width: 400px; } .lockscreen-item { border-radius: 4px; background-color: #fff; margin: 10px auto 30px; padding: 0; position: relative; width: 290px; } .lockscreen-image { border-radius: 50%; background-color: #fff; left: -10px; padding: 5px; position: absolute; top: -25px; z-index: 10; } .lockscreen-image > img { border-radius: 50%; height: 70px; width: 70px; } .lockscreen-credentials { margin-left: 70px; } .lockscreen-credentials .form-control { border: 0; } .lockscreen-credentials .btn { background-color: #fff; border: 0; padding: 0 10px; } .lockscreen-footer { margin-top: 10px; } .dark-mode .lockscreen-item { background-color: #343a40; } .dark-mode .lockscreen-logo a { color: #fff; } .dark-mode .lockscreen-credentials .btn { background-color: #343a40; } .dark-mode .lockscreen-image { background-color: #6c757d; } .login-logo, .register-logo { font-size: 2.1rem; font-weight: 300; margin-bottom: .9rem; text-align: center; } .login-logo a, .register-logo a { color: #495057; } .login-page, .register-page { -ms-flex-align: center; align-items: center; background-color: #e9ecef; display: -ms-flexbox; display: flex; -ms-flex-direction: column; flex-direction: column; height: 100vh; -ms-flex-pack: center; justify-content: center; } .login-box, .register-box { width: 360px; } @media (max-width: 576px) { .login-box, .register-box { margin-top: .5rem; width: 90%; } } .login-box .card, .register-box .card { margin-bottom: 0; } .login-card-body, .register-card-body { background-color: #fff; border-top: 0; color: #666; padding: 20px; } .login-card-body .input-group .form-control, .register-card-body .input-group .form-control { border-right: 0; } .login-card-body .input-group .form-control:focus, .register-card-body .input-group .form-control:focus { box-shadow: none; } .login-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control:focus ~ .input-group-append .input-group-text { border-color: #80bdff; } .login-card-body .input-group .form-control.is-valid:focus, .register-card-body .input-group .form-control.is-valid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .login-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-prepend .input-group-text, .register-card-body .input-group .form-control.is-valid ~ .input-group-append .input-group-text { border-color: #28a745; } .login-card-body .input-group .form-control.is-invalid:focus, .register-card-body .input-group .form-control.is-invalid:focus { box-shadow: none; } .login-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text, .register-card-body .input-group .form-control.is-invalid ~ .input-group-append .input-group-text { border-color: #dc3545; } .login-card-body .input-group .input-group-text, .register-card-body .input-group .input-group-text { background-color: transparent; border-bottom-right-radius: 0.25rem; border-left: 0; border-top-right-radius: 0.25rem; color: #777; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .login-box-msg, .register-box-msg { margin: 0; padding: 0 20px 20px; text-align: center; } .social-auth-links { margin: 10px 0; } .dark-mode .login-card-body, .dark-mode .register-card-body { background-color: #343a40; border-color: #6c757d; color: #fff; } .dark-mode .login-logo a, .dark-mode .register-logo a { color: #fff; } .error-page { margin: 20px auto 0; width: 600px; } @media (max-width: 767.98px) { .error-page { width: 100%; } } .error-page > .headline { float: left; font-size: 100px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .headline { float: none; text-align: center; } } .error-page > .error-content { display: block; margin-left: 190px; } @media (max-width: 767.98px) { .error-page > .error-content { margin-left: 0; } } .error-page > .error-content > h3 { font-size: 25px; font-weight: 300; } @media (max-width: 767.98px) { .error-page > .error-content > h3 { text-align: center; } } .invoice { background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); position: relative; } .invoice-title { margin-top: 0; } .dark-mode .invoice { background-color: #343a40; } .profile-user-img { border: 3px solid #adb5bd; margin: 0 auto; padding: 3px; width: 100px; } .profile-username { font-size: 21px; margin-top: 5px; } .post { border-bottom: 1px solid #adb5bd; color: #666; margin-bottom: 15px; padding-bottom: 15px; } .post:last-of-type { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; } .post .user-block { margin-bottom: 15px; width: 100%; } .post .row { width: 100%; } .dark-mode .post { color: #fff; border-color: #6c757d; } .product-image { max-width: 100%; height: auto; width: 100%; } .product-image-thumbs { -ms-flex-align: stretch; align-items: stretch; display: -ms-flexbox; display: flex; margin-top: 2rem; } .product-image-thumb { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); border-radius: 0.25rem; background-color: #fff; border: 1px solid #dee2e6; display: -ms-flexbox; display: flex; margin-right: 1rem; max-width: 7rem; padding: 0.5rem; } .product-image-thumb img { max-width: 100%; height: auto; -ms-flex-item-align: center; align-self: center; } .product-image-thumb:hover { opacity: .5; } .product-share a { margin-right: .5rem; } .projects td { vertical-align: middle; } .projects .list-inline { margin-bottom: 0; } .projects img.table-avatar, .projects .table-avatar img { border-radius: 50%; display: inline; width: 2.5rem; } .projects .project-state { text-align: center; } body.iframe-mode .main-sidebar { display: none; } body.iframe-mode .content-wrapper { margin-left: 0 !important; margin-top: 0 !important; padding-bottom: 0 !important; } body.iframe-mode .main-header, body.iframe-mode .main-footer { display: none; } body.iframe-mode-fullscreen { overflow: hidden; } body.iframe-mode-fullscreen.layout-navbar-fixed .wrapper .content-wrapper { margin-top: 0 !important; } .content-wrapper { height: 100%; } .content-wrapper.iframe-mode .btn-iframe-close { color: #dc3545; position: absolute; line-height: 1; right: .125rem; top: .125rem; z-index: 10; visibility: hidden; } .content-wrapper.iframe-mode .btn-iframe-close:hover, .content-wrapper.iframe-mode .btn-iframe-close:focus { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .navbar-nav { overflow-y: auto; width: 100%; } .content-wrapper.iframe-mode .navbar-nav .nav-link { white-space: nowrap; } .content-wrapper.iframe-mode .navbar-nav .nav-item { position: relative; } .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { -webkit-animation-name: fadeIn; animation-name: fadeIn; -webkit-animation-duration: 0.3s; animation-duration: 0.3s; -webkit-animation-fill-mode: both; animation-fill-mode: both; visibility: visible; } @media (hover: none) and (pointer: coarse) { .content-wrapper.iframe-mode .navbar-nav .nav-item:hover .btn-iframe-close, .content-wrapper.iframe-mode .navbar-nav .nav-item:focus .btn-iframe-close { visibility: visible; } } .content-wrapper.iframe-mode .tab-content { position: relative; } .content-wrapper.iframe-mode .tab-pane + .tab-empty { display: none; } .content-wrapper.iframe-mode .tab-empty { width: 100%; display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; } .content-wrapper.iframe-mode .tab-loading { position: absolute; top: 0; left: 0; width: 100%; display: none; background-color: #f4f6f9; } .content-wrapper.iframe-mode .tab-loading > div { display: -ms-flexbox; display: flex; -ms-flex-pack: center; justify-content: center; -ms-flex-align: center; align-items: center; width: 100%; height: 100%; } .content-wrapper.iframe-mode iframe { border: 0; width: 100%; height: 100%; margin-bottom: -8px; } .content-wrapper.iframe-mode iframe .content-wrapper { padding-bottom: 0 !important; } body.iframe-mode-fullscreen .content-wrapper.iframe-mode { position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin-left: 0 !important; height: 100%; min-height: 100%; z-index: 1048; } .permanent-btn-iframe-close .btn-iframe-close { -webkit-animation: none !important; animation: none !important; visibility: visible !important; opacity: 1; } .dark-mode .content-wrapper.iframe-mode .tab-loading { background-color: #343a40; } .content-wrapper.kanban { height: 1px; } .content-wrapper.kanban .content { height: 100%; overflow-x: auto; overflow-y: hidden; } .content-wrapper.kanban .content .container, .content-wrapper.kanban .content .container-fluid { width: -webkit-max-content; width: -moz-max-content; width: max-content; display: -ms-flexbox; display: flex; -ms-flex-align: stretch; align-items: stretch; } .content-wrapper.kanban .content-header + .content { height: calc(100% - ((2 * 15px) + (1.8rem * 1.2))); } .content-wrapper.kanban .card .card-body { padding: .5rem; } .content-wrapper.kanban .card.card-row { width: 340px; display: inline-block; margin: 0 .5rem; } .content-wrapper.kanban .card.card-row:first-child { margin-left: 0; } .content-wrapper.kanban .card.card-row .card-body { height: calc(100% - (12px + (1.8rem * 1.2) + .5rem)); overflow-y: auto; } .content-wrapper.kanban .card.card-row .card:last-child { margin-bottom: 0; border-bottom-width: 1px; } .content-wrapper.kanban .card.card-row .card .card-header { padding: .5rem .75rem; } .content-wrapper.kanban .card.card-row .card .card-body { padding: .75rem; } .content-wrapper.kanban .btn-tool.btn-link { text-decoration: underline; padding-left: 0; padding-right: 0; } /*# sourceMappingURL=adminlte.pages.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/css/alt/adminlte.plugins.css ================================================ /*! * AdminLTE v3.2.0 * Only Plugins * Author: Colorlib * Website: AdminLTE.io * License: Open source - MIT */ @-webkit-keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @keyframes flipInX { 0% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transform: perspective(400px) rotate3d(1, 0, 0, 90deg); transition-timing-function: ease-in; opacity: 0; } 40% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transform: perspective(400px) rotate3d(1, 0, 0, -20deg); transition-timing-function: ease-in; } 60% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg); transform: perspective(400px) rotate3d(1, 0, 0, 10deg); opacity: 1; } 80% { -webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg); transform: perspective(400px) rotate3d(1, 0, 0, -5deg); } 100% { -webkit-transform: perspective(400px); transform: perspective(400px); } } @-webkit-keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } @-webkit-keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @keyframes shake { 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); transform: translate(2px, 1px) rotate(0deg); } 10% { -webkit-transform: translate(-1px, -2px) rotate(-2deg); transform: translate(-1px, -2px) rotate(-2deg); } 20% { -webkit-transform: translate(-3px, 0) rotate(3deg); transform: translate(-3px, 0) rotate(3deg); } 30% { -webkit-transform: translate(0, 2px) rotate(0deg); transform: translate(0, 2px) rotate(0deg); } 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); transform: translate(1px, -1px) rotate(1deg); } 50% { -webkit-transform: translate(-1px, 2px) rotate(-1deg); transform: translate(-1px, 2px) rotate(-1deg); } 60% { -webkit-transform: translate(-3px, 1px) rotate(0deg); transform: translate(-3px, 1px) rotate(0deg); } 70% { -webkit-transform: translate(2px, 1px) rotate(-2deg); transform: translate(2px, 1px) rotate(-2deg); } 80% { -webkit-transform: translate(-1px, -1px) rotate(4deg); transform: translate(-1px, -1px) rotate(4deg); } 90% { -webkit-transform: translate(2px, 2px) rotate(0deg); transform: translate(2px, 2px) rotate(0deg); } 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); transform: translate(1px, -2px) rotate(-1deg); } } @-webkit-keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } @keyframes wobble { 0% { -webkit-transform: none; transform: none; } 15% { -webkit-transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg); } 30% { -webkit-transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg); } 45% { -webkit-transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg); } 60% { -webkit-transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg); } 75% { -webkit-transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg); } 100% { -webkit-transform: none; transform: none; } } .fc-button { background: #f8f9fa; background-image: none; border-bottom-color: #ddd; border-color: #ddd; color: #495057; } .fc-button:hover, .fc-button:active, .fc-button.hover { background-color: #e9e9e9; } .fc-header-title h2 { color: #666; font-size: 15px; line-height: 1.6em; margin-left: 10px; } .fc-header-right { padding-right: 10px; } .fc-header-left { padding-left: 10px; } .fc-widget-header { background: #fafafa; } .fc-grid { border: 0; width: 100%; } .fc-widget-header:first-of-type, .fc-widget-content:first-of-type { border-left: 0; border-right: 0; } .fc-widget-header:last-of-type, .fc-widget-content:last-of-type { border-right: 0; } .fc-toolbar, .fc-toolbar.fc-header-toolbar { margin: 0; padding: 1rem; } @media (max-width: 575.98px) { .fc-toolbar { -ms-flex-direction: column; flex-direction: column; } .fc-toolbar .fc-left { -ms-flex-order: 1; order: 1; margin-bottom: .5rem; } .fc-toolbar .fc-center { -ms-flex-order: 0; order: 0; margin-bottom: .375rem; } .fc-toolbar .fc-right { -ms-flex-order: 2; order: 2; } } .fc-day-number { font-size: 20px; font-weight: 300; padding-right: 10px; } .fc-color-picker { list-style: none; margin: 0; padding: 0; } .fc-color-picker > li { float: left; font-size: 30px; line-height: 30px; margin-right: 5px; } .fc-color-picker > li .fa, .fc-color-picker > li .fas, .fc-color-picker > li .far, .fc-color-picker > li .fab, .fc-color-picker > li .fal, .fc-color-picker > li .fad, .fc-color-picker > li .svg-inline--fa, .fc-color-picker > li .ion { transition: -webkit-transform linear .3s; transition: transform linear .3s; transition: transform linear .3s, -webkit-transform linear .3s; } .fc-color-picker > li .fa:hover, .fc-color-picker > li .fas:hover, .fc-color-picker > li .far:hover, .fc-color-picker > li .fab:hover, .fc-color-picker > li .fal:hover, .fc-color-picker > li .fad:hover, .fc-color-picker > li .svg-inline--fa:hover, .fc-color-picker > li .ion:hover { -webkit-transform: rotate(30deg); transform: rotate(30deg); } #add-new-event { transition: all linear .3s; } .external-event { box-shadow: 0 0 1px rgba(0, 0, 0, 0.125), 0 1px 3px rgba(0, 0, 0, 0.2); border-radius: 0.25rem; cursor: move; font-weight: 700; margin-bottom: 4px; padding: 5px 10px; } .external-event:hover { box-shadow: inset 0 0 90px rgba(0, 0, 0, 0.2); } .select2-container--default .select2-selection--single { border: 1px solid #ced4da; padding: 0.46875rem 0.75rem; height: calc(2.25rem + 2px); } .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-dropdown { border: 1px solid #ced4da; } .select2-container--default .select2-results__option { padding: 6px 12px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .select2-container--default .select2-selection--single .select2-selection__rendered { padding-left: 0; height: auto; margin-top: -3px; } .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__rendered { padding-right: 6px; padding-left: 20px; } .select2-container--default .select2-selection--single .select2-selection__arrow { height: 31px; right: 6px; } .select2-container--default .select2-selection--single .select2-selection__arrow b { margin-top: 0; } .select2-container--default .select2-dropdown .select2-search__field, .select2-container--default .select2-search--inline .select2-search__field { border: 1px solid #ced4da; } .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-search--inline .select2-search__field:focus { outline: none; border: 1px solid #80bdff; } .select2-container--default .select2-dropdown.select2-dropdown--below { border-top: 0; } .select2-container--default .select2-dropdown.select2-dropdown--above { border-bottom: 0; } .select2-container--default .select2-results__option[aria-disabled='true'] { color: #6c757d; } .select2-container--default .select2-results__option[aria-selected='true'] { background-color: #dee2e6; } .select2-container--default .select2-results__option[aria-selected='true'], .select2-container--default .select2-results__option[aria-selected='true']:hover { color: #1f2d3d; } .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-selection--multiple { border: 1px solid #ced4da; min-height: calc(2.25rem + 2px); } .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.375rem 0.375rem; margin-bottom: -0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { width: 100%; margin-left: 0.375rem; } .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline .select2-search__field { width: 100% !important; } .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { border: 0; margin-top: 6px; } .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; padding: 0 10px; margin-top: .31rem; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); float: right; margin-left: 5px; margin-right: -2px; } .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .text-sm .select2-container--default .select2-selection--multiple .select2-search.select2-search--inline .select2-search__field, .select2-container--default .select2-selection--multiple.text-sm .select2-search.select2-search--inline .select2-search__field { margin-top: 8px; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__choice, .select2-container--default .select2-selection--multiple.text-sm .select2-selection__choice { margin-top: .4rem; } .select2-container--default.select2-container--focus .select2-selection--single, .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-container--default.select2-container--focus .select2-search__field { border: 0; } .select2-container--default .select2-selection--single .select2-selection__rendered li { padding-right: 10px; } .input-group-prepend ~ .select2-container--default .select2-selection { border-bottom-left-radius: 0; border-top-left-radius: 0; } .input-group > .select2-container--default:not(:last-child) .select2-selection { border-bottom-right-radius: 0; border-top-right-radius: 0; } .select2-container--bootstrap4.select2-container--focus .select2-selection { box-shadow: none; } select.form-control-sm ~ .select2-container--default { font-size: 75%; } .text-sm .select2-container--default .select2-selection--single, select.form-control-sm ~ .select2-container--default .select2-selection--single { height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--single .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__rendered { margin-top: -.4rem; } .text-sm .select2-container--default .select2-selection--single .select2-selection__arrow, select.form-control-sm ~ .select2-container--default .select2-selection--single .select2-selection__arrow { top: -.12rem; } .text-sm .select2-container--default .select2-selection--multiple, select.form-control-sm ~ .select2-container--default .select2-selection--multiple { min-height: calc(1.8125rem + 2px); } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered { padding: 0 0.25rem 0.25rem; margin-top: -0.1rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered li:first-child.select2-search.select2-search--inline { margin-left: 0.25rem; } .text-sm .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field, select.form-control-sm ~ .select2-container--default .select2-selection--multiple .select2-selection__rendered .select2-search.select2-search--inline .select2-search__field { margin-top: 6px; } .maximized-card .select2-dropdown { z-index: 9999; } .select2-primary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-primary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-primary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-primary .select2-search--inline .select2-search__field:focus, .select2-primary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-primary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-primary .select2-results__option--highlighted, .select2-primary .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-primary .select2-results__option--highlighted[aria-selected]:hover, .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple:focus, .select2-primary .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-primary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-primary.select2-container--focus .select2-selection--multiple, .select2-primary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-secondary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-secondary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-secondary.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-secondary .select2-search--inline .select2-search__field:focus, .select2-secondary .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-secondary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-secondary .select2-results__option--highlighted, .select2-secondary .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-secondary .select2-results__option--highlighted[aria-selected]:hover, .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple:focus, .select2-secondary .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-secondary .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-secondary.select2-container--focus .select2-selection--multiple, .select2-secondary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-success + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-success + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-success.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-success .select2-search--inline .select2-search__field:focus, .select2-success .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-success .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-success .select2-results__option--highlighted, .select2-success .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-success .select2-results__option--highlighted[aria-selected]:hover, .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple:focus, .select2-success .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-success .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-success.select2-container--focus .select2-selection--multiple, .select2-success .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-info + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-info + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-info.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-info .select2-search--inline .select2-search__field:focus, .select2-info .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-info .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-info .select2-results__option--highlighted, .select2-info .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-info .select2-results__option--highlighted[aria-selected]:hover, .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple:focus, .select2-info .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-info .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-info.select2-container--focus .select2-selection--multiple, .select2-info .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-warning + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-warning + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-warning.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-warning .select2-search--inline .select2-search__field:focus, .select2-warning .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-warning .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-warning .select2-results__option--highlighted, .select2-warning .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-warning .select2-results__option--highlighted[aria-selected]:hover, .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple:focus, .select2-warning .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-warning .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-warning.select2-container--focus .select2-selection--multiple, .select2-warning .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-danger + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-danger + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-danger.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-danger .select2-search--inline .select2-search__field:focus, .select2-danger .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-danger .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-danger .select2-results__option--highlighted, .select2-danger .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-danger .select2-results__option--highlighted[aria-selected]:hover, .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple:focus, .select2-danger .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-danger .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-danger.select2-container--focus .select2-selection--multiple, .select2-danger .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-light + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-light + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-light.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-light .select2-search--inline .select2-search__field:focus, .select2-light .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-light .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-light .select2-results__option--highlighted, .select2-light .select2-container--default .select2-results__option--highlighted { background-color: #f8f9fa; color: #1f2d3d; } .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-light .select2-results__option--highlighted[aria-selected]:hover, .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eff1f4; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple:focus, .select2-light .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f8f9fa; border-color: #e9ecef; color: #1f2d3d; } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-light .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-light.select2-container--focus .select2-selection--multiple, .select2-light .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-dark .select2-search--inline .select2-search__field:focus, .select2-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-dark .select2-results__option--highlighted, .select2-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple:focus, .select2-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-dark.select2-container--focus .select2-selection--multiple, .select2-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .select2-lightblue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #99c5de; } .select2-lightblue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #99c5de; } .select2-container--default .select2-lightblue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lightblue .select2-search--inline .select2-search__field:focus, .select2-lightblue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lightblue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #99c5de; } .select2-container--default .select2-lightblue .select2-results__option--highlighted, .select2-lightblue .select2-container--default .select2-results__option--highlighted { background-color: #3c8dbc; color: #fff; } .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lightblue .select2-results__option--highlighted[aria-selected]:hover, .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3884b0; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple:focus, .select2-lightblue .select2-container--default .select2-selection--multiple:focus { border-color: #99c5de; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3c8dbc; border-color: #367fa9; color: #fff; } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-lightblue.select2-container--focus .select2-selection--multiple, .select2-lightblue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #99c5de; } .select2-navy + .select2-container--default.select2-container--open .select2-selection--single { border-color: #005ebf; } .select2-navy + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #005ebf; } .select2-container--default .select2-navy.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-navy .select2-search--inline .select2-search__field:focus, .select2-navy .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-navy .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #005ebf; } .select2-container--default .select2-navy .select2-results__option--highlighted, .select2-navy .select2-container--default .select2-results__option--highlighted { background-color: #001f3f; color: #fff; } .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-navy .select2-results__option--highlighted[aria-selected]:hover, .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #001730; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple:focus, .select2-navy .select2-container--default .select2-selection--multiple:focus { border-color: #005ebf; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #001f3f; border-color: #001226; color: #fff; } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-navy .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-navy.select2-container--focus .select2-selection--multiple, .select2-navy .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #005ebf; } .select2-olive + .select2-container--default.select2-container--open .select2-selection--single { border-color: #87cfaf; } .select2-olive + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #87cfaf; } .select2-container--default .select2-olive.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-olive .select2-search--inline .select2-search__field:focus, .select2-olive .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-olive .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #87cfaf; } .select2-container--default .select2-olive .select2-results__option--highlighted, .select2-olive .select2-container--default .select2-results__option--highlighted { background-color: #3d9970; color: #fff; } .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-olive .select2-results__option--highlighted[aria-selected]:hover, .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #398e68; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple:focus, .select2-olive .select2-container--default .select2-selection--multiple:focus { border-color: #87cfaf; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3d9970; border-color: #368763; color: #fff; } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-olive .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-olive.select2-container--focus .select2-selection--multiple, .select2-olive .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #87cfaf; } .select2-lime + .select2-container--default.select2-container--open .select2-selection--single { border-color: #81ffb8; } .select2-lime + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #81ffb8; } .select2-container--default .select2-lime.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-lime .select2-search--inline .select2-search__field:focus, .select2-lime .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-lime .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #81ffb8; } .select2-container--default .select2-lime .select2-results__option--highlighted, .select2-lime .select2-container--default .select2-results__option--highlighted { background-color: #01ff70; color: #1f2d3d; } .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-lime .select2-results__option--highlighted[aria-selected]:hover, .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00f169; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple:focus, .select2-lime .select2-container--default .select2-selection--multiple:focus { border-color: #81ffb8; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #01ff70; border-color: #00e765; color: #1f2d3d; } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-lime .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-lime.select2-container--focus .select2-selection--multiple, .select2-lime .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #81ffb8; } .select2-fuchsia + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f88adf; } .select2-fuchsia + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f88adf; } .select2-container--default .select2-fuchsia.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-fuchsia .select2-search--inline .select2-search__field:focus, .select2-fuchsia .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-fuchsia .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f88adf; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted, .select2-fuchsia .select2-container--default .select2-results__option--highlighted { background-color: #f012be; color: #fff; } .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-fuchsia .select2-results__option--highlighted[aria-selected]:hover, .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e40eb4; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple:focus, .select2-fuchsia .select2-container--default .select2-selection--multiple:focus { border-color: #f88adf; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f012be; border-color: #db0ead; color: #fff; } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-fuchsia.select2-container--focus .select2-selection--multiple, .select2-fuchsia .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f88adf; } .select2-maroon + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f083ab; } .select2-maroon + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f083ab; } .select2-container--default .select2-maroon.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-maroon .select2-search--inline .select2-search__field:focus, .select2-maroon .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-maroon .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f083ab; } .select2-container--default .select2-maroon .select2-results__option--highlighted, .select2-maroon .select2-container--default .select2-results__option--highlighted { background-color: #d81b60; color: #fff; } .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-maroon .select2-results__option--highlighted[aria-selected]:hover, .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ca195a; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple:focus, .select2-maroon .select2-container--default .select2-selection--multiple:focus { border-color: #f083ab; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #d81b60; border-color: #c11856; color: #fff; } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-maroon .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-maroon.select2-container--focus .select2-selection--multiple, .select2-maroon .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f083ab; } .select2-blue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #80bdff; } .select2-blue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #80bdff; } .select2-container--default .select2-blue.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-blue .select2-search--inline .select2-search__field:focus, .select2-blue .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-blue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #80bdff; } .select2-container--default .select2-blue .select2-results__option--highlighted, .select2-blue .select2-container--default .select2-results__option--highlighted { background-color: #007bff; color: #fff; } .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-blue .select2-results__option--highlighted[aria-selected]:hover, .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #0074f0; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple:focus, .select2-blue .select2-container--default .select2-selection--multiple:focus { border-color: #80bdff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #007bff; border-color: #006fe6; color: #fff; } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-blue .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-blue.select2-container--focus .select2-selection--multiple, .select2-blue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #80bdff; } .select2-indigo + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b389f9; } .select2-indigo + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b389f9; } .select2-container--default .select2-indigo.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-indigo .select2-search--inline .select2-search__field:focus, .select2-indigo .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-indigo .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b389f9; } .select2-container--default .select2-indigo .select2-results__option--highlighted, .select2-indigo .select2-container--default .select2-results__option--highlighted { background-color: #6610f2; color: #fff; } .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-indigo .select2-results__option--highlighted[aria-selected]:hover, .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #5f0de6; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple:focus, .select2-indigo .select2-container--default .select2-selection--multiple:focus { border-color: #b389f9; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6610f2; border-color: #5b0cdd; color: #fff; } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-indigo .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-indigo.select2-container--focus .select2-selection--multiple, .select2-indigo .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b389f9; } .select2-purple + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b8a2e0; } .select2-purple + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b8a2e0; } .select2-container--default .select2-purple.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-purple .select2-search--inline .select2-search__field:focus, .select2-purple .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-purple .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b8a2e0; } .select2-container--default .select2-purple .select2-results__option--highlighted, .select2-purple .select2-container--default .select2-results__option--highlighted { background-color: #6f42c1; color: #fff; } .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-purple .select2-results__option--highlighted[aria-selected]:hover, .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #683cb8; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple:focus, .select2-purple .select2-container--default .select2-selection--multiple:focus { border-color: #b8a2e0; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6f42c1; border-color: #643ab0; color: #fff; } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-purple .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-purple.select2-container--focus .select2-selection--multiple, .select2-purple .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b8a2e0; } .select2-pink + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f6b0d0; } .select2-pink + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f6b0d0; } .select2-container--default .select2-pink.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-pink .select2-search--inline .select2-search__field:focus, .select2-pink .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-pink .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f6b0d0; } .select2-container--default .select2-pink .select2-results__option--highlighted, .select2-pink .select2-container--default .select2-results__option--highlighted { background-color: #e83e8c; color: #fff; } .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-pink .select2-results__option--highlighted[aria-selected]:hover, .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e63084; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple:focus, .select2-pink .select2-container--default .select2-selection--multiple:focus { border-color: #f6b0d0; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e83e8c; border-color: #e5277e; color: #fff; } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-pink .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-pink.select2-container--focus .select2-selection--multiple, .select2-pink .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f6b0d0; } .select2-red + .select2-container--default.select2-container--open .select2-selection--single { border-color: #efa2a9; } .select2-red + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #efa2a9; } .select2-container--default .select2-red.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-red .select2-search--inline .select2-search__field:focus, .select2-red .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-red .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #efa2a9; } .select2-container--default .select2-red .select2-results__option--highlighted, .select2-red .select2-container--default .select2-results__option--highlighted { background-color: #dc3545; color: #fff; } .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-red .select2-results__option--highlighted[aria-selected]:hover, .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #da2839; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple:focus, .select2-red .select2-container--default .select2-selection--multiple:focus { border-color: #efa2a9; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #dc3545; border-color: #d32535; color: #fff; } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-red .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-red.select2-container--focus .select2-selection--multiple, .select2-red .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #efa2a9; } .select2-orange + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fec392; } .select2-orange + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fec392; } .select2-container--default .select2-orange.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-orange .select2-search--inline .select2-search__field:focus, .select2-orange .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-orange .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fec392; } .select2-container--default .select2-orange .select2-results__option--highlighted, .select2-orange .select2-container--default .select2-results__option--highlighted { background-color: #fd7e14; color: #1f2d3d; } .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-orange .select2-results__option--highlighted[aria-selected]:hover, .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #fd7605; color: #fff; } .select2-container--default .select2-orange .select2-selection--multiple:focus, .select2-orange .select2-container--default .select2-selection--multiple:focus { border-color: #fec392; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fd7e14; border-color: #f57102; color: #1f2d3d; } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-orange .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-orange.select2-container--focus .select2-selection--multiple, .select2-orange .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fec392; } .select2-yellow + .select2-container--default.select2-container--open .select2-selection--single { border-color: #ffe187; } .select2-yellow + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #ffe187; } .select2-container--default .select2-yellow.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-yellow .select2-search--inline .select2-search__field:focus, .select2-yellow .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-yellow .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #ffe187; } .select2-container--default .select2-yellow .select2-results__option--highlighted, .select2-yellow .select2-container--default .select2-results__option--highlighted { background-color: #ffc107; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-yellow .select2-results__option--highlighted[aria-selected]:hover, .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7b900; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple:focus, .select2-yellow .select2-container--default .select2-selection--multiple:focus { border-color: #ffe187; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ffc107; border-color: #edb100; color: #1f2d3d; } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-yellow .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-yellow.select2-container--focus .select2-selection--multiple, .select2-yellow .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #ffe187; } .select2-green + .select2-container--default.select2-container--open .select2-selection--single { border-color: #71dd8a; } .select2-green + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #71dd8a; } .select2-container--default .select2-green.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-green .select2-search--inline .select2-search__field:focus, .select2-green .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-green .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #71dd8a; } .select2-container--default .select2-green .select2-results__option--highlighted, .select2-green .select2-container--default .select2-results__option--highlighted { background-color: #28a745; color: #fff; } .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-green .select2-results__option--highlighted[aria-selected]:hover, .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #259b40; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple:focus, .select2-green .select2-container--default .select2-selection--multiple:focus { border-color: #71dd8a; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #28a745; border-color: #23923d; color: #fff; } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-green .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-green.select2-container--focus .select2-selection--multiple, .select2-green .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #71dd8a; } .select2-teal + .select2-container--default.select2-container--open .select2-selection--single { border-color: #7eeaca; } .select2-teal + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #7eeaca; } .select2-container--default .select2-teal.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-teal .select2-search--inline .select2-search__field:focus, .select2-teal .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-teal .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #7eeaca; } .select2-container--default .select2-teal .select2-results__option--highlighted, .select2-teal .select2-container--default .select2-results__option--highlighted { background-color: #20c997; color: #fff; } .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-teal .select2-results__option--highlighted[aria-selected]:hover, .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1ebc8d; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple:focus, .select2-teal .select2-container--default .select2-selection--multiple:focus { border-color: #7eeaca; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #20c997; border-color: #1cb386; color: #fff; } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-teal .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-teal.select2-container--focus .select2-selection--multiple, .select2-teal .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #7eeaca; } .select2-cyan + .select2-container--default.select2-container--open .select2-selection--single { border-color: #63d9ec; } .select2-cyan + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #63d9ec; } .select2-container--default .select2-cyan.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-cyan .select2-search--inline .select2-search__field:focus, .select2-cyan .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-cyan .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #63d9ec; } .select2-container--default .select2-cyan .select2-results__option--highlighted, .select2-cyan .select2-container--default .select2-results__option--highlighted { background-color: #17a2b8; color: #fff; } .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-cyan .select2-results__option--highlighted[aria-selected]:hover, .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1596aa; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple:focus, .select2-cyan .select2-container--default .select2-selection--multiple:focus { border-color: #63d9ec; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #17a2b8; border-color: #148ea1; color: #fff; } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-cyan .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-cyan.select2-container--focus .select2-selection--multiple, .select2-cyan .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #63d9ec; } .select2-white + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .select2-white + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .select2-white.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-white .select2-search--inline .select2-search__field:focus, .select2-white .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-white .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .select2-white .select2-results__option--highlighted, .select2-white .select2-container--default .select2-results__option--highlighted { background-color: #fff; color: #1f2d3d; } .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-white .select2-results__option--highlighted[aria-selected]:hover, .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7f7f7; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple:focus, .select2-white .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border-color: #f2f2f2; color: #1f2d3d; } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .select2-white .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .select2-white.select2-container--focus .select2-selection--multiple, .select2-white .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .select2-gray + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .select2-gray + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .select2-gray.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray .select2-search--inline .select2-search__field:focus, .select2-gray .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .select2-gray .select2-results__option--highlighted, .select2-gray .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray .select2-results__option--highlighted[aria-selected]:hover, .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple:focus, .select2-gray .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray.select2-container--focus .select2-selection--multiple, .select2-gray .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .select2-gray-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .select2-gray-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .select2-gray-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .select2-gray-dark .select2-search--inline .select2-search__field:focus, .select2-gray-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .select2-gray-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted, .select2-gray-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .select2-gray-dark .select2-results__option--highlighted[aria-selected]:hover, .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple:focus, .select2-gray-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .select2-gray-dark.select2-container--focus .select2-selection--multiple, .select2-gray-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .dark-mode .select2-selection { background-color: #343a40; border-color: #6c757d; } .dark-mode .select2-container--disabled .select2-selection--single { background-color: #454d55; } .dark-mode .select2-selection--single { background-color: #343a40; border-color: #6c757d; } .dark-mode .select2-selection--single .select2-selection__rendered { color: #fff; } .dark-mode .select2-dropdown .select2-search__field, .dark-mode .select2-search--inline .select2-search__field { background-color: #343a40; border-color: #6c757d; color: white; } .dark-mode .select2-dropdown { background-color: #343a40; border-color: #6c757d; color: white; } .dark-mode .select2-results__option[aria-selected="true"] { background-color: #3f474e !important; color: #dee2e6; } .dark-mode .select2-container .select2-search--inline .select2-search__field { background-color: transparent; color: #fff; } .dark-mode .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { color: #fff; } .dark-mode .select2-primary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #85a7ca; } .dark-mode .select2-primary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-primary.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-primary .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-primary .select2-search--inline .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-primary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #85a7ca; } .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted, .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted { background-color: #3f6791; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-primary .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-primary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3a5f86; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple:focus, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple:focus { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3f6791; border-color: #375a7f; color: #fff; } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-primary .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-primary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-primary.select2-container--focus .select2-selection--multiple, .dark-mode .select2-primary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #85a7ca; } .dark-mode .select2-secondary + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .dark-mode .select2-secondary + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-secondary.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-secondary .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-secondary .select2-search--inline .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-secondary .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted, .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-secondary .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-secondary .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple:focus, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-secondary .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-secondary .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-secondary.select2-container--focus .select2-selection--multiple, .dark-mode .select2-secondary .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .dark-mode .select2-success + .select2-container--default.select2-container--open .select2-selection--single { border-color: #3dffcd; } .dark-mode .select2-success + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-success.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-success .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-success .select2-search--inline .select2-search__field:focus, .dark-mode .select2-success .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-success .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-success .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #3dffcd; } .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted, .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted { background-color: #00bc8c; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-success .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-success .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00ad81; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple:focus, .dark-mode .select2-success .select2-container--default .select2-selection--multiple:focus { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #00bc8c; border-color: #00a379; color: #fff; } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-success .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-success .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-success.select2-container--focus .select2-selection--multiple, .dark-mode .select2-success .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #3dffcd; } .dark-mode .select2-info + .select2-container--default.select2-container--open .select2-selection--single { border-color: #a0cfee; } .dark-mode .select2-info + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-info.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-info .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-info .select2-search--inline .select2-search__field:focus, .dark-mode .select2-info .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-info .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-info .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #a0cfee; } .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted, .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted { background-color: #3498db; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-info .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-info .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2791d9; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple:focus, .dark-mode .select2-info .select2-container--default .select2-selection--multiple:focus { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3498db; border-color: #258cd1; color: #fff; } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-info .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-info .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-info.select2-container--focus .select2-selection--multiple, .dark-mode .select2-info .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #a0cfee; } .dark-mode .select2-warning + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f9cf8b; } .dark-mode .select2-warning + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-warning.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-warning .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-warning .select2-search--inline .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-warning .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f9cf8b; } .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted, .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted { background-color: #f39c12; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-warning .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-warning .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ea940c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple:focus, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple:focus { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f39c12; border-color: #e08e0b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-warning .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-warning .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-warning.select2-container--focus .select2-selection--multiple, .dark-mode .select2-warning .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f9cf8b; } .dark-mode .select2-danger + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f5b4ae; } .dark-mode .select2-danger + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-danger.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-danger .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-danger .select2-search--inline .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-danger .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f5b4ae; } .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted, .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted { background-color: #e74c3c; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-danger .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-danger .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e53f2e; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple:focus, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple:focus { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e74c3c; border-color: #e43725; color: #fff; } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-danger .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-danger .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-danger.select2-container--focus .select2-selection--multiple, .dark-mode .select2-danger .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f5b4ae; } .dark-mode .select2-light + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .dark-mode .select2-light + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .dark-mode .select2-light.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-light .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-light .select2-search--inline .select2-search__field:focus, .dark-mode .select2-light .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-light .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-light .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted, .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted { background-color: #f8f9fa; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-light .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-light .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eff1f4; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple:focus, .dark-mode .select2-light .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f8f9fa; border-color: #e9ecef; color: #1f2d3d; } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-light .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-light .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-light.select2-container--focus .select2-selection--multiple, .dark-mode .select2-light .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .dark-mode .select2-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .dark-mode .select2-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-dark .select2-search--inline .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted, .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-dark .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple:focus, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-dark.select2-container--focus .select2-selection--multiple, .dark-mode .select2-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .dark-mode .select2-lightblue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #e6f1f7; } .dark-mode .select2-lightblue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lightblue .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lightblue .select2-search--inline .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-lightblue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted, .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted { background-color: #86bad8; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-lightblue .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-lightblue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #7ab3d5; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple:focus, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple:focus { border-color: #e6f1f7; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #86bad8; border-color: #72afd2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-lightblue .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-lightblue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-lightblue.select2-container--focus .select2-selection--multiple, .dark-mode .select2-lightblue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #e6f1f7; } .dark-mode .select2-navy + .select2-container--default.select2-container--open .select2-selection--single { border-color: #006ad8; } .dark-mode .select2-navy + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #006ad8; } .select2-container--default .dark-mode .select2-navy.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-navy .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-navy .select2-search--inline .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-navy .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #006ad8; } .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted, .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted { background-color: #002c59; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-navy .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-navy .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #002449; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple:focus, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple:focus { border-color: #006ad8; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #002c59; border-color: #001f3f; color: #fff; } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-navy .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-navy .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-navy.select2-container--focus .select2-selection--multiple, .dark-mode .select2-navy .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #006ad8; } .dark-mode .select2-olive + .select2-container--default.select2-container--open .select2-selection--single { border-color: #cfecdf; } .dark-mode .select2-olive + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #cfecdf; } .select2-container--default .dark-mode .select2-olive.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-olive .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-olive .select2-search--inline .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-olive .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #cfecdf; } .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted, .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted { background-color: #74c8a3; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-olive .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-olive .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #69c39b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple:focus, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple:focus { border-color: #cfecdf; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #74c8a3; border-color: #62c096; color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-olive .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-olive .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-olive.select2-container--focus .select2-selection--multiple, .dark-mode .select2-olive .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #cfecdf; } .dark-mode .select2-lime + .select2-container--default.select2-container--open .select2-selection--single { border-color: #e7fff1; } .dark-mode .select2-lime + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #e7fff1; } .select2-container--default .dark-mode .select2-lime.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lime .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-lime .select2-search--inline .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-lime .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #e7fff1; } .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted, .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted { background-color: #67ffa9; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-lime .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-lime .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #58ffa1; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple:focus, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple:focus { border-color: #e7fff1; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #67ffa9; border-color: #4eff9b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-lime .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-lime .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-lime.select2-container--focus .select2-selection--multiple, .dark-mode .select2-lime .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #e7fff1; } .dark-mode .select2-fuchsia + .select2-container--default.select2-container--open .select2-selection--single { border-color: #feeaf9; } .dark-mode .select2-fuchsia + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-fuchsia .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-fuchsia .select2-search--inline .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted, .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted { background-color: #f672d8; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-fuchsia .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-fuchsia .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f564d4; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple:focus, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple:focus { border-color: #feeaf9; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f672d8; border-color: #f55ad2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-fuchsia .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-fuchsia .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-fuchsia.select2-container--focus .select2-selection--multiple, .dark-mode .select2-fuchsia .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #feeaf9; } .dark-mode .select2-maroon + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fbdee8; } .dark-mode .select2-maroon + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fbdee8; } .select2-container--default .dark-mode .select2-maroon.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-maroon .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-maroon .select2-search--inline .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-maroon .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fbdee8; } .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted, .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted { background-color: #ed6c9b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-maroon .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-maroon .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #eb5f92; color: #fff; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple:focus, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple:focus { border-color: #fbdee8; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #ed6c9b; border-color: #ea568c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-maroon .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-maroon .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-maroon.select2-container--focus .select2-selection--multiple, .dark-mode .select2-maroon .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fbdee8; } .dark-mode .select2-blue + .select2-container--default.select2-container--open .select2-selection--single { border-color: #85a7ca; } .dark-mode .select2-blue + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-blue.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-blue .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-blue .select2-search--inline .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-blue .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #85a7ca; } .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted, .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted { background-color: #3f6791; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-blue .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-blue .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #3a5f86; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple:focus, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple:focus { border-color: #85a7ca; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3f6791; border-color: #375a7f; color: #fff; } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-blue .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-blue .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-blue.select2-container--focus .select2-selection--multiple, .dark-mode .select2-blue .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #85a7ca; } .dark-mode .select2-indigo + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b389f9; } .dark-mode .select2-indigo + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b389f9; } .select2-container--default .dark-mode .select2-indigo.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-indigo .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-indigo .select2-search--inline .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-indigo .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b389f9; } .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted, .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted { background-color: #6610f2; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-indigo .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-indigo .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #5f0de6; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple:focus, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple:focus { border-color: #b389f9; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6610f2; border-color: #5b0cdd; color: #fff; } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-indigo .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-indigo .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-indigo.select2-container--focus .select2-selection--multiple, .dark-mode .select2-indigo .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b389f9; } .dark-mode .select2-purple + .select2-container--default.select2-container--open .select2-selection--single { border-color: #b8a2e0; } .dark-mode .select2-purple + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #b8a2e0; } .select2-container--default .dark-mode .select2-purple.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-purple .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-purple .select2-search--inline .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-purple .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #b8a2e0; } .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted, .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted { background-color: #6f42c1; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-purple .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-purple .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #683cb8; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple:focus, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple:focus { border-color: #b8a2e0; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6f42c1; border-color: #643ab0; color: #fff; } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-purple .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-purple .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-purple.select2-container--focus .select2-selection--multiple, .dark-mode .select2-purple .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #b8a2e0; } .dark-mode .select2-pink + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f6b0d0; } .dark-mode .select2-pink + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f6b0d0; } .select2-container--default .dark-mode .select2-pink.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-pink .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-pink .select2-search--inline .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-pink .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f6b0d0; } .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted, .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted { background-color: #e83e8c; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-pink .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-pink .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e63084; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple:focus, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple:focus { border-color: #f6b0d0; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e83e8c; border-color: #e5277e; color: #fff; } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-pink .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-pink .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-pink.select2-container--focus .select2-selection--multiple, .dark-mode .select2-pink .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f6b0d0; } .dark-mode .select2-red + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f5b4ae; } .dark-mode .select2-red + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-red.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-red .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-red .select2-search--inline .select2-search__field:focus, .dark-mode .select2-red .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-red .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-red .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f5b4ae; } .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted, .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted { background-color: #e74c3c; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-red .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-red .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #e53f2e; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple:focus, .dark-mode .select2-red .select2-container--default .select2-selection--multiple:focus { border-color: #f5b4ae; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #e74c3c; border-color: #e43725; color: #fff; } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-red .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-red .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-red.select2-container--focus .select2-selection--multiple, .dark-mode .select2-red .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f5b4ae; } .dark-mode .select2-orange + .select2-container--default.select2-container--open .select2-selection--single { border-color: #fec392; } .dark-mode .select2-orange + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #fec392; } .select2-container--default .dark-mode .select2-orange.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-orange .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-orange .select2-search--inline .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-orange .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #fec392; } .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted, .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted { background-color: #fd7e14; color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-orange .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-orange .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #fd7605; color: #fff; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple:focus, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple:focus { border-color: #fec392; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fd7e14; border-color: #f57102; color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-orange .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-orange .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-orange.select2-container--focus .select2-selection--multiple, .dark-mode .select2-orange .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #fec392; } .dark-mode .select2-yellow + .select2-container--default.select2-container--open .select2-selection--single { border-color: #f9cf8b; } .dark-mode .select2-yellow + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-yellow.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-yellow .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-yellow .select2-search--inline .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-yellow .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #f9cf8b; } .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted, .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted { background-color: #f39c12; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-yellow .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-yellow .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #ea940c; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple:focus, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple:focus { border-color: #f9cf8b; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #f39c12; border-color: #e08e0b; color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-yellow .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-yellow .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-yellow.select2-container--focus .select2-selection--multiple, .dark-mode .select2-yellow .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #f9cf8b; } .dark-mode .select2-green + .select2-container--default.select2-container--open .select2-selection--single { border-color: #3dffcd; } .dark-mode .select2-green + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-green.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-green .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-green .select2-search--inline .select2-search__field:focus, .dark-mode .select2-green .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-green .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-green .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #3dffcd; } .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted, .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted { background-color: #00bc8c; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-green .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-green .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #00ad81; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple:focus, .dark-mode .select2-green .select2-container--default .select2-selection--multiple:focus { border-color: #3dffcd; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #00bc8c; border-color: #00a379; color: #fff; } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-green .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-green .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-green.select2-container--focus .select2-selection--multiple, .dark-mode .select2-green .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #3dffcd; } .dark-mode .select2-teal + .select2-container--default.select2-container--open .select2-selection--single { border-color: #7eeaca; } .dark-mode .select2-teal + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #7eeaca; } .select2-container--default .dark-mode .select2-teal.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-teal .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-teal .select2-search--inline .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-teal .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #7eeaca; } .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted, .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted { background-color: #20c997; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-teal .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-teal .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #1ebc8d; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple:focus, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple:focus { border-color: #7eeaca; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #20c997; border-color: #1cb386; color: #fff; } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-teal .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-teal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-teal.select2-container--focus .select2-selection--multiple, .dark-mode .select2-teal .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #7eeaca; } .dark-mode .select2-cyan + .select2-container--default.select2-container--open .select2-selection--single { border-color: #a0cfee; } .dark-mode .select2-cyan + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-cyan.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-cyan .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-cyan .select2-search--inline .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-cyan .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #a0cfee; } .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted, .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted { background-color: #3498db; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-cyan .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-cyan .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2791d9; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple:focus, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple:focus { border-color: #a0cfee; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #3498db; border-color: #258cd1; color: #fff; } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-cyan .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-cyan .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-cyan.select2-container--focus .select2-selection--multiple, .dark-mode .select2-cyan .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #a0cfee; } .dark-mode .select2-white + .select2-container--default.select2-container--open .select2-selection--single { border-color: white; } .dark-mode .select2-white + .select2-container--default.select2-container--focus .select2-selection--single { border-color: white; } .select2-container--default .dark-mode .select2-white.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-white .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-white .select2-search--inline .select2-search__field:focus, .dark-mode .select2-white .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-white .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-white .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid white; } .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted, .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted { background-color: #fff; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-white .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-white .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #f7f7f7; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple:focus, .dark-mode .select2-white .select2-container--default .select2-selection--multiple:focus { border-color: white; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border-color: #f2f2f2; color: #1f2d3d; } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(31, 45, 61, 0.7); } .select2-container--default .dark-mode .select2-white .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-white .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #1f2d3d; } .select2-container--default .dark-mode .select2-white.select2-container--focus .select2-selection--multiple, .dark-mode .select2-white .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: white; } .dark-mode .select2-gray + .select2-container--default.select2-container--open .select2-selection--single { border-color: #afb5ba; } .dark-mode .select2-gray + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-gray.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray .select2-search--inline .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #afb5ba; } .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted, .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted { background-color: #6c757d; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-gray .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-gray .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #656d75; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple:focus, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple:focus { border-color: #afb5ba; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #6c757d; border-color: #60686f; color: #fff; } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-gray .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-gray .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-gray.select2-container--focus .select2-selection--multiple, .dark-mode .select2-gray .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #afb5ba; } .dark-mode .select2-gray-dark + .select2-container--default.select2-container--open .select2-selection--single { border-color: #6d7a86; } .dark-mode .select2-gray-dark + .select2-container--default.select2-container--focus .select2-selection--single { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark.select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray-dark .select2-dropdown .select2-search__field:focus, .select2-container--default .dark-mode .select2-gray-dark .select2-search--inline .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default.select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-dropdown .select2-search__field:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-search--inline .select2-search__field:focus { border: 1px solid #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted, .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted { background-color: #343a40; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted[aria-selected], .select2-container--default .dark-mode .select2-gray-dark .select2-results__option--highlighted[aria-selected]:hover, .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected], .dark-mode .select2-gray-dark .select2-container--default .select2-results__option--highlighted[aria-selected]:hover { background-color: #2d3238; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple:focus, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple:focus { border-color: #6d7a86; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #343a40; border-color: #292d32; color: #fff; } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: rgba(255, 255, 255, 0.7); } .select2-container--default .dark-mode .select2-gray-dark .select2-selection--multiple .select2-selection__choice__remove:hover, .dark-mode .select2-gray-dark .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { color: #fff; } .select2-container--default .dark-mode .select2-gray-dark.select2-container--focus .select2-selection--multiple, .dark-mode .select2-gray-dark .select2-container--default.select2-container--focus .select2-selection--multiple { border-color: #6d7a86; } .slider .tooltip.in { opacity: 0.9; } .slider.slider-vertical { height: 100%; } .slider.slider-horizontal { width: 100%; } .slider-primary .slider .slider-selection { background: #007bff; } .slider-secondary .slider .slider-selection { background: #6c757d; } .slider-success .slider .slider-selection { background: #28a745; } .slider-info .slider .slider-selection { background: #17a2b8; } .slider-warning .slider .slider-selection { background: #ffc107; } .slider-danger .slider .slider-selection { background: #dc3545; } .slider-light .slider .slider-selection { background: #f8f9fa; } .slider-dark .slider .slider-selection { background: #343a40; } .slider-lightblue .slider .slider-selection { background: #3c8dbc; } .slider-navy .slider .slider-selection { background: #001f3f; } .slider-olive .slider .slider-selection { background: #3d9970; } .slider-lime .slider .slider-selection { background: #01ff70; } .slider-fuchsia .slider .slider-selection { background: #f012be; } .slider-maroon .slider .slider-selection { background: #d81b60; } .slider-blue .slider .slider-selection { background: #007bff; } .slider-indigo .slider .slider-selection { background: #6610f2; } .slider-purple .slider .slider-selection { background: #6f42c1; } .slider-pink .slider .slider-selection { background: #e83e8c; } .slider-red .slider .slider-selection { background: #dc3545; } .slider-orange .slider .slider-selection { background: #fd7e14; } .slider-yellow .slider .slider-selection { background: #ffc107; } .slider-green .slider .slider-selection { background: #28a745; } .slider-teal .slider .slider-selection { background: #20c997; } .slider-cyan .slider .slider-selection { background: #17a2b8; } .slider-white .slider .slider-selection { background: #fff; } .slider-gray .slider .slider-selection { background: #6c757d; } .slider-gray-dark .slider .slider-selection { background: #343a40; } .dark-mode .slider-track { background-color: #4b545c; background-image: none; } .dark-mode .slider-primary .slider .slider-selection { background: #3f6791; } .dark-mode .slider-secondary .slider .slider-selection { background: #6c757d; } .dark-mode .slider-success .slider .slider-selection { background: #00bc8c; } .dark-mode .slider-info .slider .slider-selection { background: #3498db; } .dark-mode .slider-warning .slider .slider-selection { background: #f39c12; } .dark-mode .slider-danger .slider .slider-selection { background: #e74c3c; } .dark-mode .slider-light .slider .slider-selection { background: #f8f9fa; } .dark-mode .slider-dark .slider .slider-selection { background: #343a40; } .dark-mode .slider-lightblue .slider .slider-selection { background: #86bad8; } .dark-mode .slider-navy .slider .slider-selection { background: #002c59; } .dark-mode .slider-olive .slider .slider-selection { background: #74c8a3; } .dark-mode .slider-lime .slider .slider-selection { background: #67ffa9; } .dark-mode .slider-fuchsia .slider .slider-selection { background: #f672d8; } .dark-mode .slider-maroon .slider .slider-selection { background: #ed6c9b; } .dark-mode .slider-blue .slider .slider-selection { background: #3f6791; } .dark-mode .slider-indigo .slider .slider-selection { background: #6610f2; } .dark-mode .slider-purple .slider .slider-selection { background: #6f42c1; } .dark-mode .slider-pink .slider .slider-selection { background: #e83e8c; } .dark-mode .slider-red .slider .slider-selection { background: #e74c3c; } .dark-mode .slider-orange .slider .slider-selection { background: #fd7e14; } .dark-mode .slider-yellow .slider .slider-selection { background: #f39c12; } .dark-mode .slider-green .slider .slider-selection { background: #00bc8c; } .dark-mode .slider-teal .slider .slider-selection { background: #20c997; } .dark-mode .slider-cyan .slider .slider-selection { background: #3498db; } .dark-mode .slider-white .slider .slider-selection { background: #fff; } .dark-mode .slider-gray .slider .slider-selection { background: #6c757d; } .dark-mode .slider-gray-dark .slider .slider-selection { background: #343a40; } .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-primary > input:first-child:checked + label::before, .icheck-primary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-secondary > input:first-child:checked + label::before, .icheck-secondary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-success > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-success > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-success > input:first-child:checked + label::before, .icheck-success > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-info > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-info > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-info > input:first-child:checked + label::before, .icheck-info > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-warning > input:first-child:checked + label::before, .icheck-warning > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-danger > input:first-child:checked + label::before, .icheck-danger > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-light > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-light > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f8f9fa; } .icheck-light > input:first-child:checked + label::before, .icheck-light > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f8f9fa; border-color: #f8f9fa; } .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-dark > input:first-child:checked + label::before, .icheck-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3c8dbc; } .icheck-lightblue > input:first-child:checked + label::before, .icheck-lightblue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3c8dbc; border-color: #3c8dbc; } .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #001f3f; } .icheck-navy > input:first-child:checked + label::before, .icheck-navy > input:first-child:checked + input[type="hidden"] + label::before { background-color: #001f3f; border-color: #001f3f; } .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3d9970; } .icheck-olive > input:first-child:checked + label::before, .icheck-olive > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3d9970; border-color: #3d9970; } .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #01ff70; } .icheck-lime > input:first-child:checked + label::before, .icheck-lime > input:first-child:checked + input[type="hidden"] + label::before { background-color: #01ff70; border-color: #01ff70; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f012be; } .icheck-fuchsia > input:first-child:checked + label::before, .icheck-fuchsia > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f012be; border-color: #f012be; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #d81b60; } .icheck-maroon > input:first-child:checked + label::before, .icheck-maroon > input:first-child:checked + input[type="hidden"] + label::before { background-color: #d81b60; border-color: #d81b60; } .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #007bff; } .icheck-blue > input:first-child:checked + label::before, .icheck-blue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #007bff; border-color: #007bff; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6610f2; } .icheck-indigo > input:first-child:checked + label::before, .icheck-indigo > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6610f2; border-color: #6610f2; } .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6f42c1; } .icheck-purple > input:first-child:checked + label::before, .icheck-purple > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6f42c1; border-color: #6f42c1; } .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e83e8c; } .icheck-pink > input:first-child:checked + label::before, .icheck-pink > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e83e8c; border-color: #e83e8c; } .icheck-red > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-red > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #dc3545; } .icheck-red > input:first-child:checked + label::before, .icheck-red > input:first-child:checked + input[type="hidden"] + label::before { background-color: #dc3545; border-color: #dc3545; } .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fd7e14; } .icheck-orange > input:first-child:checked + label::before, .icheck-orange > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fd7e14; border-color: #fd7e14; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ffc107; } .icheck-yellow > input:first-child:checked + label::before, .icheck-yellow > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ffc107; border-color: #ffc107; } .icheck-green > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-green > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #28a745; } .icheck-green > input:first-child:checked + label::before, .icheck-green > input:first-child:checked + input[type="hidden"] + label::before { background-color: #28a745; border-color: #28a745; } .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #20c997; } .icheck-teal > input:first-child:checked + label::before, .icheck-teal > input:first-child:checked + input[type="hidden"] + label::before { background-color: #20c997; border-color: #20c997; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #17a2b8; } .icheck-cyan > input:first-child:checked + label::before, .icheck-cyan > input:first-child:checked + input[type="hidden"] + label::before { background-color: #17a2b8; border-color: #17a2b8; } .icheck-white > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-white > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fff; } .icheck-white > input:first-child:checked + label::before, .icheck-white > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fff; border-color: #fff; } .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .icheck-gray > input:first-child:checked + label::before, .icheck-gray > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .icheck-gray-dark > input:first-child:checked + label::before, .icheck-gray-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .dark-mode [class*="icheck-"] > input:first-child:not(:checked) + input[type="hidden"] + label::before, .dark-mode [class*="icheck-"] > input:first-child:not(:checked) + label::before { border-color: #6c757d; } .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-primary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-primary > input:first-child:checked + label::before, .dark-mode .icheck-primary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3f6791; border-color: #3f6791; } .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-secondary > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-secondary > input:first-child:checked + label::before, .dark-mode .icheck-secondary > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-success > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-success > input:first-child:checked + label::before, .dark-mode .icheck-success > input:first-child:checked + input[type="hidden"] + label::before { background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-info > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-info > input:first-child:checked + label::before, .dark-mode .icheck-info > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3498db; border-color: #3498db; } .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-warning > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-warning > input:first-child:checked + label::before, .dark-mode .icheck-warning > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f39c12; border-color: #f39c12; } .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-danger > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-danger > input:first-child:checked + label::before, .dark-mode .icheck-danger > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f8f9fa; } .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-light > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f8f9fa; } .dark-mode .icheck-light > input:first-child:checked + label::before, .dark-mode .icheck-light > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f8f9fa; border-color: #f8f9fa; } .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-dark > input:first-child:checked + label::before, .dark-mode .icheck-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #86bad8; } .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-lightblue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #86bad8; } .dark-mode .icheck-lightblue > input:first-child:checked + label::before, .dark-mode .icheck-lightblue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #86bad8; border-color: #86bad8; } .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #002c59; } .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-navy > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #002c59; } .dark-mode .icheck-navy > input:first-child:checked + label::before, .dark-mode .icheck-navy > input:first-child:checked + input[type="hidden"] + label::before { background-color: #002c59; border-color: #002c59; } .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #74c8a3; } .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-olive > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #74c8a3; } .dark-mode .icheck-olive > input:first-child:checked + label::before, .dark-mode .icheck-olive > input:first-child:checked + input[type="hidden"] + label::before { background-color: #74c8a3; border-color: #74c8a3; } .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #67ffa9; } .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-lime > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #67ffa9; } .dark-mode .icheck-lime > input:first-child:checked + label::before, .dark-mode .icheck-lime > input:first-child:checked + input[type="hidden"] + label::before { background-color: #67ffa9; border-color: #67ffa9; } .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f672d8; } .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-fuchsia > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f672d8; } .dark-mode .icheck-fuchsia > input:first-child:checked + label::before, .dark-mode .icheck-fuchsia > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f672d8; border-color: #f672d8; } .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #ed6c9b; } .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-maroon > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #ed6c9b; } .dark-mode .icheck-maroon > input:first-child:checked + label::before, .dark-mode .icheck-maroon > input:first-child:checked + input[type="hidden"] + label::before { background-color: #ed6c9b; border-color: #ed6c9b; } .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-blue > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3f6791; } .dark-mode .icheck-blue > input:first-child:checked + label::before, .dark-mode .icheck-blue > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3f6791; border-color: #3f6791; } .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6610f2; } .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-indigo > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6610f2; } .dark-mode .icheck-indigo > input:first-child:checked + label::before, .dark-mode .icheck-indigo > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6610f2; border-color: #6610f2; } .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6f42c1; } .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-purple > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6f42c1; } .dark-mode .icheck-purple > input:first-child:checked + label::before, .dark-mode .icheck-purple > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6f42c1; border-color: #6f42c1; } .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e83e8c; } .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-pink > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e83e8c; } .dark-mode .icheck-pink > input:first-child:checked + label::before, .dark-mode .icheck-pink > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e83e8c; border-color: #e83e8c; } .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-red > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #e74c3c; } .dark-mode .icheck-red > input:first-child:checked + label::before, .dark-mode .icheck-red > input:first-child:checked + input[type="hidden"] + label::before { background-color: #e74c3c; border-color: #e74c3c; } .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fd7e14; } .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-orange > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fd7e14; } .dark-mode .icheck-orange > input:first-child:checked + label::before, .dark-mode .icheck-orange > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fd7e14; border-color: #fd7e14; } .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-yellow > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #f39c12; } .dark-mode .icheck-yellow > input:first-child:checked + label::before, .dark-mode .icheck-yellow > input:first-child:checked + input[type="hidden"] + label::before { background-color: #f39c12; border-color: #f39c12; } .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-green > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #00bc8c; } .dark-mode .icheck-green > input:first-child:checked + label::before, .dark-mode .icheck-green > input:first-child:checked + input[type="hidden"] + label::before { background-color: #00bc8c; border-color: #00bc8c; } .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #20c997; } .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-teal > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #20c997; } .dark-mode .icheck-teal > input:first-child:checked + label::before, .dark-mode .icheck-teal > input:first-child:checked + input[type="hidden"] + label::before { background-color: #20c997; border-color: #20c997; } .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-cyan > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #3498db; } .dark-mode .icheck-cyan > input:first-child:checked + label::before, .dark-mode .icheck-cyan > input:first-child:checked + input[type="hidden"] + label::before { background-color: #3498db; border-color: #3498db; } .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #fff; } .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-white > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #fff; } .dark-mode .icheck-white > input:first-child:checked + label::before, .dark-mode .icheck-white > input:first-child:checked + input[type="hidden"] + label::before { background-color: #fff; border-color: #fff; } .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-gray > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #6c757d; } .dark-mode .icheck-gray > input:first-child:checked + label::before, .dark-mode .icheck-gray > input:first-child:checked + input[type="hidden"] + label::before { background-color: #6c757d; border-color: #6c757d; } .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + label::before, .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):hover + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + label::before, .dark-mode .icheck-gray-dark > input:first-child:not(:checked):not(:disabled):focus + input[type="hidden"] + label::before { border-color: #343a40; } .dark-mode .icheck-gray-dark > input:first-child:checked + label::before, .dark-mode .icheck-gray-dark > input:first-child:checked + input[type="hidden"] + label::before { background-color: #343a40; border-color: #343a40; } .mapael .map { position: relative; } .mapael .mapTooltip { font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; word-spacing: normal; white-space: normal; line-break: auto; border-radius: 0.25rem; font-size: 0.875rem; background-color: #000; color: #fff; display: block; max-width: 200px; padding: 0.25rem 0.5rem; position: absolute; text-align: center; word-wrap: break-word; z-index: 1070; } .mapael .myLegend { background-color: #f8f9fa; border: 1px solid #adb5bd; padding: 10px; width: 600px; } .mapael .zoomButton { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; cursor: pointer; font-weight: 700; height: 16px; left: 10px; line-height: 14px; padding-left: 1px; position: absolute; text-align: center; top: 0; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; width: 16px; } .mapael .zoomButton:hover, .mapael .zoomButton:active, .mapael .zoomButton.hover { background-color: #e9ecef; color: #2b2b2b; } .mapael .zoomReset { line-height: 12px; top: 10px; } .mapael .zoomIn { top: 30px; } .mapael .zoomOut { top: 50px; } .jqvmap-zoomin, .jqvmap-zoomout { background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 0.25rem; color: #444; height: 15px; width: 15px; padding: 1px 2px; } .jqvmap-zoomin:hover, .jqvmap-zoomin:active, .jqvmap-zoomin.hover, .jqvmap-zoomout:hover, .jqvmap-zoomout:active, .jqvmap-zoomout.hover { background-color: #e9ecef; color: #2b2b2b; } .swal2-icon.swal2-info { border-color: ligthen(#17a2b8, 20%); color: #17a2b8; } .swal2-icon.swal2-warning { border-color: ligthen(#ffc107, 20%); color: #ffc107; } .swal2-icon.swal2-error { border-color: ligthen(#dc3545, 20%); color: #dc3545; } .swal2-icon.swal2-question { border-color: ligthen(#6c757d, 20%); color: #6c757d; } .swal2-icon.swal2-success { border-color: ligthen(#28a745, 20%); color: #28a745; } .swal2-icon.swal2-success .swal2-success-ring { border-color: ligthen(#28a745, 20%); } .swal2-icon.swal2-success [class^='swal2-success-line'] { background-color: #28a745; } .dark-mode .swal2-popup { background-color: #343a40; color: #e9ecef; } .dark-mode .swal2-popup .swal2-content, .dark-mode .swal2-popup .swal2-title { color: #e9ecef; } #toast-container .toast { background-color: #007bff; } #toast-container .toast-success { background-color: #28a745; } #toast-container .toast-error { background-color: #dc3545; } #toast-container .toast-info { background-color: #17a2b8; } #toast-container .toast-warning { background-color: #ffc107; } .toast-bottom-full-width .toast, .toast-top-full-width .toast { max-width: inherit; } .pace { z-index: 1048; } .pace .pace-progress { z-index: 1049; } .pace .pace-activity { z-index: 1050; } .pace-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace { background: #fff; } .pace-barber-shop-primary .pace .pace-progress { background: #007bff; } .pace-barber-shop-primary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-primary .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-primary .pace .pace-activity { background: #007bff; } .pace-center-atom-primary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-primary .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-primary .pace-activity { border-color: #007bff; } .pace-center-atom-primary .pace-activity::after, .pace-center-atom-primary .pace-activity::before { border-color: #007bff; } .pace-center-circle-primary .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-primary .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-primary .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-primary .pace { background: #fff; border-color: #007bff; } .pace-center-simple-primary .pace .pace-progress { background: #007bff; } .pace-material-primary .pace { color: #007bff; } .pace-corner-indicator-primary .pace .pace-activity { background: #007bff; } .pace-corner-indicator-primary .pace .pace-activity::after, .pace-corner-indicator-primary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-primary .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-primary .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-primary .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-primary .pace .pace-progress { background: #007bff; } .pace-flash-primary .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-primary .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-primary .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-primary .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-primary .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-primary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-primary .pace-progress { color: #007bff; } .pace-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace { background: #fff; } .pace-barber-shop-secondary .pace .pace-progress { background: #6c757d; } .pace-barber-shop-secondary .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-secondary .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-secondary .pace .pace-activity { background: #6c757d; } .pace-center-atom-secondary .pace-progress { height: 100px; width: 80px; } .pace-center-atom-secondary .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-secondary .pace-activity { border-color: #6c757d; } .pace-center-atom-secondary .pace-activity::after, .pace-center-atom-secondary .pace-activity::before { border-color: #6c757d; } .pace-center-circle-secondary .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-secondary .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-secondary .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-secondary .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-secondary .pace .pace-progress { background: #6c757d; } .pace-material-secondary .pace { color: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-secondary .pace .pace-activity::after, .pace-corner-indicator-secondary .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-secondary .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-secondary .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-secondary .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-secondary .pace .pace-progress { background: #6c757d; } .pace-flash-secondary .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-secondary .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-secondary .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-secondary .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-secondary .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-secondary .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-secondary .pace-progress { color: #6c757d; } .pace-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace { background: #fff; } .pace-barber-shop-success .pace .pace-progress { background: #28a745; } .pace-barber-shop-success .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-success .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-success .pace .pace-activity { background: #28a745; } .pace-center-atom-success .pace-progress { height: 100px; width: 80px; } .pace-center-atom-success .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-success .pace-activity { border-color: #28a745; } .pace-center-atom-success .pace-activity::after, .pace-center-atom-success .pace-activity::before { border-color: #28a745; } .pace-center-circle-success .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-success .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-success .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-success .pace { background: #fff; border-color: #28a745; } .pace-center-simple-success .pace .pace-progress { background: #28a745; } .pace-material-success .pace { color: #28a745; } .pace-corner-indicator-success .pace .pace-activity { background: #28a745; } .pace-corner-indicator-success .pace .pace-activity::after, .pace-corner-indicator-success .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-success .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-success .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-success .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-success .pace .pace-progress { background: #28a745; } .pace-flash-success .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-success .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-success .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-success .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-success .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-success .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-success .pace-progress { color: #28a745; } .pace-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace { background: #fff; } .pace-barber-shop-info .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-info .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-info .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-info .pace .pace-activity { background: #17a2b8; } .pace-center-atom-info .pace-progress { height: 100px; width: 80px; } .pace-center-atom-info .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-info .pace-activity { border-color: #17a2b8; } .pace-center-atom-info .pace-activity::after, .pace-center-atom-info .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-info .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-info .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-info .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-info .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-info .pace .pace-progress { background: #17a2b8; } .pace-material-info .pace { color: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-info .pace .pace-activity::after, .pace-corner-indicator-info .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-info .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-info .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-info .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-info .pace .pace-progress { background: #17a2b8; } .pace-flash-info .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-info .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-info .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-info .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-info .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-info .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-info .pace-progress { color: #17a2b8; } .pace-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace { background: #1f2d3d; } .pace-barber-shop-warning .pace .pace-progress { background: #ffc107; } .pace-barber-shop-warning .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-warning .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-warning .pace .pace-activity { background: #ffc107; } .pace-center-atom-warning .pace-progress { height: 100px; width: 80px; } .pace-center-atom-warning .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-warning .pace-activity { border-color: #ffc107; } .pace-center-atom-warning .pace-activity::after, .pace-center-atom-warning .pace-activity::before { border-color: #ffc107; } .pace-center-circle-warning .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-warning .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-warning .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-warning .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-warning .pace .pace-progress { background: #ffc107; } .pace-material-warning .pace { color: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-warning .pace .pace-activity::after, .pace-corner-indicator-warning .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-warning .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-warning .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-warning .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-warning .pace .pace-progress { background: #ffc107; } .pace-flash-warning .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-warning .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-warning .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-warning .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-warning .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-warning .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-warning .pace-progress { color: #ffc107; } .pace-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace { background: #fff; } .pace-barber-shop-danger .pace .pace-progress { background: #dc3545; } .pace-barber-shop-danger .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-danger .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-danger .pace .pace-activity { background: #dc3545; } .pace-center-atom-danger .pace-progress { height: 100px; width: 80px; } .pace-center-atom-danger .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-danger .pace-activity { border-color: #dc3545; } .pace-center-atom-danger .pace-activity::after, .pace-center-atom-danger .pace-activity::before { border-color: #dc3545; } .pace-center-circle-danger .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-danger .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-danger .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-danger .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-danger .pace .pace-progress { background: #dc3545; } .pace-material-danger .pace { color: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-danger .pace .pace-activity::after, .pace-corner-indicator-danger .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-danger .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-danger .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-danger .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-danger .pace .pace-progress { background: #dc3545; } .pace-flash-danger .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-danger .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-danger .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-danger .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-danger .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-danger .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-danger .pace-progress { color: #dc3545; } .pace-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace { background: #1f2d3d; } .pace-barber-shop-light .pace .pace-progress { background: #f8f9fa; } .pace-barber-shop-light .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-light .pace .pace-progress::after { color: rgba(248, 249, 250, 0.2); } .pace-bounce-light .pace .pace-activity { background: #f8f9fa; } .pace-center-atom-light .pace-progress { height: 100px; width: 80px; } .pace-center-atom-light .pace-progress::before { background: #f8f9fa; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-light .pace-activity { border-color: #f8f9fa; } .pace-center-atom-light .pace-activity::after, .pace-center-atom-light .pace-activity::before { border-color: #f8f9fa; } .pace-center-circle-light .pace .pace-progress { background: rgba(248, 249, 250, 0.8); color: #1f2d3d; } .pace-center-radar-light .pace .pace-activity { border-color: #f8f9fa transparent transparent; } .pace-center-radar-light .pace .pace-activity::before { border-color: #f8f9fa transparent transparent; } .pace-center-simple-light .pace { background: #1f2d3d; border-color: #f8f9fa; } .pace-center-simple-light .pace .pace-progress { background: #f8f9fa; } .pace-material-light .pace { color: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity { background: #f8f9fa; } .pace-corner-indicator-light .pace .pace-activity::after, .pace-corner-indicator-light .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-light .pace .pace-activity::before { border-right-color: rgba(248, 249, 250, 0.2); border-left-color: rgba(248, 249, 250, 0.2); } .pace-corner-indicator-light .pace .pace-activity::after { border-top-color: rgba(248, 249, 250, 0.2); border-bottom-color: rgba(248, 249, 250, 0.2); } .pace-fill-left-light .pace .pace-progress { background-color: rgba(248, 249, 250, 0.2); } .pace-flash-light .pace .pace-progress { background: #f8f9fa; } .pace-flash-light .pace .pace-progress-inner { box-shadow: 0 0 10px #f8f9fa, 0 0 5px #f8f9fa; } .pace-flash-light .pace .pace-activity { border-top-color: #f8f9fa; border-left-color: #f8f9fa; } .pace-loading-bar-light .pace .pace-progress { background: #f8f9fa; color: #f8f9fa; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-light .pace .pace-activity { box-shadow: inset 0 0 0 2px #f8f9fa, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-light .pace .pace-progress { background-color: #f8f9fa; box-shadow: inset -1px 0 #f8f9fa, inset 0 -1px #f8f9fa, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-light .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-light .pace-progress { color: #f8f9fa; } .pace-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace { background: #fff; } .pace-barber-shop-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-dark .pace-activity { border-color: #343a40; } .pace-center-atom-dark .pace-activity::after, .pace-center-atom-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-dark .pace .pace-progress { background: #343a40; } .pace-material-dark .pace { color: #343a40; } .pace-corner-indicator-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-dark .pace .pace-activity::after, .pace-corner-indicator-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-dark .pace .pace-progress { background: #343a40; } .pace-flash-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-dark .pace-progress { color: #343a40; } .pace-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace { background: #fff; } .pace-barber-shop-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-barber-shop-lightblue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lightblue .pace .pace-progress::after { color: rgba(60, 141, 188, 0.2); } .pace-bounce-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-center-atom-lightblue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lightblue .pace-progress::before { background: #3c8dbc; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lightblue .pace-activity { border-color: #3c8dbc; } .pace-center-atom-lightblue .pace-activity::after, .pace-center-atom-lightblue .pace-activity::before { border-color: #3c8dbc; } .pace-center-circle-lightblue .pace .pace-progress { background: rgba(60, 141, 188, 0.8); color: #fff; } .pace-center-radar-lightblue .pace .pace-activity { border-color: #3c8dbc transparent transparent; } .pace-center-radar-lightblue .pace .pace-activity::before { border-color: #3c8dbc transparent transparent; } .pace-center-simple-lightblue .pace { background: #fff; border-color: #3c8dbc; } .pace-center-simple-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-material-lightblue .pace { color: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity { background: #3c8dbc; } .pace-corner-indicator-lightblue .pace .pace-activity::after, .pace-corner-indicator-lightblue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-lightblue .pace .pace-activity::before { border-right-color: rgba(60, 141, 188, 0.2); border-left-color: rgba(60, 141, 188, 0.2); } .pace-corner-indicator-lightblue .pace .pace-activity::after { border-top-color: rgba(60, 141, 188, 0.2); border-bottom-color: rgba(60, 141, 188, 0.2); } .pace-fill-left-lightblue .pace .pace-progress { background-color: rgba(60, 141, 188, 0.2); } .pace-flash-lightblue .pace .pace-progress { background: #3c8dbc; } .pace-flash-lightblue .pace .pace-progress-inner { box-shadow: 0 0 10px #3c8dbc, 0 0 5px #3c8dbc; } .pace-flash-lightblue .pace .pace-activity { border-top-color: #3c8dbc; border-left-color: #3c8dbc; } .pace-loading-bar-lightblue .pace .pace-progress { background: #3c8dbc; color: #3c8dbc; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-lightblue .pace .pace-activity { box-shadow: inset 0 0 0 2px #3c8dbc, inset 0 0 0 7px #fff; } .pace-mac-osx-lightblue .pace .pace-progress { background-color: #3c8dbc; box-shadow: inset -1px 0 #3c8dbc, inset 0 -1px #3c8dbc, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-lightblue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-lightblue .pace-progress { color: #3c8dbc; } .pace-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace { background: #fff; } .pace-barber-shop-navy .pace .pace-progress { background: #001f3f; } .pace-barber-shop-navy .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-navy .pace .pace-progress::after { color: rgba(0, 31, 63, 0.2); } .pace-bounce-navy .pace .pace-activity { background: #001f3f; } .pace-center-atom-navy .pace-progress { height: 100px; width: 80px; } .pace-center-atom-navy .pace-progress::before { background: #001f3f; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-navy .pace-activity { border-color: #001f3f; } .pace-center-atom-navy .pace-activity::after, .pace-center-atom-navy .pace-activity::before { border-color: #001f3f; } .pace-center-circle-navy .pace .pace-progress { background: rgba(0, 31, 63, 0.8); color: #fff; } .pace-center-radar-navy .pace .pace-activity { border-color: #001f3f transparent transparent; } .pace-center-radar-navy .pace .pace-activity::before { border-color: #001f3f transparent transparent; } .pace-center-simple-navy .pace { background: #fff; border-color: #001f3f; } .pace-center-simple-navy .pace .pace-progress { background: #001f3f; } .pace-material-navy .pace { color: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity { background: #001f3f; } .pace-corner-indicator-navy .pace .pace-activity::after, .pace-corner-indicator-navy .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-navy .pace .pace-activity::before { border-right-color: rgba(0, 31, 63, 0.2); border-left-color: rgba(0, 31, 63, 0.2); } .pace-corner-indicator-navy .pace .pace-activity::after { border-top-color: rgba(0, 31, 63, 0.2); border-bottom-color: rgba(0, 31, 63, 0.2); } .pace-fill-left-navy .pace .pace-progress { background-color: rgba(0, 31, 63, 0.2); } .pace-flash-navy .pace .pace-progress { background: #001f3f; } .pace-flash-navy .pace .pace-progress-inner { box-shadow: 0 0 10px #001f3f, 0 0 5px #001f3f; } .pace-flash-navy .pace .pace-activity { border-top-color: #001f3f; border-left-color: #001f3f; } .pace-loading-bar-navy .pace .pace-progress { background: #001f3f; color: #001f3f; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-navy .pace .pace-activity { box-shadow: inset 0 0 0 2px #001f3f, inset 0 0 0 7px #fff; } .pace-mac-osx-navy .pace .pace-progress { background-color: #001f3f; box-shadow: inset -1px 0 #001f3f, inset 0 -1px #001f3f, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-navy .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-navy .pace-progress { color: #001f3f; } .pace-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace { background: #fff; } .pace-barber-shop-olive .pace .pace-progress { background: #3d9970; } .pace-barber-shop-olive .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-olive .pace .pace-progress::after { color: rgba(61, 153, 112, 0.2); } .pace-bounce-olive .pace .pace-activity { background: #3d9970; } .pace-center-atom-olive .pace-progress { height: 100px; width: 80px; } .pace-center-atom-olive .pace-progress::before { background: #3d9970; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-olive .pace-activity { border-color: #3d9970; } .pace-center-atom-olive .pace-activity::after, .pace-center-atom-olive .pace-activity::before { border-color: #3d9970; } .pace-center-circle-olive .pace .pace-progress { background: rgba(61, 153, 112, 0.8); color: #fff; } .pace-center-radar-olive .pace .pace-activity { border-color: #3d9970 transparent transparent; } .pace-center-radar-olive .pace .pace-activity::before { border-color: #3d9970 transparent transparent; } .pace-center-simple-olive .pace { background: #fff; border-color: #3d9970; } .pace-center-simple-olive .pace .pace-progress { background: #3d9970; } .pace-material-olive .pace { color: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity { background: #3d9970; } .pace-corner-indicator-olive .pace .pace-activity::after, .pace-corner-indicator-olive .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-olive .pace .pace-activity::before { border-right-color: rgba(61, 153, 112, 0.2); border-left-color: rgba(61, 153, 112, 0.2); } .pace-corner-indicator-olive .pace .pace-activity::after { border-top-color: rgba(61, 153, 112, 0.2); border-bottom-color: rgba(61, 153, 112, 0.2); } .pace-fill-left-olive .pace .pace-progress { background-color: rgba(61, 153, 112, 0.2); } .pace-flash-olive .pace .pace-progress { background: #3d9970; } .pace-flash-olive .pace .pace-progress-inner { box-shadow: 0 0 10px #3d9970, 0 0 5px #3d9970; } .pace-flash-olive .pace .pace-activity { border-top-color: #3d9970; border-left-color: #3d9970; } .pace-loading-bar-olive .pace .pace-progress { background: #3d9970; color: #3d9970; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-olive .pace .pace-activity { box-shadow: inset 0 0 0 2px #3d9970, inset 0 0 0 7px #fff; } .pace-mac-osx-olive .pace .pace-progress { background-color: #3d9970; box-shadow: inset -1px 0 #3d9970, inset 0 -1px #3d9970, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-olive .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-olive .pace-progress { color: #3d9970; } .pace-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace { background: #1f2d3d; } .pace-barber-shop-lime .pace .pace-progress { background: #01ff70; } .pace-barber-shop-lime .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-lime .pace .pace-progress::after { color: rgba(1, 255, 112, 0.2); } .pace-bounce-lime .pace .pace-activity { background: #01ff70; } .pace-center-atom-lime .pace-progress { height: 100px; width: 80px; } .pace-center-atom-lime .pace-progress::before { background: #01ff70; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-lime .pace-activity { border-color: #01ff70; } .pace-center-atom-lime .pace-activity::after, .pace-center-atom-lime .pace-activity::before { border-color: #01ff70; } .pace-center-circle-lime .pace .pace-progress { background: rgba(1, 255, 112, 0.8); color: #1f2d3d; } .pace-center-radar-lime .pace .pace-activity { border-color: #01ff70 transparent transparent; } .pace-center-radar-lime .pace .pace-activity::before { border-color: #01ff70 transparent transparent; } .pace-center-simple-lime .pace { background: #1f2d3d; border-color: #01ff70; } .pace-center-simple-lime .pace .pace-progress { background: #01ff70; } .pace-material-lime .pace { color: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity { background: #01ff70; } .pace-corner-indicator-lime .pace .pace-activity::after, .pace-corner-indicator-lime .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-lime .pace .pace-activity::before { border-right-color: rgba(1, 255, 112, 0.2); border-left-color: rgba(1, 255, 112, 0.2); } .pace-corner-indicator-lime .pace .pace-activity::after { border-top-color: rgba(1, 255, 112, 0.2); border-bottom-color: rgba(1, 255, 112, 0.2); } .pace-fill-left-lime .pace .pace-progress { background-color: rgba(1, 255, 112, 0.2); } .pace-flash-lime .pace .pace-progress { background: #01ff70; } .pace-flash-lime .pace .pace-progress-inner { box-shadow: 0 0 10px #01ff70, 0 0 5px #01ff70; } .pace-flash-lime .pace .pace-activity { border-top-color: #01ff70; border-left-color: #01ff70; } .pace-loading-bar-lime .pace .pace-progress { background: #01ff70; color: #01ff70; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-lime .pace .pace-activity { box-shadow: inset 0 0 0 2px #01ff70, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-lime .pace .pace-progress { background-color: #01ff70; box-shadow: inset -1px 0 #01ff70, inset 0 -1px #01ff70, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-lime .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-lime .pace-progress { color: #01ff70; } .pace-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace { background: #fff; } .pace-barber-shop-fuchsia .pace .pace-progress { background: #f012be; } .pace-barber-shop-fuchsia .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-fuchsia .pace .pace-progress::after { color: rgba(240, 18, 190, 0.2); } .pace-bounce-fuchsia .pace .pace-activity { background: #f012be; } .pace-center-atom-fuchsia .pace-progress { height: 100px; width: 80px; } .pace-center-atom-fuchsia .pace-progress::before { background: #f012be; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-fuchsia .pace-activity { border-color: #f012be; } .pace-center-atom-fuchsia .pace-activity::after, .pace-center-atom-fuchsia .pace-activity::before { border-color: #f012be; } .pace-center-circle-fuchsia .pace .pace-progress { background: rgba(240, 18, 190, 0.8); color: #fff; } .pace-center-radar-fuchsia .pace .pace-activity { border-color: #f012be transparent transparent; } .pace-center-radar-fuchsia .pace .pace-activity::before { border-color: #f012be transparent transparent; } .pace-center-simple-fuchsia .pace { background: #fff; border-color: #f012be; } .pace-center-simple-fuchsia .pace .pace-progress { background: #f012be; } .pace-material-fuchsia .pace { color: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity { background: #f012be; } .pace-corner-indicator-fuchsia .pace .pace-activity::after, .pace-corner-indicator-fuchsia .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-fuchsia .pace .pace-activity::before { border-right-color: rgba(240, 18, 190, 0.2); border-left-color: rgba(240, 18, 190, 0.2); } .pace-corner-indicator-fuchsia .pace .pace-activity::after { border-top-color: rgba(240, 18, 190, 0.2); border-bottom-color: rgba(240, 18, 190, 0.2); } .pace-fill-left-fuchsia .pace .pace-progress { background-color: rgba(240, 18, 190, 0.2); } .pace-flash-fuchsia .pace .pace-progress { background: #f012be; } .pace-flash-fuchsia .pace .pace-progress-inner { box-shadow: 0 0 10px #f012be, 0 0 5px #f012be; } .pace-flash-fuchsia .pace .pace-activity { border-top-color: #f012be; border-left-color: #f012be; } .pace-loading-bar-fuchsia .pace .pace-progress { background: #f012be; color: #f012be; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-fuchsia .pace .pace-activity { box-shadow: inset 0 0 0 2px #f012be, inset 0 0 0 7px #fff; } .pace-mac-osx-fuchsia .pace .pace-progress { background-color: #f012be; box-shadow: inset -1px 0 #f012be, inset 0 -1px #f012be, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-fuchsia .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-fuchsia .pace-progress { color: #f012be; } .pace-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace { background: #fff; } .pace-barber-shop-maroon .pace .pace-progress { background: #d81b60; } .pace-barber-shop-maroon .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-maroon .pace .pace-progress::after { color: rgba(216, 27, 96, 0.2); } .pace-bounce-maroon .pace .pace-activity { background: #d81b60; } .pace-center-atom-maroon .pace-progress { height: 100px; width: 80px; } .pace-center-atom-maroon .pace-progress::before { background: #d81b60; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-maroon .pace-activity { border-color: #d81b60; } .pace-center-atom-maroon .pace-activity::after, .pace-center-atom-maroon .pace-activity::before { border-color: #d81b60; } .pace-center-circle-maroon .pace .pace-progress { background: rgba(216, 27, 96, 0.8); color: #fff; } .pace-center-radar-maroon .pace .pace-activity { border-color: #d81b60 transparent transparent; } .pace-center-radar-maroon .pace .pace-activity::before { border-color: #d81b60 transparent transparent; } .pace-center-simple-maroon .pace { background: #fff; border-color: #d81b60; } .pace-center-simple-maroon .pace .pace-progress { background: #d81b60; } .pace-material-maroon .pace { color: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity { background: #d81b60; } .pace-corner-indicator-maroon .pace .pace-activity::after, .pace-corner-indicator-maroon .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-maroon .pace .pace-activity::before { border-right-color: rgba(216, 27, 96, 0.2); border-left-color: rgba(216, 27, 96, 0.2); } .pace-corner-indicator-maroon .pace .pace-activity::after { border-top-color: rgba(216, 27, 96, 0.2); border-bottom-color: rgba(216, 27, 96, 0.2); } .pace-fill-left-maroon .pace .pace-progress { background-color: rgba(216, 27, 96, 0.2); } .pace-flash-maroon .pace .pace-progress { background: #d81b60; } .pace-flash-maroon .pace .pace-progress-inner { box-shadow: 0 0 10px #d81b60, 0 0 5px #d81b60; } .pace-flash-maroon .pace .pace-activity { border-top-color: #d81b60; border-left-color: #d81b60; } .pace-loading-bar-maroon .pace .pace-progress { background: #d81b60; color: #d81b60; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-maroon .pace .pace-activity { box-shadow: inset 0 0 0 2px #d81b60, inset 0 0 0 7px #fff; } .pace-mac-osx-maroon .pace .pace-progress { background-color: #d81b60; box-shadow: inset -1px 0 #d81b60, inset 0 -1px #d81b60, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-maroon .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-maroon .pace-progress { color: #d81b60; } .pace-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace { background: #fff; } .pace-barber-shop-blue .pace .pace-progress { background: #007bff; } .pace-barber-shop-blue .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-blue .pace .pace-progress::after { color: rgba(0, 123, 255, 0.2); } .pace-bounce-blue .pace .pace-activity { background: #007bff; } .pace-center-atom-blue .pace-progress { height: 100px; width: 80px; } .pace-center-atom-blue .pace-progress::before { background: #007bff; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-blue .pace-activity { border-color: #007bff; } .pace-center-atom-blue .pace-activity::after, .pace-center-atom-blue .pace-activity::before { border-color: #007bff; } .pace-center-circle-blue .pace .pace-progress { background: rgba(0, 123, 255, 0.8); color: #fff; } .pace-center-radar-blue .pace .pace-activity { border-color: #007bff transparent transparent; } .pace-center-radar-blue .pace .pace-activity::before { border-color: #007bff transparent transparent; } .pace-center-simple-blue .pace { background: #fff; border-color: #007bff; } .pace-center-simple-blue .pace .pace-progress { background: #007bff; } .pace-material-blue .pace { color: #007bff; } .pace-corner-indicator-blue .pace .pace-activity { background: #007bff; } .pace-corner-indicator-blue .pace .pace-activity::after, .pace-corner-indicator-blue .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-blue .pace .pace-activity::before { border-right-color: rgba(0, 123, 255, 0.2); border-left-color: rgba(0, 123, 255, 0.2); } .pace-corner-indicator-blue .pace .pace-activity::after { border-top-color: rgba(0, 123, 255, 0.2); border-bottom-color: rgba(0, 123, 255, 0.2); } .pace-fill-left-blue .pace .pace-progress { background-color: rgba(0, 123, 255, 0.2); } .pace-flash-blue .pace .pace-progress { background: #007bff; } .pace-flash-blue .pace .pace-progress-inner { box-shadow: 0 0 10px #007bff, 0 0 5px #007bff; } .pace-flash-blue .pace .pace-activity { border-top-color: #007bff; border-left-color: #007bff; } .pace-loading-bar-blue .pace .pace-progress { background: #007bff; color: #007bff; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-blue .pace .pace-activity { box-shadow: inset 0 0 0 2px #007bff, inset 0 0 0 7px #fff; } .pace-mac-osx-blue .pace .pace-progress { background-color: #007bff; box-shadow: inset -1px 0 #007bff, inset 0 -1px #007bff, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-blue .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-blue .pace-progress { color: #007bff; } .pace-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace { background: #fff; } .pace-barber-shop-indigo .pace .pace-progress { background: #6610f2; } .pace-barber-shop-indigo .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-indigo .pace .pace-progress::after { color: rgba(102, 16, 242, 0.2); } .pace-bounce-indigo .pace .pace-activity { background: #6610f2; } .pace-center-atom-indigo .pace-progress { height: 100px; width: 80px; } .pace-center-atom-indigo .pace-progress::before { background: #6610f2; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-indigo .pace-activity { border-color: #6610f2; } .pace-center-atom-indigo .pace-activity::after, .pace-center-atom-indigo .pace-activity::before { border-color: #6610f2; } .pace-center-circle-indigo .pace .pace-progress { background: rgba(102, 16, 242, 0.8); color: #fff; } .pace-center-radar-indigo .pace .pace-activity { border-color: #6610f2 transparent transparent; } .pace-center-radar-indigo .pace .pace-activity::before { border-color: #6610f2 transparent transparent; } .pace-center-simple-indigo .pace { background: #fff; border-color: #6610f2; } .pace-center-simple-indigo .pace .pace-progress { background: #6610f2; } .pace-material-indigo .pace { color: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity { background: #6610f2; } .pace-corner-indicator-indigo .pace .pace-activity::after, .pace-corner-indicator-indigo .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-indigo .pace .pace-activity::before { border-right-color: rgba(102, 16, 242, 0.2); border-left-color: rgba(102, 16, 242, 0.2); } .pace-corner-indicator-indigo .pace .pace-activity::after { border-top-color: rgba(102, 16, 242, 0.2); border-bottom-color: rgba(102, 16, 242, 0.2); } .pace-fill-left-indigo .pace .pace-progress { background-color: rgba(102, 16, 242, 0.2); } .pace-flash-indigo .pace .pace-progress { background: #6610f2; } .pace-flash-indigo .pace .pace-progress-inner { box-shadow: 0 0 10px #6610f2, 0 0 5px #6610f2; } .pace-flash-indigo .pace .pace-activity { border-top-color: #6610f2; border-left-color: #6610f2; } .pace-loading-bar-indigo .pace .pace-progress { background: #6610f2; color: #6610f2; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-indigo .pace .pace-activity { box-shadow: inset 0 0 0 2px #6610f2, inset 0 0 0 7px #fff; } .pace-mac-osx-indigo .pace .pace-progress { background-color: #6610f2; box-shadow: inset -1px 0 #6610f2, inset 0 -1px #6610f2, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-indigo .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-indigo .pace-progress { color: #6610f2; } .pace-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace { background: #fff; } .pace-barber-shop-purple .pace .pace-progress { background: #6f42c1; } .pace-barber-shop-purple .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-purple .pace .pace-progress::after { color: rgba(111, 66, 193, 0.2); } .pace-bounce-purple .pace .pace-activity { background: #6f42c1; } .pace-center-atom-purple .pace-progress { height: 100px; width: 80px; } .pace-center-atom-purple .pace-progress::before { background: #6f42c1; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-purple .pace-activity { border-color: #6f42c1; } .pace-center-atom-purple .pace-activity::after, .pace-center-atom-purple .pace-activity::before { border-color: #6f42c1; } .pace-center-circle-purple .pace .pace-progress { background: rgba(111, 66, 193, 0.8); color: #fff; } .pace-center-radar-purple .pace .pace-activity { border-color: #6f42c1 transparent transparent; } .pace-center-radar-purple .pace .pace-activity::before { border-color: #6f42c1 transparent transparent; } .pace-center-simple-purple .pace { background: #fff; border-color: #6f42c1; } .pace-center-simple-purple .pace .pace-progress { background: #6f42c1; } .pace-material-purple .pace { color: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity { background: #6f42c1; } .pace-corner-indicator-purple .pace .pace-activity::after, .pace-corner-indicator-purple .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-purple .pace .pace-activity::before { border-right-color: rgba(111, 66, 193, 0.2); border-left-color: rgba(111, 66, 193, 0.2); } .pace-corner-indicator-purple .pace .pace-activity::after { border-top-color: rgba(111, 66, 193, 0.2); border-bottom-color: rgba(111, 66, 193, 0.2); } .pace-fill-left-purple .pace .pace-progress { background-color: rgba(111, 66, 193, 0.2); } .pace-flash-purple .pace .pace-progress { background: #6f42c1; } .pace-flash-purple .pace .pace-progress-inner { box-shadow: 0 0 10px #6f42c1, 0 0 5px #6f42c1; } .pace-flash-purple .pace .pace-activity { border-top-color: #6f42c1; border-left-color: #6f42c1; } .pace-loading-bar-purple .pace .pace-progress { background: #6f42c1; color: #6f42c1; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-purple .pace .pace-activity { box-shadow: inset 0 0 0 2px #6f42c1, inset 0 0 0 7px #fff; } .pace-mac-osx-purple .pace .pace-progress { background-color: #6f42c1; box-shadow: inset -1px 0 #6f42c1, inset 0 -1px #6f42c1, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-purple .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-purple .pace-progress { color: #6f42c1; } .pace-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace { background: #fff; } .pace-barber-shop-pink .pace .pace-progress { background: #e83e8c; } .pace-barber-shop-pink .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-pink .pace .pace-progress::after { color: rgba(232, 62, 140, 0.2); } .pace-bounce-pink .pace .pace-activity { background: #e83e8c; } .pace-center-atom-pink .pace-progress { height: 100px; width: 80px; } .pace-center-atom-pink .pace-progress::before { background: #e83e8c; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-pink .pace-activity { border-color: #e83e8c; } .pace-center-atom-pink .pace-activity::after, .pace-center-atom-pink .pace-activity::before { border-color: #e83e8c; } .pace-center-circle-pink .pace .pace-progress { background: rgba(232, 62, 140, 0.8); color: #fff; } .pace-center-radar-pink .pace .pace-activity { border-color: #e83e8c transparent transparent; } .pace-center-radar-pink .pace .pace-activity::before { border-color: #e83e8c transparent transparent; } .pace-center-simple-pink .pace { background: #fff; border-color: #e83e8c; } .pace-center-simple-pink .pace .pace-progress { background: #e83e8c; } .pace-material-pink .pace { color: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity { background: #e83e8c; } .pace-corner-indicator-pink .pace .pace-activity::after, .pace-corner-indicator-pink .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-pink .pace .pace-activity::before { border-right-color: rgba(232, 62, 140, 0.2); border-left-color: rgba(232, 62, 140, 0.2); } .pace-corner-indicator-pink .pace .pace-activity::after { border-top-color: rgba(232, 62, 140, 0.2); border-bottom-color: rgba(232, 62, 140, 0.2); } .pace-fill-left-pink .pace .pace-progress { background-color: rgba(232, 62, 140, 0.2); } .pace-flash-pink .pace .pace-progress { background: #e83e8c; } .pace-flash-pink .pace .pace-progress-inner { box-shadow: 0 0 10px #e83e8c, 0 0 5px #e83e8c; } .pace-flash-pink .pace .pace-activity { border-top-color: #e83e8c; border-left-color: #e83e8c; } .pace-loading-bar-pink .pace .pace-progress { background: #e83e8c; color: #e83e8c; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-pink .pace .pace-activity { box-shadow: inset 0 0 0 2px #e83e8c, inset 0 0 0 7px #fff; } .pace-mac-osx-pink .pace .pace-progress { background-color: #e83e8c; box-shadow: inset -1px 0 #e83e8c, inset 0 -1px #e83e8c, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-pink .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-pink .pace-progress { color: #e83e8c; } .pace-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace { background: #fff; } .pace-barber-shop-red .pace .pace-progress { background: #dc3545; } .pace-barber-shop-red .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-red .pace .pace-progress::after { color: rgba(220, 53, 69, 0.2); } .pace-bounce-red .pace .pace-activity { background: #dc3545; } .pace-center-atom-red .pace-progress { height: 100px; width: 80px; } .pace-center-atom-red .pace-progress::before { background: #dc3545; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-red .pace-activity { border-color: #dc3545; } .pace-center-atom-red .pace-activity::after, .pace-center-atom-red .pace-activity::before { border-color: #dc3545; } .pace-center-circle-red .pace .pace-progress { background: rgba(220, 53, 69, 0.8); color: #fff; } .pace-center-radar-red .pace .pace-activity { border-color: #dc3545 transparent transparent; } .pace-center-radar-red .pace .pace-activity::before { border-color: #dc3545 transparent transparent; } .pace-center-simple-red .pace { background: #fff; border-color: #dc3545; } .pace-center-simple-red .pace .pace-progress { background: #dc3545; } .pace-material-red .pace { color: #dc3545; } .pace-corner-indicator-red .pace .pace-activity { background: #dc3545; } .pace-corner-indicator-red .pace .pace-activity::after, .pace-corner-indicator-red .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-red .pace .pace-activity::before { border-right-color: rgba(220, 53, 69, 0.2); border-left-color: rgba(220, 53, 69, 0.2); } .pace-corner-indicator-red .pace .pace-activity::after { border-top-color: rgba(220, 53, 69, 0.2); border-bottom-color: rgba(220, 53, 69, 0.2); } .pace-fill-left-red .pace .pace-progress { background-color: rgba(220, 53, 69, 0.2); } .pace-flash-red .pace .pace-progress { background: #dc3545; } .pace-flash-red .pace .pace-progress-inner { box-shadow: 0 0 10px #dc3545, 0 0 5px #dc3545; } .pace-flash-red .pace .pace-activity { border-top-color: #dc3545; border-left-color: #dc3545; } .pace-loading-bar-red .pace .pace-progress { background: #dc3545; color: #dc3545; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-red .pace .pace-activity { box-shadow: inset 0 0 0 2px #dc3545, inset 0 0 0 7px #fff; } .pace-mac-osx-red .pace .pace-progress { background-color: #dc3545; box-shadow: inset -1px 0 #dc3545, inset 0 -1px #dc3545, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-red .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-red .pace-progress { color: #dc3545; } .pace-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace { background: #1f2d3d; } .pace-barber-shop-orange .pace .pace-progress { background: #fd7e14; } .pace-barber-shop-orange .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-orange .pace .pace-progress::after { color: rgba(253, 126, 20, 0.2); } .pace-bounce-orange .pace .pace-activity { background: #fd7e14; } .pace-center-atom-orange .pace-progress { height: 100px; width: 80px; } .pace-center-atom-orange .pace-progress::before { background: #fd7e14; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-orange .pace-activity { border-color: #fd7e14; } .pace-center-atom-orange .pace-activity::after, .pace-center-atom-orange .pace-activity::before { border-color: #fd7e14; } .pace-center-circle-orange .pace .pace-progress { background: rgba(253, 126, 20, 0.8); color: #1f2d3d; } .pace-center-radar-orange .pace .pace-activity { border-color: #fd7e14 transparent transparent; } .pace-center-radar-orange .pace .pace-activity::before { border-color: #fd7e14 transparent transparent; } .pace-center-simple-orange .pace { background: #1f2d3d; border-color: #fd7e14; } .pace-center-simple-orange .pace .pace-progress { background: #fd7e14; } .pace-material-orange .pace { color: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity { background: #fd7e14; } .pace-corner-indicator-orange .pace .pace-activity::after, .pace-corner-indicator-orange .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-orange .pace .pace-activity::before { border-right-color: rgba(253, 126, 20, 0.2); border-left-color: rgba(253, 126, 20, 0.2); } .pace-corner-indicator-orange .pace .pace-activity::after { border-top-color: rgba(253, 126, 20, 0.2); border-bottom-color: rgba(253, 126, 20, 0.2); } .pace-fill-left-orange .pace .pace-progress { background-color: rgba(253, 126, 20, 0.2); } .pace-flash-orange .pace .pace-progress { background: #fd7e14; } .pace-flash-orange .pace .pace-progress-inner { box-shadow: 0 0 10px #fd7e14, 0 0 5px #fd7e14; } .pace-flash-orange .pace .pace-activity { border-top-color: #fd7e14; border-left-color: #fd7e14; } .pace-loading-bar-orange .pace .pace-progress { background: #fd7e14; color: #fd7e14; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-orange .pace .pace-activity { box-shadow: inset 0 0 0 2px #fd7e14, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-orange .pace .pace-progress { background-color: #fd7e14; box-shadow: inset -1px 0 #fd7e14, inset 0 -1px #fd7e14, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-orange .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-orange .pace-progress { color: #fd7e14; } .pace-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace { background: #1f2d3d; } .pace-barber-shop-yellow .pace .pace-progress { background: #ffc107; } .pace-barber-shop-yellow .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-yellow .pace .pace-progress::after { color: rgba(255, 193, 7, 0.2); } .pace-bounce-yellow .pace .pace-activity { background: #ffc107; } .pace-center-atom-yellow .pace-progress { height: 100px; width: 80px; } .pace-center-atom-yellow .pace-progress::before { background: #ffc107; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-yellow .pace-activity { border-color: #ffc107; } .pace-center-atom-yellow .pace-activity::after, .pace-center-atom-yellow .pace-activity::before { border-color: #ffc107; } .pace-center-circle-yellow .pace .pace-progress { background: rgba(255, 193, 7, 0.8); color: #1f2d3d; } .pace-center-radar-yellow .pace .pace-activity { border-color: #ffc107 transparent transparent; } .pace-center-radar-yellow .pace .pace-activity::before { border-color: #ffc107 transparent transparent; } .pace-center-simple-yellow .pace { background: #1f2d3d; border-color: #ffc107; } .pace-center-simple-yellow .pace .pace-progress { background: #ffc107; } .pace-material-yellow .pace { color: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity { background: #ffc107; } .pace-corner-indicator-yellow .pace .pace-activity::after, .pace-corner-indicator-yellow .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-yellow .pace .pace-activity::before { border-right-color: rgba(255, 193, 7, 0.2); border-left-color: rgba(255, 193, 7, 0.2); } .pace-corner-indicator-yellow .pace .pace-activity::after { border-top-color: rgba(255, 193, 7, 0.2); border-bottom-color: rgba(255, 193, 7, 0.2); } .pace-fill-left-yellow .pace .pace-progress { background-color: rgba(255, 193, 7, 0.2); } .pace-flash-yellow .pace .pace-progress { background: #ffc107; } .pace-flash-yellow .pace .pace-progress-inner { box-shadow: 0 0 10px #ffc107, 0 0 5px #ffc107; } .pace-flash-yellow .pace .pace-activity { border-top-color: #ffc107; border-left-color: #ffc107; } .pace-loading-bar-yellow .pace .pace-progress { background: #ffc107; color: #ffc107; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-yellow .pace .pace-activity { box-shadow: inset 0 0 0 2px #ffc107, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-yellow .pace .pace-progress { background-color: #ffc107; box-shadow: inset -1px 0 #ffc107, inset 0 -1px #ffc107, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-yellow .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-yellow .pace-progress { color: #ffc107; } .pace-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace { background: #fff; } .pace-barber-shop-green .pace .pace-progress { background: #28a745; } .pace-barber-shop-green .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-green .pace .pace-progress::after { color: rgba(40, 167, 69, 0.2); } .pace-bounce-green .pace .pace-activity { background: #28a745; } .pace-center-atom-green .pace-progress { height: 100px; width: 80px; } .pace-center-atom-green .pace-progress::before { background: #28a745; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-green .pace-activity { border-color: #28a745; } .pace-center-atom-green .pace-activity::after, .pace-center-atom-green .pace-activity::before { border-color: #28a745; } .pace-center-circle-green .pace .pace-progress { background: rgba(40, 167, 69, 0.8); color: #fff; } .pace-center-radar-green .pace .pace-activity { border-color: #28a745 transparent transparent; } .pace-center-radar-green .pace .pace-activity::before { border-color: #28a745 transparent transparent; } .pace-center-simple-green .pace { background: #fff; border-color: #28a745; } .pace-center-simple-green .pace .pace-progress { background: #28a745; } .pace-material-green .pace { color: #28a745; } .pace-corner-indicator-green .pace .pace-activity { background: #28a745; } .pace-corner-indicator-green .pace .pace-activity::after, .pace-corner-indicator-green .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-green .pace .pace-activity::before { border-right-color: rgba(40, 167, 69, 0.2); border-left-color: rgba(40, 167, 69, 0.2); } .pace-corner-indicator-green .pace .pace-activity::after { border-top-color: rgba(40, 167, 69, 0.2); border-bottom-color: rgba(40, 167, 69, 0.2); } .pace-fill-left-green .pace .pace-progress { background-color: rgba(40, 167, 69, 0.2); } .pace-flash-green .pace .pace-progress { background: #28a745; } .pace-flash-green .pace .pace-progress-inner { box-shadow: 0 0 10px #28a745, 0 0 5px #28a745; } .pace-flash-green .pace .pace-activity { border-top-color: #28a745; border-left-color: #28a745; } .pace-loading-bar-green .pace .pace-progress { background: #28a745; color: #28a745; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-green .pace .pace-activity { box-shadow: inset 0 0 0 2px #28a745, inset 0 0 0 7px #fff; } .pace-mac-osx-green .pace .pace-progress { background-color: #28a745; box-shadow: inset -1px 0 #28a745, inset 0 -1px #28a745, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-green .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-green .pace-progress { color: #28a745; } .pace-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace { background: #fff; } .pace-barber-shop-teal .pace .pace-progress { background: #20c997; } .pace-barber-shop-teal .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-teal .pace .pace-progress::after { color: rgba(32, 201, 151, 0.2); } .pace-bounce-teal .pace .pace-activity { background: #20c997; } .pace-center-atom-teal .pace-progress { height: 100px; width: 80px; } .pace-center-atom-teal .pace-progress::before { background: #20c997; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-teal .pace-activity { border-color: #20c997; } .pace-center-atom-teal .pace-activity::after, .pace-center-atom-teal .pace-activity::before { border-color: #20c997; } .pace-center-circle-teal .pace .pace-progress { background: rgba(32, 201, 151, 0.8); color: #fff; } .pace-center-radar-teal .pace .pace-activity { border-color: #20c997 transparent transparent; } .pace-center-radar-teal .pace .pace-activity::before { border-color: #20c997 transparent transparent; } .pace-center-simple-teal .pace { background: #fff; border-color: #20c997; } .pace-center-simple-teal .pace .pace-progress { background: #20c997; } .pace-material-teal .pace { color: #20c997; } .pace-corner-indicator-teal .pace .pace-activity { background: #20c997; } .pace-corner-indicator-teal .pace .pace-activity::after, .pace-corner-indicator-teal .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-teal .pace .pace-activity::before { border-right-color: rgba(32, 201, 151, 0.2); border-left-color: rgba(32, 201, 151, 0.2); } .pace-corner-indicator-teal .pace .pace-activity::after { border-top-color: rgba(32, 201, 151, 0.2); border-bottom-color: rgba(32, 201, 151, 0.2); } .pace-fill-left-teal .pace .pace-progress { background-color: rgba(32, 201, 151, 0.2); } .pace-flash-teal .pace .pace-progress { background: #20c997; } .pace-flash-teal .pace .pace-progress-inner { box-shadow: 0 0 10px #20c997, 0 0 5px #20c997; } .pace-flash-teal .pace .pace-activity { border-top-color: #20c997; border-left-color: #20c997; } .pace-loading-bar-teal .pace .pace-progress { background: #20c997; color: #20c997; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-teal .pace .pace-activity { box-shadow: inset 0 0 0 2px #20c997, inset 0 0 0 7px #fff; } .pace-mac-osx-teal .pace .pace-progress { background-color: #20c997; box-shadow: inset -1px 0 #20c997, inset 0 -1px #20c997, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-teal .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-teal .pace-progress { color: #20c997; } .pace-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace { background: #fff; } .pace-barber-shop-cyan .pace .pace-progress { background: #17a2b8; } .pace-barber-shop-cyan .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-cyan .pace .pace-progress::after { color: rgba(23, 162, 184, 0.2); } .pace-bounce-cyan .pace .pace-activity { background: #17a2b8; } .pace-center-atom-cyan .pace-progress { height: 100px; width: 80px; } .pace-center-atom-cyan .pace-progress::before { background: #17a2b8; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-cyan .pace-activity { border-color: #17a2b8; } .pace-center-atom-cyan .pace-activity::after, .pace-center-atom-cyan .pace-activity::before { border-color: #17a2b8; } .pace-center-circle-cyan .pace .pace-progress { background: rgba(23, 162, 184, 0.8); color: #fff; } .pace-center-radar-cyan .pace .pace-activity { border-color: #17a2b8 transparent transparent; } .pace-center-radar-cyan .pace .pace-activity::before { border-color: #17a2b8 transparent transparent; } .pace-center-simple-cyan .pace { background: #fff; border-color: #17a2b8; } .pace-center-simple-cyan .pace .pace-progress { background: #17a2b8; } .pace-material-cyan .pace { color: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity { background: #17a2b8; } .pace-corner-indicator-cyan .pace .pace-activity::after, .pace-corner-indicator-cyan .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-cyan .pace .pace-activity::before { border-right-color: rgba(23, 162, 184, 0.2); border-left-color: rgba(23, 162, 184, 0.2); } .pace-corner-indicator-cyan .pace .pace-activity::after { border-top-color: rgba(23, 162, 184, 0.2); border-bottom-color: rgba(23, 162, 184, 0.2); } .pace-fill-left-cyan .pace .pace-progress { background-color: rgba(23, 162, 184, 0.2); } .pace-flash-cyan .pace .pace-progress { background: #17a2b8; } .pace-flash-cyan .pace .pace-progress-inner { box-shadow: 0 0 10px #17a2b8, 0 0 5px #17a2b8; } .pace-flash-cyan .pace .pace-activity { border-top-color: #17a2b8; border-left-color: #17a2b8; } .pace-loading-bar-cyan .pace .pace-progress { background: #17a2b8; color: #17a2b8; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-cyan .pace .pace-activity { box-shadow: inset 0 0 0 2px #17a2b8, inset 0 0 0 7px #fff; } .pace-mac-osx-cyan .pace .pace-progress { background-color: #17a2b8; box-shadow: inset -1px 0 #17a2b8, inset 0 -1px #17a2b8, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-cyan .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-cyan .pace-progress { color: #17a2b8; } .pace-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace { background: #1f2d3d; } .pace-barber-shop-white .pace .pace-progress { background: #fff; } .pace-barber-shop-white .pace .pace-activity { background-image: linear-gradient(45deg, rgba(31, 45, 61, 0.2) 25%, transparent 25%, transparent 50%, rgba(31, 45, 61, 0.2) 50%, rgba(31, 45, 61, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-white .pace .pace-progress::after { color: rgba(255, 255, 255, 0.2); } .pace-bounce-white .pace .pace-activity { background: #fff; } .pace-center-atom-white .pace-progress { height: 100px; width: 80px; } .pace-center-atom-white .pace-progress::before { background: #fff; color: #1f2d3d; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-white .pace-activity { border-color: #fff; } .pace-center-atom-white .pace-activity::after, .pace-center-atom-white .pace-activity::before { border-color: #fff; } .pace-center-circle-white .pace .pace-progress { background: rgba(255, 255, 255, 0.8); color: #1f2d3d; } .pace-center-radar-white .pace .pace-activity { border-color: #fff transparent transparent; } .pace-center-radar-white .pace .pace-activity::before { border-color: #fff transparent transparent; } .pace-center-simple-white .pace { background: #1f2d3d; border-color: #fff; } .pace-center-simple-white .pace .pace-progress { background: #fff; } .pace-material-white .pace { color: #fff; } .pace-corner-indicator-white .pace .pace-activity { background: #fff; } .pace-corner-indicator-white .pace .pace-activity::after, .pace-corner-indicator-white .pace .pace-activity::before { border: 5px solid #1f2d3d; } .pace-corner-indicator-white .pace .pace-activity::before { border-right-color: rgba(255, 255, 255, 0.2); border-left-color: rgba(255, 255, 255, 0.2); } .pace-corner-indicator-white .pace .pace-activity::after { border-top-color: rgba(255, 255, 255, 0.2); border-bottom-color: rgba(255, 255, 255, 0.2); } .pace-fill-left-white .pace .pace-progress { background-color: rgba(255, 255, 255, 0.2); } .pace-flash-white .pace .pace-progress { background: #fff; } .pace-flash-white .pace .pace-progress-inner { box-shadow: 0 0 10px #fff, 0 0 5px #fff; } .pace-flash-white .pace .pace-activity { border-top-color: #fff; border-left-color: #fff; } .pace-loading-bar-white .pace .pace-progress { background: #fff; color: #fff; box-shadow: 120px 0 #1f2d3d, 240px 0 #1f2d3d; } .pace-loading-bar-white .pace .pace-activity { box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 7px #1f2d3d; } .pace-mac-osx-white .pace .pace-progress { background-color: #fff; box-shadow: inset -1px 0 #fff, inset 0 -1px #fff, inset 0 2px rgba(31, 45, 61, 0.5), inset 0 6px rgba(31, 45, 61, 0.3); } .pace-mac-osx-white .pace .pace-activity { background-image: radial-gradient(rgba(31, 45, 61, 0.65) 0%, rgba(31, 45, 61, 0.15) 100%); height: 12px; } .pace-progress-color-white .pace-progress { color: #fff; } .pace-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace { background: #fff; } .pace-barber-shop-gray .pace .pace-progress { background: #6c757d; } .pace-barber-shop-gray .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray .pace .pace-progress::after { color: rgba(108, 117, 125, 0.2); } .pace-bounce-gray .pace .pace-activity { background: #6c757d; } .pace-center-atom-gray .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray .pace-progress::before { background: #6c757d; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray .pace-activity { border-color: #6c757d; } .pace-center-atom-gray .pace-activity::after, .pace-center-atom-gray .pace-activity::before { border-color: #6c757d; } .pace-center-circle-gray .pace .pace-progress { background: rgba(108, 117, 125, 0.8); color: #fff; } .pace-center-radar-gray .pace .pace-activity { border-color: #6c757d transparent transparent; } .pace-center-radar-gray .pace .pace-activity::before { border-color: #6c757d transparent transparent; } .pace-center-simple-gray .pace { background: #fff; border-color: #6c757d; } .pace-center-simple-gray .pace .pace-progress { background: #6c757d; } .pace-material-gray .pace { color: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity { background: #6c757d; } .pace-corner-indicator-gray .pace .pace-activity::after, .pace-corner-indicator-gray .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray .pace .pace-activity::before { border-right-color: rgba(108, 117, 125, 0.2); border-left-color: rgba(108, 117, 125, 0.2); } .pace-corner-indicator-gray .pace .pace-activity::after { border-top-color: rgba(108, 117, 125, 0.2); border-bottom-color: rgba(108, 117, 125, 0.2); } .pace-fill-left-gray .pace .pace-progress { background-color: rgba(108, 117, 125, 0.2); } .pace-flash-gray .pace .pace-progress { background: #6c757d; } .pace-flash-gray .pace .pace-progress-inner { box-shadow: 0 0 10px #6c757d, 0 0 5px #6c757d; } .pace-flash-gray .pace .pace-activity { border-top-color: #6c757d; border-left-color: #6c757d; } .pace-loading-bar-gray .pace .pace-progress { background: #6c757d; color: #6c757d; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray .pace .pace-activity { box-shadow: inset 0 0 0 2px #6c757d, inset 0 0 0 7px #fff; } .pace-mac-osx-gray .pace .pace-progress { background-color: #6c757d; box-shadow: inset -1px 0 #6c757d, inset 0 -1px #6c757d, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray .pace-progress { color: #6c757d; } .pace-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace { background: #fff; } .pace-barber-shop-gray-dark .pace .pace-progress { background: #343a40; } .pace-barber-shop-gray-dark .pace .pace-activity { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); } .pace-big-counter-gray-dark .pace .pace-progress::after { color: rgba(52, 58, 64, 0.2); } .pace-bounce-gray-dark .pace .pace-activity { background: #343a40; } .pace-center-atom-gray-dark .pace-progress { height: 100px; width: 80px; } .pace-center-atom-gray-dark .pace-progress::before { background: #343a40; color: #fff; font-size: .8rem; line-height: .7rem; padding-top: 17%; } .pace-center-atom-gray-dark .pace-activity { border-color: #343a40; } .pace-center-atom-gray-dark .pace-activity::after, .pace-center-atom-gray-dark .pace-activity::before { border-color: #343a40; } .pace-center-circle-gray-dark .pace .pace-progress { background: rgba(52, 58, 64, 0.8); color: #fff; } .pace-center-radar-gray-dark .pace .pace-activity { border-color: #343a40 transparent transparent; } .pace-center-radar-gray-dark .pace .pace-activity::before { border-color: #343a40 transparent transparent; } .pace-center-simple-gray-dark .pace { background: #fff; border-color: #343a40; } .pace-center-simple-gray-dark .pace .pace-progress { background: #343a40; } .pace-material-gray-dark .pace { color: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity { background: #343a40; } .pace-corner-indicator-gray-dark .pace .pace-activity::after, .pace-corner-indicator-gray-dark .pace .pace-activity::before { border: 5px solid #fff; } .pace-corner-indicator-gray-dark .pace .pace-activity::before { border-right-color: rgba(52, 58, 64, 0.2); border-left-color: rgba(52, 58, 64, 0.2); } .pace-corner-indicator-gray-dark .pace .pace-activity::after { border-top-color: rgba(52, 58, 64, 0.2); border-bottom-color: rgba(52, 58, 64, 0.2); } .pace-fill-left-gray-dark .pace .pace-progress { background-color: rgba(52, 58, 64, 0.2); } .pace-flash-gray-dark .pace .pace-progress { background: #343a40; } .pace-flash-gray-dark .pace .pace-progress-inner { box-shadow: 0 0 10px #343a40, 0 0 5px #343a40; } .pace-flash-gray-dark .pace .pace-activity { border-top-color: #343a40; border-left-color: #343a40; } .pace-loading-bar-gray-dark .pace .pace-progress { background: #343a40; color: #343a40; box-shadow: 120px 0 #fff, 240px 0 #fff; } .pace-loading-bar-gray-dark .pace .pace-activity { box-shadow: inset 0 0 0 2px #343a40, inset 0 0 0 7px #fff; } .pace-mac-osx-gray-dark .pace .pace-progress { background-color: #343a40; box-shadow: inset -1px 0 #343a40, inset 0 -1px #343a40, inset 0 2px rgba(255, 255, 255, 0.5), inset 0 6px rgba(255, 255, 255, 0.3); } .pace-mac-osx-gray-dark .pace .pace-activity { background-image: radial-gradient(rgba(255, 255, 255, 0.65) 0%, rgba(255, 255, 255, 0.15) 100%); height: 12px; } .pace-progress-color-gray-dark .pace-progress { color: #343a40; } /** * bootstrap-switch - Turn checkboxes and radio buttons into toggle switches. * * @version v3.4 (MODDED) * @homepage https://bttstrp.github.io/bootstrap-switch * @author Mattia Larentis (http://larentis.eu) * @license MIT */ .bootstrap-switch { border: 1px solid #ced4da; border-radius: 0.25rem; cursor: pointer; direction: ltr; display: inline-block; line-height: .5rem; overflow: hidden; position: relative; text-align: left; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; vertical-align: middle; z-index: 0; } .bootstrap-switch .bootstrap-switch-container { border-radius: 0.25rem; display: inline-block; top: 0; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } .bootstrap-switch:focus-within { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off, .bootstrap-switch .bootstrap-switch-label { box-sizing: border-box; cursor: pointer; display: table-cell; font-size: 1rem; font-weight: 500; line-height: 1.2rem; padding: .25rem .5rem; vertical-align: middle; } .bootstrap-switch .bootstrap-switch-handle-on, .bootstrap-switch .bootstrap-switch-handle-off { text-align: center; z-index: 1; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default { background: #e9ecef; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-secondary, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-secondary { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-light, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-light { background: #f8f9fa; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lightblue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lightblue { background: #3c8dbc; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-navy, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-navy { background: #001f3f; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-olive, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-olive { background: #3d9970; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lime, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lime { background: #01ff70; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-fuchsia, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-fuchsia { background: #f012be; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-maroon, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-maroon { background: #d81b60; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue { background: #007bff; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-indigo, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-indigo { background: #6610f2; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-purple, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-purple { background: #6f42c1; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-pink, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-pink { background: #e83e8c; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red { background: #dc3545; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange { background: #fd7e14; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-yellow, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-yellow { background: #ffc107; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green { background: #28a745; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-teal, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-teal { background: #20c997; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-cyan, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-cyan { background: #17a2b8; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-white, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-white { background: #fff; color: #1f2d3d; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray { background: #6c757d; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray-dark, .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray-dark { background: #343a40; color: #fff; } .bootstrap-switch .bootstrap-switch-handle-on { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .bootstrap-switch .bootstrap-switch-handle-off { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch input[type='radio'], .bootstrap-switch input[type='checkbox'] { filter: alpha(opacity=0); left: 0; margin: 0; opacity: 0; position: absolute; top: 0; visibility: hidden; z-index: -1; } .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-mini .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .1rem .3rem; } .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-small .bootstrap-switch-label { font-size: .875rem; line-height: 1.5; padding: .2rem .4rem; } .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-large .bootstrap-switch-label { font-size: 1.25rem; line-height: 1.3333333rem; padding: .3rem .5rem; } .bootstrap-switch.bootstrap-switch-disabled, .bootstrap-switch.bootstrap-switch-readonly, .bootstrap-switch.bootstrap-switch-indeterminate { cursor: default; } .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-disabled .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-readonly .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-on, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-handle-off, .bootstrap-switch.bootstrap-switch-indeterminate .bootstrap-switch-label { cursor: default; filter: alpha(opacity=50); opacity: .5; } .bootstrap-switch.bootstrap-switch-animate .bootstrap-switch-container { transition: margin-left .5s; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-on { border-radius: 0 0.1rem 0.1rem 0; } .bootstrap-switch.bootstrap-switch-inverse .bootstrap-switch-handle-off { border-radius: 0.1rem 0 0 0.1rem; } .bootstrap-switch.bootstrap-switch-on .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-off .bootstrap-switch-label { border-bottom-right-radius: 0.1rem; border-top-right-radius: 0.1rem; } .bootstrap-switch.bootstrap-switch-off .bootstrap-switch-label, .bootstrap-switch.bootstrap-switch-inverse.bootstrap-switch-on .bootstrap-switch-label { border-bottom-left-radius: 0.1rem; border-top-left-radius: 0.1rem; } .dark-mode .bootstrap-switch { border-color: #6c757d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-default, .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-default { background-color: #3a4047; color: #fff; border-color: #454d55; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-primary, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-primary { background: #3f6791; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-secondary, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-secondary { background: #6c757d; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-success, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-success { background: #00bc8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-info, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-info { background: #3498db; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-warning, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-warning { background: #f39c12; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-danger, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-danger { background: #e74c3c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-light, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-light { background: #f8f9fa; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-dark, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-dark { background: #343a40; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lightblue, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lightblue { background: #86bad8; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-navy, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-navy { background: #002c59; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-olive, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-olive { background: #74c8a3; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-lime, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-lime { background: #67ffa9; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-fuchsia, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-fuchsia { background: #f672d8; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-maroon, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-maroon { background: #ed6c9b; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-blue, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-blue { background: #3f6791; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-indigo, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-indigo { background: #6610f2; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-purple, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-purple { background: #6f42c1; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-pink, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-pink { background: #e83e8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-red, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-red { background: #e74c3c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-orange, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-orange { background: #fd7e14; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-yellow, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-yellow { background: #f39c12; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-green, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-green { background: #00bc8c; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-teal, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-teal { background: #20c997; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-cyan, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-cyan { background: #3498db; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-white, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-white { background: #fff; color: #1f2d3d; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray { background: #6c757d; color: #fff; } .dark-mode .bootstrap-switch .bootstrap-switch-handle-on.bootstrap-switch-gray-dark, .dark-mode .bootstrap-switch .bootstrap-switch-handle-off.bootstrap-switch-gray-dark { background: #343a40; color: #fff; } .dark-mode .daterangepicker { background-color: #3f474e; border: inherit; } .dark-mode .daterangepicker::before, .dark-mode .daterangepicker::after { border-bottom-color: #3f474e; } .dark-mode .daterangepicker td.available:hover, .dark-mode .daterangepicker th.available:hover { background-color: #3f474e; } .dark-mode .daterangepicker td.in-range { background-color: #4b545c; color: #fff; } .dark-mode .daterangepicker td.off, .dark-mode .daterangepicker td.off.in-range, .dark-mode .daterangepicker td.off.start-date, .dark-mode .daterangepicker td.off.end-date { background-color: #292d32; color: #fff; } .dark-mode .daterangepicker .ranges li:hover { background-color: #343a40; } .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar { border-color: #4b545c; } .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar.left, .dark-mode .daterangepicker.show-ranges.ltr .drp-calendar.right { border-color: #4b545c; padding-top: 0; } .dark-mode .daterangepicker .drp-buttons { border-color: #4b545c; } .dark-mode .daterangepicker .calendar-table { background-color: #343a40; border-color: #4b545c; } .dark-mode .daterangepicker .calendar-table th, .dark-mode .daterangepicker .calendar-table td { color: #fff; } .dark-mode .daterangepicker .calendar-table .next span, .dark-mode .daterangepicker .calendar-table .prev span { border-color: #fff; } .dark-mode .daterangepicker select.hourselect, .dark-mode .daterangepicker select.minuteselect, .dark-mode .daterangepicker select.secondselect, .dark-mode .daterangepicker select.ampmselect { background-color: #343a40; border-color: #4b545c; } .jqstooltip { height: auto !important; padding: 5px !important; width: auto !important; } .connectedSortable { min-height: 100px; } .ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .sort-highlight { background: #f8f9fa; border: 1px dashed #dee2e6; margin-bottom: 10px; } .chart { overflow: hidden; position: relative; } .dark-mode .irs--flat .irs-line { background-color: #4b545c; } .dark-mode .jsgrid-edit-row > .jsgrid-cell, .dark-mode .jsgrid-filter-row > .jsgrid-cell, .dark-mode .jsgrid-grid-body, .dark-mode .jsgrid-grid-header, .dark-mode .jsgrid-header-row > .jsgrid-header-cell, .dark-mode .jsgrid-insert-row > .jsgrid-cell, .dark-mode .jsgrid-row > .jsgrid-cell, .dark-mode .jsgrid-alt-row > .jsgrid-cell { border-color: #6c757d; } .dark-mode .jsgrid-header-row > .jsgrid-header-cell, .dark-mode .jsgrid-row > .jsgrid-cell { background-color: #343a40; } .dark-mode .jsgrid-alt-row > .jsgrid-cell { background-color: #3a4047; } .dark-mode .jsgrid-selected-row > .jsgrid-cell { background-color: #3f474e; } /*# sourceMappingURL=adminlte.plugins.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/dist/js/adminlte.js ================================================ /*! * AdminLTE v3.2.0 (https://adminlte.io) * Copyright 2014-2022 Colorlib * Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) : typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.adminlte = {}, global.jQuery)); })(this, (function (exports, $) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var $__default = /*#__PURE__*/_interopDefaultLegacy($); /** * -------------------------------------------- * AdminLTE CardRefresh.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$e = 'CardRefresh'; var DATA_KEY$e = 'lte.cardrefresh'; var EVENT_KEY$7 = "." + DATA_KEY$e; var JQUERY_NO_CONFLICT$e = $__default["default"].fn[NAME$e]; var EVENT_LOADED = "loaded" + EVENT_KEY$7; var EVENT_OVERLAY_ADDED = "overlay.added" + EVENT_KEY$7; var EVENT_OVERLAY_REMOVED = "overlay.removed" + EVENT_KEY$7; var CLASS_NAME_CARD$1 = 'card'; var SELECTOR_CARD$1 = "." + CLASS_NAME_CARD$1; var SELECTOR_DATA_REFRESH = '[data-card-widget="card-refresh"]'; var Default$c = { source: '', sourceSelector: '', params: {}, trigger: SELECTOR_DATA_REFRESH, content: '.card-body', loadInContent: true, loadOnInit: true, loadErrorTemplate: true, responseType: '', overlayTemplate: '
', errorTemplate: '', onLoadStart: function onLoadStart() {}, onLoadDone: function onLoadDone(response) { return response; }, onLoadFail: function onLoadFail(_jqXHR, _textStatus, _errorThrown) {} }; var CardRefresh = /*#__PURE__*/function () { function CardRefresh(element, settings) { this._element = element; this._parent = element.parents(SELECTOR_CARD$1).first(); this._settings = $__default["default"].extend({}, Default$c, settings); this._overlay = $__default["default"](this._settings.overlayTemplate); if (element.hasClass(CLASS_NAME_CARD$1)) { this._parent = element; } if (this._settings.source === '') { throw new Error('Source url was not defined. Please specify a url in your CardRefresh source option.'); } } var _proto = CardRefresh.prototype; _proto.load = function load() { var _this = this; this._addOverlay(); this._settings.onLoadStart.call($__default["default"](this)); $__default["default"].get(this._settings.source, this._settings.params, function (response) { if (_this._settings.loadInContent) { if (_this._settings.sourceSelector !== '') { response = $__default["default"](response).find(_this._settings.sourceSelector).html(); } _this._parent.find(_this._settings.content).html(response); } _this._settings.onLoadDone.call($__default["default"](_this), response); _this._removeOverlay(); }, this._settings.responseType !== '' && this._settings.responseType).fail(function (jqXHR, textStatus, errorThrown) { _this._removeOverlay(); if (_this._settings.loadErrorTemplate) { var msg = $__default["default"](_this._settings.errorTemplate).text(errorThrown); _this._parent.find(_this._settings.content).empty().append(msg); } _this._settings.onLoadFail.call($__default["default"](_this), jqXHR, textStatus, errorThrown); }); $__default["default"](this._element).trigger($__default["default"].Event(EVENT_LOADED)); }; _proto._addOverlay = function _addOverlay() { this._parent.append(this._overlay); $__default["default"](this._element).trigger($__default["default"].Event(EVENT_OVERLAY_ADDED)); }; _proto._removeOverlay = function _removeOverlay() { this._parent.find(this._overlay).remove(); $__default["default"](this._element).trigger($__default["default"].Event(EVENT_OVERLAY_REMOVED)); } // Private ; _proto._init = function _init() { var _this2 = this; $__default["default"](this).find(this._settings.trigger).on('click', function () { _this2.load(); }); if (this._settings.loadOnInit) { this.load(); } } // Static ; CardRefresh._jQueryInterface = function _jQueryInterface(config) { var data = $__default["default"](this).data(DATA_KEY$e); var _options = $__default["default"].extend({}, Default$c, $__default["default"](this).data()); if (!data) { data = new CardRefresh($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$e, typeof config === 'string' ? data : config); } if (typeof config === 'string' && /load/.test(config)) { data[config](); } else { data._init($__default["default"](this)); } }; return CardRefresh; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_DATA_REFRESH, function (event) { if (event) { event.preventDefault(); } CardRefresh._jQueryInterface.call($__default["default"](this), 'load'); }); $__default["default"](function () { $__default["default"](SELECTOR_DATA_REFRESH).each(function () { CardRefresh._jQueryInterface.call($__default["default"](this)); }); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$e] = CardRefresh._jQueryInterface; $__default["default"].fn[NAME$e].Constructor = CardRefresh; $__default["default"].fn[NAME$e].noConflict = function () { $__default["default"].fn[NAME$e] = JQUERY_NO_CONFLICT$e; return CardRefresh._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE CardWidget.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$d = 'CardWidget'; var DATA_KEY$d = 'lte.cardwidget'; var EVENT_KEY$6 = "." + DATA_KEY$d; var JQUERY_NO_CONFLICT$d = $__default["default"].fn[NAME$d]; var EVENT_EXPANDED$3 = "expanded" + EVENT_KEY$6; var EVENT_COLLAPSED$4 = "collapsed" + EVENT_KEY$6; var EVENT_MAXIMIZED = "maximized" + EVENT_KEY$6; var EVENT_MINIMIZED = "minimized" + EVENT_KEY$6; var EVENT_REMOVED$1 = "removed" + EVENT_KEY$6; var CLASS_NAME_CARD = 'card'; var CLASS_NAME_COLLAPSED$1 = 'collapsed-card'; var CLASS_NAME_COLLAPSING = 'collapsing-card'; var CLASS_NAME_EXPANDING = 'expanding-card'; var CLASS_NAME_WAS_COLLAPSED = 'was-collapsed'; var CLASS_NAME_MAXIMIZED = 'maximized-card'; var SELECTOR_DATA_REMOVE = '[data-card-widget="remove"]'; var SELECTOR_DATA_COLLAPSE = '[data-card-widget="collapse"]'; var SELECTOR_DATA_MAXIMIZE = '[data-card-widget="maximize"]'; var SELECTOR_CARD = "." + CLASS_NAME_CARD; var SELECTOR_CARD_HEADER = '.card-header'; var SELECTOR_CARD_BODY = '.card-body'; var SELECTOR_CARD_FOOTER = '.card-footer'; var Default$b = { animationSpeed: 'normal', collapseTrigger: SELECTOR_DATA_COLLAPSE, removeTrigger: SELECTOR_DATA_REMOVE, maximizeTrigger: SELECTOR_DATA_MAXIMIZE, collapseIcon: 'fa-minus', expandIcon: 'fa-plus', maximizeIcon: 'fa-expand', minimizeIcon: 'fa-compress' }; var CardWidget = /*#__PURE__*/function () { function CardWidget(element, settings) { this._element = element; this._parent = element.parents(SELECTOR_CARD).first(); if (element.hasClass(CLASS_NAME_CARD)) { this._parent = element; } this._settings = $__default["default"].extend({}, Default$b, settings); } var _proto = CardWidget.prototype; _proto.collapse = function collapse() { var _this = this; this._parent.addClass(CLASS_NAME_COLLAPSING).children(SELECTOR_CARD_BODY + ", " + SELECTOR_CARD_FOOTER).slideUp(this._settings.animationSpeed, function () { _this._parent.addClass(CLASS_NAME_COLLAPSED$1).removeClass(CLASS_NAME_COLLAPSING); }); this._parent.find("> " + SELECTOR_CARD_HEADER + " " + this._settings.collapseTrigger + " ." + this._settings.collapseIcon).addClass(this._settings.expandIcon).removeClass(this._settings.collapseIcon); this._element.trigger($__default["default"].Event(EVENT_COLLAPSED$4), this._parent); }; _proto.expand = function expand() { var _this2 = this; this._parent.addClass(CLASS_NAME_EXPANDING).children(SELECTOR_CARD_BODY + ", " + SELECTOR_CARD_FOOTER).slideDown(this._settings.animationSpeed, function () { _this2._parent.removeClass(CLASS_NAME_COLLAPSED$1).removeClass(CLASS_NAME_EXPANDING); }); this._parent.find("> " + SELECTOR_CARD_HEADER + " " + this._settings.collapseTrigger + " ." + this._settings.expandIcon).addClass(this._settings.collapseIcon).removeClass(this._settings.expandIcon); this._element.trigger($__default["default"].Event(EVENT_EXPANDED$3), this._parent); }; _proto.remove = function remove() { this._parent.slideUp(); this._element.trigger($__default["default"].Event(EVENT_REMOVED$1), this._parent); }; _proto.toggle = function toggle() { if (this._parent.hasClass(CLASS_NAME_COLLAPSED$1)) { this.expand(); return; } this.collapse(); }; _proto.maximize = function maximize() { this._parent.find(this._settings.maximizeTrigger + " ." + this._settings.maximizeIcon).addClass(this._settings.minimizeIcon).removeClass(this._settings.maximizeIcon); this._parent.css({ height: this._parent.height(), width: this._parent.width(), transition: 'all .15s' }).delay(150).queue(function () { var $element = $__default["default"](this); $element.addClass(CLASS_NAME_MAXIMIZED); $__default["default"]('html').addClass(CLASS_NAME_MAXIMIZED); if ($element.hasClass(CLASS_NAME_COLLAPSED$1)) { $element.addClass(CLASS_NAME_WAS_COLLAPSED); } $element.dequeue(); }); this._element.trigger($__default["default"].Event(EVENT_MAXIMIZED), this._parent); }; _proto.minimize = function minimize() { this._parent.find(this._settings.maximizeTrigger + " ." + this._settings.minimizeIcon).addClass(this._settings.maximizeIcon).removeClass(this._settings.minimizeIcon); this._parent.css('cssText', "height: " + this._parent[0].style.height + " !important; width: " + this._parent[0].style.width + " !important; transition: all .15s;").delay(10).queue(function () { var $element = $__default["default"](this); $element.removeClass(CLASS_NAME_MAXIMIZED); $__default["default"]('html').removeClass(CLASS_NAME_MAXIMIZED); $element.css({ height: 'inherit', width: 'inherit' }); if ($element.hasClass(CLASS_NAME_WAS_COLLAPSED)) { $element.removeClass(CLASS_NAME_WAS_COLLAPSED); } $element.dequeue(); }); this._element.trigger($__default["default"].Event(EVENT_MINIMIZED), this._parent); }; _proto.toggleMaximize = function toggleMaximize() { if (this._parent.hasClass(CLASS_NAME_MAXIMIZED)) { this.minimize(); return; } this.maximize(); } // Private ; _proto._init = function _init(card) { var _this3 = this; this._parent = card; $__default["default"](this).find(this._settings.collapseTrigger).click(function () { _this3.toggle(); }); $__default["default"](this).find(this._settings.maximizeTrigger).click(function () { _this3.toggleMaximize(); }); $__default["default"](this).find(this._settings.removeTrigger).click(function () { _this3.remove(); }); } // Static ; CardWidget._jQueryInterface = function _jQueryInterface(config) { var data = $__default["default"](this).data(DATA_KEY$d); var _options = $__default["default"].extend({}, Default$b, $__default["default"](this).data()); if (!data) { data = new CardWidget($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$d, typeof config === 'string' ? data : config); } if (typeof config === 'string' && /collapse|expand|remove|toggle|maximize|minimize|toggleMaximize/.test(config)) { data[config](); } else if (typeof config === 'object') { data._init($__default["default"](this)); } }; return CardWidget; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_DATA_COLLAPSE, function (event) { if (event) { event.preventDefault(); } CardWidget._jQueryInterface.call($__default["default"](this), 'toggle'); }); $__default["default"](document).on('click', SELECTOR_DATA_REMOVE, function (event) { if (event) { event.preventDefault(); } CardWidget._jQueryInterface.call($__default["default"](this), 'remove'); }); $__default["default"](document).on('click', SELECTOR_DATA_MAXIMIZE, function (event) { if (event) { event.preventDefault(); } CardWidget._jQueryInterface.call($__default["default"](this), 'toggleMaximize'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$d] = CardWidget._jQueryInterface; $__default["default"].fn[NAME$d].Constructor = CardWidget; $__default["default"].fn[NAME$d].noConflict = function () { $__default["default"].fn[NAME$d] = JQUERY_NO_CONFLICT$d; return CardWidget._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE ControlSidebar.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$c = 'ControlSidebar'; var DATA_KEY$c = 'lte.controlsidebar'; var EVENT_KEY$5 = "." + DATA_KEY$c; var JQUERY_NO_CONFLICT$c = $__default["default"].fn[NAME$c]; var EVENT_COLLAPSED$3 = "collapsed" + EVENT_KEY$5; var EVENT_COLLAPSED_DONE$1 = "collapsed-done" + EVENT_KEY$5; var EVENT_EXPANDED$2 = "expanded" + EVENT_KEY$5; var SELECTOR_CONTROL_SIDEBAR = '.control-sidebar'; var SELECTOR_CONTROL_SIDEBAR_CONTENT$1 = '.control-sidebar-content'; var SELECTOR_DATA_TOGGLE$4 = '[data-widget="control-sidebar"]'; var SELECTOR_HEADER$1 = '.main-header'; var SELECTOR_FOOTER$1 = '.main-footer'; var CLASS_NAME_CONTROL_SIDEBAR_ANIMATE = 'control-sidebar-animate'; var CLASS_NAME_CONTROL_SIDEBAR_OPEN$1 = 'control-sidebar-open'; var CLASS_NAME_CONTROL_SIDEBAR_SLIDE = 'control-sidebar-slide-open'; var CLASS_NAME_LAYOUT_FIXED$1 = 'layout-fixed'; var CLASS_NAME_NAVBAR_FIXED = 'layout-navbar-fixed'; var CLASS_NAME_NAVBAR_SM_FIXED = 'layout-sm-navbar-fixed'; var CLASS_NAME_NAVBAR_MD_FIXED = 'layout-md-navbar-fixed'; var CLASS_NAME_NAVBAR_LG_FIXED = 'layout-lg-navbar-fixed'; var CLASS_NAME_NAVBAR_XL_FIXED = 'layout-xl-navbar-fixed'; var CLASS_NAME_FOOTER_FIXED = 'layout-footer-fixed'; var CLASS_NAME_FOOTER_SM_FIXED = 'layout-sm-footer-fixed'; var CLASS_NAME_FOOTER_MD_FIXED = 'layout-md-footer-fixed'; var CLASS_NAME_FOOTER_LG_FIXED = 'layout-lg-footer-fixed'; var CLASS_NAME_FOOTER_XL_FIXED = 'layout-xl-footer-fixed'; var Default$a = { controlsidebarSlide: true, scrollbarTheme: 'os-theme-light', scrollbarAutoHide: 'l', target: SELECTOR_CONTROL_SIDEBAR, animationSpeed: 300 }; /** * Class Definition * ==================================================== */ var ControlSidebar = /*#__PURE__*/function () { function ControlSidebar(element, config) { this._element = element; this._config = config; } // Public var _proto = ControlSidebar.prototype; _proto.collapse = function collapse() { var _this = this; var $body = $__default["default"]('body'); var $html = $__default["default"]('html'); // Show the control sidebar if (this._config.controlsidebarSlide) { $html.addClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE); $body.removeClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () { $__default["default"](SELECTOR_CONTROL_SIDEBAR).hide(); $html.removeClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE); $__default["default"](this).dequeue(); }); } else { $body.removeClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1); } $__default["default"](this._element).trigger($__default["default"].Event(EVENT_COLLAPSED$3)); setTimeout(function () { $__default["default"](_this._element).trigger($__default["default"].Event(EVENT_COLLAPSED_DONE$1)); }, this._config.animationSpeed); }; _proto.show = function show(toggle) { if (toggle === void 0) { toggle = false; } var $body = $__default["default"]('body'); var $html = $__default["default"]('html'); if (toggle) { $__default["default"](SELECTOR_CONTROL_SIDEBAR).hide(); } // Collapse the control sidebar if (this._config.controlsidebarSlide) { $html.addClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE); $__default["default"](this._config.target).show().delay(10).queue(function () { $body.addClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () { $html.removeClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE); $__default["default"](this).dequeue(); }); $__default["default"](this).dequeue(); }); } else { $body.addClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1); } this._fixHeight(); this._fixScrollHeight(); $__default["default"](this._element).trigger($__default["default"].Event(EVENT_EXPANDED$2)); }; _proto.toggle = function toggle() { var $body = $__default["default"]('body'); var target = this._config.target; var notVisible = !$__default["default"](target).is(':visible'); var shouldClose = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE); var shouldToggle = notVisible && ($body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE)); if (notVisible || shouldToggle) { // Open the control sidebar this.show(notVisible); } else if (shouldClose) { // Close the control sidebar this.collapse(); } } // Private ; _proto._init = function _init() { var _this2 = this; var $body = $__default["default"]('body'); var shouldNotHideAll = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE); if (shouldNotHideAll) { $__default["default"](SELECTOR_CONTROL_SIDEBAR).not(this._config.target).hide(); $__default["default"](this._config.target).css('display', 'block'); } else { $__default["default"](SELECTOR_CONTROL_SIDEBAR).hide(); } this._fixHeight(); this._fixScrollHeight(); $__default["default"](window).resize(function () { _this2._fixHeight(); _this2._fixScrollHeight(); }); $__default["default"](window).scroll(function () { var $body = $__default["default"]('body'); var shouldFixHeight = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN$1) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE); if (shouldFixHeight) { _this2._fixScrollHeight(); } }); }; _proto._isNavbarFixed = function _isNavbarFixed() { var $body = $__default["default"]('body'); return $body.hasClass(CLASS_NAME_NAVBAR_FIXED) || $body.hasClass(CLASS_NAME_NAVBAR_SM_FIXED) || $body.hasClass(CLASS_NAME_NAVBAR_MD_FIXED) || $body.hasClass(CLASS_NAME_NAVBAR_LG_FIXED) || $body.hasClass(CLASS_NAME_NAVBAR_XL_FIXED); }; _proto._isFooterFixed = function _isFooterFixed() { var $body = $__default["default"]('body'); return $body.hasClass(CLASS_NAME_FOOTER_FIXED) || $body.hasClass(CLASS_NAME_FOOTER_SM_FIXED) || $body.hasClass(CLASS_NAME_FOOTER_MD_FIXED) || $body.hasClass(CLASS_NAME_FOOTER_LG_FIXED) || $body.hasClass(CLASS_NAME_FOOTER_XL_FIXED); }; _proto._fixScrollHeight = function _fixScrollHeight() { var $body = $__default["default"]('body'); var $controlSidebar = $__default["default"](this._config.target); if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED$1)) { return; } var heights = { scroll: $__default["default"](document).height(), window: $__default["default"](window).height(), header: $__default["default"](SELECTOR_HEADER$1).outerHeight(), footer: $__default["default"](SELECTOR_FOOTER$1).outerHeight() }; var positions = { bottom: Math.abs(heights.window + $__default["default"](window).scrollTop() - heights.scroll), top: $__default["default"](window).scrollTop() }; var navbarFixed = this._isNavbarFixed() && $__default["default"](SELECTOR_HEADER$1).css('position') === 'fixed'; var footerFixed = this._isFooterFixed() && $__default["default"](SELECTOR_FOOTER$1).css('position') === 'fixed'; var $controlsidebarContent = $__default["default"](this._config.target + ", " + this._config.target + " " + SELECTOR_CONTROL_SIDEBAR_CONTENT$1); if (positions.top === 0 && positions.bottom === 0) { $controlSidebar.css({ bottom: heights.footer, top: heights.header }); $controlsidebarContent.css('height', heights.window - (heights.header + heights.footer)); } else if (positions.bottom <= heights.footer) { if (footerFixed === false) { var top = heights.header - positions.top; $controlSidebar.css('bottom', heights.footer - positions.bottom).css('top', top >= 0 ? top : 0); $controlsidebarContent.css('height', heights.window - (heights.footer - positions.bottom)); } else { $controlSidebar.css('bottom', heights.footer); } } else if (positions.top <= heights.header) { if (navbarFixed === false) { $controlSidebar.css('top', heights.header - positions.top); $controlsidebarContent.css('height', heights.window - (heights.header - positions.top)); } else { $controlSidebar.css('top', heights.header); } } else if (navbarFixed === false) { $controlSidebar.css('top', 0); $controlsidebarContent.css('height', heights.window); } else { $controlSidebar.css('top', heights.header); } if (footerFixed && navbarFixed) { $controlsidebarContent.css('height', '100%'); $controlSidebar.css('height', ''); } else if (footerFixed || navbarFixed) { $controlsidebarContent.css('height', '100%'); $controlsidebarContent.css('height', ''); } }; _proto._fixHeight = function _fixHeight() { var $body = $__default["default"]('body'); var $controlSidebar = $__default["default"](this._config.target + " " + SELECTOR_CONTROL_SIDEBAR_CONTENT$1); if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED$1)) { $controlSidebar.attr('style', ''); return; } var heights = { window: $__default["default"](window).height(), header: $__default["default"](SELECTOR_HEADER$1).outerHeight(), footer: $__default["default"](SELECTOR_FOOTER$1).outerHeight() }; var sidebarHeight = heights.window - heights.header; if (this._isFooterFixed() && $__default["default"](SELECTOR_FOOTER$1).css('position') === 'fixed') { sidebarHeight = heights.window - heights.header - heights.footer; } $controlSidebar.css('height', sidebarHeight); if (typeof $__default["default"].fn.overlayScrollbars !== 'undefined') { $controlSidebar.overlayScrollbars({ className: this._config.scrollbarTheme, sizeAutoCapable: true, scrollbars: { autoHide: this._config.scrollbarAutoHide, clickScrolling: true } }); } } // Static ; ControlSidebar._jQueryInterface = function _jQueryInterface(operation) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$c); var _options = $__default["default"].extend({}, Default$a, $__default["default"](this).data()); if (!data) { data = new ControlSidebar(this, _options); $__default["default"](this).data(DATA_KEY$c, data); } if (data[operation] === 'undefined') { throw new Error(operation + " is not a function"); } data[operation](); }); }; return ControlSidebar; }(); /** * * Data Api implementation * ==================================================== */ $__default["default"](document).on('click', SELECTOR_DATA_TOGGLE$4, function (event) { event.preventDefault(); ControlSidebar._jQueryInterface.call($__default["default"](this), 'toggle'); }); $__default["default"](document).ready(function () { ControlSidebar._jQueryInterface.call($__default["default"](SELECTOR_DATA_TOGGLE$4), '_init'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$c] = ControlSidebar._jQueryInterface; $__default["default"].fn[NAME$c].Constructor = ControlSidebar; $__default["default"].fn[NAME$c].noConflict = function () { $__default["default"].fn[NAME$c] = JQUERY_NO_CONFLICT$c; return ControlSidebar._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE DirectChat.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$b = 'DirectChat'; var DATA_KEY$b = 'lte.directchat'; var EVENT_KEY$4 = "." + DATA_KEY$b; var JQUERY_NO_CONFLICT$b = $__default["default"].fn[NAME$b]; var EVENT_TOGGLED = "toggled" + EVENT_KEY$4; var SELECTOR_DATA_TOGGLE$3 = '[data-widget="chat-pane-toggle"]'; var SELECTOR_DIRECT_CHAT = '.direct-chat'; var CLASS_NAME_DIRECT_CHAT_OPEN = 'direct-chat-contacts-open'; /** * Class Definition * ==================================================== */ var DirectChat = /*#__PURE__*/function () { function DirectChat(element) { this._element = element; } var _proto = DirectChat.prototype; _proto.toggle = function toggle() { $__default["default"](this._element).parents(SELECTOR_DIRECT_CHAT).first().toggleClass(CLASS_NAME_DIRECT_CHAT_OPEN); $__default["default"](this._element).trigger($__default["default"].Event(EVENT_TOGGLED)); } // Static ; DirectChat._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$b); if (!data) { data = new DirectChat($__default["default"](this)); $__default["default"](this).data(DATA_KEY$b, data); } data[config](); }); }; return DirectChat; }(); /** * * Data Api implementation * ==================================================== */ $__default["default"](document).on('click', SELECTOR_DATA_TOGGLE$3, function (event) { if (event) { event.preventDefault(); } DirectChat._jQueryInterface.call($__default["default"](this), 'toggle'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$b] = DirectChat._jQueryInterface; $__default["default"].fn[NAME$b].Constructor = DirectChat; $__default["default"].fn[NAME$b].noConflict = function () { $__default["default"].fn[NAME$b] = JQUERY_NO_CONFLICT$b; return DirectChat._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE Dropdown.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$a = 'Dropdown'; var DATA_KEY$a = 'lte.dropdown'; var JQUERY_NO_CONFLICT$a = $__default["default"].fn[NAME$a]; var SELECTOR_NAVBAR = '.navbar'; var SELECTOR_DROPDOWN_MENU = '.dropdown-menu'; var SELECTOR_DROPDOWN_MENU_ACTIVE = '.dropdown-menu.show'; var SELECTOR_DROPDOWN_TOGGLE = '[data-toggle="dropdown"]'; var CLASS_NAME_DROPDOWN_RIGHT = 'dropdown-menu-right'; var CLASS_NAME_DROPDOWN_SUBMENU = 'dropdown-submenu'; // TODO: this is unused; should be removed along with the extend? var Default$9 = {}; /** * Class Definition * ==================================================== */ var Dropdown = /*#__PURE__*/function () { function Dropdown(element, config) { this._config = config; this._element = element; } // Public var _proto = Dropdown.prototype; _proto.toggleSubmenu = function toggleSubmenu() { this._element.siblings().show().toggleClass('show'); if (!this._element.next().hasClass('show')) { this._element.parents(SELECTOR_DROPDOWN_MENU).first().find('.show').removeClass('show').hide(); } this._element.parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function () { $__default["default"]('.dropdown-submenu .show').removeClass('show').hide(); }); }; _proto.fixPosition = function fixPosition() { var $element = $__default["default"](SELECTOR_DROPDOWN_MENU_ACTIVE); if ($element.length === 0) { return; } if ($element.hasClass(CLASS_NAME_DROPDOWN_RIGHT)) { $element.css({ left: 'inherit', right: 0 }); } else { $element.css({ left: 0, right: 'inherit' }); } var offset = $element.offset(); var width = $element.width(); var visiblePart = $__default["default"](window).width() - offset.left; if (offset.left < 0) { $element.css({ left: 'inherit', right: offset.left - 5 }); } else if (visiblePart < width) { $element.css({ left: 'inherit', right: 0 }); } } // Static ; Dropdown._jQueryInterface = function _jQueryInterface(config) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$a); var _config = $__default["default"].extend({}, Default$9, $__default["default"](this).data()); if (!data) { data = new Dropdown($__default["default"](this), _config); $__default["default"](this).data(DATA_KEY$a, data); } if (config === 'toggleSubmenu' || config === 'fixPosition') { data[config](); } }); }; return Dropdown; }(); /** * Data API * ==================================================== */ $__default["default"](SELECTOR_DROPDOWN_MENU + " " + SELECTOR_DROPDOWN_TOGGLE).on('click', function (event) { event.preventDefault(); event.stopPropagation(); Dropdown._jQueryInterface.call($__default["default"](this), 'toggleSubmenu'); }); $__default["default"](SELECTOR_NAVBAR + " " + SELECTOR_DROPDOWN_TOGGLE).on('click', function (event) { event.preventDefault(); if ($__default["default"](event.target).parent().hasClass(CLASS_NAME_DROPDOWN_SUBMENU)) { return; } setTimeout(function () { Dropdown._jQueryInterface.call($__default["default"](this), 'fixPosition'); }, 1); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$a] = Dropdown._jQueryInterface; $__default["default"].fn[NAME$a].Constructor = Dropdown; $__default["default"].fn[NAME$a].noConflict = function () { $__default["default"].fn[NAME$a] = JQUERY_NO_CONFLICT$a; return Dropdown._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE ExpandableTable.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$9 = 'ExpandableTable'; var DATA_KEY$9 = 'lte.expandableTable'; var EVENT_KEY$3 = "." + DATA_KEY$9; var JQUERY_NO_CONFLICT$9 = $__default["default"].fn[NAME$9]; var EVENT_EXPANDED$1 = "expanded" + EVENT_KEY$3; var EVENT_COLLAPSED$2 = "collapsed" + EVENT_KEY$3; var SELECTOR_TABLE = '.expandable-table'; var SELECTOR_EXPANDABLE_BODY = '.expandable-body'; var SELECTOR_DATA_TOGGLE$2 = '[data-widget="expandable-table"]'; var SELECTOR_ARIA_ATTR = 'aria-expanded'; /** * Class Definition * ==================================================== */ var ExpandableTable = /*#__PURE__*/function () { function ExpandableTable(element, options) { this._options = options; this._element = element; } // Public var _proto = ExpandableTable.prototype; _proto.init = function init() { $__default["default"](SELECTOR_DATA_TOGGLE$2).each(function (_, $header) { var $type = $__default["default"]($header).attr(SELECTOR_ARIA_ATTR); var $body = $__default["default"]($header).next(SELECTOR_EXPANDABLE_BODY).children().first().children(); if ($type === 'true') { $body.show(); } else if ($type === 'false') { $body.hide(); $body.parent().parent().addClass('d-none'); } }); }; _proto.toggleRow = function toggleRow() { var $element = this._element; if ($element[0].nodeName !== 'TR') { $element = $element.parent(); if ($element[0].nodeName !== 'TR') { $element = $element.parent(); } } var time = 500; var $type = $element.attr(SELECTOR_ARIA_ATTR); var $body = $element.next(SELECTOR_EXPANDABLE_BODY).children().first().children(); $body.stop(); if ($type === 'true') { $body.slideUp(time, function () { $element.next(SELECTOR_EXPANDABLE_BODY).addClass('d-none'); }); $element.attr(SELECTOR_ARIA_ATTR, 'false'); $element.trigger($__default["default"].Event(EVENT_COLLAPSED$2)); } else if ($type === 'false') { $element.next(SELECTOR_EXPANDABLE_BODY).removeClass('d-none'); $body.slideDown(time); $element.attr(SELECTOR_ARIA_ATTR, 'true'); $element.trigger($__default["default"].Event(EVENT_EXPANDED$1)); } } // Static ; ExpandableTable._jQueryInterface = function _jQueryInterface(operation) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$9); if (!data) { data = new ExpandableTable($__default["default"](this)); $__default["default"](this).data(DATA_KEY$9, data); } if (typeof operation === 'string' && /init|toggleRow/.test(operation)) { data[operation](); } }); }; return ExpandableTable; }(); /** * Data API * ==================================================== */ $__default["default"](SELECTOR_TABLE).ready(function () { ExpandableTable._jQueryInterface.call($__default["default"](this), 'init'); }); $__default["default"](document).on('click', SELECTOR_DATA_TOGGLE$2, function () { ExpandableTable._jQueryInterface.call($__default["default"](this), 'toggleRow'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$9] = ExpandableTable._jQueryInterface; $__default["default"].fn[NAME$9].Constructor = ExpandableTable; $__default["default"].fn[NAME$9].noConflict = function () { $__default["default"].fn[NAME$9] = JQUERY_NO_CONFLICT$9; return ExpandableTable._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE Fullscreen.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$8 = 'Fullscreen'; var DATA_KEY$8 = 'lte.fullscreen'; var JQUERY_NO_CONFLICT$8 = $__default["default"].fn[NAME$8]; var SELECTOR_DATA_WIDGET$2 = '[data-widget="fullscreen"]'; var SELECTOR_ICON = SELECTOR_DATA_WIDGET$2 + " i"; var EVENT_FULLSCREEN_CHANGE = 'webkitfullscreenchange mozfullscreenchange fullscreenchange MSFullscreenChange'; var Default$8 = { minimizeIcon: 'fa-compress-arrows-alt', maximizeIcon: 'fa-expand-arrows-alt' }; /** * Class Definition * ==================================================== */ var Fullscreen = /*#__PURE__*/function () { function Fullscreen(_element, _options) { this.element = _element; this.options = $__default["default"].extend({}, Default$8, _options); } // Public var _proto = Fullscreen.prototype; _proto.toggle = function toggle() { if (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) { this.windowed(); } else { this.fullscreen(); } }; _proto.toggleIcon = function toggleIcon() { if (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) { $__default["default"](SELECTOR_ICON).removeClass(this.options.maximizeIcon).addClass(this.options.minimizeIcon); } else { $__default["default"](SELECTOR_ICON).removeClass(this.options.minimizeIcon).addClass(this.options.maximizeIcon); } }; _proto.fullscreen = function fullscreen() { if (document.documentElement.requestFullscreen) { document.documentElement.requestFullscreen(); } else if (document.documentElement.webkitRequestFullscreen) { document.documentElement.webkitRequestFullscreen(); } else if (document.documentElement.msRequestFullscreen) { document.documentElement.msRequestFullscreen(); } }; _proto.windowed = function windowed() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } // Static ; Fullscreen._jQueryInterface = function _jQueryInterface(config) { var data = $__default["default"](this).data(DATA_KEY$8); if (!data) { data = $__default["default"](this).data(); } var _options = $__default["default"].extend({}, Default$8, typeof config === 'object' ? config : data); var plugin = new Fullscreen($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$8, typeof config === 'object' ? config : data); if (typeof config === 'string' && /toggle|toggleIcon|fullscreen|windowed/.test(config)) { plugin[config](); } else { plugin.init(); } }; return Fullscreen; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_DATA_WIDGET$2, function () { Fullscreen._jQueryInterface.call($__default["default"](this), 'toggle'); }); $__default["default"](document).on(EVENT_FULLSCREEN_CHANGE, function () { Fullscreen._jQueryInterface.call($__default["default"](SELECTOR_DATA_WIDGET$2), 'toggleIcon'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$8] = Fullscreen._jQueryInterface; $__default["default"].fn[NAME$8].Constructor = Fullscreen; $__default["default"].fn[NAME$8].noConflict = function () { $__default["default"].fn[NAME$8] = JQUERY_NO_CONFLICT$8; return Fullscreen._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE IFrame.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$7 = 'IFrame'; var DATA_KEY$7 = 'lte.iframe'; var JQUERY_NO_CONFLICT$7 = $__default["default"].fn[NAME$7]; var SELECTOR_DATA_TOGGLE$1 = '[data-widget="iframe"]'; var SELECTOR_DATA_TOGGLE_CLOSE = '[data-widget="iframe-close"]'; var SELECTOR_DATA_TOGGLE_SCROLL_LEFT = '[data-widget="iframe-scrollleft"]'; var SELECTOR_DATA_TOGGLE_SCROLL_RIGHT = '[data-widget="iframe-scrollright"]'; var SELECTOR_DATA_TOGGLE_FULLSCREEN = '[data-widget="iframe-fullscreen"]'; var SELECTOR_CONTENT_WRAPPER = '.content-wrapper'; var SELECTOR_CONTENT_IFRAME = SELECTOR_CONTENT_WRAPPER + " iframe"; var SELECTOR_TAB_NAV = SELECTOR_CONTENT_WRAPPER + ".iframe-mode .nav"; var SELECTOR_TAB_NAVBAR_NAV = SELECTOR_CONTENT_WRAPPER + ".iframe-mode .navbar-nav"; var SELECTOR_TAB_NAVBAR_NAV_ITEM = SELECTOR_TAB_NAVBAR_NAV + " .nav-item"; var SELECTOR_TAB_NAVBAR_NAV_LINK = SELECTOR_TAB_NAVBAR_NAV + " .nav-link"; var SELECTOR_TAB_CONTENT = SELECTOR_CONTENT_WRAPPER + ".iframe-mode .tab-content"; var SELECTOR_TAB_EMPTY = SELECTOR_TAB_CONTENT + " .tab-empty"; var SELECTOR_TAB_LOADING = SELECTOR_TAB_CONTENT + " .tab-loading"; var SELECTOR_TAB_PANE = SELECTOR_TAB_CONTENT + " .tab-pane"; var SELECTOR_SIDEBAR_MENU_ITEM = '.main-sidebar .nav-item > a.nav-link'; var SELECTOR_SIDEBAR_SEARCH_ITEM = '.sidebar-search-results .list-group-item'; var SELECTOR_HEADER_MENU_ITEM = '.main-header .nav-item a.nav-link'; var SELECTOR_HEADER_DROPDOWN_ITEM = '.main-header a.dropdown-item'; var CLASS_NAME_IFRAME_MODE$1 = 'iframe-mode'; var CLASS_NAME_FULLSCREEN_MODE = 'iframe-mode-fullscreen'; var Default$7 = { onTabClick: function onTabClick(item) { return item; }, onTabChanged: function onTabChanged(item) { return item; }, onTabCreated: function onTabCreated(item) { return item; }, autoIframeMode: true, autoItemActive: true, autoShowNewTab: true, autoDarkMode: false, allowDuplicates: false, allowReload: true, loadingScreen: true, useNavbarItems: true, scrollOffset: 40, scrollBehaviorSwap: false, iconMaximize: 'fa-expand', iconMinimize: 'fa-compress' }; /** * Class Definition * ==================================================== */ var IFrame = /*#__PURE__*/function () { function IFrame(element, config) { this._config = config; this._element = element; this._init(); } // Public var _proto = IFrame.prototype; _proto.onTabClick = function onTabClick(item) { this._config.onTabClick(item); }; _proto.onTabChanged = function onTabChanged(item) { this._config.onTabChanged(item); }; _proto.onTabCreated = function onTabCreated(item) { this._config.onTabCreated(item); }; _proto.createTab = function createTab(title, link, uniqueName, autoOpen) { var _this = this; var tabId = "panel-" + uniqueName; var navId = "tab-" + uniqueName; if (this._config.allowDuplicates) { tabId += "-" + Math.floor(Math.random() * 1000); navId += "-" + Math.floor(Math.random() * 1000); } var newNavItem = "
  • " + title + "
  • "; $__default["default"](SELECTOR_TAB_NAVBAR_NAV).append(unescape(escape(newNavItem))); var newTabItem = "
    "; $__default["default"](SELECTOR_TAB_CONTENT).append(unescape(escape(newTabItem))); if (autoOpen) { if (this._config.loadingScreen) { var $loadingScreen = $__default["default"](SELECTOR_TAB_LOADING); $loadingScreen.fadeIn(); $__default["default"](tabId + " iframe").ready(function () { if (typeof _this._config.loadingScreen === 'number') { _this.switchTab("#" + navId); setTimeout(function () { $loadingScreen.fadeOut(); }, _this._config.loadingScreen); } else { _this.switchTab("#" + navId); $loadingScreen.fadeOut(); } }); } else { this.switchTab("#" + navId); } } this.onTabCreated($__default["default"]("#" + navId)); }; _proto.openTabSidebar = function openTabSidebar(item, autoOpen) { if (autoOpen === void 0) { autoOpen = this._config.autoShowNewTab; } var $item = $__default["default"](item).clone(); if ($item.attr('href') === undefined) { $item = $__default["default"](item).parent('a').clone(); } $item.find('.right, .search-path').remove(); var title = $item.find('p').text(); if (title === '') { title = $item.text(); } var link = $item.attr('href'); if (link === '#' || link === '' || link === undefined) { return; } var uniqueName = unescape(link).replace('./', '').replace(/["#&'./:=?[\]]/gi, '-').replace(/(--)/gi, ''); var navId = "tab-" + uniqueName; if (!this._config.allowDuplicates && $__default["default"]("#" + navId).length > 0) { return this.switchTab("#" + navId, this._config.allowReload); } if (!this._config.allowDuplicates && $__default["default"]("#" + navId).length === 0 || this._config.allowDuplicates) { this.createTab(title, link, uniqueName, autoOpen); } }; _proto.switchTab = function switchTab(item, reload) { var _this2 = this; if (reload === void 0) { reload = false; } var $item = $__default["default"](item); var tabId = $item.attr('href'); $__default["default"](SELECTOR_TAB_EMPTY).hide(); if (reload) { var $loadingScreen = $__default["default"](SELECTOR_TAB_LOADING); if (this._config.loadingScreen) { $loadingScreen.show(0, function () { $__default["default"](tabId + " iframe").attr('src', $__default["default"](tabId + " iframe").attr('src')).ready(function () { if (_this2._config.loadingScreen) { if (typeof _this2._config.loadingScreen === 'number') { setTimeout(function () { $loadingScreen.fadeOut(); }, _this2._config.loadingScreen); } else { $loadingScreen.fadeOut(); } } }); }); } else { $__default["default"](tabId + " iframe").attr('src', $__default["default"](tabId + " iframe").attr('src')); } } $__default["default"](SELECTOR_TAB_NAVBAR_NAV + " .active").tab('dispose').removeClass('active'); this._fixHeight(); $item.tab('show'); $item.parents('li').addClass('active'); this.onTabChanged($item); if (this._config.autoItemActive) { this._setItemActive($__default["default"](tabId + " iframe").attr('src')); } }; _proto.removeActiveTab = function removeActiveTab(type, element) { if (type == 'all') { $__default["default"](SELECTOR_TAB_NAVBAR_NAV_ITEM).remove(); $__default["default"](SELECTOR_TAB_PANE).remove(); $__default["default"](SELECTOR_TAB_EMPTY).show(); } else if (type == 'all-other') { $__default["default"](SELECTOR_TAB_NAVBAR_NAV_ITEM + ":not(.active)").remove(); $__default["default"](SELECTOR_TAB_PANE + ":not(.active)").remove(); } else if (type == 'only-this') { var $navClose = $__default["default"](element); var $navItem = $navClose.parent('.nav-item'); var $navItemParent = $navItem.parent(); var navItemIndex = $navItem.index(); var tabId = $navClose.siblings('.nav-link').attr('aria-controls'); $navItem.remove(); $__default["default"]("#" + tabId).remove(); if ($__default["default"](SELECTOR_TAB_CONTENT).children().length == $__default["default"](SELECTOR_TAB_EMPTY + ", " + SELECTOR_TAB_LOADING).length) { $__default["default"](SELECTOR_TAB_EMPTY).show(); } else { var prevNavItemIndex = navItemIndex - 1; this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link')); } } else { var _$navItem = $__default["default"](SELECTOR_TAB_NAVBAR_NAV_ITEM + ".active"); var _$navItemParent = _$navItem.parent(); var _navItemIndex = _$navItem.index(); _$navItem.remove(); $__default["default"](SELECTOR_TAB_PANE + ".active").remove(); if ($__default["default"](SELECTOR_TAB_CONTENT).children().length == $__default["default"](SELECTOR_TAB_EMPTY + ", " + SELECTOR_TAB_LOADING).length) { $__default["default"](SELECTOR_TAB_EMPTY).show(); } else { var _prevNavItemIndex = _navItemIndex - 1; this.switchTab(_$navItemParent.children().eq(_prevNavItemIndex).find('a.nav-link')); } } }; _proto.toggleFullscreen = function toggleFullscreen() { if ($__default["default"]('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) { $__default["default"](SELECTOR_DATA_TOGGLE_FULLSCREEN + " i").removeClass(this._config.iconMinimize).addClass(this._config.iconMaximize); $__default["default"]('body').removeClass(CLASS_NAME_FULLSCREEN_MODE); $__default["default"](SELECTOR_TAB_EMPTY + ", " + SELECTOR_TAB_LOADING).height('100%'); $__default["default"](SELECTOR_CONTENT_WRAPPER).height('100%'); $__default["default"](SELECTOR_CONTENT_IFRAME).height('100%'); } else { $__default["default"](SELECTOR_DATA_TOGGLE_FULLSCREEN + " i").removeClass(this._config.iconMaximize).addClass(this._config.iconMinimize); $__default["default"]('body').addClass(CLASS_NAME_FULLSCREEN_MODE); } $__default["default"](window).trigger('resize'); this._fixHeight(true); } // Private ; _proto._init = function _init() { var usingDefTab = $__default["default"](SELECTOR_TAB_CONTENT).children().length > 2; this._setupListeners(); this._fixHeight(true); if (usingDefTab) { var $el = $__default["default"]("" + SELECTOR_TAB_PANE).first(); // eslint-disable-next-line no-console console.log($el); var uniqueName = $el.attr('id').replace('panel-', ''); var navId = "#tab-" + uniqueName; this.switchTab(navId, true); } }; _proto._initFrameElement = function _initFrameElement() { if (window.frameElement && this._config.autoIframeMode) { var $body = $__default["default"]('body'); $body.addClass(CLASS_NAME_IFRAME_MODE$1); if (this._config.autoDarkMode) { $body.addClass('dark-mode'); } } }; _proto._navScroll = function _navScroll(offset) { var leftPos = $__default["default"](SELECTOR_TAB_NAVBAR_NAV).scrollLeft(); $__default["default"](SELECTOR_TAB_NAVBAR_NAV).animate({ scrollLeft: leftPos + offset }, 250, 'linear'); }; _proto._setupListeners = function _setupListeners() { var _this3 = this; $__default["default"](window).on('resize', function () { setTimeout(function () { _this3._fixHeight(); }, 1); }); if ($__default["default"](SELECTOR_CONTENT_WRAPPER).hasClass(CLASS_NAME_IFRAME_MODE$1)) { $__default["default"](document).on('click', SELECTOR_SIDEBAR_MENU_ITEM + ", " + SELECTOR_SIDEBAR_SEARCH_ITEM, function (e) { e.preventDefault(); _this3.openTabSidebar(e.target); }); if (this._config.useNavbarItems) { $__default["default"](document).on('click', SELECTOR_HEADER_MENU_ITEM + ", " + SELECTOR_HEADER_DROPDOWN_ITEM, function (e) { e.preventDefault(); _this3.openTabSidebar(e.target); }); } } $__default["default"](document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, function (e) { e.preventDefault(); _this3.onTabClick(e.target); _this3.switchTab(e.target); }); $__default["default"](document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, function (e) { e.preventDefault(); _this3.onTabClick(e.target); _this3.switchTab(e.target); }); $__default["default"](document).on('click', SELECTOR_DATA_TOGGLE_CLOSE, function (e) { e.preventDefault(); var target = e.target; if (target.nodeName == 'I') { target = e.target.offsetParent; } _this3.removeActiveTab(target.attributes['data-type'] ? target.attributes['data-type'].nodeValue : null, target); }); $__default["default"](document).on('click', SELECTOR_DATA_TOGGLE_FULLSCREEN, function (e) { e.preventDefault(); _this3.toggleFullscreen(); }); var mousedown = false; var mousedownInterval = null; $__default["default"](document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_LEFT, function (e) { e.preventDefault(); clearInterval(mousedownInterval); var scrollOffset = _this3._config.scrollOffset; if (!_this3._config.scrollBehaviorSwap) { scrollOffset = -scrollOffset; } mousedown = true; _this3._navScroll(scrollOffset); mousedownInterval = setInterval(function () { _this3._navScroll(scrollOffset); }, 250); }); $__default["default"](document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_RIGHT, function (e) { e.preventDefault(); clearInterval(mousedownInterval); var scrollOffset = _this3._config.scrollOffset; if (_this3._config.scrollBehaviorSwap) { scrollOffset = -scrollOffset; } mousedown = true; _this3._navScroll(scrollOffset); mousedownInterval = setInterval(function () { _this3._navScroll(scrollOffset); }, 250); }); $__default["default"](document).on('mouseup', function () { if (mousedown) { mousedown = false; clearInterval(mousedownInterval); mousedownInterval = null; } }); }; _proto._setItemActive = function _setItemActive(href) { $__default["default"](SELECTOR_SIDEBAR_MENU_ITEM + ", " + SELECTOR_HEADER_DROPDOWN_ITEM).removeClass('active'); $__default["default"](SELECTOR_HEADER_MENU_ITEM).parent().removeClass('active'); var $headerMenuItem = $__default["default"](SELECTOR_HEADER_MENU_ITEM + "[href$=\"" + href + "\"]"); var $headerDropdownItem = $__default["default"](SELECTOR_HEADER_DROPDOWN_ITEM + "[href$=\"" + href + "\"]"); var $sidebarMenuItem = $__default["default"](SELECTOR_SIDEBAR_MENU_ITEM + "[href$=\"" + href + "\"]"); $headerMenuItem.each(function (i, e) { $__default["default"](e).parent().addClass('active'); }); $headerDropdownItem.each(function (i, e) { $__default["default"](e).addClass('active'); }); $sidebarMenuItem.each(function (i, e) { $__default["default"](e).addClass('active'); $__default["default"](e).parents('.nav-treeview').prevAll('.nav-link').addClass('active'); }); }; _proto._fixHeight = function _fixHeight(tabEmpty) { if (tabEmpty === void 0) { tabEmpty = false; } if ($__default["default"]('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) { var windowHeight = $__default["default"](window).height(); var navbarHeight = $__default["default"](SELECTOR_TAB_NAV).outerHeight(); $__default["default"](SELECTOR_TAB_EMPTY + ", " + SELECTOR_TAB_LOADING + ", " + SELECTOR_CONTENT_IFRAME).height(windowHeight - navbarHeight); $__default["default"](SELECTOR_CONTENT_WRAPPER).height(windowHeight); } else { var contentWrapperHeight = parseFloat($__default["default"](SELECTOR_CONTENT_WRAPPER).css('height')); var _navbarHeight = $__default["default"](SELECTOR_TAB_NAV).outerHeight(); if (tabEmpty == true) { setTimeout(function () { $__default["default"](SELECTOR_TAB_EMPTY + ", " + SELECTOR_TAB_LOADING).height(contentWrapperHeight - _navbarHeight); }, 50); } else { $__default["default"](SELECTOR_CONTENT_IFRAME).height(contentWrapperHeight - _navbarHeight); } } } // Static ; IFrame._jQueryInterface = function _jQueryInterface(config) { if ($__default["default"](SELECTOR_DATA_TOGGLE$1).length > 0) { var data = $__default["default"](this).data(DATA_KEY$7); if (!data) { data = $__default["default"](this).data(); } var _options = $__default["default"].extend({}, Default$7, typeof config === 'object' ? config : data); localStorage.setItem('AdminLTE:IFrame:Options', JSON.stringify(_options)); var plugin = new IFrame($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$7, typeof config === 'object' ? config : data); if (typeof config === 'string' && /createTab|openTabSidebar|switchTab|removeActiveTab/.test(config)) { plugin[config](); } } else { new IFrame($__default["default"](this), JSON.parse(localStorage.getItem('AdminLTE:IFrame:Options')))._initFrameElement(); } }; return IFrame; }(); /** * Data API * ==================================================== */ $__default["default"](window).on('load', function () { IFrame._jQueryInterface.call($__default["default"](SELECTOR_DATA_TOGGLE$1)); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$7] = IFrame._jQueryInterface; $__default["default"].fn[NAME$7].Constructor = IFrame; $__default["default"].fn[NAME$7].noConflict = function () { $__default["default"].fn[NAME$7] = JQUERY_NO_CONFLICT$7; return IFrame._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE Layout.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$6 = 'Layout'; var DATA_KEY$6 = 'lte.layout'; var JQUERY_NO_CONFLICT$6 = $__default["default"].fn[NAME$6]; var SELECTOR_HEADER = '.main-header'; var SELECTOR_MAIN_SIDEBAR = '.main-sidebar'; var SELECTOR_SIDEBAR$1 = '.main-sidebar .sidebar'; var SELECTOR_CONTENT = '.content-wrapper'; var SELECTOR_CONTROL_SIDEBAR_CONTENT = '.control-sidebar-content'; var SELECTOR_CONTROL_SIDEBAR_BTN = '[data-widget="control-sidebar"]'; var SELECTOR_FOOTER = '.main-footer'; var SELECTOR_PUSHMENU_BTN = '[data-widget="pushmenu"]'; var SELECTOR_LOGIN_BOX = '.login-box'; var SELECTOR_REGISTER_BOX = '.register-box'; var SELECTOR_PRELOADER = '.preloader'; var CLASS_NAME_SIDEBAR_COLLAPSED$1 = 'sidebar-collapse'; var CLASS_NAME_SIDEBAR_FOCUSED = 'sidebar-focused'; var CLASS_NAME_LAYOUT_FIXED = 'layout-fixed'; var CLASS_NAME_CONTROL_SIDEBAR_SLIDE_OPEN = 'control-sidebar-slide-open'; var CLASS_NAME_CONTROL_SIDEBAR_OPEN = 'control-sidebar-open'; var CLASS_NAME_IFRAME_MODE = 'iframe-mode'; var Default$6 = { scrollbarTheme: 'os-theme-light', scrollbarAutoHide: 'l', panelAutoHeight: true, panelAutoHeightMode: 'min-height', preloadDuration: 200, loginRegisterAutoHeight: true }; /** * Class Definition * ==================================================== */ var Layout = /*#__PURE__*/function () { function Layout(element, config) { this._config = config; this._element = element; } // Public var _proto = Layout.prototype; _proto.fixLayoutHeight = function fixLayoutHeight(extra) { if (extra === void 0) { extra = null; } var $body = $__default["default"]('body'); var controlSidebar = 0; if ($body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE_OPEN) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN) || extra === 'control_sidebar') { controlSidebar = $__default["default"](SELECTOR_CONTROL_SIDEBAR_CONTENT).outerHeight(); } var heights = { window: $__default["default"](window).height(), header: $__default["default"](SELECTOR_HEADER).length > 0 ? $__default["default"](SELECTOR_HEADER).outerHeight() : 0, footer: $__default["default"](SELECTOR_FOOTER).length > 0 ? $__default["default"](SELECTOR_FOOTER).outerHeight() : 0, sidebar: $__default["default"](SELECTOR_SIDEBAR$1).length > 0 ? $__default["default"](SELECTOR_SIDEBAR$1).height() : 0, controlSidebar: controlSidebar }; var max = this._max(heights); var offset = this._config.panelAutoHeight; if (offset === true) { offset = 0; } var $contentSelector = $__default["default"](SELECTOR_CONTENT); if (offset !== false) { if (max === heights.controlSidebar) { $contentSelector.css(this._config.panelAutoHeightMode, max + offset); } else if (max === heights.window) { $contentSelector.css(this._config.panelAutoHeightMode, max + offset - heights.header - heights.footer); } else { $contentSelector.css(this._config.panelAutoHeightMode, max + offset - heights.header); } if (this._isFooterFixed()) { $contentSelector.css(this._config.panelAutoHeightMode, parseFloat($contentSelector.css(this._config.panelAutoHeightMode)) + heights.footer); } } if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED)) { return; } if (typeof $__default["default"].fn.overlayScrollbars !== 'undefined') { $__default["default"](SELECTOR_SIDEBAR$1).overlayScrollbars({ className: this._config.scrollbarTheme, sizeAutoCapable: true, scrollbars: { autoHide: this._config.scrollbarAutoHide, clickScrolling: true } }); } else { $__default["default"](SELECTOR_SIDEBAR$1).css('overflow-y', 'auto'); } }; _proto.fixLoginRegisterHeight = function fixLoginRegisterHeight() { var $body = $__default["default"]('body'); var $selector = $__default["default"](SELECTOR_LOGIN_BOX + ", " + SELECTOR_REGISTER_BOX); if ($body.hasClass(CLASS_NAME_IFRAME_MODE)) { $body.css('height', '100%'); $__default["default"]('.wrapper').css('height', '100%'); $__default["default"]('html').css('height', '100%'); } else if ($selector.length === 0) { $body.css('height', 'auto'); $__default["default"]('html').css('height', 'auto'); } else { var boxHeight = $selector.height(); if ($body.css(this._config.panelAutoHeightMode) !== boxHeight) { $body.css(this._config.panelAutoHeightMode, boxHeight); } } } // Private ; _proto._init = function _init() { var _this = this; // Activate layout height watcher this.fixLayoutHeight(); if (this._config.loginRegisterAutoHeight === true) { this.fixLoginRegisterHeight(); } else if (this._config.loginRegisterAutoHeight === parseInt(this._config.loginRegisterAutoHeight, 10)) { setInterval(this.fixLoginRegisterHeight, this._config.loginRegisterAutoHeight); } $__default["default"](SELECTOR_SIDEBAR$1).on('collapsed.lte.treeview expanded.lte.treeview', function () { _this.fixLayoutHeight(); }); $__default["default"](SELECTOR_MAIN_SIDEBAR).on('mouseenter mouseleave', function () { if ($__default["default"]('body').hasClass(CLASS_NAME_SIDEBAR_COLLAPSED$1)) { _this.fixLayoutHeight(); } }); $__default["default"](SELECTOR_PUSHMENU_BTN).on('collapsed.lte.pushmenu shown.lte.pushmenu', function () { setTimeout(function () { _this.fixLayoutHeight(); }, 300); }); $__default["default"](SELECTOR_CONTROL_SIDEBAR_BTN).on('collapsed.lte.controlsidebar', function () { _this.fixLayoutHeight(); }).on('expanded.lte.controlsidebar', function () { _this.fixLayoutHeight('control_sidebar'); }); $__default["default"](window).resize(function () { _this.fixLayoutHeight(); }); setTimeout(function () { $__default["default"]('body.hold-transition').removeClass('hold-transition'); }, 50); setTimeout(function () { var $preloader = $__default["default"](SELECTOR_PRELOADER); if ($preloader) { $preloader.css('height', 0); setTimeout(function () { $preloader.children().hide(); }, 200); } }, this._config.preloadDuration); }; _proto._max = function _max(numbers) { // Calculate the maximum number in a list var max = 0; Object.keys(numbers).forEach(function (key) { if (numbers[key] > max) { max = numbers[key]; } }); return max; }; _proto._isFooterFixed = function _isFooterFixed() { return $__default["default"](SELECTOR_FOOTER).css('position') === 'fixed'; } // Static ; Layout._jQueryInterface = function _jQueryInterface(config) { if (config === void 0) { config = ''; } return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$6); var _options = $__default["default"].extend({}, Default$6, $__default["default"](this).data()); if (!data) { data = new Layout($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$6, data); } if (config === 'init' || config === '') { data._init(); } else if (config === 'fixLayoutHeight' || config === 'fixLoginRegisterHeight') { data[config](); } }); }; return Layout; }(); /** * Data API * ==================================================== */ $__default["default"](window).on('load', function () { Layout._jQueryInterface.call($__default["default"]('body')); }); $__default["default"](SELECTOR_SIDEBAR$1 + " a").on('focusin', function () { $__default["default"](SELECTOR_MAIN_SIDEBAR).addClass(CLASS_NAME_SIDEBAR_FOCUSED); }).on('focusout', function () { $__default["default"](SELECTOR_MAIN_SIDEBAR).removeClass(CLASS_NAME_SIDEBAR_FOCUSED); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$6] = Layout._jQueryInterface; $__default["default"].fn[NAME$6].Constructor = Layout; $__default["default"].fn[NAME$6].noConflict = function () { $__default["default"].fn[NAME$6] = JQUERY_NO_CONFLICT$6; return Layout._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE PushMenu.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$5 = 'PushMenu'; var DATA_KEY$5 = 'lte.pushmenu'; var EVENT_KEY$2 = "." + DATA_KEY$5; var JQUERY_NO_CONFLICT$5 = $__default["default"].fn[NAME$5]; var EVENT_COLLAPSED$1 = "collapsed" + EVENT_KEY$2; var EVENT_COLLAPSED_DONE = "collapsed-done" + EVENT_KEY$2; var EVENT_SHOWN = "shown" + EVENT_KEY$2; var SELECTOR_TOGGLE_BUTTON$1 = '[data-widget="pushmenu"]'; var SELECTOR_BODY = 'body'; var SELECTOR_OVERLAY = '#sidebar-overlay'; var SELECTOR_WRAPPER = '.wrapper'; var CLASS_NAME_COLLAPSED = 'sidebar-collapse'; var CLASS_NAME_OPEN$3 = 'sidebar-open'; var CLASS_NAME_IS_OPENING$1 = 'sidebar-is-opening'; var CLASS_NAME_CLOSED = 'sidebar-closed'; var Default$5 = { autoCollapseSize: 992, enableRemember: false, noTransitionAfterReload: true, animationSpeed: 300 }; /** * Class Definition * ==================================================== */ var PushMenu = /*#__PURE__*/function () { function PushMenu(element, options) { this._element = element; this._options = $__default["default"].extend({}, Default$5, options); if ($__default["default"](SELECTOR_OVERLAY).length === 0) { this._addOverlay(); } this._init(); } // Public var _proto = PushMenu.prototype; _proto.expand = function expand() { var $bodySelector = $__default["default"](SELECTOR_BODY); if (this._options.autoCollapseSize && $__default["default"](window).width() <= this._options.autoCollapseSize) { $bodySelector.addClass(CLASS_NAME_OPEN$3); } $bodySelector.addClass(CLASS_NAME_IS_OPENING$1).removeClass(CLASS_NAME_COLLAPSED + " " + CLASS_NAME_CLOSED).delay(50).queue(function () { $bodySelector.removeClass(CLASS_NAME_IS_OPENING$1); $__default["default"](this).dequeue(); }); if (this._options.enableRemember) { localStorage.setItem("remember" + EVENT_KEY$2, CLASS_NAME_OPEN$3); } $__default["default"](this._element).trigger($__default["default"].Event(EVENT_SHOWN)); }; _proto.collapse = function collapse() { var _this = this; var $bodySelector = $__default["default"](SELECTOR_BODY); if (this._options.autoCollapseSize && $__default["default"](window).width() <= this._options.autoCollapseSize) { $bodySelector.removeClass(CLASS_NAME_OPEN$3).addClass(CLASS_NAME_CLOSED); } $bodySelector.addClass(CLASS_NAME_COLLAPSED); if (this._options.enableRemember) { localStorage.setItem("remember" + EVENT_KEY$2, CLASS_NAME_COLLAPSED); } $__default["default"](this._element).trigger($__default["default"].Event(EVENT_COLLAPSED$1)); setTimeout(function () { $__default["default"](_this._element).trigger($__default["default"].Event(EVENT_COLLAPSED_DONE)); }, this._options.animationSpeed); }; _proto.toggle = function toggle() { if ($__default["default"](SELECTOR_BODY).hasClass(CLASS_NAME_COLLAPSED)) { this.expand(); } else { this.collapse(); } }; _proto.autoCollapse = function autoCollapse(resize) { if (resize === void 0) { resize = false; } if (!this._options.autoCollapseSize) { return; } var $bodySelector = $__default["default"](SELECTOR_BODY); if ($__default["default"](window).width() <= this._options.autoCollapseSize) { if (!$bodySelector.hasClass(CLASS_NAME_OPEN$3)) { this.collapse(); } } else if (resize === true) { if ($bodySelector.hasClass(CLASS_NAME_OPEN$3)) { $bodySelector.removeClass(CLASS_NAME_OPEN$3); } else if ($bodySelector.hasClass(CLASS_NAME_CLOSED)) { this.expand(); } } }; _proto.remember = function remember() { if (!this._options.enableRemember) { return; } var $body = $__default["default"]('body'); var toggleState = localStorage.getItem("remember" + EVENT_KEY$2); if (toggleState === CLASS_NAME_COLLAPSED) { if (this._options.noTransitionAfterReload) { $body.addClass('hold-transition').addClass(CLASS_NAME_COLLAPSED).delay(50).queue(function () { $__default["default"](this).removeClass('hold-transition'); $__default["default"](this).dequeue(); }); } else { $body.addClass(CLASS_NAME_COLLAPSED); } } else if (this._options.noTransitionAfterReload) { $body.addClass('hold-transition').removeClass(CLASS_NAME_COLLAPSED).delay(50).queue(function () { $__default["default"](this).removeClass('hold-transition'); $__default["default"](this).dequeue(); }); } else { $body.removeClass(CLASS_NAME_COLLAPSED); } } // Private ; _proto._init = function _init() { var _this2 = this; this.remember(); this.autoCollapse(); $__default["default"](window).resize(function () { _this2.autoCollapse(true); }); }; _proto._addOverlay = function _addOverlay() { var _this3 = this; var overlay = $__default["default"]('
    ', { id: 'sidebar-overlay' }); overlay.on('click', function () { _this3.collapse(); }); $__default["default"](SELECTOR_WRAPPER).append(overlay); } // Static ; PushMenu._jQueryInterface = function _jQueryInterface(operation) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$5); var _options = $__default["default"].extend({}, Default$5, $__default["default"](this).data()); if (!data) { data = new PushMenu(this, _options); $__default["default"](this).data(DATA_KEY$5, data); } if (typeof operation === 'string' && /collapse|expand|toggle/.test(operation)) { data[operation](); } }); }; return PushMenu; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_TOGGLE_BUTTON$1, function (event) { event.preventDefault(); var button = event.currentTarget; if ($__default["default"](button).data('widget') !== 'pushmenu') { button = $__default["default"](button).closest(SELECTOR_TOGGLE_BUTTON$1); } PushMenu._jQueryInterface.call($__default["default"](button), 'toggle'); }); $__default["default"](window).on('load', function () { PushMenu._jQueryInterface.call($__default["default"](SELECTOR_TOGGLE_BUTTON$1)); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$5] = PushMenu._jQueryInterface; $__default["default"].fn[NAME$5].Constructor = PushMenu; $__default["default"].fn[NAME$5].noConflict = function () { $__default["default"].fn[NAME$5] = JQUERY_NO_CONFLICT$5; return PushMenu._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE SidebarSearch.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$4 = 'SidebarSearch'; var DATA_KEY$4 = 'lte.sidebar-search'; var JQUERY_NO_CONFLICT$4 = $__default["default"].fn[NAME$4]; var CLASS_NAME_OPEN$2 = 'sidebar-search-open'; var CLASS_NAME_ICON_SEARCH = 'fa-search'; var CLASS_NAME_ICON_CLOSE = 'fa-times'; var CLASS_NAME_HEADER = 'nav-header'; var CLASS_NAME_SEARCH_RESULTS = 'sidebar-search-results'; var CLASS_NAME_LIST_GROUP = 'list-group'; var SELECTOR_DATA_WIDGET$1 = '[data-widget="sidebar-search"]'; var SELECTOR_SIDEBAR = '.main-sidebar .nav-sidebar'; var SELECTOR_NAV_LINK = '.nav-link'; var SELECTOR_NAV_TREEVIEW = '.nav-treeview'; var SELECTOR_SEARCH_INPUT$1 = SELECTOR_DATA_WIDGET$1 + " .form-control"; var SELECTOR_SEARCH_BUTTON = SELECTOR_DATA_WIDGET$1 + " .btn"; var SELECTOR_SEARCH_ICON = SELECTOR_SEARCH_BUTTON + " i"; var SELECTOR_SEARCH_LIST_GROUP = "." + CLASS_NAME_LIST_GROUP; var SELECTOR_SEARCH_RESULTS = "." + CLASS_NAME_SEARCH_RESULTS; var SELECTOR_SEARCH_RESULTS_GROUP = SELECTOR_SEARCH_RESULTS + " ." + CLASS_NAME_LIST_GROUP; var Default$4 = { arrowSign: '->', minLength: 3, maxResults: 7, highlightName: true, highlightPath: false, highlightClass: 'text-light', notFoundText: 'No element found!' }; var SearchItems = []; /** * Class Definition * ==================================================== */ var SidebarSearch = /*#__PURE__*/function () { function SidebarSearch(_element, _options) { this.element = _element; this.options = $__default["default"].extend({}, Default$4, _options); this.items = []; } // Public var _proto = SidebarSearch.prototype; _proto.init = function init() { var _this = this; if ($__default["default"](SELECTOR_DATA_WIDGET$1).length === 0) { return; } if ($__default["default"](SELECTOR_DATA_WIDGET$1).next(SELECTOR_SEARCH_RESULTS).length === 0) { $__default["default"](SELECTOR_DATA_WIDGET$1).after($__default["default"]('
    ', { class: CLASS_NAME_SEARCH_RESULTS })); } if ($__default["default"](SELECTOR_SEARCH_RESULTS).children(SELECTOR_SEARCH_LIST_GROUP).length === 0) { $__default["default"](SELECTOR_SEARCH_RESULTS).append($__default["default"]('
    ', { class: CLASS_NAME_LIST_GROUP })); } this._addNotFound(); $__default["default"](SELECTOR_SIDEBAR).children().each(function (i, child) { _this._parseItem(child); }); }; _proto.search = function search() { var _this2 = this; var searchValue = $__default["default"](SELECTOR_SEARCH_INPUT$1).val().toLowerCase(); if (searchValue.length < this.options.minLength) { $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).empty(); this._addNotFound(); this.close(); return; } var searchResults = SearchItems.filter(function (item) { return item.name.toLowerCase().includes(searchValue); }); var endResults = $__default["default"](searchResults.slice(0, this.options.maxResults)); $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).empty(); if (endResults.length === 0) { this._addNotFound(); } else { endResults.each(function (i, result) { $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).append(_this2._renderItem(escape(result.name), encodeURI(result.link), result.path)); }); } this.open(); }; _proto.open = function open() { $__default["default"](SELECTOR_DATA_WIDGET$1).parent().addClass(CLASS_NAME_OPEN$2); $__default["default"](SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_SEARCH).addClass(CLASS_NAME_ICON_CLOSE); }; _proto.close = function close() { $__default["default"](SELECTOR_DATA_WIDGET$1).parent().removeClass(CLASS_NAME_OPEN$2); $__default["default"](SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_CLOSE).addClass(CLASS_NAME_ICON_SEARCH); }; _proto.toggle = function toggle() { if ($__default["default"](SELECTOR_DATA_WIDGET$1).parent().hasClass(CLASS_NAME_OPEN$2)) { this.close(); } else { this.open(); } } // Private ; _proto._parseItem = function _parseItem(item, path) { var _this3 = this; if (path === void 0) { path = []; } if ($__default["default"](item).hasClass(CLASS_NAME_HEADER)) { return; } var itemObject = {}; var navLink = $__default["default"](item).clone().find("> " + SELECTOR_NAV_LINK); var navTreeview = $__default["default"](item).clone().find("> " + SELECTOR_NAV_TREEVIEW); var link = navLink.attr('href'); var name = navLink.find('p').children().remove().end().text(); itemObject.name = this._trimText(name); itemObject.link = link; itemObject.path = path; if (navTreeview.length === 0) { SearchItems.push(itemObject); } else { var newPath = itemObject.path.concat([itemObject.name]); navTreeview.children().each(function (i, child) { _this3._parseItem(child, newPath); }); } }; _proto._trimText = function _trimText(text) { return $.trim(text.replace(/(\r\n|\n|\r)/gm, ' ')); }; _proto._renderItem = function _renderItem(name, link, path) { var _this4 = this; path = path.join(" " + this.options.arrowSign + " "); name = unescape(name); link = decodeURI(link); if (this.options.highlightName || this.options.highlightPath) { var searchValue = $__default["default"](SELECTOR_SEARCH_INPUT$1).val().toLowerCase(); var regExp = new RegExp(searchValue, 'gi'); if (this.options.highlightName) { name = name.replace(regExp, function (str) { return "" + str + ""; }); } if (this.options.highlightPath) { path = path.replace(regExp, function (str) { return "" + str + ""; }); } } var groupItemElement = $__default["default"]('', { href: decodeURIComponent(link), class: 'list-group-item' }); var searchTitleElement = $__default["default"]('
    ', { class: 'search-title' }).html(name); var searchPathElement = $__default["default"]('
    ', { class: 'search-path' }).html(path); groupItemElement.append(searchTitleElement).append(searchPathElement); return groupItemElement; }; _proto._addNotFound = function _addNotFound() { $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).append(this._renderItem(this.options.notFoundText, '#', [])); } // Static ; SidebarSearch._jQueryInterface = function _jQueryInterface(config) { var data = $__default["default"](this).data(DATA_KEY$4); if (!data) { data = $__default["default"](this).data(); } var _options = $__default["default"].extend({}, Default$4, typeof config === 'object' ? config : data); var plugin = new SidebarSearch($__default["default"](this), _options); $__default["default"](this).data(DATA_KEY$4, typeof config === 'object' ? config : data); if (typeof config === 'string' && /init|toggle|close|open|search/.test(config)) { plugin[config](); } else { plugin.init(); } }; return SidebarSearch; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_SEARCH_BUTTON, function (event) { event.preventDefault(); SidebarSearch._jQueryInterface.call($__default["default"](SELECTOR_DATA_WIDGET$1), 'toggle'); }); $__default["default"](document).on('keyup', SELECTOR_SEARCH_INPUT$1, function (event) { if (event.keyCode == 38) { event.preventDefault(); $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).children().last().focus(); return; } if (event.keyCode == 40) { event.preventDefault(); $__default["default"](SELECTOR_SEARCH_RESULTS_GROUP).children().first().focus(); return; } setTimeout(function () { SidebarSearch._jQueryInterface.call($__default["default"](SELECTOR_DATA_WIDGET$1), 'search'); }, 100); }); $__default["default"](document).on('keydown', SELECTOR_SEARCH_RESULTS_GROUP, function (event) { var $focused = $__default["default"](':focus'); if (event.keyCode == 38) { event.preventDefault(); if ($focused.is(':first-child')) { $focused.siblings().last().focus(); } else { $focused.prev().focus(); } } if (event.keyCode == 40) { event.preventDefault(); if ($focused.is(':last-child')) { $focused.siblings().first().focus(); } else { $focused.next().focus(); } } }); $__default["default"](window).on('load', function () { SidebarSearch._jQueryInterface.call($__default["default"](SELECTOR_DATA_WIDGET$1), 'init'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$4] = SidebarSearch._jQueryInterface; $__default["default"].fn[NAME$4].Constructor = SidebarSearch; $__default["default"].fn[NAME$4].noConflict = function () { $__default["default"].fn[NAME$4] = JQUERY_NO_CONFLICT$4; return SidebarSearch._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE NavbarSearch.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$3 = 'NavbarSearch'; var DATA_KEY$3 = 'lte.navbar-search'; var JQUERY_NO_CONFLICT$3 = $__default["default"].fn[NAME$3]; var SELECTOR_TOGGLE_BUTTON = '[data-widget="navbar-search"]'; var SELECTOR_SEARCH_BLOCK = '.navbar-search-block'; var SELECTOR_SEARCH_INPUT = '.form-control'; var CLASS_NAME_OPEN$1 = 'navbar-search-open'; var Default$3 = { resetOnClose: true, target: SELECTOR_SEARCH_BLOCK }; /** * Class Definition * ==================================================== */ var NavbarSearch = /*#__PURE__*/function () { function NavbarSearch(_element, _options) { this._element = _element; this._config = $__default["default"].extend({}, Default$3, _options); } // Public var _proto = NavbarSearch.prototype; _proto.open = function open() { $__default["default"](this._config.target).css('display', 'flex').hide().fadeIn().addClass(CLASS_NAME_OPEN$1); $__default["default"](this._config.target + " " + SELECTOR_SEARCH_INPUT).focus(); }; _proto.close = function close() { $__default["default"](this._config.target).fadeOut().removeClass(CLASS_NAME_OPEN$1); if (this._config.resetOnClose) { $__default["default"](this._config.target + " " + SELECTOR_SEARCH_INPUT).val(''); } }; _proto.toggle = function toggle() { if ($__default["default"](this._config.target).hasClass(CLASS_NAME_OPEN$1)) { this.close(); } else { this.open(); } } // Static ; NavbarSearch._jQueryInterface = function _jQueryInterface(options) { return this.each(function () { var data = $__default["default"](this).data(DATA_KEY$3); var _options = $__default["default"].extend({}, Default$3, $__default["default"](this).data()); if (!data) { data = new NavbarSearch(this, _options); $__default["default"](this).data(DATA_KEY$3, data); } if (!/toggle|close|open/.test(options)) { throw new Error("Undefined method " + options); } data[options](); }); }; return NavbarSearch; }(); /** * Data API * ==================================================== */ $__default["default"](document).on('click', SELECTOR_TOGGLE_BUTTON, function (event) { event.preventDefault(); var button = $__default["default"](event.currentTarget); if (button.data('widget') !== 'navbar-search') { button = button.closest(SELECTOR_TOGGLE_BUTTON); } NavbarSearch._jQueryInterface.call(button, 'toggle'); }); /** * jQuery API * ==================================================== */ $__default["default"].fn[NAME$3] = NavbarSearch._jQueryInterface; $__default["default"].fn[NAME$3].Constructor = NavbarSearch; $__default["default"].fn[NAME$3].noConflict = function () { $__default["default"].fn[NAME$3] = JQUERY_NO_CONFLICT$3; return NavbarSearch._jQueryInterface; }; /** * -------------------------------------------- * AdminLTE Toasts.js * License MIT * -------------------------------------------- */ /** * Constants * ==================================================== */ var NAME$2 = 'Toasts'; var DATA_KEY$2 = 'lte.toasts'; var EVENT_KEY$1 = "." + DATA_KEY$2; var JQUERY_NO_CONFLICT$2 = $__default["default"].fn[NAME$2]; var EVENT_INIT = "init" + EVENT_KEY$1; var EVENT_CREATED = "created" + EVENT_KEY$1; var EVENT_REMOVED = "removed" + EVENT_KEY$1; var SELECTOR_CONTAINER_TOP_RIGHT = '#toastsContainerTopRight'; var SELECTOR_CONTAINER_TOP_LEFT = '#toastsContainerTopLeft'; var SELECTOR_CONTAINER_BOTTOM_RIGHT = '#toastsContainerBottomRight'; var SELECTOR_CONTAINER_BOTTOM_LEFT = '#toastsContainerBottomLeft'; var CLASS_NAME_TOP_RIGHT = 'toasts-top-right'; var CLASS_NAME_TOP_LEFT = 'toasts-top-left'; var CLASS_NAME_BOTTOM_RIGHT = 'toasts-bottom-right'; var CLASS_NAME_BOTTOM_LEFT = 'toasts-bottom-left'; var POSITION_TOP_RIGHT = 'topRight'; var POSITION_TOP_LEFT = 'topLeft'; var POSITION_BOTTOM_RIGHT = 'bottomRight'; var POSITION_BOTTOM_LEFT = 'bottomLeft'; var Default$2 = { position: POSITION_TOP_RIGHT, fixed: true, autohide: false, autoremove: true, delay: 1000, fade: true, icon: null, image: null, imageAlt: null, imageHeight: '25px', title: null, subtitle: null, close: true, body: null, class: null }; /** * Class Definition * ==================================================== */ var Toasts = /*#__PURE__*/function () { function Toasts(element, config) { this._config = config; this._prepareContainer(); $__default["default"]('body').trigger($__default["default"].Event(EVENT_INIT)); } // Public var _proto = Toasts.prototype; _proto.create = function create() { var toast = $__default["default"]('"};n?l.globals.seriesGoals[e][i]&&Array.isArray(l.globals.seriesGoals[e][i])?y():(v.innerHTML="",m.innerHTML=""):y()}else v.innerHTML="",m.innerHTML="";null!==f&&(a[e].querySelector(".apexcharts-tooltip-text-z-label").innerHTML=l.config.tooltip.z.title,a[e].querySelector(".apexcharts-tooltip-text-z-value").innerHTML=void 0!==f?f:""),n&&p[0]&&(null==h||l.globals.ancillaryCollapsedSeriesIndices.indexOf(e)>-1||l.globals.collapsedSeriesIndices.indexOf(e)>-1?p[0].parentNode.style.display="none":p[0].parentNode.style.display=l.config.tooltip.items.display)}},{key:"toggleActiveInactiveSeries",value:function(t){var e=this.w;if(t)this.tooltipUtil.toggleAllTooltipSeriesGroups("enable");else{this.tooltipUtil.toggleAllTooltipSeriesGroups("disable");var i=e.globals.dom.baseEl.querySelector(".apexcharts-tooltip-series-group");i&&(i.classList.add("apexcharts-active"),i.style.display=e.config.tooltip.items.display)}}},{key:"getValuesToPrint",value:function(t){var e=t.i,i=t.j,a=this.w,s=this.ctx.series.filteredSeriesX(),r="",n="",o=null,l=null,c={series:a.globals.series,seriesIndex:e,dataPointIndex:i,w:a},h=a.globals.ttZFormatter;null===i?l=a.globals.series[e]:a.globals.isXNumeric&&"treemap"!==a.config.chart.type?(r=s[e][i],0===s[e].length&&(r=s[this.tooltipUtil.getFirstActiveXArray(s)][i])):r=void 0!==a.globals.labels[i]?a.globals.labels[i]:"";var d=r;return r=a.globals.isXNumeric&&"datetime"===a.config.xaxis.type?new H(this.ctx).xLabelFormat(a.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new R(this.ctx).formatDate,w:this.w}):a.globals.isBarHorizontal?a.globals.yLabelFormatters[0](d,c):a.globals.xLabelFormatter(d,c),void 0!==a.config.tooltip.x.formatter&&(r=a.globals.ttKeyFormatter(d,c)),a.globals.seriesZ.length>0&&a.globals.seriesZ[e].length>0&&(o=h(a.globals.seriesZ[e][i],a)),n="function"==typeof a.config.xaxis.tooltip.formatter?a.globals.xaxisTooltipFormatter(d,c):r,{val:Array.isArray(l)?l.join(" "):l,xVal:Array.isArray(r)?r.join(" "):r,xAxisTTVal:Array.isArray(n)?n.join(" "):n,zVal:o}}},{key:"handleCustomTooltip",value:function(t){var e=t.i,i=t.j,a=t.y1,s=t.y2,r=t.w,n=this.ttCtx.getElTooltip(),o=r.config.tooltip.custom;Array.isArray(o)&&o[e]&&(o=o[e]),n.innerHTML=o({ctx:this.ctx,series:r.globals.series,seriesIndex:e,dataPointIndex:i,y1:a,y2:s,w:r})}}])&&Fe(e.prototype,i),t}();function Ne(t,e){for(var i=0;i1&&void 0!==arguments[1]?arguments[1]:null,i=this.ttCtx,a=this.w,s=i.getElXCrosshairs(),r=t-i.xcrosshairsWidth/2,n=a.globals.labels.slice().length;if(null!==e&&(r=a.globals.gridWidth/n*e),null===s||a.globals.isBarHorizontal||(s.setAttribute("x",r),s.setAttribute("x1",r),s.setAttribute("x2",r),s.setAttribute("y2",a.globals.gridHeight),s.classList.add("apexcharts-active")),r<0&&(r=0),r>a.globals.gridWidth&&(r=a.globals.gridWidth),i.isXAxisTooltipEnabled){var o=r;"tickWidth"!==a.config.xaxis.crosshairs.width&&"barWidth"!==a.config.xaxis.crosshairs.width||(o=r+i.xcrosshairsWidth/2),this.moveXAxisTooltip(o)}}},{key:"moveYCrosshairs",value:function(t){var e=this.ttCtx;null!==e.ycrosshairs&&b.setAttrs(e.ycrosshairs,{y1:t,y2:t}),null!==e.ycrosshairsHidden&&b.setAttrs(e.ycrosshairsHidden,{y1:t,y2:t})}},{key:"moveXAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;if(null!==i.xaxisTooltip&&0!==i.xcrosshairsWidth){i.xaxisTooltip.classList.add("apexcharts-active");var a,s=i.xaxisOffY+e.config.xaxis.tooltip.offsetY+e.globals.translateY+1+e.config.xaxis.offsetY;t-=i.xaxisTooltip.getBoundingClientRect().width/2,isNaN(t)||(t+=e.globals.translateX,a=new b(this.ctx).getTextRects(i.xaxisTooltipText.innerHTML),i.xaxisTooltipText.style.minWidth=a.width+"px",i.xaxisTooltip.style.left=t+"px",i.xaxisTooltip.style.top=s+"px")}}},{key:"moveYAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;null===i.yaxisTTEls&&(i.yaxisTTEls=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip"));var a=parseInt(i.ycrosshairsHidden.getAttribute("y1"),10),s=e.globals.translateY+a,r=i.yaxisTTEls[t].getBoundingClientRect().height,n=e.globals.translateYAxisX[t]-2;e.config.yaxis[t].opposite&&(n-=26),s-=r/2,-1===e.globals.ignoreYAxisIndexes.indexOf(t)?(i.yaxisTTEls[t].classList.add("apexcharts-active"),i.yaxisTTEls[t].style.top=s+"px",i.yaxisTTEls[t].style.left=n+e.config.yaxis[t].tooltip.offsetX+"px"):i.yaxisTTEls[t].classList.remove("apexcharts-active")}},{key:"moveTooltip",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=this.ttCtx,r=s.getElTooltip(),n=s.tooltipRect,o=null!==i?parseFloat(i):1,l=parseFloat(t)+o+5,c=parseFloat(e)+o/2;if(l>a.globals.gridWidth/2&&(l=l-n.ttWidth-o-10),l>a.globals.gridWidth-n.ttWidth-10&&(l=a.globals.gridWidth-n.ttWidth),l<-20&&(l=-20),a.config.tooltip.followCursor){var h=s.getElGrid(),d=h.getBoundingClientRect();c=s.e.clientY+a.globals.translateY-d.top-n.ttHeight/2}else a.globals.isBarHorizontal||n.ttHeight/2+c>a.globals.gridHeight&&(c=a.globals.gridHeight-n.ttHeight+a.globals.translateY);isNaN(l)||(l+=a.globals.translateX,r.style.left=l+"px",r.style.top=c+"px")}},{key:"moveMarkers",value:function(t,e){var i=this.w,a=this.ttCtx;if(i.globals.markers.size[t]>0)for(var s=i.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(t,"'] .apexcharts-marker")),r=0;r0&&(c.setAttribute("r",o),c.setAttribute("cx",i),c.setAttribute("cy",a)),this.moveXCrosshairs(i),r.fixedTooltip||this.moveTooltip(i,a,o)}}},{key:"moveDynamicPointsOnHover",value:function(t){var e,i=this.ttCtx,a=i.w,s=0,r=0,n=a.globals.pointsArray;e=new ut(this.ctx).getActiveConfigSeriesIndex("asc",["line","area","scatter","bubble"]);var o=i.tooltipUtil.getHoverMarkerSize(e);n[e]&&(s=n[e][t][0],r=n[e][t][1]);var l=i.tooltipUtil.getAllMarkers();if(null!==l)for(var c=0;c0?(l[c]&&l[c].setAttribute("r",o),l[c]&&l[c].setAttribute("cy",d)):l[c]&&l[c].setAttribute("r",0)}}if(this.moveXCrosshairs(s),!i.fixedTooltip){var f=r||a.globals.gridHeight;this.moveTooltip(s,f,o)}}},{key:"moveStickyTooltipOverBars",value:function(t){var e=this.w,i=this.ttCtx,a=e.globals.columnSeries?e.globals.columnSeries.length:e.globals.series.length,s=a>=2&&a%2==0?Math.floor(a/2):Math.floor(a/2)+1;e.globals.isBarHorizontal&&(s=new ut(this.ctx).getActiveConfigSeriesIndex("desc")+1);var r=e.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(s,"'] path[j='").concat(t,"'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"']")),n=r?parseFloat(r.getAttribute("cx")):0,o=r?parseFloat(r.getAttribute("cy")):0,l=r?parseFloat(r.getAttribute("barWidth")):0,c=i.getElGrid().getBoundingClientRect(),h=r.classList.contains("apexcharts-candlestick-area")||r.classList.contains("apexcharts-boxPlot-area");if(e.globals.isXNumeric?(r&&!h&&(n-=a%2!=0?l/2:0),r&&h&&e.globals.comboCharts&&(n-=l/2)):e.globals.isBarHorizontal||(n=i.xAxisTicksPositions[t-1]+i.dataPointsDividedWidth/2,isNaN(n)&&(n=i.xAxisTicksPositions[t]-i.dataPointsDividedWidth/2)),e.globals.isBarHorizontal?o-=i.tooltipRect.ttHeight:e.config.tooltip.followCursor?o=i.e.clientY-c.top-i.tooltipRect.ttHeight/2:o+i.tooltipRect.ttHeight+15>e.globals.gridHeight&&(o=e.globals.gridHeight),e.globals.isBarHorizontal||this.moveXCrosshairs(n),!i.fixedTooltip){var d=o||e.globals.gridHeight;this.moveTooltip(n,d)}}}],i&&Ne(e.prototype,i),t}();function je(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,a=new Array(e);i2&&void 0!==arguments[2]?arguments[2]:null,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w;"bubble"!==s.config.chart.type&&this.newPointSize(t,e);var r=e.getAttribute("cx"),n=e.getAttribute("cy");if(null!==i&&null!==a&&(r=i,n=a),this.tooltipPosition.moveXCrosshairs(r),!this.fixedTooltip){if("radar"===s.config.chart.type){var o=this.ttCtx.getElGrid(),l=o.getBoundingClientRect();r=this.ttCtx.e.clientX-l.left}this.tooltipPosition.moveTooltip(r,n,s.config.markers.hover.size)}}},{key:"enlargePoints",value:function(t){for(var e=this.w,i=this,a=this.ttCtx,s=t,r=e.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"),n=e.config.markers.hover.size,o=0;o=0?t[e].setAttribute("r",i):t[e].setAttribute("r",0)}}}],i&&Be(e.prototype,i),t}();function Ve(t,e){for(var i=0;io.globals.gridWidth/2&&(a=h-n.tooltipRect.ttWidth/2+u),n.w.config.tooltip.followCursor){var f=o.globals.dom.elWrap.getBoundingClientRect();a=o.globals.clientX-f.left-(a>o.globals.gridWidth/2?n.tooltipRect.ttWidth:0),s=o.globals.clientY-f.top-(s>o.globals.gridHeight/2?n.tooltipRect.ttHeight:0)}}return{x:a,y:s}}},{key:"handleMarkerTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=t.x,o=t.y,l=this.w,c=this.ttCtx;if(a.target.classList.contains("apexcharts-marker")){var h=parseInt(s.paths.getAttribute("cx"),10),d=parseInt(s.paths.getAttribute("cy"),10),u=parseFloat(s.paths.getAttribute("val"));if(i=parseInt(s.paths.getAttribute("rel"),10),e=parseInt(s.paths.parentNode.parentNode.parentNode.getAttribute("rel"),10)-1,c.intersect){var g=n.findAncestor(s.paths,"apexcharts-series");g&&(e=parseInt(g.getAttribute("data:realIndex"),10))}if(c.tooltipLabels.drawSeriesTexts({ttItems:s.ttItems,i:e,j:i,shared:!c.showOnIntersect&&l.config.tooltip.shared,e:a}),"mouseup"===a.type&&c.markerClick(a,e,i),l.globals.capturedSeriesIndex=e,l.globals.capturedDataPointIndex=i,r=h,o=d+l.globals.translateY-1.4*c.tooltipRect.ttHeight,c.w.config.tooltip.followCursor){var f=c.getElGrid().getBoundingClientRect();o=c.e.clientY+l.globals.translateY-f.top}u<0&&(o=d),c.marker.enlargeCurrentPoint(i,s.paths,r,o)}return{x:r,y:o}}},{key:"handleBarTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,n=this.ttCtx,o=n.getElTooltip(),l=0,c=0,h=0,d=this.getBarTooltipXY({e:a,opt:s});e=d.i;var u=d.barHeight,g=d.j;r.globals.capturedSeriesIndex=e,r.globals.capturedDataPointIndex=g,r.globals.isBarHorizontal&&n.tooltipUtil.hasBars()||!r.config.tooltip.shared?(c=d.x,h=d.y,i=Array.isArray(r.config.stroke.width)?r.config.stroke.width[e]:r.config.stroke.width,l=c):r.globals.comboCharts||r.config.tooltip.shared||(l/=2),isNaN(h)&&(h=r.globals.svgHeight-n.tooltipRect.ttHeight);var f=parseInt(s.paths.parentNode.getAttribute("data:realIndex"),10),p=r.globals.isMultipleYAxis?r.config.yaxis[f]&&r.config.yaxis[f].reversed:r.config.yaxis[0].reversed;if(c+n.tooltipRect.ttWidth>r.globals.gridWidth&&!p?c-=n.tooltipRect.ttWidth:c<0&&(c=0),n.w.config.tooltip.followCursor){var x=n.getElGrid().getBoundingClientRect();h=n.e.clientY-x.top}null===n.tooltip&&(n.tooltip=r.globals.dom.baseEl.querySelector(".apexcharts-tooltip")),r.config.tooltip.shared||(r.globals.comboBarCount>0?n.tooltipPosition.moveXCrosshairs(l+i/2):n.tooltipPosition.moveXCrosshairs(l)),!n.fixedTooltip&&(!r.config.tooltip.shared||r.globals.isBarHorizontal&&n.tooltipUtil.hasBars())&&(p&&(c-=n.tooltipRect.ttWidth)<0&&(c=0),!p||r.globals.isBarHorizontal&&n.tooltipUtil.hasBars()||(h=h+u-2*(r.globals.series[e][g]<0?u:0)),h=h+r.globals.translateY-n.tooltipRect.ttHeight/2,o.style.left=c+r.globals.translateX+"px",o.style.top=h+"px")}},{key:"getBarTooltipXY",value:function(t){var e=t.e,i=t.opt,a=this.w,s=null,r=this.ttCtx,n=0,o=0,l=0,c=0,h=0,d=e.target.classList;if(d.contains("apexcharts-bar-area")||d.contains("apexcharts-candlestick-area")||d.contains("apexcharts-boxPlot-area")||d.contains("apexcharts-rangebar-area")){var u=e.target,g=u.getBoundingClientRect(),f=i.elGrid.getBoundingClientRect(),p=g.height;h=g.height;var x=g.width,b=parseInt(u.getAttribute("cx"),10),v=parseInt(u.getAttribute("cy"),10);c=parseFloat(u.getAttribute("barWidth"));var m="touchmove"===e.type?e.touches[0].clientX:e.clientX;s=parseInt(u.getAttribute("j"),10),n=parseInt(u.parentNode.getAttribute("rel"),10)-1;var y=u.getAttribute("data-range-y1"),w=u.getAttribute("data-range-y2");a.globals.comboCharts&&(n=parseInt(u.parentNode.getAttribute("data:realIndex"),10)),r.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:n,j:s,y1:y?parseInt(y,10):null,y2:w?parseInt(w,10):null,shared:!r.showOnIntersect&&a.config.tooltip.shared,e}),a.config.tooltip.followCursor?a.globals.isBarHorizontal?(o=m-f.left+15,l=v-r.dataPointsDividedHeight+p/2-r.tooltipRect.ttHeight/2):(o=a.globals.isXNumeric?b-x/2:b-r.dataPointsDividedWidth+x/2,l=e.clientY-f.top-r.tooltipRect.ttHeight/2-15):a.globals.isBarHorizontal?((o=b)0&&i.setAttribute("width",e.xcrosshairsWidth)}},{key:"handleYCrosshair",value:function(){var t=this.w,e=this.ttCtx;e.ycrosshairs=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs"),e.ycrosshairsHidden=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs-hidden")}},{key:"drawYaxisTooltipText",value:function(t,e,i){var a=this.ttCtx,s=this.w,r=s.globals.yLabelFormatters[t];if(a.yaxisTooltips[t]){var n=a.getElGrid().getBoundingClientRect(),o=(e-n.top)*i.yRatio[t],l=s.globals.maxYArr[t]-s.globals.minYArr[t],c=s.globals.minYArr[t]+(l-o);a.tooltipPosition.moveYCrosshairs(e-n.top),a.yaxisTooltipText[t].innerHTML=r(c),a.tooltipPosition.moveYAxisTooltip(t)}}}])&&Ue(e.prototype,i),t}();function Ze(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function $e(t){for(var e=1;e0&&this.addPathsEventListeners(g,h),this.tooltipUtil.hasBars()&&!this.tConfig.shared&&this.addDatapointEventsListeners(h)}}},{key:"drawFixedTooltipRect",value:function(){var t=this.w,e=this.getElTooltip(),i=e.getBoundingClientRect(),a=i.width+10,s=i.height+10,r=this.tConfig.fixed.offsetX,n=this.tConfig.fixed.offsetY,o=this.tConfig.fixed.position.toLowerCase();return o.indexOf("right")>-1&&(r=r+t.globals.svgWidth-a+10),o.indexOf("bottom")>-1&&(n=n+t.globals.svgHeight-s-10),e.style.left=r+"px",e.style.top=n+"px",{x:r,y:n,ttWidth:a,ttHeight:s}}},{key:"addDatapointEventsListeners",value:function(t){var e=this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area");this.addPathsEventListeners(e,t)}},{key:"addPathsEventListeners",value:function(t,e){for(var i=this,a=function(a){var s={paths:t[a],tooltipEl:e.tooltipEl,tooltipY:e.tooltipY,tooltipX:e.tooltipX,elGrid:e.elGrid,hoverArea:e.hoverArea,ttItems:e.ttItems};["mousemove","mouseup","touchmove","mouseout","touchend"].map((function(e){return t[a].addEventListener(e,i.onSeriesHover.bind(i,s),{capture:!1,passive:!0})}))},s=0;s=100?this.seriesHover(t,e):(clearTimeout(this.seriesHoverTimeout),this.seriesHoverTimeout=setTimeout((function(){i.seriesHover(t,e)}),100-a))}},{key:"seriesHover",value:function(t,e){var i=this;this.lastHoverTime=Date.now();var a=[],s=this.w;s.config.chart.group&&(a=this.ctx.getGroupedCharts()),s.globals.axisCharts&&(s.globals.minX===-1/0&&s.globals.maxX===1/0||0===s.globals.dataPoints)||(a.length?a.forEach((function(a){var s=i.getElTooltip(a),r={paths:t.paths,tooltipEl:s,tooltipY:t.tooltipY,tooltipX:t.tooltipX,elGrid:t.elGrid,hoverArea:t.hoverArea,ttItems:a.w.globals.tooltip.ttItems};a.w.globals.minX===i.w.globals.minX&&a.w.globals.maxX===i.w.globals.maxX&&a.w.globals.tooltip.seriesHoverByContext({chartCtx:a,ttCtx:a.w.globals.tooltip,opt:r,e})})):this.seriesHoverByContext({chartCtx:this.ctx,ttCtx:this.w.globals.tooltip,opt:t,e}))}},{key:"seriesHoverByContext",value:function(t){var e=t.chartCtx,i=t.ttCtx,a=t.opt,s=t.e,r=e.w,n=this.getElTooltip();n&&(i.tooltipRect={x:0,y:0,ttWidth:n.getBoundingClientRect().width,ttHeight:n.getBoundingClientRect().height},i.e=s,!i.tooltipUtil.hasBars()||r.globals.comboCharts||i.isBarShared||this.tConfig.onDatasetHover.highlightDataSeries&&new ut(e).toggleSeriesOnHover(s,s.target.parentNode),i.fixedTooltip&&i.drawFixedTooltipRect(),r.globals.axisCharts?i.axisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}):i.nonAxisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}))}},{key:"axisChartsTooltips",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,n=s.elGrid.getBoundingClientRect(),o="touchmove"===a.type?a.touches[0].clientX:a.clientX,l="touchmove"===a.type?a.touches[0].clientY:a.clientY;if(this.clientY=l,this.clientX=o,r.globals.capturedSeriesIndex=-1,r.globals.capturedDataPointIndex=-1,ln.top+n.height)this.handleMouseOut(s);else{if(Array.isArray(this.tConfig.enabledOnSeries)&&!r.config.tooltip.shared){var c=parseInt(s.paths.getAttribute("index"),10);if(this.tConfig.enabledOnSeries.indexOf(c)<0)return void this.handleMouseOut(s)}var h=this.getElTooltip(),d=this.getElXCrosshairs(),u=r.globals.xyCharts||"bar"===r.config.chart.type&&!r.globals.isBarHorizontal&&this.tooltipUtil.hasBars()&&this.tConfig.shared||r.globals.comboCharts&&this.tooltipUtil.hasBars();if("mousemove"===a.type||"touchmove"===a.type||"mouseup"===a.type){if(r.globals.collapsedSeries.length+r.globals.ancillaryCollapsedSeries.length===r.globals.series.length)return;null!==d&&d.classList.add("apexcharts-active");var g=this.yaxisTooltips.filter((function(t){return!0===t}));if(null!==this.ycrosshairs&&g.length&&this.ycrosshairs.classList.add("apexcharts-active"),u&&!this.showOnIntersect)this.handleStickyTooltip(a,o,l,s);else if("heatmap"===r.config.chart.type||"treemap"===r.config.chart.type){var f=this.intersect.handleHeatTreeTooltip({e:a,opt:s,x:e,y:i,type:r.config.chart.type});e=f.x,i=f.y,h.style.left=e+"px",h.style.top=i+"px"}else this.tooltipUtil.hasBars()&&this.intersect.handleBarTooltip({e:a,opt:s}),this.tooltipUtil.hasMarkers()&&this.intersect.handleMarkerTooltip({e:a,opt:s,x:e,y:i});if(this.yaxisTooltips.length)for(var p=0;pl.width?this.handleMouseOut(a):null!==o?this.handleStickyCapturedSeries(t,o,a,n):(this.tooltipUtil.isXoverlap(n)||s.globals.isBarHorizontal)&&this.create(t,this,0,n,a.ttItems)}},{key:"handleStickyCapturedSeries",value:function(t,e,i,a){var s=this.w;this.tConfig.shared||null!==s.globals.series[e][a]?void 0!==s.globals.series[e][a]?this.tConfig.shared&&this.tooltipUtil.isXoverlap(a)&&this.tooltipUtil.isInitialSeriesSameLen()?this.create(t,this,e,a,i.ttItems):this.create(t,this,e,a,i.ttItems,!1):this.tooltipUtil.isXoverlap(a)&&this.create(t,this,0,a,i.ttItems):this.handleMouseOut(i)}},{key:"deactivateHoverFilter",value:function(){for(var t=this.w,e=new b(this.ctx),i=t.globals.dom.Paper.select(".apexcharts-bar-area"),a=0;a5&&void 0!==arguments[5]?arguments[5]:null,A=this.w,S=e;"mouseup"===t.type&&this.markerClick(t,i,a),null===k&&(k=this.tConfig.shared);var C=this.tooltipUtil.hasMarkers(),P=this.tooltipUtil.getElBars();if(A.config.legend.tooltipHoverFormatter){var L=A.config.legend.tooltipHoverFormatter,O=Array.from(this.legendLabels);O.forEach((function(t){var e=t.getAttribute("data:default-text");t.innerHTML=decodeURIComponent(e)}));for(var T=0;T0?S.marker.enlargePoints(a):S.tooltipPosition.moveDynamicPointsOnHover(a)),this.tooltipUtil.hasBars()&&(this.barSeriesHeight=this.tooltipUtil.getBarsHeight(P),this.barSeriesHeight>0)){var Y=new b(this.ctx),D=A.globals.dom.Paper.select(".apexcharts-bar-area[j='".concat(a,"']"));this.deactivateHoverFilter(),this.tooltipPosition.moveStickyTooltipOverBars(a);for(var R=0;Rs.globals.gridHeight&&(g=s.globals.gridHeight-v)),{bcx:c,bcy:l,dataLabelsX:e,dataLabelsY:g,totalDataLabelsX:a,totalDataLabelsY:i,totalDataLabelsAnchor:"middle"}}},{key:"calculateBarsDataLabelsPosition",value:function(t){var e=this.w,i=t.x,a=t.i,s=t.j,r=t.realIndex,n=t.bcy,o=t.barHeight,l=t.barWidth,c=t.textRects,h=t.dataLabelsX,d=t.strokeWidth,u=t.dataLabelsConfig,g=t.barDataLabelsConfig,f=t.barTotalDataLabelsConfig,p=t.offX,x=t.offY,v=e.globals.gridHeight/e.globals.dataPoints;l=Math.abs(l);var m,y,w=n-(this.barCtx.isRangeBar?0:v)+o/2+c.height/2+x-3,k="start",A=this.barCtx.series[a][s]<0,S=i;switch(this.barCtx.isReversed&&(S=i+l-(A?2*l:0),i=e.globals.gridWidth-l),g.position){case"center":h=A?S+l/2-p:Math.max(c.width/2,S-l/2)+p;break;case"bottom":h=A?S+l-d-Math.round(c.width/2)-p:S-l+d+Math.round(c.width/2)+p;break;case"top":h=A?S-d+Math.round(c.width/2)-p:S-d-Math.round(c.width/2)+p}if(this.barCtx.lastActiveBarSerieIndex===r&&f.enabled){var C=new b(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({realIndex:r,j:s}),u.fontSize);A?(m=S-d+Math.round(C.width/2)-p-f.offsetX-15,k="end"):m=S-d-Math.round(C.width/2)+p+f.offsetX+15,y=w+f.offsetY}return e.config.chart.stacked||(h<0?h=h+c.width+d:h+c.width/2>e.globals.gridWidth&&(h=e.globals.gridWidth-c.width-d)),{bcx:i,bcy:n,dataLabelsX:h,dataLabelsY:w,totalDataLabelsX:m,totalDataLabelsY:y,totalDataLabelsAnchor:k}}},{key:"drawCalculatedDataLabels",value:function(t){var e=t.x,i=t.y,a=t.val,s=t.i,r=t.j,n=t.textRects,o=t.barHeight,l=t.barWidth,c=t.dataLabelsConfig,h=this.w,d="rotate(0)";"vertical"===h.config.plotOptions.bar.dataLabels.orientation&&(d="rotate(-90, ".concat(e,", ").concat(i,")"));var u=new ht(this.barCtx.ctx),g=new b(this.barCtx.ctx),f=c.formatter,p=null,x=h.globals.collapsedSeriesIndices.indexOf(s)>-1;if(c.enabled&&!x){p=g.group({class:"apexcharts-data-labels",transform:d});var v="";void 0!==a&&(v=f(a,ei(ei({},h),{},{seriesIndex:s,dataPointIndex:r,w:h})));var m=h.globals.series[s][r]<0,y=h.config.plotOptions.bar.dataLabels.position;"vertical"===h.config.plotOptions.bar.dataLabels.orientation&&("top"===y&&(c.textAnchor=m?"end":"start"),"center"===y&&(c.textAnchor="middle"),"bottom"===y&&(c.textAnchor=m?"end":"start")),this.barCtx.isRangeBar&&this.barCtx.barOptions.dataLabels.hideOverflowingLabels&&lMath.abs(l)&&(v=""):n.height/1.6>Math.abs(o)&&(v=""));var w=ei({},c);this.barCtx.isHorizontal&&a<0&&("start"===c.textAnchor?w.textAnchor="end":"end"===c.textAnchor&&(w.textAnchor="start")),u.plotDataLabelsText({x:e,y:i,text:v,i:s,j:r,parent:p,dataLabelsConfig:w,alwaysDrawDataLabel:!0,offsetCorrection:!0})}return p}},{key:"drawTotalDataLabels",value:function(t){var e,i=t.x,a=t.y,s=t.val,r=t.realIndex,n=t.textAnchor,o=t.barTotalDataLabelsConfig,l=new b(this.barCtx.ctx);return o.enabled&&void 0!==i&&void 0!==a&&this.barCtx.lastActiveBarSerieIndex===r&&(e=l.drawText({x:i,y:a,foreColor:o.style.color,text:s,textAnchor:n,fontFamily:o.style.fontFamily,fontSize:o.style.fontSize,fontWeight:o.style.fontWeight})),e}}])&&ai(e.prototype,i),t}();function ri(t,e,i){return e in t?Object.defineProperty(t,e,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[e]=i,t}function ni(t,e){for(var i=0;i0&&(this.barCtx.seriesLen=this.barCtx.seriesLen+1,this.barCtx.totalItems+=t[i].length),e.globals.isXNumeric)for(var a=0;ae.globals.minX&&e.globals.seriesX[i][a]0&&(a=l.globals.minXDiff/d),(r=a/this.barCtx.seriesLen*parseInt(this.barCtx.barOptions.columnWidth,10)/100)<1&&(r=1)}n=l.globals.gridHeight-this.barCtx.baseLineY[this.barCtx.yaxisIndex]-(this.barCtx.isReversed?l.globals.gridHeight:0)+(this.barCtx.isReversed?2*this.barCtx.baseLineY[this.barCtx.yaxisIndex]:0),t=l.globals.padHorizontal+(a-r*this.barCtx.seriesLen)/2}return{x:t,y:e,yDivision:i,xDivision:a,barHeight:s,barWidth:r,zeroH:n,zeroW:o}}},{key:"getPathFillColor",value:function(t,e,i,a){var s,r,n,o,l=this.w,c=new st(this.barCtx.ctx),h=null,d=this.barCtx.barOptions.distributed?i:e;return this.barCtx.barOptions.colors.ranges.length>0&&this.barCtx.barOptions.colors.ranges.map((function(a){t[e][i]>=a.from&&t[e][i]<=a.to&&(h=a.color)})),l.config.series[e].data[i]&&l.config.series[e].data[i].fillColor&&(h=l.config.series[e].data[i].fillColor),c.fillPath({seriesNumber:this.barCtx.barOptions.distributed?d:a,dataPointIndex:i,color:h,value:t[e][i],fillConfig:null===(s=l.config.series[e].data[i])||void 0===s?void 0:s.fill,fillType:null!==(r=l.config.series[e].data[i])&&void 0!==r&&null!==(n=r.fill)&&void 0!==n&&n.type?null===(o=l.config.series[e].data[i])||void 0===o?void 0:o.fill.type:l.config.fill.type})}},{key:"getStrokeWidth",value:function(t,e,i){var a=0,s=this.w;return this.barCtx.series[t][e]?this.barCtx.isNullValue=!1:this.barCtx.isNullValue=!0,s.config.stroke.show&&(this.barCtx.isNullValue||(a=Array.isArray(this.barCtx.strokeWidth)?this.barCtx.strokeWidth[i]:this.barCtx.strokeWidth)),a}},{key:"shouldApplyRadius",value:function(t){var e=this.w,i=!1;return e.config.plotOptions.bar.borderRadius>0&&(e.config.chart.stacked&&"last"===e.config.plotOptions.bar.borderRadiusWhenStacked?this.barCtx.lastActiveBarSerieIndex===t&&(i=!0):i=!0),i}},{key:"barBackground",value:function(t){var e=t.j,i=t.i,a=t.x1,s=t.x2,r=t.y1,n=t.y2,o=t.elSeries,l=this.w,c=new b(this.barCtx.ctx),h=new ut(this.barCtx.ctx).getActiveConfigSeriesIndex();if(this.barCtx.barOptions.colors.backgroundBarColors.length>0&&h===i){e>=this.barCtx.barOptions.colors.backgroundBarColors.length&&(e%=this.barCtx.barOptions.colors.backgroundBarColors.length);var d=this.barCtx.barOptions.colors.backgroundBarColors[e],u=c.drawRect(void 0!==a?a:0,void 0!==r?r:0,void 0!==s?s:l.globals.gridWidth,void 0!==n?n:l.globals.gridHeight,this.barCtx.barOptions.colors.backgroundBarRadius,d,this.barCtx.barOptions.colors.backgroundBarOpacity);o.add(u),u.node.classList.add("apexcharts-backgroundBar")}}},{key:"getColumnPaths",value:function(t){var e,i=t.barWidth,a=t.barXPosition,s=t.y1,r=t.y2,n=t.strokeWidth,o=t.realIndex,l=t.i,c=t.j,h=t.w,d=new b(this.barCtx.ctx);(n=Array.isArray(n)?n[o]:n)||(n=0);var u=i,g=a;null!==(e=h.config.series[o].data[c])&&void 0!==e&&e.columnWidthOffset&&(g=a-h.config.series[o].data[c].columnWidthOffset/2,u=i+h.config.series[o].data[c].columnWidthOffset);var f=g,p=g+u;s+=.001,r+=.001;var x=d.move(f,s),v=d.move(f,s),m=d.line(p-n,s);return h.globals.previousPaths.length>0&&(v=this.barCtx.getPreviousPath(o,c,!1)),x=x+d.line(f,r)+d.line(p-n,r)+d.line(p-n,s)+("around"===h.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),v=v+d.line(f,s)+m+m+m+m+m+d.line(f,s)+("around"===h.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(o)&&(x=d.roundPathCorners(x,h.config.plotOptions.bar.borderRadius)),h.config.chart.stacked&&(this.barCtx.yArrj.push(r),this.barCtx.yArrjF.push(Math.abs(s-r)),this.barCtx.yArrjVal.push(this.barCtx.series[l][c])),{pathTo:x,pathFrom:v}}},{key:"getBarpaths",value:function(t){var e,i=t.barYPosition,a=t.barHeight,s=t.x1,r=t.x2,n=t.strokeWidth,o=t.realIndex,l=t.i,c=t.j,h=t.w,d=new b(this.barCtx.ctx);(n=Array.isArray(n)?n[o]:n)||(n=0);var u=i,g=a;null!==(e=h.config.series[o].data[c])&&void 0!==e&&e.barHeightOffset&&(u=i-h.config.series[o].data[c].barHeightOffset/2,g=a+h.config.series[o].data[c].barHeightOffset);var f=u,p=u+g;s+=.001,r+=.001;var x=d.move(s,f),v=d.move(s,f);h.globals.previousPaths.length>0&&(v=this.barCtx.getPreviousPath(o,c,!1));var m=d.line(s,p-n);return x=x+d.line(r,f)+d.line(r,p-n)+m+("around"===h.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),v=v+d.line(s,f)+m+m+m+m+m+d.line(s,f)+("around"===h.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(o)&&(x=d.roundPathCorners(x,h.config.plotOptions.bar.borderRadius)),h.config.chart.stacked&&(this.barCtx.xArrj.push(r),this.barCtx.xArrjF.push(Math.abs(s-r)),this.barCtx.xArrjVal.push(this.barCtx.series[l][c])),{pathTo:x,pathFrom:v}}},{key:"checkZeroSeries",value:function(t){for(var e=t.series,i=this.w,a=0;a=0;n--)this.barCtx.zeroSerieses.indexOf(n)>-1&&n===this.radiusOnSeriesNumber&&(this.barCtx.radiusOnSeriesNumber-=1);for(var o=e.length-1;o>=0;o--)i.globals.collapsedSeriesIndices.indexOf(this.barCtx.radiusOnSeriesNumber)>-1&&(this.barCtx.radiusOnSeriesNumber-=1)}},{key:"getXForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e+t/this.barCtx.invertedYRatio-2*(this.barCtx.isReversed?t/this.barCtx.invertedYRatio:0)),a}},{key:"getYForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e-t/this.barCtx.yRatio[this.barCtx.yaxisIndex]+2*(this.barCtx.isReversed?t/this.barCtx.yRatio[this.barCtx.yaxisIndex]:0)),a}},{key:"getGoalValues",value:function(t,e,i,a,s){var r=this,n=this.w,o=[];return n.globals.seriesGoals[a]&&n.globals.seriesGoals[a][s]&&Array.isArray(n.globals.seriesGoals[a][s])&&n.globals.seriesGoals[a][s].forEach((function(a){var s;o.push((ri(s={},t,"x"===t?r.getXForValue(a.value,e,!1):r.getYForValue(a.value,i,!1)),ri(s,"attrs",a),s))})),o}},{key:"drawGoalLine",value:function(t){var e=t.barXPosition,i=t.barYPosition,a=t.goalX,s=t.goalY,r=t.barWidth,n=t.barHeight,o=new b(this.barCtx.ctx),l=o.group({className:"apexcharts-bar-goals-groups"}),c=null;return this.barCtx.isHorizontal?Array.isArray(a)&&a.forEach((function(t){var e=void 0!==t.attrs.strokeHeight?t.attrs.strokeHeight:n/2,a=i+e+n/2;c=o.drawLine(t.x,a-2*e,t.x,a,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeWidth?t.attrs.strokeWidth:2,t.attrs.strokeLineCap),l.add(c)})):Array.isArray(s)&&s.forEach((function(t){var i=void 0!==t.attrs.strokeWidth?t.attrs.strokeWidth:r/2,a=e+i+r/2;c=o.drawLine(a-2*i,t.y,a,t.y,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeHeight?t.attrs.strokeHeight:2,t.attrs.strokeLineCap),l.add(c)})),l}}],i&&ni(e.prototype,i),t}();function li(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function ci(t){for(var e=1;ethis.barOptions.dataLabels.maxItems&&console.warn("WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering.");for(var o=0,l=0;o0&&(this.visibleI=this.visibleI+1);var w=0,k=0;this.yRatio.length>1&&(this.yaxisIndex=v),this.isReversed=i.config.yaxis[this.yaxisIndex]&&i.config.yaxis[this.yaxisIndex].reversed;var A=this.barHelpers.initialPositions();f=A.y,w=A.barHeight,h=A.yDivision,u=A.zeroW,g=A.x,k=A.barWidth,c=A.xDivision,d=A.zeroH,this.horizontal||x.push(g+k/2);for(var S=a.group({class:"apexcharts-datalabels","data:realIndex":v}),C=a.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),P=0;P0&&x.push(g+k/2),p.push(f);var I=this.barHelpers.getPathFillColor(t,o,P,v);this.renderSeries({realIndex:v,pathFill:I,j:P,i:o,pathFrom:O.pathFrom,pathTo:O.pathTo,strokeWidth:L,elSeries:m,x:g,y:f,series:t,barHeight:w,barWidth:k,elDataLabelsWrap:S,elGoalsMarkers:C,visibleSeries:this.visibleI,type:"bar"})}i.globals.seriesXvalues[v]=x,i.globals.seriesYvalues[v]=p,r.add(m)}return r}},{key:"renderSeries",value:function(t){var e=t.realIndex,i=t.pathFill,a=t.lineFill,s=t.j,r=t.i,n=t.pathFrom,o=t.pathTo,l=t.strokeWidth,c=t.elSeries,h=t.x,u=t.y,g=t.y1,f=t.y2,p=t.series,x=t.barHeight,v=t.barWidth,m=t.barYPosition,y=t.elDataLabelsWrap,w=t.elGoalsMarkers,k=t.visibleSeries,A=t.type,S=this.w,C=new b(this.ctx);a||(a=this.barOptions.distributed?S.globals.stroke.colors[s]:S.globals.stroke.colors[e]),S.config.series[r].data[s]&&S.config.series[r].data[s].strokeColor&&(a=S.config.series[r].data[s].strokeColor),this.isNullValue&&(i="none");var P=s/S.config.chart.animations.animateGradually.delay*(S.config.chart.animations.speed/S.globals.dataPoints)/2.4,L=C.renderPaths({i:r,j:s,realIndex:e,pathFrom:n,pathTo:o,stroke:a,strokeWidth:l,strokeLineCap:S.config.stroke.lineCap,fill:i,animationDelay:P,initialSpeed:S.config.chart.animations.speed,dataChangeSpeed:S.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(A,"-area")});L.attr("clip-path","url(#gridRectMask".concat(S.globals.cuid,")"));var O=S.config.forecastDataPoints;O.count>0&&s>=S.globals.dataPoints-O.count&&(L.node.setAttribute("stroke-dasharray",O.dashArray),L.node.setAttribute("stroke-width",O.strokeWidth),L.node.setAttribute("fill-opacity",O.fillOpacity)),void 0!==g&&void 0!==f&&(L.attr("data-range-y1",g),L.attr("data-range-y2",f)),new d(this.ctx).setSelectionFilter(L,e,s),c.add(L);var T=new si(this).handleBarDataLabels({x:h,y:u,y1:g,y2:f,i:r,j:s,series:p,realIndex:e,barHeight:x,barWidth:v,barYPosition:m,renderedPath:L,visibleSeries:k});return null!==T.dataLabels&&y.add(T.dataLabels),T.totalDataLabels&&y.add(T.totalDataLabels),c.add(y),w&&c.add(w),c}},{key:"drawBarPaths",value:function(t){var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,n=t.x,o=t.y,l=t.yDivision,c=t.elSeries,h=this.w,d=i.i,u=i.j;if(h.globals.isXNumeric)e=(o=(h.globals.seriesX[d][u]-h.globals.minX)/this.invertedXRatio-a)+a*this.visibleI;else if(h.config.plotOptions.bar.hideZeroBarsWhenGrouped){var g=0,f=0;h.globals.seriesPercent.forEach((function(t,e){t[u]&&g++,e0&&parseInt(r.realIndex,10)===parseInt(t,10)&&void 0!==a.globals.previousPaths[s].paths[e]&&(i=a.globals.previousPaths[s].paths[e].d)}return i}}])&&di(e.prototype,i),t}();function gi(t){return gi="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},gi(t)}function fi(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function pi(t){for(var e=1;e0&&(this.totalItems+=t[r].length);for(var o=this.graphics.group({class:"apexcharts-bar-series apexcharts-plot-series"}),l=0,c=0,h=function(s,r){var h=void 0,d=void 0,u=void 0,g=void 0,f=[],p=[],x=a.globals.comboCharts?e[s]:s;i.yRatio.length>1&&(i.yaxisIndex=x),i.isReversed=a.config.yaxis[i.yaxisIndex]&&a.config.yaxis[i.yaxisIndex].reversed;var b=i.graphics.group({class:"apexcharts-series",seriesName:n.escapeString(a.globals.seriesNames[x]),rel:s+1,"data:realIndex":x});i.ctx.series.addCollapsedClassToSeries(b,x);var v=i.graphics.group({class:"apexcharts-datalabels","data:realIndex":x}),m=i.graphics.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),y=0,w=0,k=i.initialPositions(l,c,h,d,u,g);c=k.y,y=k.barHeight,d=k.yDivision,g=k.zeroW,l=k.x,w=k.barWidth,h=k.xDivision,u=k.zeroH,i.yArrj=[],i.yArrjF=[],i.yArrjVal=[],i.xArrj=[],i.xArrjF=[],i.xArrjVal=[],1===i.prevY.length&&i.prevY[0].every((function(t){return isNaN(t)}))&&(i.prevY[0]=i.prevY[0].map((function(t){return u})),i.prevYF[0]=i.prevYF[0].map((function(t){return 0})));for(var A=0;A1?(i=l.globals.minXDiff/this.xRatio)*parseInt(this.barOptions.columnWidth,10)/100:o*parseInt(l.config.plotOptions.bar.columnWidth,10)/100,s=l.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?l.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),t=l.globals.padHorizontal+(i-o)/2),{x:t,y:e,yDivision:a,xDivision:i,barHeight:n,barWidth:o,zeroH:s,zeroW:r}}},{key:"drawStackedBarPaths",value:function(t){for(var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,n=t.x,o=t.y,l=t.yDivision,c=t.elSeries,h=this.w,d=o,u=i.i,g=i.j,f=0,p=0;p0){var x=r;this.prevXVal[u-1][g]<0?x=this.series[u][g]>=0?this.prevX[u-1][g]+f-2*(this.isReversed?f:0):this.prevX[u-1][g]:this.prevXVal[u-1][g]>=0&&(x=this.series[u][g]>=0?this.prevX[u-1][g]:this.prevX[u-1][g]-f+2*(this.isReversed?f:0)),e=x}else e=r;n=null===this.series[u][g]?e:e+this.series[u][g]/this.invertedYRatio-2*(this.isReversed?this.series[u][g]/this.invertedYRatio:0);var b=this.barHelpers.getBarpaths({barYPosition:d,barHeight:a,x1:e,x2:n,strokeWidth:s,series:this.series,realIndex:i.realIndex,i:u,j:g,w:h});return this.barHelpers.barBackground({j:g,i:u,y1:d,y2:a,elSeries:c}),o+=l,{pathTo:b.pathTo,pathFrom:b.pathFrom,goalX:this.barHelpers.getGoalValues("x",r,null,u,g),barYPosition:d,x:n,y:o}}},{key:"drawStackedColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=t.y,s=t.xDivision,r=t.barWidth,n=t.zeroH,o=(t.strokeWidth,t.elSeries),l=this.w,c=e.i,h=e.j,d=e.bc;if(l.globals.isXNumeric){var u=l.globals.seriesX[c][h];u||(u=0),i=(u-l.globals.minX)/this.xRatio-r/2}for(var g,f=i,p=0,x=0;x0&&!l.globals.isXNumeric||c>0&&l.globals.isXNumeric&&l.globals.seriesX[c-1][h]===l.globals.seriesX[c][h]){var b,v,m=Math.min(this.yRatio.length+1,c+1);if(void 0!==this.prevY[c-1])for(var y=1;y=0?v-p+2*(this.isReversed?p:0):v;break}if(this.prevYVal[c-w][h]>=0){b=this.series[c][h]>=0?v:v+p-2*(this.isReversed?p:0);break}}void 0===b&&(b=l.globals.gridHeight),g=this.prevYF[0].every((function(t){return 0===t}))&&this.prevYF.slice(1,c).every((function(t){return t.every((function(t){return isNaN(t)}))}))?n:b}else g=n;a=this.series[c][h]?g-this.series[c][h]/this.yRatio[this.yaxisIndex]+2*(this.isReversed?this.series[c][h]/this.yRatio[this.yaxisIndex]:0):g;var k=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:r,y1:g,y2:a,yRatio:this.yRatio[this.yaxisIndex],strokeWidth:this.strokeWidth,series:this.series,realIndex:e.realIndex,i:c,j:h,w:l});return this.barHelpers.barBackground({bc:d,j:h,i:c,x1:f,x2:r,elSeries:o}),i+=s,{pathTo:k.pathTo,pathFrom:k.pathFrom,goalY:this.barHelpers.getGoalValues("y",null,n,c,h),barXPosition:f,x:l.globals.isXNumeric?i-s:i,y:a}}}])&&vi(e.prototype,i),o}(ui);const Ai=ki;function Si(t){return Si="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Si(t)}function Ci(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function Pi(t){for(var e=1;e0&&(i.visibleI=i.visibleI+1),i.yRatio.length>1&&(i.yaxisIndex=m);var w=i.barHelpers.initialPositions();x=w.y,g=w.barHeight,h=w.yDivision,u=w.zeroW,p=w.x,f=w.barWidth,c=w.xDivision,d=w.zeroH,v.push(p+f/2);for(var k=s.group({class:"apexcharts-datalabels","data:realIndex":m}),A=function(e){var s=i.barHelpers.getStrokeWidth(o,e,m),n=null,l={indexes:{i:o,j:e,realIndex:m},x:p,y:x,strokeWidth:s,elSeries:y};n=i.isHorizontal?i.drawHorizontalBoxPaths(Pi(Pi({},l),{},{yDivision:h,barHeight:g,zeroW:u})):i.drawVerticalBoxPaths(Pi(Pi({},l),{},{xDivision:c,barWidth:f,zeroH:d})),x=n.y,p=n.x,e>0&&v.push(p+f/2),b.push(x),n.pathTo.forEach((function(l,c){var h=!i.isBoxPlot&&i.candlestickOptions.wick.useFillColor?n.color[c]:a.globals.stroke.colors[o],d=r.fillPath({seriesNumber:m,dataPointIndex:e,color:n.color[c],value:t[o][e]});i.renderSeries({realIndex:m,pathFill:d,lineFill:h,j:e,i:o,pathFrom:n.pathFrom,pathTo:l,strokeWidth:s,elSeries:y,x:p,y:x,series:t,barHeight:g,barWidth:f,elDataLabelsWrap:k,visibleSeries:i.visibleI,type:a.config.chart.type})}))},S=0;Sv.c&&(d=!1);var w=Math.min(v.o,v.c),k=Math.max(v.o,v.c),A=v.m;o.globals.isXNumeric&&(i=(o.globals.seriesX[x][h]-o.globals.minX)/this.xRatio-s/2);var S=i+s*this.visibleI;void 0===this.series[c][h]||null===this.series[c][h]?(w=r,k=r):(w=r-w/p,k=r-k/p,m=r-v.h/p,y=r-v.l/p,A=r-v.m/p);var C=l.move(S,r),P=l.move(S+s/2,w);return o.globals.previousPaths.length>0&&(P=this.getPreviousPath(x,h,!0)),C=this.isBoxPlot?[l.move(S,w)+l.line(S+s/2,w)+l.line(S+s/2,m)+l.line(S+s/4,m)+l.line(S+s-s/4,m)+l.line(S+s/2,m)+l.line(S+s/2,w)+l.line(S+s,w)+l.line(S+s,A)+l.line(S,A)+l.line(S,w+n/2),l.move(S,A)+l.line(S+s,A)+l.line(S+s,k)+l.line(S+s/2,k)+l.line(S+s/2,y)+l.line(S+s-s/4,y)+l.line(S+s/4,y)+l.line(S+s/2,y)+l.line(S+s/2,k)+l.line(S,k)+l.line(S,A)+"z"]:[l.move(S,k)+l.line(S+s/2,k)+l.line(S+s/2,m)+l.line(S+s/2,k)+l.line(S+s,k)+l.line(S+s,w)+l.line(S+s/2,w)+l.line(S+s/2,y)+l.line(S+s/2,w)+l.line(S,w)+l.line(S,k-n/2)],P+=l.move(S,w),o.globals.isXNumeric||(i+=a),{pathTo:C,pathFrom:P,x:i,y:k,barXPosition:S,color:this.isBoxPlot?f:d?[u]:[g]}}},{key:"drawHorizontalBoxPaths",value:function(t){var e=t.indexes,i=(t.x,t.y),a=t.yDivision,s=t.barHeight,r=t.zeroW,n=t.strokeWidth,o=this.w,l=new b(this.ctx),c=e.i,h=e.j,d=this.boxOptions.colors.lower;this.isBoxPlot&&(d=[this.boxOptions.colors.lower,this.boxOptions.colors.upper]);var u=this.invertedYRatio,g=e.realIndex,f=this.getOHLCValue(g,h),p=r,x=r,v=Math.min(f.o,f.c),m=Math.max(f.o,f.c),y=f.m;o.globals.isXNumeric&&(i=(o.globals.seriesX[g][h]-o.globals.minX)/this.invertedXRatio-s/2);var w=i+s*this.visibleI;void 0===this.series[c][h]||null===this.series[c][h]?(v=r,m=r):(v=r+v/u,m=r+m/u,p=r+f.h/u,x=r+f.l/u,y=r+f.m/u);var k=l.move(r,w),A=l.move(v,w+s/2);return o.globals.previousPaths.length>0&&(A=this.getPreviousPath(g,h,!0)),k=[l.move(v,w)+l.line(v,w+s/2)+l.line(p,w+s/2)+l.line(p,w+s/2-s/4)+l.line(p,w+s/2+s/4)+l.line(p,w+s/2)+l.line(v,w+s/2)+l.line(v,w+s)+l.line(y,w+s)+l.line(y,w)+l.line(v+n/2,w),l.move(y,w)+l.line(y,w+s)+l.line(m,w+s)+l.line(m,w+s/2)+l.line(x,w+s/2)+l.line(x,w+s-s/4)+l.line(x,w+s/4)+l.line(x,w+s/2)+l.line(m,w+s/2)+l.line(m,w)+l.line(y,w)+"z"],A+=l.move(v,w),o.globals.isXNumeric||(i+=a),{pathTo:k,pathFrom:A,x:m,y:i,barYPosition:w,color:d}}},{key:"getOHLCValue",value:function(t,e){var i=this.w;return{o:this.isBoxPlot?i.globals.seriesCandleH[t][e]:i.globals.seriesCandleO[t][e],h:this.isBoxPlot?i.globals.seriesCandleO[t][e]:i.globals.seriesCandleH[t][e],m:i.globals.seriesCandleM[t][e],l:this.isBoxPlot?i.globals.seriesCandleC[t][e]:i.globals.seriesCandleL[t][e],c:this.isBoxPlot?i.globals.seriesCandleL[t][e]:i.globals.seriesCandleC[t][e]}}}])&&Ti(e.prototype,i),o}(ui);const Xi=zi;function Yi(t){return function(t){if(Array.isArray(t))return Di(t)}(t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(t)||function(t,e){if(t){if("string"==typeof t)return Di(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Di(t,e):void 0}}(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Di(t,e){(null==e||e>t.length)&&(e=t.length);for(var i=0,a=new Array(e);i0&&i.colorScale.ranges.map((function(t,i){t.from<=0&&(e=!0)})),e}},{key:"getShadeColor",value:function(t,e,i,a){var s=this.w,r=1,o=s.config.plotOptions[t].shadeIntensity,l=this.determineColor(t,e,i);s.globals.hasNegs||a?r=s.config.plotOptions[t].reverseNegativeShade?l.percent<0?l.percent/100*(1.25*o):(1-l.percent/100)*(1.25*o):l.percent<=0?1-(1+l.percent/100)*o:(1-l.percent/100)*o:(r=1-l.percent/100,"treemap"===t&&(r=(1-l.percent/100)*(1.25*o)));var c=l.color,h=new n;return s.config.plotOptions[t].enableShades&&(c="dark"===this.w.config.theme.mode?n.hexToRgba(h.shadeColor(-1*r,l.color),s.config.fill.opacity):n.hexToRgba(h.shadeColor(r,l.color),s.config.fill.opacity)),{color:c,colorProps:l}}},{key:"determineColor",value:function(t,e,i){var a=this.w,s=a.globals.series[e][i],r=a.config.plotOptions[t],n=r.colorScale.inverse?i:e;r.distributed&&"treemap"===a.config.chart.type&&(n=i);var o=a.globals.colors[n],l=null,c=Math.min.apply(Math,Yi(a.globals.series[e])),h=Math.max.apply(Math,Yi(a.globals.series[e]));r.distributed||"heatmap"!==t||(c=a.globals.minY,h=a.globals.maxY),void 0!==r.colorScale.min&&(c=r.colorScale.mina.globals.maxY?r.colorScale.max:a.globals.maxY);var d=Math.abs(h)+Math.abs(c),u=100*s/(0===d?d-1e-6:d);return r.colorScale.ranges.length>0&&r.colorScale.ranges.map((function(t,e){if(s>=t.from&&s<=t.to){o=t.color,l=t.foreColor?t.foreColor:null,c=t.from,h=t.to;var i=Math.abs(h)+Math.abs(c);u=100*s/(0===i?i-1e-6:i)}})),{color:o,foreColor:l,percent:u}}},{key:"calculateDataLabels",value:function(t){var e=t.text,i=t.x,a=t.y,s=t.i,r=t.j,n=t.colorProps,o=t.fontSize,l=this.w.config.dataLabels,c=new b(this.ctx),h=new ht(this.ctx),d=null;if(l.enabled){d=c.group({class:"apexcharts-data-labels"});var u=l.offsetX,g=l.offsetY,f=i+u,p=a+parseFloat(l.style.fontSize)/3+g;h.plotDataLabelsText({x:f,y:p,text:e,i:s,j:r,color:n.foreColor,parent:d,fontSize:o,dataLabelsConfig:l})}return d}},{key:"addListeners",value:function(t){var e=new b(this.ctx);t.node.addEventListener("mouseenter",e.pathMouseEnter.bind(this,t)),t.node.addEventListener("mouseleave",e.pathMouseLeave.bind(this,t)),t.node.addEventListener("mousedown",e.pathMouseDown.bind(this,t))}}])&&Ri(e.prototype,i),t}();function Hi(t,e){for(var i=0;i=0;l?h++:h--){var u=i.group({class:"apexcharts-series apexcharts-heatmap-series",seriesName:n.escapeString(e.globals.seriesNames[h]),rel:h+1,"data:realIndex":h});if(this.ctx.series.addCollapsedClassToSeries(u,h),e.config.chart.dropShadow.enabled){var g=e.config.chart.dropShadow;new d(this.ctx).dropShadow(u,g,h)}for(var f=0,p=e.config.plotOptions.heatmap.shadeIntensity,x=0;x-1&&this.pieClicked(g),i.config.dataLabels.enabled){var A=w.x,S=w.y,C=100*p/this.fullAngle+"%";if(0!==p&&i.config.plotOptions.pie.dataLabels.minAngleToShowLabelthis.fullAngle?e.endAngle=e.endAngle-(a+n):a+n=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle&&(l=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle-.01),Math.ceil(l)>this.fullAngle&&(l-=this.fullAngle);var c=Math.PI*(l-90)/180,h=e.centerX+s*Math.cos(o),d=e.centerY+s*Math.sin(o),u=e.centerX+s*Math.cos(c),g=e.centerY+s*Math.sin(c),f=n.polarToCartesian(e.centerX,e.centerY,e.donutSize,l),p=n.polarToCartesian(e.centerX,e.centerY,e.donutSize,r),x=a>180?1:0,b=["M",h,d,"A",s,s,0,x,1,u,g];return"donut"===e.chartType?[].concat(b,["L",f.x,f.y,"A",e.donutSize,e.donutSize,0,x,0,p.x,p.y,"L",h,d,"z"]).join(" "):"pie"===e.chartType||"polarArea"===e.chartType?[].concat(b,["L",e.centerX,e.centerY,"L",h,d]).join(" "):[].concat(b).join(" ")}},{key:"drawPolarElements",value:function(t){var e=this.w,i=new Lt(this.ctx),a=new b(this.ctx),s=new ji(this.ctx),r=a.group(),n=a.group(),o=i.niceScale(0,Math.ceil(this.maxY),e.config.yaxis[0].tickAmount,0,!0),l=o.result.reverse(),c=o.result.length;this.maxY=o.niceMax;for(var h=e.globals.radialSize,d=h/(c-1),u=0;u1&&t.total.show&&(s=t.total.color);var n=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-label"),o=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-value");i=(0,t.value.formatter)(i,r),a||"function"!=typeof t.total.formatter||(i=t.total.formatter(r));var l=e===t.total.label;e=t.name.formatter(e,l,r),null!==n&&(n.textContent=e),null!==o&&(o.textContent=i),null!==n&&(n.style.fill=s)}},{key:"printDataLabelsInner",value:function(t,e){var i=this.w,a=t.getAttribute("data:value"),s=i.globals.seriesNames[parseInt(t.parentNode.getAttribute("rel"),10)-1];i.globals.series.length>1&&this.printInnerLabels(e,s,a,t);var r=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group");null!==r&&(r.style.opacity=1)}},{key:"drawSpokes",value:function(t){var e=this,i=this.w,a=new b(this.ctx),s=i.config.plotOptions.polarArea.spokes;if(0!==s.strokeWidth){for(var r=[],o=360/i.globals.series.length,l=0;l1)n&&!e.total.showAlways?l({makeSliceOut:!1,printLabel:!0}):this.printInnerLabels(e,e.total.label,e.total.formatter(s));else if(l({makeSliceOut:!1,printLabel:!0}),!n)if(s.globals.selectedDataPoints.length&&s.globals.series.length>1)if(s.globals.selectedDataPoints[0].length>0){var c=s.globals.selectedDataPoints[0],h=s.globals.dom.baseEl.querySelector(".apexcharts-".concat(this.chartType.toLowerCase(),"-slice-").concat(c));this.printDataLabelsInner(h,e)}else r&&s.globals.selectedDataPoints.length&&0===s.globals.selectedDataPoints[0].length&&(r.style.opacity=0);else r&&s.globals.series.length>1&&(r.style.opacity=0)}}])&&Bi(e.prototype,i),t}();function Vi(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function _i(t){for(var e=1;e0&&(x=e.getPreviousPath(o));for(var b=0;b=10?t.x>0?(i="start",a+=10):t.x<0&&(i="end",a-=10):i="middle",Math.abs(t.y)>=e-10&&(t.y<0?s-=10:t.y>0&&(s+=10)),{textAnchor:i,newX:a,newY:s}}},{key:"getPreviousPath",value:function(t){for(var e=this.w,i=null,a=0;a0&&parseInt(s.realIndex,10)===parseInt(t,10)&&void 0!==e.globals.previousPaths[a].paths[0]&&(i=e.globals.previousPaths[a].paths[0].d)}return i}},{key:"getDataPointsPos",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.dataPointsLen;t=t||[],e=e||[];for(var a=[],s=0;s=360&&(g=360-Math.abs(this.startAngle)-.1);var f=i.drawPath({d:"",stroke:h,strokeWidth:n*parseInt(c.strokeWidth,10)/100,fill:"none",strokeOpacity:c.opacity,classes:"apexcharts-radialbar-area"});if(c.dropShadow.enabled){var p=c.dropShadow;s.dropShadow(f,p)}l.add(f),f.attr("id","apexcharts-radialbarTrack-"+o),this.animatePaths(f,{centerX:t.centerX,centerY:t.centerY,endAngle:g,startAngle:u,size:t.size,i:o,totalItems:2,animBeginArr:0,dur:0,isTrack:!0,easing:e.globals.easing})}return a}},{key:"drawArcs",value:function(t){var e=this.w,i=new b(this.ctx),a=new st(this.ctx),s=new d(this.ctx),r=i.group(),o=this.getStrokeWidth(t);t.size=t.size-o/2;var l=e.config.plotOptions.radialBar.hollow.background,c=t.size-o*t.series.length-this.margin*t.series.length-o*parseInt(e.config.plotOptions.radialBar.track.strokeWidth,10)/100/2,h=c-e.config.plotOptions.radialBar.hollow.margin;void 0!==e.config.plotOptions.radialBar.hollow.image&&(l=this.drawHollowImage(t,r,c,l));var u=this.drawHollow({size:h,centerX:t.centerX,centerY:t.centerY,fill:l||"transparent"});if(e.config.plotOptions.radialBar.hollow.dropShadow.enabled){var g=e.config.plotOptions.radialBar.hollow.dropShadow;s.dropShadow(u,g)}var f=1;!this.radialDataLabels.total.show&&e.globals.series.length>1&&(f=0);var p=null;this.radialDataLabels.show&&(p=this.renderInnerDataLabels(this.radialDataLabels,{hollowSize:c,centerX:t.centerX,centerY:t.centerY,opacity:f})),"back"===e.config.plotOptions.radialBar.hollow.position&&(r.add(u),p&&r.add(p));var x=!1;e.config.plotOptions.radialBar.inverseOrder&&(x=!0);for(var v=x?t.series.length-1:0;x?v>=0:v100?100:t.series[v])/100,S=Math.round(this.totalAngle*A)+this.startAngle,C=void 0;e.globals.dataChanged&&(k=this.startAngle,C=Math.round(this.totalAngle*n.negToZero(e.globals.previousPaths[v])/100)+k),Math.abs(S)+Math.abs(w)>=360&&(S-=.01),Math.abs(C)+Math.abs(k)>=360&&(C-=.01);var P=S-w,L=Array.isArray(e.config.stroke.dashArray)?e.config.stroke.dashArray[v]:e.config.stroke.dashArray,O=i.drawPath({d:"",stroke:y,strokeWidth:o,fill:"none",fillOpacity:e.config.fill.opacity,classes:"apexcharts-radialbar-area apexcharts-radialbar-slice-"+v,strokeDashArray:L});if(b.setAttrs(O.node,{"data:angle":P,"data:value":t.series[v]}),e.config.chart.dropShadow.enabled){var T=e.config.chart.dropShadow;s.dropShadow(O,T,v)}s.setSelectionFilter(O,0,v),this.addListeners(O,this.radialDataLabels),m.add(O),O.attr({index:0,j:v});var E=0;!this.initialAnim||e.globals.resized||e.globals.dataChanged||(E=e.config.chart.animations.speed),e.globals.dataChanged&&(E=e.config.chart.animations.dynamicAnimation.speed),this.animDur=E/(1.2*t.series.length)+this.animDur,this.animBeginArr.push(this.animDur),this.animatePaths(O,{centerX:t.centerX,centerY:t.centerY,endAngle:S,startAngle:w,prevEndAngle:C,prevStartAngle:k,size:t.size,i:v,totalItems:2,animBeginArr:this.animBeginArr,dur:E,shouldSetPrevPaths:!0,easing:e.globals.easing})}return{g:r,elHollow:u,dataLabels:p}}},{key:"drawHollow",value:function(t){var e=new b(this.ctx).drawCircle(2*t.size);return e.attr({class:"apexcharts-radialbar-hollow",cx:t.centerX,cy:t.centerY,r:t.size,fill:t.fill}),e}},{key:"drawHollowImage",value:function(t,e,i,a){var s=this.w,r=new st(this.ctx),o=n.randomId(),l=s.config.plotOptions.radialBar.hollow.image;if(s.config.plotOptions.radialBar.hollow.imageClipped)r.clippedImgArea({width:i,height:i,image:l,patternID:"pattern".concat(s.globals.cuid).concat(o)}),a="url(#pattern".concat(s.globals.cuid).concat(o,")");else{var c=s.config.plotOptions.radialBar.hollow.imageWidth,h=s.config.plotOptions.radialBar.hollow.imageHeight;if(void 0===c&&void 0===h){var d=s.globals.dom.Paper.image(l).loaded((function(e){this.move(t.centerX-e.width/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-e.height/2+s.config.plotOptions.radialBar.hollow.imageOffsetY)}));e.add(d)}else{var u=s.globals.dom.Paper.image(l).loaded((function(e){this.move(t.centerX-c/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-h/2+s.config.plotOptions.radialBar.hollow.imageOffsetY),this.size(c,h)}));e.add(u)}}return a}},{key:"getStrokeWidth",value:function(t){var e=this.w;return t.size*(100-parseInt(e.config.plotOptions.radialBar.hollow.size,10))/100/(t.series.length+1)-this.margin}}])&&Qi(e.prototype,i),o}(Gi);function aa(t){return aa="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},aa(t)}function sa(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function ra(t){for(var e=1;e0&&(this.visibleI=this.visibleI+1);var p=0,x=0;this.yRatio.length>1&&(this.yaxisIndex=g);var v=this.barHelpers.initialPositions();d=v.y,c=v.zeroW,h=v.x,x=v.barWidth,o=v.xDivision,l=v.zeroH;for(var m=a.group({class:"apexcharts-datalabels","data:realIndex":g}),y=a.group({class:"apexcharts-rangebar-goals-markers",style:"pointer-events: none"}),w=0;w0}));return a=l.config.plotOptions.bar.rangeBarGroupRows?s+n*u:s+r*this.visibleI+n*u,g>-1&&!l.config.plotOptions.bar.rangeBarOverlap&&(c=l.globals.seriesRange[e][g].overlaps).indexOf(h)>-1&&(a=(r=o.barHeight/c.length)*this.visibleI+n*(100-parseInt(this.barOptions.barHeight,10))/100/2+r*(this.visibleI+c.indexOf(h))+n*u),{barYPosition:a,barHeight:r}}},{key:"drawRangeColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=(t.strokeWidth,t.xDivision),s=t.barWidth,r=t.zeroH,n=this.w,o=e.i,l=e.j,c=this.yRatio[this.yaxisIndex],h=e.realIndex,d=this.getRangeValue(h,l),u=Math.min(d.start,d.end),g=Math.max(d.start,d.end);n.globals.isXNumeric&&(i=(n.globals.seriesX[o][l]-n.globals.minX)/this.xRatio-s/2);var f=i+s*this.visibleI;void 0===this.series[o][l]||null===this.series[o][l]?u=r:(u=r-u/c,g=r-g/c);var p=Math.abs(g-u),x=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:s,y1:u,y2:g,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,realIndex:e.realIndex,i:h,j:l,w:n});return n.globals.isXNumeric||(i+=a),{pathTo:x.pathTo,pathFrom:x.pathFrom,barHeight:p,x:i,y:g,goalY:this.barHelpers.getGoalValues("y",null,r,o,l),barXPosition:f}}},{key:"drawRangeBarPaths",value:function(t){var e=t.indexes,i=t.y,a=t.y1,s=t.y2,r=t.yDivision,n=t.barHeight,o=t.barYPosition,l=t.zeroW,c=this.w,h=l+a/this.invertedYRatio,d=l+s/this.invertedYRatio,u=Math.abs(d-h),g=this.barHelpers.getBarpaths({barYPosition:o,barHeight:n,x1:h,x2:d,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,i:e.realIndex,realIndex:e.realIndex,j:e.j,w:c});return c.globals.isXNumeric||(i+=r),{pathTo:g.pathTo,pathFrom:g.pathFrom,barWidth:u,x:d,goalX:this.barHelpers.getGoalValues("x",l,null,e.realIndex,e.j),y:i}}},{key:"getRangeValue",value:function(t,e){var i=this.w;return{start:i.globals.seriesRangeStart[t][e],end:i.globals.seriesRangeEnd[t][e]}}}])&&la(e.prototype,i),o}(ui);const ga=ua;function fa(t,e){for(var i=0;i0&&parseInt(n.realIndex,10)===parseInt(a,10)&&("line"===n.type?(this.lineCtx.appendPathFrom=!1,e=s.globals.previousPaths[r].paths[0].d):"area"===n.type&&(this.lineCtx.appendPathFrom=!1,i=s.globals.previousPaths[r].paths[0].d,s.config.stroke.show&&s.globals.previousPaths[r].paths[1]&&(e=s.globals.previousPaths[r].paths[1].d)))}return{pathFromLine:e,pathFromArea:i}}},{key:"determineFirstPrevY",value:function(t){var e,i=t.i,a=t.series,s=t.prevY,r=t.lineYPosition,n=this.w;if(void 0!==(null===(e=a[i])||void 0===e?void 0:e[0]))s=(r=n.config.chart.stacked&&i>0?this.lineCtx.prevSeriesY[i-1][0]:this.lineCtx.zeroY)-a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]+2*(this.lineCtx.isReversed?a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]:0);else if(n.config.chart.stacked&&i>0&&void 0===a[i][0])for(var o=i-1;o>=0;o--)if(null!==a[o][0]&&void 0!==a[o][0]){s=r=this.lineCtx.prevSeriesY[o][0];break}return{prevY:s,lineYPosition:r}}}])&&fa(e.prototype,i),t}();function xa(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function ba(t){for(var e=1;e0&&(f=(s.globals.seriesX[d][0]-s.globals.minX)/this.xRatio),g.push(f);var p,x=f,v=void 0,m=x,w=this.zeroY,k=this.zeroY;w=this.lineHelpers.determineFirstPrevY({i:h,series:t,prevY:w,lineYPosition:0}).prevY,u.push(w),p=w,"rangeArea"===n&&(v=k=this.lineHelpers.determineFirstPrevY({i:h,series:a,prevY:k,lineYPosition:0}).prevY);var A={type:n,series:t,realIndex:d,i:h,x:f,y:1,pX:x,pY:p,pathsFrom:this._calculatePathsFrom({type:n,series:t,i:h,realIndex:d,prevX:m,prevY:w,prevY2:k}),linePaths:[],areaPaths:[],seriesIndex:i,lineYPosition:0,xArrj:g,yArrj:u,seriesRangeEnd:a},S=this._iterateOverDataPoints(ba(ba({},A),{},{iterations:"rangeArea"===n?t[h].length-1:void 0,isRangeStart:!0}));if("rangeArea"===n){var C=this._calculatePathsFrom({series:a,i:h,realIndex:d,prevX:m,prevY:k}),P=this._iterateOverDataPoints(ba(ba({},A),{},{series:a,pY:v,pathsFrom:C,iterations:a[h].length-1,isRangeStart:!1}));S.linePaths[0]=P.linePath+S.linePath,S.pathFromLine=P.pathFromLine+S.pathFromLine}this._handlePaths({type:n,realIndex:d,i:h,paths:S}),this.elSeries.add(this.elPointsMain),this.elSeries.add(this.elDataLabelsWrap),c.push(this.elSeries)}if(s.config.chart.stacked)for(var L=c.length;L>0;L--)o.add(c[L-1]);else for(var O=0;O1&&(this.yaxisIndex=i),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed,this.zeroY=a.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?a.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),this.areaBottomY=this.zeroY,(this.zeroY>a.globals.gridHeight||"end"===a.config.plotOptions.area.fillTo)&&(this.areaBottomY=a.globals.gridHeight),this.categoryAxisCorrection=this.xDivision/2,this.elSeries=s.group({class:"apexcharts-series",seriesName:n.escapeString(a.globals.seriesNames[i])}),this.elPointsMain=s.group({class:"apexcharts-series-markers-wrap","data:realIndex":i}),this.elDataLabelsWrap=s.group({class:"apexcharts-datalabels","data:realIndex":i});var r=t[e].length===a.globals.dataPoints;this.elSeries.attr({"data:longestSeries":r,rel:e+1,"data:realIndex":i}),this.appendPathFrom=!0}},{key:"_calculatePathsFrom",value:function(t){var e,i,a,s,r=t.type,n=t.series,o=t.i,l=t.realIndex,c=t.prevX,h=t.prevY,d=t.prevY2,u=this.w,g=new b(this.ctx);if(null===n[o][0]){for(var f=0;f0){var p=this.lineHelpers.checkPreviousPaths({pathFromLine:a,pathFromArea:s,realIndex:l});a=p.pathFromLine,s=p.pathFromArea}return{prevX:c,prevY:h,linePath:e,areaPath:i,pathFromLine:a,pathFromArea:s}}},{key:"_handlePaths",value:function(t){var e=t.type,i=t.realIndex,a=t.i,s=t.paths,r=this.w,n=new b(this.ctx),o=new st(this.ctx);this.prevSeriesY.push(s.yArrj),r.globals.seriesXvalues[i]=s.xArrj,r.globals.seriesYvalues[i]=s.yArrj;var l=r.config.forecastDataPoints;if(l.count>0&&"rangeArea"!==e){var c=r.globals.seriesXvalues[i][r.globals.seriesXvalues[i].length-l.count-1],h=n.drawRect(c,0,r.globals.gridWidth,r.globals.gridHeight,0);r.globals.dom.elForecastMask.appendChild(h.node);var d=n.drawRect(0,0,c,r.globals.gridHeight,0);r.globals.dom.elNonForecastMask.appendChild(d.node)}this.pointsChart||r.globals.delayedElements.push({el:this.elPointsMain.node,index:i});var u={i:a,realIndex:i,animationDelay:a,initialSpeed:r.config.chart.animations.speed,dataChangeSpeed:r.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(e)};if("area"===e)for(var g=o.fillPath({seriesNumber:i}),f=0;f0&&"rangeArea"!==e){var A=n.renderPaths(w);A.node.setAttribute("stroke-dasharray",l.dashArray),l.strokeWidth&&A.node.setAttribute("stroke-width",l.strokeWidth),this.elSeries.add(A),A.attr("clip-path","url(#forecastMask".concat(r.globals.cuid,")")),k.attr("clip-path","url(#nonForecastMask".concat(r.globals.cuid,")"))}}}}},{key:"_iterateOverDataPoints",value:function(t){var e=t.type,i=t.series,a=t.iterations,s=t.realIndex,r=t.i,o=t.x,l=t.y,c=t.pX,h=t.pY,d=t.pathsFrom,u=t.linePaths,g=t.areaPaths,f=t.seriesIndex,p=t.lineYPosition,x=t.xArrj,v=t.yArrj,m=t.isRangeStart,y=t.seriesRangeEnd,w=this.w,k=new b(this.ctx),A=this.yRatio,S=d.prevY,C=d.linePath,P=d.areaPath,L=d.pathFromLine,O=d.pathFromArea,T=n.isNumber(w.globals.minYArr[s])?w.globals.minYArr[s]:w.globals.minY;a||(a=w.globals.dataPoints>1?w.globals.dataPoints-1:w.globals.dataPoints);for(var E=l,I=0;I0&&w.globals.collapsedSeries.length-1){e--;break}return e>=0?e:0}(r-1)][I+1]:this.zeroY,M?l=p-T/A[this.yaxisIndex]+2*(this.isReversed?T/A[this.yaxisIndex]:0):(l=p-i[r][I+1]/A[this.yaxisIndex]+2*(this.isReversed?i[r][I+1]/A[this.yaxisIndex]:0),"rangeArea"===e&&(E=p-y[r][I+1]/A[this.yaxisIndex]+2*(this.isReversed?y[r][I+1]/A[this.yaxisIndex]:0))),x.push(o),v.push(l);var X=this.lineHelpers.calculatePoints({series:i,x:o,y:l,realIndex:s,i:r,j:I,prevY:S}),Y=this._createPaths({type:e,series:i,i:r,realIndex:s,j:I,x:o,y:l,y2:E,pX:c,pY:h,linePath:C,areaPath:P,linePaths:u,areaPaths:g,seriesIndex:f,isRangeStart:m});g=Y.areaPaths,u=Y.linePaths,c=Y.pX,h=Y.pY,P=Y.areaPath,C=Y.linePath,this.appendPathFrom&&(L+=k.line(o,this.zeroY),O+=k.line(o,this.zeroY)),this.handleNullDataPoints(i,X,r,I,s),this._handleMarkersAndLabels({type:e,pointsPos:X,i:r,j:I,realIndex:s,isRangeStart:m})}return{yArrj:v,xArrj:x,pathFromArea:O,areaPaths:g,pathFromLine:L,linePaths:u,linePath:C,areaPath:P}}},{key:"_handleMarkersAndLabels",value:function(t){var e=t.type,i=t.pointsPos,a=t.isRangeStart,s=t.i,r=t.j,n=t.realIndex,o=this.w,l=new ht(this.ctx);if(this.pointsChart)this.scatter.draw(this.elSeries,r,{realIndex:n,pointsPos:i,zRatio:this.zRatio,elParent:this.elPointsMain});else{o.globals.series[s].length>1&&this.elPointsMain.node.classList.add("apexcharts-element-hidden");var c=this.markers.plotChartMarkers(i,n,r+1);null!==c&&this.elPointsMain.add(c)}var h=l.drawDataLabel({type:e,isRangeStart:a,pos:i,i:n,j:r+1});null!==h&&this.elDataLabelsWrap.add(h)}},{key:"_createPaths",value:function(t){var e=t.type,i=t.series,a=t.i,s=t.realIndex,r=t.j,n=t.x,o=t.y,l=t.y2,c=t.pX,h=t.pY,d=t.linePath,u=t.areaPath,g=t.linePaths,f=t.areaPaths,p=t.seriesIndex,x=t.isRangeStart,v=this.w,m=new b(this.ctx),y=v.config.stroke.curve,w=this.areaBottomY;if(Array.isArray(v.config.stroke.curve)&&(y=Array.isArray(p)?v.config.stroke.curve[p[a]]:v.config.stroke.curve[a]),"smooth"===y){var k=.35*(n-c);v.globals.hasNullValues?(null!==i[a][r]&&(null!==i[a][r+1]?(d=m.move(c,h)+m.curve(c+k,h,n-k,o,n+1,o),u=m.move(c+1,h)+m.curve(c+k,h,n-k,o,n+1,o)+m.line(n,w)+m.line(c,w)+"z"):(d=m.move(c,h),u=m.move(c,h)+"z")),g.push(d),f.push(u)):(d+=m.curve(c+k,h,n-k,o,n,o),u+=m.curve(c+k,h,n-k,o,n,o)),c=n,h=o,r===i[a].length-2&&(u=u+m.curve(c,h,n,o,n,w)+m.move(n,o)+"z","rangeArea"===e&&x?d=d+m.curve(c,h,n,o,n,l)+m.move(n,l)+"z":v.globals.hasNullValues||(g.push(d),f.push(u)))}else{if(null===i[a][r+1]){d+=m.move(n,o);var A=v.globals.isXNumeric?(v.globals.seriesX[s][r]-v.globals.minX)/this.xRatio:n-this.xDivision;u=u+m.line(A,w)+m.move(n,o)+"z"}null===i[a][r]&&(d+=m.move(n,o),u+=m.move(n,w)),"stepline"===y?(d=d+m.line(n,null,"H")+m.line(null,o,"V"),u=u+m.line(n,null,"H")+m.line(null,o,"V")):"straight"===y&&(d+=m.line(n,o),u+=m.line(n,o)),r===i[a].length-2&&(u=u+m.line(n,w)+m.move(n,o)+"z","rangeArea"===e&&x?d=d+m.line(n,l)+m.move(n,l)+"z":(g.push(d),f.push(u)))}return{linePaths:g,areaPaths:f,pX:c,pY:h,linePath:d,areaPath:u}}},{key:"handleNullDataPoints",value:function(t,e,i,a,s){var r=this.w;if(null===t[i][a]&&r.config.markers.showNullDataPoints||1===t[i].length){var n=this.markers.plotChartMarkers(e,s,a+1,this.strokeWidth-r.config.markers.strokeWidth/2,!0);null!==n&&this.elPointsMain.add(n)}}}])&&ma(e.prototype,i),t}();function wa(t,e){for(var i=0;ir-a&&l.width<=n-s){var c=o.rotateAroundCenter(t.node);t.node.setAttribute("transform","rotate(-90 ".concat(c.x," ").concat(c.y,")"))}}},{key:"animateTreemap",value:function(t,e,i,a){var s=new l(this.ctx);s.animateRect(t,{x:e.x,y:e.y,width:e.width,height:e.height},{x:i.x,y:i.y,width:i.width,height:i.height},a,(function(){s.animationCompleted(t)}))}}])&&wa(e.prototype,i),t}();function Aa(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function Sa(t){for(var e=1;e5e4&&(a.globals.disableZoomOut=!0);var n=s.getTimeUnitsfromTimestamp(t,e,this.utc),o=a.globals.gridWidth/r,l=o/24,c=l/60,h=c/60,d=Math.floor(24*r),u=Math.floor(1440*r),g=Math.floor(86400*r),f=Math.floor(r),p=Math.floor(r/30),x=Math.floor(r/365),b={minMillisecond:n.minMillisecond,minSecond:n.minSecond,minMinute:n.minMinute,minHour:n.minHour,minDate:n.minDate,minMonth:n.minMonth,minYear:n.minYear},v={firstVal:b,currentMillisecond:b.minMillisecond,currentSecond:b.minSecond,currentMinute:b.minMinute,currentHour:b.minHour,currentMonthDate:b.minDate,currentDate:b.minDate,currentMonth:b.minMonth,currentYear:b.minYear,daysWidthOnXAxis:o,hoursWidthOnXAxis:l,minutesWidthOnXAxis:c,secondsWidthOnXAxis:h,numberOfSeconds:g,numberOfMinutes:u,numberOfHours:d,numberOfDays:f,numberOfMonths:p,numberOfYears:x};switch(this.tickInterval){case"years":this.generateYearScale(v);break;case"months":case"half_year":this.generateMonthScale(v);break;case"months_days":case"months_fortnight":case"days":case"week_days":this.generateDayScale(v);break;case"hours":this.generateHourScale(v);break;case"minutes_fives":case"minutes":this.generateMinuteScale(v);break;case"seconds_tens":case"seconds_fives":case"seconds":this.generateSecondScale(v)}var m=this.timeScaleArray.map((function(t){var e={position:t.position,unit:t.unit,year:t.year,day:t.day?t.day:1,hour:t.hour?t.hour:0,month:t.month+1};return"month"===t.unit?Sa(Sa({},e),{},{day:1,value:t.value+1}):"day"===t.unit||"hour"===t.unit?Sa(Sa({},e),{},{value:t.value}):"minute"===t.unit?Sa(Sa({},e),{},{value:t.value,minute:t.value}):"second"===t.unit?Sa(Sa({},e),{},{value:t.value,minute:t.minute,second:t.second}):t}));return m.filter((function(t){var e=1,s=Math.ceil(a.globals.gridWidth/120),r=t.value;void 0!==a.config.xaxis.tickAmount&&(s=a.config.xaxis.tickAmount),m.length>s&&(e=Math.floor(m.length/s));var n=!1,o=!1;switch(i.tickInterval){case"years":"year"===t.unit&&(n=!0);break;case"half_year":e=7,"year"===t.unit&&(n=!0);break;case"months":e=1,"year"===t.unit&&(n=!0);break;case"months_fortnight":e=15,"year"!==t.unit&&"month"!==t.unit||(n=!0),30===r&&(o=!0);break;case"months_days":e=10,"month"===t.unit&&(n=!0),30===r&&(o=!0);break;case"week_days":e=8,"month"===t.unit&&(n=!0);break;case"days":e=1,"month"===t.unit&&(n=!0);break;case"hours":"day"===t.unit&&(n=!0);break;case"minutes_fives":case"seconds_fives":r%5!=0&&(o=!0);break;case"seconds_tens":r%10!=0&&(o=!0)}if("hours"===i.tickInterval||"minutes_fives"===i.tickInterval||"seconds_tens"===i.tickInterval||"seconds_fives"===i.tickInterval){if(!o)return!0}else if((r%e==0||n)&&!o)return!0}))}},{key:"recalcDimensionsBasedOnFormat",value:function(t,e){var i=this.w,a=this.formatDates(t),s=this.removeOverlappingTS(a);i.globals.timescaleLabels=s.slice(),new se(this.ctx).plotCoords()}},{key:"determineInterval",value:function(t){var e=24*t,i=60*e;switch(!0){case t/365>5:this.tickInterval="years";break;case t>800:this.tickInterval="half_year";break;case t>180:this.tickInterval="months";break;case t>90:this.tickInterval="months_fortnight";break;case t>60:this.tickInterval="months_days";break;case t>30:this.tickInterval="week_days";break;case t>2:this.tickInterval="days";break;case e>2.4:this.tickInterval="hours";break;case i>15:this.tickInterval="minutes_fives";break;case i>5:this.tickInterval="minutes";break;case i>1:this.tickInterval="seconds_tens";break;case 60*i>20:this.tickInterval="seconds_fives";break;default:this.tickInterval="seconds"}}},{key:"generateYearScale",value:function(t){var e=t.firstVal,i=t.currentMonth,a=t.currentYear,s=t.daysWidthOnXAxis,r=t.numberOfYears,o=e.minYear,l=0,c=new R(this.ctx),h="year";if(e.minDate>1||e.minMonth>0){var d=c.determineRemainingDaysOfYear(e.minYear,e.minMonth,e.minDate);l=(c.determineDaysOfYear(e.minYear)-d+1)*s,o=e.minYear+1,this.timeScaleArray.push({position:l,value:o,unit:h,year:o,month:n.monthMod(i+1)})}else 1===e.minDate&&0===e.minMonth&&this.timeScaleArray.push({position:l,value:o,unit:h,year:a,month:n.monthMod(i+1)});for(var u=o,g=l,f=0;f1){c=(h.determineDaysOfMonths(a+1,e.minYear)-i+1)*r,l=n.monthMod(a+1);var g=s+u,f=n.monthMod(l),p=l;0===l&&(d="year",p=g,f=1,g+=u+=1),this.timeScaleArray.push({position:c,value:p,unit:d,year:g,month:f})}else this.timeScaleArray.push({position:c,value:l,unit:d,year:s,month:n.monthMod(a)});for(var x=l+1,b=c,v=0,m=1;vo.determineDaysOfMonths(e+1,i)?(h=1,l="month",g=e+=1,e):e},u=(24-e.minHour)*s,g=c,f=d(h,i,a);0===e.minHour&&1===e.minDate?(u=0,g=n.monthMod(e.minMonth),l="month",h=e.minDate,r++):1!==e.minDate&&0===e.minHour&&0===e.minMinute&&(u=0,c=e.minDate,g=c,f=d(h=c,i,a)),this.timeScaleArray.push({position:u,value:g,unit:l,year:this._getYear(a,f,0),month:n.monthMod(f),day:h});for(var p=u,x=0;xl.determineDaysOfMonths(e+1,s)&&(x=1,e+=1),{month:e,date:x}},d=function(t,e){return t>l.determineDaysOfMonths(e+1,s)?e+=1:e},u=60-(e.minMinute+e.minSecond/60),g=u*r,f=e.minHour+1,p=f+1;60===u&&(g=0,p=(f=e.minHour)+1);var x=i,b=d(x,a);this.timeScaleArray.push({position:g,value:f,unit:c,day:x,hour:p,year:s,month:n.monthMod(b)});for(var v=g,m=0;m=24&&(p=0,c="day",b=h(x+=1,b).month,b=d(x,b));var y=this._getYear(s,b,0);v=60*r+v;var w=0===p?x:p;this.timeScaleArray.push({position:v,value:w,unit:c,hour:p,day:x,year:y,month:n.monthMod(b)}),p++}}},{key:"generateMinuteScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,l=t.currentYear,c=t.minutesWidthOnXAxis,h=t.secondsWidthOnXAxis,d=t.numberOfMinutes,u=a+1,g=r,f=o,p=l,x=s,b=(60-i-e/1e3)*h,v=0;v=60&&(u=0,24===(x+=1)&&(x=0)),this.timeScaleArray.push({position:b,value:u,unit:"minute",hour:x,minute:u,day:g,year:this._getYear(p,f,0),month:n.monthMod(f)}),b+=c,u++}},{key:"generateSecondScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,l=t.currentYear,c=t.secondsWidthOnXAxis,h=t.numberOfSeconds,d=i+1,u=a,g=r,f=o,p=l,x=s,b=(1e3-e)/1e3*c,v=0;v=60&&(d=0,++u>=60&&(u=0,24==++x&&(x=0))),this.timeScaleArray.push({position:b,value:d,unit:"second",hour:x,minute:u,second:d,day:g,year:this._getYear(p,f,0),month:n.monthMod(f)}),b+=c,d++}},{key:"createRawDateString",value:function(t,e){var i=t.year;return 0===t.month&&(t.month=1),i+="-"+("0"+t.month.toString()).slice(-2),"day"===t.unit?i+="day"===t.unit?"-"+("0"+e).slice(-2):"-01":i+="-"+("0"+(t.day?t.day:"1")).slice(-2),"hour"===t.unit?i+="hour"===t.unit?"T"+("0"+e).slice(-2):"T00":i+="T"+("0"+(t.hour?t.hour:"0")).slice(-2),"minute"===t.unit?i+=":"+("0"+e).slice(-2):i+=":"+(t.minute?("0"+t.minute).slice(-2):"00"),"second"===t.unit?i+=":"+("0"+e).slice(-2):i+=":00",this.utc&&(i+=".000Z"),i}},{key:"formatDates",value:function(t){var e=this,i=this.w;return t.map((function(t){var a=t.value.toString(),s=new R(e.ctx),r=e.createRawDateString(t,a),n=s.getDate(s.parseDate(r));if(e.utc||(n=s.getDate(s.parseDateWithTimezone(r))),void 0===i.config.xaxis.labels.format){var o="dd MMM",l=i.config.xaxis.labels.datetimeFormatter;"year"===t.unit&&(o=l.year),"month"===t.unit&&(o=l.month),"day"===t.unit&&(o=l.day),"hour"===t.unit&&(o=l.hour),"minute"===t.unit&&(o=l.minute),"second"===t.unit&&(o=l.second),a=s.formatDate(n,o)}else a=s.formatDate(n,i.config.xaxis.labels.format);return{dateString:r,position:t.position,value:a,unit:t.unit,year:t.year,month:t.month}}))}},{key:"removeOverlappingTS",value:function(t){var e,i=this,a=new b(this.ctx),s=!1;t.length>0&&t[0].value&&t.every((function(e){return e.value.length===t[0].value.length}))&&(s=!0,e=a.getTextRects(t[0].value).width);var r=0,n=t.map((function(n,o){if(o>0&&i.w.config.xaxis.labels.hideOverlappingLabels){var l=s?e:a.getTextRects(t[r].value).width,c=t[r].position;return n.position>c+l+10?(r=o,n):null}return n}));return n.filter((function(t){return null!==t}))}},{key:"_getYear",value:function(t,e,i){return t+Math.floor(e/12)+i}}])&&Pa(e.prototype,i),t}();function Oa(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function Ta(t){for(var e=1;et.length)&&(e=t.length);for(var i=0,a=new Array(e);i-1,t.xyCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble"].indexOf(i)>-1,t.isBarHorizontal=("bar"===e.chart.type||"rangeBar"===e.chart.type||"boxPlot"===e.chart.type)&&e.plotOptions.bar.horizontal,t.chartClass=".apexcharts"+t.chartID,t.dom.baseEl=this.el,t.dom.elWrap=document.createElement("div"),b.setAttrs(t.dom.elWrap,{id:t.chartClass.substring(1),class:"apexcharts-canvas "+t.chartClass.substring(1)}),this.el.appendChild(t.dom.elWrap),t.dom.Paper=new window.SVG.Doc(t.dom.elWrap),t.dom.Paper.attr({class:"apexcharts-svg","xmlns:data":"ApexChartsNS",transform:"translate(".concat(e.chart.offsetX,", ").concat(e.chart.offsetY,")")}),t.dom.Paper.node.style.background=e.chart.background,this.setSVGDimensions(),t.dom.elGraphical=t.dom.Paper.group().attr({class:"apexcharts-inner apexcharts-graphical"}),t.dom.elAnnotations=t.dom.Paper.group().attr({class:"apexcharts-annotations"}),t.dom.elDefs=t.dom.Paper.defs(),t.dom.elLegendWrap=document.createElement("div"),t.dom.elLegendWrap.classList.add("apexcharts-legend"),t.dom.elWrap.appendChild(t.dom.elLegendWrap),t.dom.Paper.add(t.dom.elGraphical),t.dom.elGraphical.add(t.dom.elDefs)}},{key:"plotChartType",value:function(t,e){var i=this.w,a=i.config,s=i.globals,r={series:[],i:[]},n={series:[],i:[]},o={series:[],i:[]},l={series:[],i:[]},c={series:[],i:[]},h={series:[],i:[]},d={series:[],i:[]},u={series:[],i:[]},g={series:[],seriesRangeEnd:[],i:[]};s.series.map((function(e,f){var p=0;void 0!==t[f].type?("column"===t[f].type||"bar"===t[f].type?(s.series.length>1&&a.plotOptions.bar.horizontal&&console.warn("Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"),c.series.push(e),c.i.push(f),p++,i.globals.columnSeries=c.series):"area"===t[f].type?(n.series.push(e),n.i.push(f),p++):"line"===t[f].type?(r.series.push(e),r.i.push(f),p++):"scatter"===t[f].type?(o.series.push(e),o.i.push(f)):"bubble"===t[f].type?(l.series.push(e),l.i.push(f),p++):"candlestick"===t[f].type?(h.series.push(e),h.i.push(f),p++):"boxPlot"===t[f].type?(d.series.push(e),d.i.push(f),p++):"rangeBar"===t[f].type?(u.series.push(e),u.i.push(f),p++):"rangeArea"===t[f].type?(g.series.push(s.seriesRangeStart[f]),g.seriesRangeEnd.push(s.seriesRangeEnd[f]),g.i.push(f),p++):console.warn("You have specified an unrecognized chart type. Available types for this property are line/area/column/bar/scatter/bubble"),p>1&&(s.comboCharts=!0)):(r.series.push(e),r.i.push(f))}));var f=new ya(this.ctx,e),p=new Xi(this.ctx,e);this.ctx.pie=new Gi(this.ctx);var x=new ia(this.ctx);this.ctx.rangeBar=new ga(this.ctx,e);var b=new $i(this.ctx),v=[];if(s.comboCharts){if(n.series.length>0&&v.push(f.draw(n.series,"area",n.i)),c.series.length>0)if(i.config.chart.stacked){var m=new Ai(this.ctx,e);v.push(m.draw(c.series,c.i))}else this.ctx.bar=new ui(this.ctx,e),v.push(this.ctx.bar.draw(c.series,c.i));if(g.series.length>0&&v.push(f.draw(g.series,"rangeArea",g.i,g.seriesRangeEnd)),r.series.length>0&&v.push(f.draw(r.series,"line",r.i)),h.series.length>0&&v.push(p.draw(h.series,h.i)),d.series.length>0&&v.push(p.draw(d.series,d.i)),u.series.length>0&&v.push(this.ctx.rangeBar.draw(u.series,u.i)),o.series.length>0){var y=new ya(this.ctx,e,!0);v.push(y.draw(o.series,"scatter",o.i))}if(l.series.length>0){var w=new ya(this.ctx,e,!0);v.push(w.draw(l.series,"bubble",l.i))}}else switch(a.chart.type){case"line":v=f.draw(s.series,"line");break;case"area":v=f.draw(s.series,"area");break;case"bar":a.chart.stacked?v=new Ai(this.ctx,e).draw(s.series):(this.ctx.bar=new ui(this.ctx,e),v=this.ctx.bar.draw(s.series));break;case"candlestick":case"boxPlot":v=new Xi(this.ctx,e).draw(s.series);break;case"rangeBar":v=this.ctx.rangeBar.draw(s.series);break;case"rangeArea":v=f.draw(s.seriesRangeStart,"rangeArea",void 0,s.seriesRangeEnd);break;case"heatmap":v=new Ni(this.ctx,e).draw(s.series);break;case"treemap":v=new ka(this.ctx,e).draw(s.series);break;case"pie":case"donut":case"polarArea":v=this.ctx.pie.draw(s.series);break;case"radialBar":v=x.draw(s.series);break;case"radar":v=b.draw(s.series);break;default:v=f.draw(s.series)}return v}},{key:"setSVGDimensions",value:function(){var t=this.w.globals,e=this.w.config;t.svgWidth=e.chart.width,t.svgHeight=e.chart.height;var i=n.getDimensions(this.el),a=e.chart.width.toString().split(/[0-9]+/g).pop();"%"===a?n.isNumber(i[0])&&(0===i[0].width&&(i=n.getDimensions(this.el.parentNode)),t.svgWidth=i[0]*parseInt(e.chart.width,10)/100):"px"!==a&&""!==a||(t.svgWidth=parseInt(e.chart.width,10));var s=e.chart.height.toString().split(/[0-9]+/g).pop();if("auto"!==t.svgHeight&&""!==t.svgHeight)if("%"===s){var r=n.getDimensions(this.el.parentNode);t.svgHeight=r[1]*parseInt(e.chart.height,10)/100}else t.svgHeight=parseInt(e.chart.height,10);else t.axisCharts?t.svgHeight=t.svgWidth/1.61:t.svgHeight=t.svgWidth/1.2;if(t.svgWidth<0&&(t.svgWidth=0),t.svgHeight<0&&(t.svgHeight=0),b.setAttrs(t.dom.Paper.node,{width:t.svgWidth,height:t.svgHeight}),"%"!==s){var o=e.chart.sparkline.enabled?0:t.axisCharts?e.chart.parentHeightOffset:0;t.dom.Paper.node.parentNode.parentNode.style.minHeight=t.svgHeight+o+"px"}t.dom.elWrap.style.width=t.svgWidth+"px",t.dom.elWrap.style.height=t.svgHeight+"px"}},{key:"shiftGraphPosition",value:function(){var t=this.w.globals,e=t.translateY,i={transform:"translate("+t.translateX+", "+e+")"};b.setAttrs(t.dom.elGraphical.node,i)}},{key:"resizeNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=0,a=t.config.chart.sparkline.enabled?1:15;a+=t.config.grid.padding.bottom,"top"!==t.config.legend.position&&"bottom"!==t.config.legend.position||!t.config.legend.show||t.config.legend.floating||(i=new le(this.ctx).legendHelpers.getLegendBBox().clwh+10);var s=t.globals.dom.baseEl.querySelector(".apexcharts-radialbar, .apexcharts-pie"),r=2.05*t.globals.radialSize;if(s&&!t.config.chart.sparkline.enabled&&0!==t.config.plotOptions.radialBar.startAngle){var o=n.getBoundingClientRect(s);r=o.bottom;var l=o.bottom-o.top;r=Math.max(2.05*t.globals.radialSize,l)}var c=r+e.translateY+i+a;e.dom.elLegendForeign&&e.dom.elLegendForeign.setAttribute("height",c),t.config.chart.height&&String(t.config.chart.height).indexOf("%")>0||(e.dom.elWrap.style.height=c+"px",b.setAttrs(e.dom.Paper.node,{height:c}),e.dom.Paper.node.parentNode.parentNode.style.minHeight=c+"px")}},{key:"coreCalculations",value:function(){new Et(this.ctx).init()}},{key:"resetGlobals",value:function(){var t=this,e=function(){return t.w.config.series.map((function(t){return[]}))},i=new J,a=this.w.globals;i.initGlobalVars(a),a.seriesXvalues=e(),a.seriesYvalues=e()}},{key:"isMultipleY",value:function(){if(this.w.config.yaxis.constructor===Array&&this.w.config.yaxis.length>1)return this.w.globals.isMultipleYAxis=!0,!0}},{key:"xySettings",value:function(){var t=null,e=this.w;if(e.globals.axisCharts){if("back"===e.config.xaxis.crosshairs.position&&new Nt(this.ctx).drawXCrosshairs(),"back"===e.config.yaxis[0].crosshairs.position&&new Nt(this.ctx).drawYCrosshairs(),"datetime"===e.config.xaxis.type&&void 0===e.config.xaxis.labels.formatter){this.ctx.timeScale=new La(this.ctx);var i=[];isFinite(e.globals.minX)&&isFinite(e.globals.maxX)&&!e.globals.isBarHorizontal?i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minX,e.globals.maxX):e.globals.isBarHorizontal&&(i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minY,e.globals.maxY)),this.ctx.timeScale.recalcDimensionsBasedOnFormat(i)}t=new y(this.ctx).getCalculatedRatios()}return t}},{key:"updateSourceChart",value:function(t){this.ctx.w.globals.selection=void 0,this.ctx.updateHelpers._updateOptions({chart:{selection:{xaxis:{min:t.w.globals.minX,max:t.w.globals.maxX}}}},!1,!1)}},{key:"setupBrushHandler",value:function(){var t=this,e=this.w;if(e.config.chart.brush.enabled&&"function"!=typeof e.config.chart.events.selection){var i=e.config.chart.brush.targets||[e.config.chart.brush.target];i.forEach((function(e){var i=ApexCharts.getChartByID(e);i.w.globals.brushSource=t.ctx,"function"!=typeof i.w.config.chart.events.zoomed&&(i.w.config.chart.events.zoomed=function(){t.updateSourceChart(i)}),"function"!=typeof i.w.config.chart.events.scrolled&&(i.w.config.chart.events.scrolled=function(){t.updateSourceChart(i)})})),e.config.chart.events.selection=function(t,a){i.forEach((function(t){var i=ApexCharts.getChartByID(t),s=n.clone(e.config.yaxis);if(e.config.chart.brush.autoScaleYaxis&&1===i.w.globals.series.length){var r=new Lt(i);s=r.autoScaleY(i,s,a)}var o=i.w.config.yaxis.reduce((function(t,e,a){return[].concat(function(t){if(Array.isArray(t))return Ia(t)}(r=t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(r)||function(t,e){if(t){if("string"==typeof t)return Ia(t,e);var i=Object.prototype.toString.call(t).slice(8,-1);return"Object"===i&&t.constructor&&(i=t.constructor.name),"Map"===i||"Set"===i?Array.from(t):"Arguments"===i||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(i)?Ia(t,e):void 0}}(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),[Ta(Ta({},i.w.config.yaxis[a]),{},{min:s[0].min,max:s[0].max})]);var r}),[]);i.ctx.updateHelpers._updateOptions({xaxis:{min:a.xaxis.min,max:a.xaxis.max},yaxis:o},!1,!1,!1,!1)}))}}}}])&&Ma(e.prototype,i),t}();function Xa(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function Ya(t){for(var e=1;e1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return new Promise((function(o){var l=[e.ctx];s&&(l=e.ctx.getSyncedCharts()),e.ctx.w.globals.isExecCalled&&(l=[e.ctx],e.ctx.w.globals.isExecCalled=!1),l.forEach((function(s,c){var h=s.w;if(h.globals.shouldAnimate=a,i||(h.globals.resized=!0,h.globals.dataChanged=!0,a&&s.series.getPreviousPaths()),t&&"object"===Ra(t)&&(s.config=new Z(t),t=y.extendArrayProps(s.config,t,h),s.w.globals.chartID!==e.ctx.w.globals.chartID&&delete t.series,h.config=n.extend(h.config,t),r&&(h.globals.lastXAxis=t.xaxis?n.clone(t.xaxis):[],h.globals.lastYAxis=t.yaxis?n.clone(t.yaxis):[],h.globals.initialConfig=n.extend({},h.config),h.globals.initialSeries=n.clone(h.config.series),t.series))){for(var d=0;d2&&void 0!==arguments[2]&&arguments[2];return new Promise((function(s){var r,o=i.w;return o.globals.shouldAnimate=e,o.globals.dataChanged=!0,e&&i.ctx.series.getPreviousPaths(),o.globals.axisCharts?(0===(r=t.map((function(t,e){return i._extendSeries(t,e)}))).length&&(r=[{data:[]}]),o.config.series=r):o.config.series=t.slice(),a&&(o.globals.initialConfig.series=n.clone(o.config.series),o.globals.initialSeries=n.clone(o.config.series)),i.ctx.update().then((function(){s(i.ctx)}))}))}},{key:"_extendSeries",value:function(t,e){var i=this.w,a=i.config.series[e];return Ya(Ya({},i.config.series[e]),{},{name:t.name?t.name:a&&a.name,color:t.color?t.color:a&&a.color,type:t.type?t.type:a&&a.type,data:t.data?t.data:a&&a.data})}},{key:"toggleDataPointSelection",value:function(t,e){var i=this.w,a=null,s=".apexcharts-series[data\\:realIndex='".concat(t,"']");return i.globals.axisCharts?a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(e,"'], ").concat(s," circle[j='").concat(e,"'], ").concat(s," rect[j='").concat(e,"']")).members[0]:void 0===e&&(a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(t,"']")).members[0],"pie"!==i.config.chart.type&&"polarArea"!==i.config.chart.type&&"donut"!==i.config.chart.type||this.ctx.pie.pieClicked(t)),a?(new b(this.ctx).pathMouseDown(a,null),a.node?a.node:null):(console.warn("toggleDataPointSelection: Element not found"),null)}},{key:"forceXAxisUpdate",value:function(t){var e=this.w;if(["min","max"].forEach((function(i){void 0!==t.xaxis[i]&&(e.config.xaxis[i]=t.xaxis[i],e.globals.lastXAxis[i]=t.xaxis[i])})),t.xaxis.categories&&t.xaxis.categories.length&&(e.config.xaxis.categories=t.xaxis.categories),e.config.xaxis.convertedCatToNumeric){var i=new _(t);t=i.convertCatToNumericXaxis(t,this.ctx)}return t}},{key:"forceYAxisUpdate",value:function(t){return t.chart&&t.chart.stacked&&"100%"===t.chart.stackType&&(Array.isArray(t.yaxis)?t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})):(t.yaxis.min=0,t.yaxis.max=100)),t}},{key:"revertDefaultAxisMinMax",value:function(t){var e=this,i=this.w,a=i.globals.lastXAxis,s=i.globals.lastYAxis;t&&t.xaxis&&(a=t.xaxis),t&&t.yaxis&&(s=t.yaxis),i.config.xaxis.min=a.min,i.config.xaxis.max=a.max;i.config.yaxis.map((function(t,a){i.globals.zoomed||void 0!==s[a]?function(t){void 0!==s[t]&&(i.config.yaxis[t].min=s[t].min,i.config.yaxis[t].max=s[t].max)}(a):void 0!==e.ctx.opts.yaxis[a]&&(t.min=e.ctx.opts.yaxis[a].min,t.max=e.ctx.opts.yaxis[a].max)}))}}],i&&Fa(e.prototype,i),t}();function Na(t,e){for(var i=0;i0&&void 0!==arguments[0]?arguments[0]:null,i=this,a=i.w;return new Promise((function(s,r){if(null===i.el)return r(new Error("Not enough data to display or target element not found"));(null===e||a.globals.allSeriesCollapsed)&&i.series.handleNoData(),i.grid=new Ct(i);var n=i.grid.drawGrid();if(i.annotations=new z(i),i.annotations.drawImageAnnos(),i.annotations.drawTextAnnos(),"back"===a.config.grid.position&&n&&(a.globals.dom.elGraphical.add(n.el),n&&n.elGridBorders&&n.elGridBorders.node&&a.globals.dom.elGraphical.add(n.elGridBorders)),Array.isArray(e.elGraph))for(var o=0;o0&&a.globals.memory.methodsToExec.forEach((function(t){t.method(t.params,!1,t.context)})),a.globals.axisCharts||a.globals.noData||i.core.resizeNonAxisCharts(),s(i)}))}},{key:"destroy",value:function(){var t,e;window.removeEventListener("resize",this.windowResizeHandler),this.el.parentNode,t=this.parentResizeHandler,(e=Ga.get(t))&&(e.disconnect(),Ga.delete(t));var i=this.w.config.chart.id;i&&Apex._chartInstances.forEach((function(t,e){t.id===n.escapeString(i)&&Apex._chartInstances.splice(e,1)})),new Ba(this.ctx).clear({isUpdating:!1})}},{key:"updateOptions",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],n=this.w;return n.globals.selection=void 0,t.series&&(this.series.resetSeries(!1,!0,!1),t.series.length&&t.series[0].data&&(t.series=t.series.map((function(t,i){return e.updateHelpers._extendSeries(t,i)}))),this.updateHelpers.revertDefaultAxisMinMax()),t.xaxis&&(t=this.updateHelpers.forceXAxisUpdate(t)),t.yaxis&&(t=this.updateHelpers.forceYAxisUpdate(t)),n.globals.collapsedSeriesIndices.length>0&&this.series.clearPreviousPaths(),t.theme&&(t=this.theme.updateThemeOptions(t)),this.updateHelpers._updateOptions(t,i,a,s,r)}},{key:"updateSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(t,e,i)}},{key:"appendSeries",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w.config.series.slice();return a.push(t),this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(a,e,i)}},{key:"appendData",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this;i.w.globals.dataChanged=!0,i.series.getPreviousPaths();for(var a=i.w.config.series.slice(),s=0;s0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.series.resetSeries(t,e)}},{key:"addEventListener",value:function(t,e){this.events.addEventListener(t,e)}},{key:"removeEventListener",value:function(t,e){this.events.removeEventListener(t,e)}},{key:"addXaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addXaxisAnnotationExternal(t,e,a)}},{key:"addYaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addYaxisAnnotationExternal(t,e,a)}},{key:"addPointAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addPointAnnotationExternal(t,e,a)}},{key:"clearAnnotations",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,e=this;t&&(e=t),e.annotations.clearAnnotations(e)}},{key:"removeAnnotation",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=this;e&&(i=e),i.annotations.removeAnnotation(i,t)}},{key:"getChartArea",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner")}},{key:"getSeriesTotalXRange",value:function(t,e){return this.coreUtils.getSeriesTotalsXRange(t,e)}},{key:"getHighestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new Et(this.ctx);return e.getMinYMaxY(t).highestY}},{key:"getLowestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new Et(this.ctx);return e.getMinYMaxY(t).lowestY}},{key:"getSeriesTotal",value:function(){return this.w.globals.seriesTotals}},{key:"toggleDataPointSelection",value:function(t,e){return this.updateHelpers.toggleDataPointSelection(t,e)}},{key:"zoomX",value:function(t,e){this.ctx.toolbar.zoomUpdateOptions(t,e)}},{key:"setLocale",value:function(t){this.localization.setCurrentLocaleValues(t)}},{key:"dataURI",value:function(t){return new yt(this.ctx).dataURI(t)}},{key:"exportToCSV",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=new yt(this.ctx);return e.exportToCSV(t)}},{key:"paper",value:function(){return this.w.globals.dom.Paper}},{key:"_parentResizeCallback",value:function(){this.w.globals.animationEnded&&this.w.config.chart.redrawOnParentResize&&this._windowResize()}},{key:"_windowResize",value:function(){var t=this;clearTimeout(this.w.globals.resizeTimer),this.w.globals.resizeTimer=window.setTimeout((function(){t.w.globals.resized=!0,t.w.globals.dataChanged=!1,t.ctx.update()}),150)}},{key:"_windowResizeHandler",value:function(){var t=this.w.config.chart.redrawOnWindowResize;"function"==typeof t&&(t=t()),t&&this._windowResize()}}],a=[{key:"getChartByID",value:function(t){var e=n.escapeString(t),i=Apex._chartInstances.filter((function(t){return t.id===e}))[0];return i&&i.chart}},{key:"initOnLoad",value:function(){for(var e=document.querySelectorAll("[data-apexcharts]"),i=0;i2?s-2:0),n=2;n{window.TreemapSquared={},function(){"use strict";window.TreemapSquared.generate=function(){function t(e,i,a,s){this.xoffset=e,this.yoffset=i,this.height=s,this.width=a,this.shortestEdge=function(){return Math.min(this.height,this.width)},this.getCoordinates=function(t){var e,i=[],a=this.xoffset,s=this.yoffset,n=r(t)/this.height,o=r(t)/this.width;if(this.width>=this.height)for(e=0;e=this.height){var a=e/this.height,s=this.width-a;i=new t(this.xoffset+a,this.yoffset,s,this.height)}else{var r=e/this.width,n=this.height-r;i=new t(this.xoffset,this.yoffset+r,this.width,n)}return i}}function e(e,a,s,n,o){n=void 0===n?0:n,o=void 0===o?0:o;var l=i(function(t,e){var i,a=[],s=e/r(t);for(i=0;i=a(s,i))}(e,l=t[0],o)?(e.push(l),i(t.slice(1),e,s,n)):(c=s.cutArea(r(e),n),n.push(s.getCoordinates(e)),i(t,[],c,n)),n;n.push(s.getCoordinates(e))}function a(t,e){var i=Math.min.apply(Math,t),a=Math.max.apply(Math,t),s=r(t);return Math.max(Math.pow(e,2)*a/Math.pow(s,2),Math.pow(s,2)/(Math.pow(e,2)*i))}function s(t){return t&&t.constructor===Array}function r(t){var e,i=0;for(e=0;e=0;a--)if(t[a])for(var s in e)t[a].prototype[s]=e[s];i.Set&&i.Set.inherit&&i.Set.inherit()},i.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,i.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&i.extend(e,t.extend),t.construct&&i.extend(t.parent||i.Container,t.construct),e},i.adopt=function(e){return e?e.instance?e.instance:((a="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new i.Nested:new i.Doc:"linearGradient"==e.nodeName?new i.Gradient("linear"):"radialGradient"==e.nodeName?new i.Gradient("radial"):i[d(e.nodeName)]?new(i[d(e.nodeName)]):new i.Element(e)).type=e.nodeName,a.node=e,e.instance=a,a instanceof i.Doc&&a.namespace().defs(),a.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),a):null;var a},i.prepare=function(){var t=e.getElementsByTagName("body")[0],a=(t?new i.Doc(t):i.adopt(e.documentElement).nested()).size(2,0);i.parser={body:t||e.documentElement,draw:a.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden").node,poly:a.polyline().node,path:a.path().node,native:i.create("svg")}},i.parser={native:i.create("svg")},e.addEventListener("DOMContentLoaded",(function(){i.parser.draw||i.prepare()}),!1),i.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},i.utils={map:function(t,e){for(var i=t.length,a=[],s=0;s1?1:t,new i.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),i.Color.test=function(t){return t+="",i.regex.isHex.test(t)||i.regex.isRgb.test(t)},i.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},i.Color.isColor=function(t){return i.Color.isRgb(t)||i.Color.test(t)},i.Array=function(t,e){0==(t=(t||[]).valueOf()).length&&e&&(t=e.valueOf()),this.value=this.parse(t)},i.extend(i.Array,{toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:this.split(t)}}),i.PointArray=function(t,e){i.Array.call(this,t,e||[[0,0]])},i.PointArray.prototype=new i.Array,i.PointArray.prototype.constructor=i.PointArray;for(var a={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]}},s="mlhvqtcsaz".split(""),n=0,o=s.length;nl);return r},bbox:function(){return i.parser.draw||i.prepare(),i.parser.path.setAttribute("d",this.toString()),i.parser.path.getBBox()}}),i.Number=i.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(i.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof i.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new i.Number(t),new i.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new i.Number(t),new i.Number(this-t,this.unit||t.unit)},times:function(t){return t=new i.Number(t),new i.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new i.Number(t),new i.Number(this/t,this.unit||t.unit)},to:function(t){var e=new i.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new i.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new i.Number(this.destination).minus(this).times(t).plus(this):this}}}),i.Element=i.invent({create:function(t){this._stroke=i.defaults.attrs.stroke,this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this,this._stroke=t.getAttribute("stroke")||this._stroke)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var a=g(this,t,e);return this.width(new i.Number(a.width)).height(new i.Number(a.height))},clone:function(t){this.writeDataToDom();var e=x(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return"none"!=this.style("display")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(i.regex.delimiter)},hasClass:function(t){return-1!=this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter((function(e){return e!=t})).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return i.get(this.attr(t))},parent:function(e){var a=this;if(!a.node.parentNode)return null;if(a=i.adopt(a.node.parentNode),!e)return a;for(;a&&a.node instanceof t.SVGElement;){if("string"==typeof e?a.matches(e):a instanceof e)return a;if(!a.node.parentNode||"#document"==a.node.parentNode.nodeName)return null;a=i.adopt(a.node.parentNode)}},doc:function(){return this instanceof i.Doc?this:this.parent(i.Doc)},parents:function(t){var e=[],i=this;do{if(!(i=i.parent(t))||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return function(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}(this.node,t)},native:function(){return this.node},svg:function(t){var a=e.createElement("svg");if(!(t&&this instanceof i.Parent))return a.appendChild(t=e.createElement("svg")),this.writeDataToDom(),t.appendChild(this.node.cloneNode(!0)),a.innerHTML.replace(/^/,"").replace(/<\/svg>$/,"");a.innerHTML=""+t.replace(/\n/,"").replace(/<([\w:-]+)([^<]+?)\/>/g,"<$1$2>")+"";for(var s=0,r=a.firstChild.childNodes.length;s":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},i.morph=function(t){return function(e,a){return new i.MorphObj(e,a).at(t)}},i.Situation=i.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new i.Number(t.duration).valueOf(),this.delay=new i.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),i.FX=i.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,a){"object"===r(t)&&(e=t.ease,a=t.delay,t=t.duration);var s=new i.Situation({duration:t||1e3,delay:a||0,ease:i.easing[e||"-"]||e});return this.queue(s),this},target:function(t){return t&&t instanceof i.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof i.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof i.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e=this.situation;if(e.init)return this;for(var a in e.animations){t=this.target()[a](),Array.isArray(t)||(t=[t]),Array.isArray(e.animations[a])||(e.animations[a]=[e.animations[a]]);for(var s=t.length;s--;)e.animations[a][s]instanceof i.Number&&(t[s]=new i.Number(t[s])),e.animations[a][s]=t[s].morph(e.animations[a][s])}for(var a in e.attrs)e.attrs[a]=new i.MorphObj(this.target().attr(a),e.attrs[a]);for(var a in e.styles)e.styles[a]=new i.MorphObj(this.target().style(a),e.styles[a]);return e.initialTransformation=this.target().matrixify(),e.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},after:function(t){var e=this.last();return this.target().on("finished.fx",(function i(a){a.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))})),this._callStart()},during:function(t){var e=this.last(),a=function(a){a.detail.situation==e&&t.call(this,a.detail.pos,i.morph(a.detail.pos),a.detail.eased,e)};return this.target().off("during.fx",a).on("during.fx",a),this.after((function(){this.off("during.fx",a)})),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){var e,i,a;t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops?(e=Math.max(this.absPos,0),i=Math.floor(e),!0===this.situation.loops||ithis.lastPos&&r<=s&&(this.situation.once[r].call(this.target(),this.pos,s),delete this.situation.once[r]);return this.active&&this.target().fire("during",{pos:this.pos,eased:s,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=s,this):this},eachAt:function(){var t,e=this,a=this.target(),s=this.situation;for(var r in s.animations)t=[].concat(s.animations[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),a[r].apply(a,t);for(var r in s.attrs)t=[r].concat(s.attrs[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),a.attr.apply(a,t);for(var r in s.styles)t=[r].concat(s.styles[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),a.style.apply(a,t);if(s.transforms.length){t=s.initialTransformation,r=0;for(var n=s.transforms.length;r=0;--a)this[m[a]]=null!=t[m[a]]?t[m[a]]:e[m[a]]},extend:{extract:function(){var t=f(this,0,1),e=(f(this,1,0),180/Math.PI*Math.atan2(t.y,t.x)-90);return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(e*Math.PI/180)+this.f*Math.sin(e*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(e*Math.PI/180)+this.e*Math.sin(-e*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),rotation:e,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new i.Matrix(this)}},clone:function(){return new i.Matrix(this)},morph:function(t){return this.destination=new i.Matrix(t),this},multiply:function(t){return new i.Matrix(this.native().multiply(function(t){return t instanceof i.Matrix||(t=new i.Matrix(t)),t}(t).native()))},inverse:function(){return new i.Matrix(this.native().inverse())},translate:function(t,e){return new i.Matrix(this.native().translate(t||0,e||0))},native:function(){for(var t=i.parser.native.createSVGMatrix(),e=m.length-1;e>=0;e--)t[m[e]]=this[m[e]];return t},toString:function(){return"matrix("+v(this.a)+","+v(this.b)+","+v(this.c)+","+v(this.d)+","+v(this.e)+","+v(this.f)+")"}},parent:i.Element,construct:{ctm:function(){return new i.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof i.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new i.Matrix(e)}return new i.Matrix(this.node.getScreenCTM())}}}),i.Point=i.invent({create:function(t,e){var i;i=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===r(t)?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:{x:0,y:0},this.x=i.x,this.y=i.y},extend:{clone:function(){return new i.Point(this)},morph:function(t,e){return this.destination=new i.Point(t,e),this}}}),i.extend(i.Element,{point:function(t,e){return new i.Point(t,e).transform(this.screenCTM().inverse())}}),i.extend(i.Element,{attr:function(t,e,a){if(null==t){for(t={},a=(e=this.node.attributes).length-1;a>=0;a--)t[e[a].nodeName]=i.regex.isNumber.test(e[a].nodeValue)?parseFloat(e[a].nodeValue):e[a].nodeValue;return t}if("object"===r(t))for(var s in t)this.attr(s,t[s]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?i.defaults.attrs[t]:i.regex.isNumber.test(e)?parseFloat(e):e;"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),"fill"!=t&&"stroke"!=t||(i.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof i.Image&&(e=this.doc().defs().pattern(0,0,(function(){this.add(e)})))),"number"==typeof e?e=new i.Number(e):i.Color.isColor(e)?e=new i.Color(e):Array.isArray(e)&&(e=new i.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof a?this.node.setAttributeNS(a,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),i.extend(i.Element,{transform:function(t,e){var a;return"object"!==r(t)?(a=new i.Matrix(this).extract(),"string"==typeof t?a[t]:a):(a=new i.Matrix(this),e=!!e||!!t.relative,null!=t.a&&(a=e?a.multiply(new i.Matrix(t)):new i.Matrix(t)),this.attr("transform",a))}}),i.extend(i.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(i.regex.transforms).slice(0,-1).map((function(t){var e=t.trim().split("(");return[e[0],e[1].split(i.regex.delimiter).map((function(t){return parseFloat(t)}))]})).reduce((function(t,e){return"matrix"==e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])}),new i.Matrix)},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),i.Transformation=i.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var i=0,a=this.arguments.length;i=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return i.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){for(var a=this.children(),s=0,r=a.length;s=0;a--)e.childNodes[a]instanceof t.SVGElement&&x(e.childNodes[a]);return i.adopt(e).id(i.eid(e.nodeName))}function b(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function v(t){return Math.abs(t)>1e-37?t:0}["fill","stroke"].forEach((function(t){var e={};e[t]=function(e){if(void 0===e)return this;if("string"==typeof e||i.Color.isRgb(e)||e&&"function"==typeof e.fill)this.attr(t,e);else for(var a=l[t].length-1;a>=0;a--)null!=e[l[t][a]]&&this.attr(l.prefix(t,l[t][a]),e[l[t][a]]);return this},i.extend(i.Element,i.FX,e)})),i.extend(i.Element,i.FX,{translate:function(t,e){return this.transform({x:t,y:e})},matrix:function(t){return this.attr("transform",new i.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new i.Number(t).plus(this instanceof i.FX?0:this.x()),!0)},dy:function(t){return this.y(new i.Number(t).plus(this instanceof i.FX?0:this.y()),!0)}}),i.extend(i.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return this.node.getPointAtLength(t)}}),i.Set=i.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){for(var t=[].slice.call(arguments),e=0,i=t.length;e-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members}},construct:{set:function(t){return new i.Set(t)}}}),i.FX.Set=i.invent({create:function(t){this.set=t}}),i.Set.inherit=function(){var t=[];for(var e in i.Shape.prototype)"function"==typeof i.Shape.prototype[e]&&"function"!=typeof i.Set.prototype[e]&&t.push(e);for(var e in t.forEach((function(t){i.Set.prototype[t]=function(){for(var e=0,a=this.members.length;e=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),i.get=function(t){var a=e.getElementById(function(t){var e=(t||"").toString().match(i.regex.reference);if(e)return e[1]}(t)||t);return i.adopt(a)},i.select=function(t,a){return new i.Set(i.utils.map((a||e).querySelectorAll(t),(function(t){return i.adopt(t)})))},i.extend(i.Parent,{select:function(t){return i.select(t,this.node)}});var m="abcdef".split("");if("function"!=typeof t.CustomEvent){var y=function(t,i){i=i||{bubbles:!1,cancelable:!1,detail:void 0};var a=e.createEvent("CustomEvent");return a.initCustomEvent(t,i.bubbles,i.cancelable,i.detail),a};y.prototype=t.Event.prototype,i.CustomEvent=y}else i.CustomEvent=t.CustomEvent;return i}(s,s.document)}.call(e,i,e,t),void 0===a||(t.exports=a)},539:(t,e,i)=>{(e=i(922)(!1)).push([t.id,'@keyframes opaque {\n 0% {\n opacity: 0\n }\n\n to {\n opacity: 1\n }\n}\n\n@keyframes resizeanim {\n 0%,to {\n opacity: 0\n }\n}\n\n.apexcharts-canvas {\n position: relative;\n user-select: none\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n -webkit-appearance: none;\n width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n border-radius: 4px;\n background-color: rgba(0,0,0,.5);\n box-shadow: 0 0 1px rgba(255,255,255,.5);\n -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)\n}\n\n.apexcharts-inner {\n position: relative\n}\n\n.apexcharts-text tspan {\n font-family: inherit\n}\n\n.legend-mouseover-inactive {\n transition: .15s ease all;\n opacity: .2\n}\n\n.apexcharts-legend-text {\n padding-left: 15px;\n margin-left: -15px;\n}\n\n.apexcharts-series-collapsed {\n opacity: 0\n}\n\n.apexcharts-tooltip {\n border-radius: 5px;\n box-shadow: 2px 2px 6px -4px #999;\n cursor: default;\n font-size: 14px;\n left: 62px;\n opacity: 0;\n pointer-events: none;\n position: absolute;\n top: 20px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n white-space: nowrap;\n z-index: 12;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n border: 1px solid #e3e3e3;\n background: rgba(255,255,255,.96)\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n color: #fff;\n background: rgba(30,30,30,.8)\n}\n\n.apexcharts-tooltip * {\n font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n padding: 6px;\n font-size: 15px;\n margin-bottom: 4px\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {\n background: #eceff1;\n border-bottom: 1px solid #ddd\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n background: rgba(0,0,0,.7);\n border-bottom: 1px solid #333\n}\n\n.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {\n display: inline-block;\n margin-left: 5px;\n font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {\n display: none\n}\n\n.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {\n margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n width: 12px;\n height: 12px;\n position: relative;\n top: 0;\n margin-right: 10px;\n border-radius: 50%\n}\n\n.apexcharts-tooltip-series-group {\n padding: 0 10px;\n display: none;\n text-align: left;\n justify-content: left;\n align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {\n padding-bottom: 4px\n}\n\n.apexcharts-tooltip-series-group-hidden {\n opacity: 0;\n height: 0;\n line-height: 0;\n padding: 0!important\n}\n\n.apexcharts-tooltip-y-group {\n padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,.apexcharts-tooltip-box {\n padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n display: flex;\n flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_boundingRect,.svg_select_points_rot {\n pointer-events: none;\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {\n cursor: ew-resize;\n opacity: 1;\n visibility: visible\n}\n\n.svg_select_points {\n fill: #efefef;\n stroke: #333;\n rx: 2\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0,0,0,.7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {\n opacity: 0\n}\n\n.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-legend {\t\n display: flex;\t\n overflow: auto;\t\n padding: 0 10px;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\t\n flex-wrap: wrap\t\n}\t\n.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n flex-direction: column;\t\n bottom: 0;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n justify-content: flex-start;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\t\n justify-content: center; \t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\t\n justify-content: flex-end;\t\n}\t\n.apexcharts-legend-series {\t\n cursor: pointer;\t\n line-height: normal;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{\t\n display: flex;\t\n align-items: center;\t\n}\t\n.apexcharts-legend-text {\t\n position: relative;\t\n font-size: 14px;\t\n}\t\n.apexcharts-legend-text *, .apexcharts-legend-marker * {\t\n pointer-events: none;\t\n}\t\n.apexcharts-legend-marker {\t\n position: relative;\t\n display: inline-block;\t\n cursor: pointer;\t\n margin-right: 3px;\t\n border-style: solid;\n}\t\n \n.apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{\t\n display: inline-block;\t\n}\t\n.apexcharts-legend-series.apexcharts-no-click {\t\n cursor: auto;\t\n}\t\n.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\t\n display: none !important;\t\n}\t\n.apexcharts-inactive-legend {\t\n opacity: 0.45;\t\n}\n\n.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {\n pointer-events: none\n}\n\n.apexcharts-marker {\n transition: .15s ease all\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,.resize-triggers,.resize-triggers>div {\n content: " ";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n',""]),t.exports=e},274:(t,e,i)=>{var a=i(379),s=i(539);"string"==typeof(s=s.__esModule?s.default:s)&&(s=[[t.id,s,""]]);var r=(a(t.id,s,{insert:"head",singleton:!1}),s.locals?s.locals:{});t.exports=r},379:(t,e,i)=>{"use strict";var a,s=function(){var t={};return function(e){if(void 0===t[e]){var i=document.querySelector(e);if(window.HTMLIFrameElement&&i instanceof window.HTMLIFrameElement)try{i=i.contentDocument.head}catch(t){i=null}t[e]=i}return t[e]}}(),r={};function n(t,e,i){for(var a=0;a{t.exports=''},355:t=>{t.exports=''},686:t=>{t.exports=''},798:t=>{t.exports=''},323:t=>{t.exports=''},618:t=>{t.exports=''},688:t=>{t.exports=''}},e={};function i(a){if(e[a])return e[a].exports;var s=e[a]={id:a,exports:{}};return t[a].call(s.exports,s,s.exports,i),s.exports}return i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var a in e)i.o(e,a)&&!i.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:e[a]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i(978)})()})); ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/apexcharts.common.js ================================================ /*! * ApexCharts v3.37.1 * (c) 2018-2023 ApexCharts * Released under the MIT License. */ "use strict";function t(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function e(e){for(var i=1;it.length)&&(e=t.length);for(var i=0,a=new Array(e);i>16,o=i>>8&255,n=255&i;return"#"+(16777216+65536*(Math.round((a-r)*s)+r)+256*(Math.round((a-o)*s)+o)+(Math.round((a-n)*s)+n)).toString(16).slice(1)}},{key:"shadeColor",value:function(e,i){return t.isColorHex(i)?this.shadeHexColor(e,i):this.shadeRGBColor(e,i)}}],[{key:"bind",value:function(t,e){return function(){return t.apply(e,arguments)}}},{key:"isObject",value:function(t){return t&&"object"===i(t)&&!Array.isArray(t)&&null!=t}},{key:"is",value:function(t,e){return Object.prototype.toString.call(e)==="[object "+t+"]"}},{key:"listToArray",value:function(t){var e,i=[];for(e=0;ee.length?t:e}))),t.length>e.length?t:e}),0)}},{key:"hexToRgba",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"#999999",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.6;"#"!==t.substring(0,1)&&(t="#999999");var i=t.replace("#","");i=i.match(new RegExp("(.{"+i.length/3+"})","g"));for(var a=0;a1&&void 0!==arguments[1]?arguments[1]:"x",i=t.toString().slice();return i=i.replace(/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi,e)}},{key:"negToZero",value:function(t){return t<0?0:t}},{key:"moveIndexInArray",value:function(t,e,i){if(i>=t.length)for(var a=i-t.length+1;a--;)t.push(void 0);return t.splice(i,0,t.splice(e,1)[0]),t}},{key:"extractNumber",value:function(t){return parseFloat(t.replace(/[^\d.]*/g,""))}},{key:"findAncestor",value:function(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t}},{key:"setELstyles",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t.style.key=e[i])}},{key:"isNumber",value:function(t){return!isNaN(t)&&parseFloat(Number(t))===t&&!isNaN(parseInt(t,10))}},{key:"isFloat",value:function(t){return Number(t)===t&&t%1!=0}},{key:"isSafari",value:function(){return/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}},{key:"isFirefox",value:function(){return navigator.userAgent.toLowerCase().indexOf("firefox")>-1}},{key:"isIE11",value:function(){if(-1!==window.navigator.userAgent.indexOf("MSIE")||window.navigator.appVersion.indexOf("Trident/")>-1)return!0}},{key:"isIE",value:function(){var t=window.navigator.userAgent,e=t.indexOf("MSIE ");if(e>0)return parseInt(t.substring(e+5,t.indexOf(".",e)),10);if(t.indexOf("Trident/")>0){var i=t.indexOf("rv:");return parseInt(t.substring(i+3,t.indexOf(".",i)),10)}var a=t.indexOf("Edge/");return a>0&&parseInt(t.substring(a+5,t.indexOf(".",a)),10)}}]),t}(),b=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.setEasingFunctions()}return r(t,[{key:"setEasingFunctions",value:function(){var t;if(!this.w.globals.easing){switch(this.w.config.chart.animations.easing){case"linear":t="-";break;case"easein":t="<";break;case"easeout":t=">";break;case"easeinout":default:t="<>";break;case"swing":t=function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1};break;case"bounce":t=function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375};break;case"elastic":t=function(t){return t===!!t?t:Math.pow(2,-10*t)*Math.sin((t-.075)*(2*Math.PI)/.3)+1}}this.w.globals.easing=t}}},{key:"animateLine",value:function(t,e,i,a){t.attr(e).animate(a).attr(i)}},{key:"animateMarker",value:function(t,e,i,a,s,r){e||(e=0),t.attr({r:e,width:e,height:e}).animate(a,s).attr({r:i,width:i.width,height:i.height}).afterAll((function(){r()}))}},{key:"animateCircle",value:function(t,e,i,a,s){t.attr({r:e.r,cx:e.cx,cy:e.cy}).animate(a,s).attr({r:i.r,cx:i.cx,cy:i.cy})}},{key:"animateRect",value:function(t,e,i,a,s){t.attr(e).animate(a).attr(i).afterAll((function(){return s()}))}},{key:"animatePathsGradually",value:function(t){var e=t.el,i=t.realIndex,a=t.j,s=t.fill,r=t.pathFrom,o=t.pathTo,n=t.speed,l=t.delay,h=this.w,c=0;h.config.chart.animations.animateGradually.enabled&&(c=h.config.chart.animations.animateGradually.delay),h.config.chart.animations.dynamicAnimation.enabled&&h.globals.dataChanged&&"bar"!==h.config.chart.type&&(c=0),this.morphSVG(e,i,a,"line"!==h.config.chart.type||h.globals.comboCharts?s:"stroke",r,o,n,l*c)}},{key:"showDelayedElements",value:function(){this.w.globals.delayedElements.forEach((function(t){t.el.classList.remove("apexcharts-element-hidden")}))}},{key:"animationCompleted",value:function(t){var e=this.w;e.globals.animationEnded||(e.globals.animationEnded=!0,this.showDelayedElements(),"function"==typeof e.config.chart.events.animationEnd&&e.config.chart.events.animationEnd(this.ctx,{el:t,w:e}))}},{key:"morphSVG",value:function(t,e,i,a,s,r,o,n){var l=this,h=this.w;s||(s=t.attr("pathFrom")),r||(r=t.attr("pathTo"));var c=function(t){return"radar"===h.config.chart.type&&(o=1),"M 0 ".concat(h.globals.gridHeight)};(!s||s.indexOf("undefined")>-1||s.indexOf("NaN")>-1)&&(s=c()),(!r||r.indexOf("undefined")>-1||r.indexOf("NaN")>-1)&&(r=c()),h.globals.shouldAnimate||(o=1),t.plot(s).animate(1,h.globals.easing,n).plot(s).animate(o,h.globals.easing,n).plot(r).afterAll((function(){x.isNumber(i)?i===h.globals.series[h.globals.maxValsInArrayIndex].length-2&&h.globals.shouldAnimate&&l.animationCompleted(t):"none"!==a&&h.globals.shouldAnimate&&(!h.globals.comboCharts&&e===h.globals.series.length-1||h.globals.comboCharts)&&l.animationCompleted(t),l.showDelayedElements()}))}}]),t}(),v=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"getDefaultFilter",value:function(t,e){var i=this.w;t.unfilter(!0),(new window.SVG.Filter).size("120%","180%","-5%","-40%"),"none"!==i.config.states.normal.filter?this.applyFilter(t,e,i.config.states.normal.filter.type,i.config.states.normal.filter.value):i.config.chart.dropShadow.enabled&&this.dropShadow(t,i.config.chart.dropShadow,e)}},{key:"addNormalFilter",value:function(t,e){var i=this.w;i.config.chart.dropShadow.enabled&&!t.node.classList.contains("apexcharts-marker")&&this.dropShadow(t,i.config.chart.dropShadow,e)}},{key:"addLightenFilter",value:function(t,e,i){var a=this,s=this.w,r=i.intensity;t.unfilter(!0);new window.SVG.Filter;t.filter((function(t){var i=s.config.chart.dropShadow;(i.enabled?a.addShadow(t,e,i):t).componentTransfer({rgb:{type:"linear",slope:1.5,intercept:r}})})),t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)}},{key:"addDarkenFilter",value:function(t,e,i){var a=this,s=this.w,r=i.intensity;t.unfilter(!0);new window.SVG.Filter;t.filter((function(t){var i=s.config.chart.dropShadow;(i.enabled?a.addShadow(t,e,i):t).componentTransfer({rgb:{type:"linear",slope:r}})})),t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)}},{key:"applyFilter",value:function(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:.5;switch(i){case"none":this.addNormalFilter(t,e);break;case"lighten":this.addLightenFilter(t,e,{intensity:a});break;case"darken":this.addDarkenFilter(t,e,{intensity:a})}}},{key:"addShadow",value:function(t,e,i){var a=i.blur,s=i.top,r=i.left,o=i.color,n=i.opacity,l=t.flood(Array.isArray(o)?o[e]:o,n).composite(t.sourceAlpha,"in").offset(r,s).gaussianBlur(a).merge(t.source);return t.blend(t.source,l)}},{key:"dropShadow",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=e.top,s=e.left,r=e.blur,o=e.color,n=e.opacity,l=e.noUserSpaceOnUse,h=this.w;return t.unfilter(!0),x.isIE()&&"radialBar"===h.config.chart.type||(o=Array.isArray(o)?o[i]:o,t.filter((function(t){var e=null;e=x.isSafari()||x.isFirefox()||x.isIE()?t.flood(o,n).composite(t.sourceAlpha,"in").offset(s,a).gaussianBlur(r):t.flood(o,n).composite(t.sourceAlpha,"in").offset(s,a).gaussianBlur(r).merge(t.source),t.blend(t.source,e)})),l||t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)),t}},{key:"setSelectionFilter",value:function(t,e,i){var a=this.w;if(void 0!==a.globals.selectedDataPoints[e]&&a.globals.selectedDataPoints[e].indexOf(i)>-1){t.node.setAttribute("selected",!0);var s=a.config.states.active.filter;"none"!==s&&this.applyFilter(t,e,s.type,s.value)}}},{key:"_scaleFilterSize",value:function(t){!function(e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}({width:"200%",height:"200%",x:"-50%",y:"-50%"})}}]),t}(),m=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"roundPathCorners",value:function(t,e){function i(t,e,i){var s=e.x-t.x,r=e.y-t.y,o=Math.sqrt(s*s+r*r);return a(t,e,Math.min(1,i/o))}function a(t,e,i){return{x:t.x+(e.x-t.x)*i,y:t.y+(e.y-t.y)*i}}function s(t,e){t.length>2&&(t[t.length-2]=e.x,t[t.length-1]=e.y)}function r(t){return{x:parseFloat(t[t.length-2]),y:parseFloat(t[t.length-1])}}var o=t.split(/[,\s]/).reduce((function(t,e){var i=e.match("([a-zA-Z])(.+)");return i?(t.push(i[1]),t.push(i[2])):t.push(e),t}),[]).reduce((function(t,e){return parseFloat(e)==e&&t.length?t[t.length-1].push(e):t.push([e]),t}),[]),n=[];if(o.length>1){var l=r(o[0]),h=null;"Z"==o[o.length-1][0]&&o[0].length>2&&(h=["L",l.x,l.y],o[o.length-1]=h),n.push(o[0]);for(var c=1;c2&&"L"==g[0]&&u.length>2&&"L"==u[0]){var f,p,x=r(d),b=r(g),v=r(u);f=i(b,x,e),p=i(b,v,e),s(g,f),g.origPoint=b,n.push(g);var m=a(f,b,.5),y=a(b,p,.5),w=["C",m.x,m.y,y.x,y.y,p.x,p.y];w.origPoint=b,n.push(w)}else n.push(g)}if(h){var k=r(n[n.length-1]);n.push(["Z"]),s(n[0],k)}}else n=o;return n.reduce((function(t,e){return t+e.join(" ")+" "}),"")}},{key:"drawLine",value:function(t,e,i,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"#a8a8a8",r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,o=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,n=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"butt",l=this.w,h=l.globals.dom.Paper.line().attr({x1:t,y1:e,x2:i,y2:a,stroke:s,"stroke-dasharray":r,"stroke-width":o,"stroke-linecap":n});return h}},{key:"drawRect",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"#fefefe",o=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1,n=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,l=arguments.length>8&&void 0!==arguments[8]?arguments[8]:null,h=arguments.length>9&&void 0!==arguments[9]?arguments[9]:0,c=this.w,d=c.globals.dom.Paper.rect();return d.attr({x:t,y:e,width:i>0?i:0,height:a>0?a:0,rx:s,ry:s,opacity:o,"stroke-width":null!==n?n:0,stroke:null!==l?l:"none","stroke-dasharray":h}),d.node.setAttribute("fill",r),d}},{key:"drawPolygon",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"#e1e1e1",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"none",s=this.w,r=s.globals.dom.Paper.polygon(t).attr({fill:a,stroke:e,"stroke-width":i});return r}},{key:"drawCircle",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.w;t<0&&(t=0);var a=i.globals.dom.Paper.circle(2*t);return null!==e&&a.attr(e),a}},{key:"drawPath",value:function(t){var e=t.d,i=void 0===e?"":e,a=t.stroke,s=void 0===a?"#a8a8a8":a,r=t.strokeWidth,o=void 0===r?1:r,n=t.fill,l=t.fillOpacity,h=void 0===l?1:l,c=t.strokeOpacity,d=void 0===c?1:c,g=t.classes,u=t.strokeLinecap,f=void 0===u?null:u,p=t.strokeDashArray,x=void 0===p?0:p,b=this.w;return null===f&&(f=b.config.stroke.lineCap),(i.indexOf("undefined")>-1||i.indexOf("NaN")>-1)&&(i="M 0 ".concat(b.globals.gridHeight)),b.globals.dom.Paper.path(i).attr({fill:n,"fill-opacity":h,stroke:s,"stroke-opacity":d,"stroke-linecap":f,"stroke-width":o,"stroke-dasharray":x,class:g})}},{key:"group",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w,i=e.globals.dom.Paper.group();return null!==t&&i.attr(t),i}},{key:"move",value:function(t,e){var i=["M",t,e].join(" ");return i}},{key:"line",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=null;return null===i?a=[" L",t,e].join(" "):"H"===i?a=[" H",t].join(" "):"V"===i&&(a=[" V",e].join(" ")),a}},{key:"curve",value:function(t,e,i,a,s,r){var o=["C",t,e,i,a,s,r].join(" ");return o}},{key:"quadraticCurve",value:function(t,e,i,a){return["Q",t,e,i,a].join(" ")}},{key:"arc",value:function(t,e,i,a,s,r,o){var n=arguments.length>7&&void 0!==arguments[7]&&arguments[7],l="A";n&&(l="a");var h=[l,t,e,i,a,s,r,o].join(" ");return h}},{key:"renderPaths",value:function(t){var i,a=t.j,s=t.realIndex,r=t.pathFrom,o=t.pathTo,n=t.stroke,l=t.strokeWidth,h=t.strokeLinecap,c=t.fill,d=t.animationDelay,g=t.initialSpeed,u=t.dataChangeSpeed,f=t.className,p=t.shouldClipToGrid,x=void 0===p||p,m=t.bindEventsOnPaths,y=void 0===m||m,w=t.drawShadow,k=void 0===w||w,A=this.w,S=new v(this.ctx),C=new b(this.ctx),L=this.w.config.chart.animations.enabled,P=L&&this.w.config.chart.animations.dynamicAnimation.enabled,T=!!(L&&!A.globals.resized||P&&A.globals.dataChanged&&A.globals.shouldAnimate);T?i=r:(i=o,A.globals.animationEnded=!0);var M=A.config.stroke.dashArray,I=0;I=Array.isArray(M)?M[s]:A.config.stroke.dashArray;var z=this.drawPath({d:i,stroke:n,strokeWidth:l,fill:c,fillOpacity:1,classes:f,strokeLinecap:h,strokeDashArray:I});if(z.attr("index",s),x&&z.attr({"clip-path":"url(#gridRectMask".concat(A.globals.cuid,")")}),"none"!==A.config.states.normal.filter.type)S.getDefaultFilter(z,s);else if(A.config.chart.dropShadow.enabled&&k&&(!A.config.chart.dropShadow.enabledOnSeries||A.config.chart.dropShadow.enabledOnSeries&&-1!==A.config.chart.dropShadow.enabledOnSeries.indexOf(s))){var X=A.config.chart.dropShadow;S.dropShadow(z,X,s)}y&&(z.node.addEventListener("mouseenter",this.pathMouseEnter.bind(this,z)),z.node.addEventListener("mouseleave",this.pathMouseLeave.bind(this,z)),z.node.addEventListener("mousedown",this.pathMouseDown.bind(this,z))),z.attr({pathTo:o,pathFrom:r});var E={el:z,j:a,realIndex:s,pathFrom:r,pathTo:o,fill:c,strokeWidth:l,delay:d};return!L||A.globals.resized||A.globals.dataChanged?!A.globals.resized&&A.globals.dataChanged||C.showDelayedElements():C.animatePathsGradually(e(e({},E),{},{speed:g})),A.globals.dataChanged&&P&&T&&C.animatePathsGradually(e(e({},E),{},{speed:u})),z}},{key:"drawPattern",value:function(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"#a8a8a8",s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=this.w,o=r.globals.dom.Paper.pattern(e,i,(function(r){"horizontalLines"===t?r.line(0,0,i,0).stroke({color:a,width:s+1}):"verticalLines"===t?r.line(0,0,0,e).stroke({color:a,width:s+1}):"slantedLines"===t?r.line(0,0,e,i).stroke({color:a,width:s}):"squares"===t?r.rect(e,i).fill("none").stroke({color:a,width:s}):"circles"===t&&r.circle(e).fill("none").stroke({color:a,width:s})}));return o}},{key:"drawGradient",value:function(t,e,i,a,s){var r,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,n=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,l=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,h=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0,c=this.w;e.length<9&&0===e.indexOf("#")&&(e=x.hexToRgba(e,a)),i.length<9&&0===i.indexOf("#")&&(i=x.hexToRgba(i,s));var d=0,g=1,u=1,f=null;null!==n&&(d=void 0!==n[0]?n[0]/100:0,g=void 0!==n[1]?n[1]/100:1,u=void 0!==n[2]?n[2]/100:1,f=void 0!==n[3]?n[3]/100:null);var p=!("donut"!==c.config.chart.type&&"pie"!==c.config.chart.type&&"polarArea"!==c.config.chart.type&&"bubble"!==c.config.chart.type);if(r=null===l||0===l.length?c.globals.dom.Paper.gradient(p?"radial":"linear",(function(t){t.at(d,e,a),t.at(g,i,s),t.at(u,i,s),null!==f&&t.at(f,e,a)})):c.globals.dom.Paper.gradient(p?"radial":"linear",(function(t){(Array.isArray(l[h])?l[h]:l).forEach((function(e){t.at(e.offset/100,e.color,e.opacity)}))})),p){var b=c.globals.gridWidth/2,v=c.globals.gridHeight/2;"bubble"!==c.config.chart.type?r.attr({gradientUnits:"userSpaceOnUse",cx:b,cy:v,r:o}):r.attr({cx:.5,cy:.5,r:.8,fx:.2,fy:.2})}else"vertical"===t?r.from(0,0).to(0,1):"diagonal"===t?r.from(0,0).to(1,1):"horizontal"===t?r.from(0,1).to(1,1):"diagonal2"===t&&r.from(1,0).to(0,1);return r}},{key:"getTextBasedOnMaxWidth",value:function(t){var e=t.text,i=t.maxWidth,a=t.fontSize,s=t.fontFamily,r=this.getTextRects(e,a,s),o=r.width/e.length,n=Math.floor(i/o);return i-1){var n=i.globals.selectedDataPoints[s].indexOf(r);i.globals.selectedDataPoints[s].splice(n,1)}}else{if(!i.config.states.active.allowMultipleDataPointsSelection&&i.globals.selectedDataPoints.length>0){i.globals.selectedDataPoints=[];var l=i.globals.dom.Paper.select(".apexcharts-series path").members,h=i.globals.dom.Paper.select(".apexcharts-series circle, .apexcharts-series rect").members,c=function(t){Array.prototype.forEach.call(t,(function(t){t.node.setAttribute("selected","false"),a.getDefaultFilter(t,s)}))};c(l),c(h)}t.node.setAttribute("selected","true"),o="true",void 0===i.globals.selectedDataPoints[s]&&(i.globals.selectedDataPoints[s]=[]),i.globals.selectedDataPoints[s].push(r)}if("true"===o){var d=i.config.states.active.filter;if("none"!==d)a.applyFilter(t,s,d.type,d.value);else if("none"!==i.config.states.hover.filter&&!i.globals.isTouchDevice){var g=i.config.states.hover.filter;a.applyFilter(t,s,g.type,g.value)}}else if("none"!==i.config.states.active.filter.type)if("none"===i.config.states.hover.filter.type||i.globals.isTouchDevice)a.getDefaultFilter(t,s);else{g=i.config.states.hover.filter;a.applyFilter(t,s,g.type,g.value)}"function"==typeof i.config.chart.events.dataPointSelection&&i.config.chart.events.dataPointSelection(e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}),e&&this.ctx.events.fireEvent("dataPointSelection",[e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}])}},{key:"rotateAroundCenter",value:function(t){var e={};return t&&"function"==typeof t.getBBox&&(e=t.getBBox()),{x:e.x+e.width/2,y:e.y+e.height/2}}},{key:"getTextRects",value:function(t,e,i,a){var s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],r=this.w,o=this.drawText({x:-200,y:-200,text:t,textAnchor:"start",fontSize:e,fontFamily:i,foreColor:"#fff",opacity:0});a&&o.attr("transform",a),r.globals.dom.Paper.add(o);var n=o.bbox();return s||(n=o.node.getBoundingClientRect()),o.remove(),{width:n.width,height:n.height}}},{key:"placeTextWithEllipsis",value:function(t,e,i){if("function"==typeof t.getComputedTextLength&&(t.textContent=e,e.length>0&&t.getComputedTextLength()>=i/1.1)){for(var a=e.length-3;a>0;a-=3)if(t.getSubStringLength(0,a)<=i/1.1)return void(t.textContent=e.substring(0,a)+"...");t.textContent="."}}}],[{key:"setAttrs",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}}]),t}(),y=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"getStackedSeriesTotals",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=this.w,i=[];if(0===e.globals.series.length)return i;for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:null;return null===t?this.w.config.series.reduce((function(t,e){return t+e}),0):this.w.globals.series[t].reduce((function(t,e){return t+e}),0)}},{key:"isSeriesNull",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return 0===(null===t?this.w.config.series.filter((function(t){return null!==t})):this.w.config.series[t].data.filter((function(t){return null!==t}))).length}},{key:"seriesHaveSameValues",value:function(t){return this.w.globals.series[t].every((function(t,e,i){return t===i[0]}))}},{key:"getCategoryLabels",value:function(t){var e=this.w,i=t.slice();return e.config.xaxis.convertedCatToNumeric&&(i=t.map((function(t,i){return e.config.xaxis.labels.formatter(t-e.globals.minX+1)}))),i}},{key:"getLargestSeries",value:function(){var t=this.w;t.globals.maxValsInArrayIndex=t.globals.series.map((function(t){return t.length})).indexOf(Math.max.apply(Math,t.globals.series.map((function(t){return t.length}))))}},{key:"getLargestMarkerSize",value:function(){var t=this.w,e=0;return t.globals.markers.size.forEach((function(t){e=Math.max(e,t)})),t.config.markers.discrete&&t.config.markers.discrete.length&&t.config.markers.discrete.forEach((function(t){e=Math.max(e,t.size)})),e>0&&(e+=t.config.markers.hover.sizeOffset+1),t.globals.markers.largestSize=e,e}},{key:"getSeriesTotals",value:function(){var t=this.w;t.globals.seriesTotals=t.globals.series.map((function(t,e){var i=0;if(Array.isArray(t))for(var a=0;at&&i.globals.seriesX[s][o]0&&(e=!0),{comboBarCount:i,comboCharts:e}}},{key:"extendArrayProps",value:function(t,e,i){return e.yaxis&&(e=t.extendYAxis(e,i)),e.annotations&&(e.annotations.yaxis&&(e=t.extendYAxisAnnotations(e)),e.annotations.xaxis&&(e=t.extendXAxisAnnotations(e)),e.annotations.points&&(e=t.extendPointAnnotations(e))),e}}]),t}(),w=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e}return r(t,[{key:"setOrientations",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.w;if("vertical"===t.label.orientation){var a=null!==e?e:0,s=i.globals.dom.baseEl.querySelector(".apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='".concat(a,"']"));if(null!==s){var r=s.getBoundingClientRect();s.setAttribute("x",parseFloat(s.getAttribute("x"))-r.height+4),"top"===t.label.position?s.setAttribute("y",parseFloat(s.getAttribute("y"))+r.width):s.setAttribute("y",parseFloat(s.getAttribute("y"))-r.width);var o=this.annoCtx.graphics.rotateAroundCenter(s),n=o.x,l=o.y;s.setAttribute("transform","rotate(-90 ".concat(n," ").concat(l,")"))}}}},{key:"addBackgroundToAnno",value:function(t,e){var i=this.w;if(!t||void 0===e.label.text||void 0!==e.label.text&&!String(e.label.text).trim())return null;var a=i.globals.dom.baseEl.querySelector(".apexcharts-grid").getBoundingClientRect(),s=t.getBoundingClientRect(),r=e.label.style.padding.left,o=e.label.style.padding.right,n=e.label.style.padding.top,l=e.label.style.padding.bottom;"vertical"===e.label.orientation&&(n=e.label.style.padding.left,l=e.label.style.padding.right,r=e.label.style.padding.top,o=e.label.style.padding.bottom);var h=s.left-a.left-r,c=s.top-a.top-n,d=this.annoCtx.graphics.drawRect(h-i.globals.barPadForNumericAxis,c,s.width+r+o,s.height+n+l,e.label.borderRadius,e.label.style.background,1,e.label.borderWidth,e.label.borderColor,0);return e.id&&d.node.classList.add(e.id),d}},{key:"annotationsBackground",value:function(){var t=this,e=this.w,i=function(i,a,s){var r=e.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(a,"']"));if(r){var o=r.parentNode,n=t.addBackgroundToAnno(r,i);n&&(o.insertBefore(n.node,r),i.label.mouseEnter&&n.node.addEventListener("mouseenter",i.label.mouseEnter.bind(t,i)),i.label.mouseLeave&&n.node.addEventListener("mouseleave",i.label.mouseLeave.bind(t,i)),i.label.click&&n.node.addEventListener("click",i.label.click.bind(t,i)))}};e.config.annotations.xaxis.map((function(t,e){i(t,e,"xaxis")})),e.config.annotations.yaxis.map((function(t,e){i(t,e,"yaxis")})),e.config.annotations.points.map((function(t,e){i(t,e,"point")}))}},{key:"getY1Y2",value:function(t,e){var i,a="y1"===t?e.y:e.y2,s=this.w;if(this.annoCtx.invertAxis){var r=s.globals.labels.indexOf(a);s.config.xaxis.convertedCatToNumeric&&(r=s.globals.categoryLabels.indexOf(a));var o=s.globals.dom.baseEl.querySelector(".apexcharts-yaxis-texts-g text:nth-child("+(r+1)+")");o&&(i=parseFloat(o.getAttribute("y")))}else{var n;if(s.config.yaxis[e.yAxisIndex].logarithmic)n=(a=new y(this.annoCtx.ctx).getLogVal(a,e.yAxisIndex))/s.globals.yLogRatio[e.yAxisIndex];else n=(a-s.globals.minYArr[e.yAxisIndex])/(s.globals.yRange[e.yAxisIndex]/s.globals.gridHeight);i=s.globals.gridHeight-n,!e.marker||void 0!==e.y&&null!==e.y||(i=0),s.config.yaxis[e.yAxisIndex]&&s.config.yaxis[e.yAxisIndex].reversed&&(i=n)}return"string"==typeof a&&a.indexOf("px")>-1&&(i=parseFloat(a)),i}},{key:"getX1X2",value:function(t,e){var i=this.w,a=this.annoCtx.invertAxis?i.globals.minY:i.globals.minX,s=this.annoCtx.invertAxis?i.globals.maxY:i.globals.maxX,r=this.annoCtx.invertAxis?i.globals.yRange[0]:i.globals.xRange,o=(e.x-a)/(r/i.globals.gridWidth);this.annoCtx.inversedReversedAxis&&(o=(s-e.x)/(r/i.globals.gridWidth)),"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric||this.annoCtx.invertAxis||i.globals.dataFormatXNumeric||(o=this.getStringX(e.x));var n=(e.x2-a)/(r/i.globals.gridWidth);return this.annoCtx.inversedReversedAxis&&(n=(s-e.x2)/(r/i.globals.gridWidth)),"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric||this.annoCtx.invertAxis||i.globals.dataFormatXNumeric||(n=this.getStringX(e.x2)),void 0!==e.x&&null!==e.x||!e.marker||(o=i.globals.gridWidth),"x1"===t&&"string"==typeof e.x&&e.x.indexOf("px")>-1&&(o=parseFloat(e.x)),"x2"===t&&"string"==typeof e.x2&&e.x2.indexOf("px")>-1&&(n=parseFloat(e.x2)),"x1"===t?o:n}},{key:"getStringX",value:function(t){var e=this.w,i=t;e.config.xaxis.convertedCatToNumeric&&e.globals.categoryLabels.length&&(t=e.globals.categoryLabels.indexOf(t)+1);var a=e.globals.labels.indexOf(t),s=e.globals.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g text:nth-child("+(a+1)+")");return s&&(i=parseFloat(s.getAttribute("x"))),i}}]),t}(),k=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e,this.invertAxis=this.annoCtx.invertAxis,this.helpers=new w(this.annoCtx)}return r(t,[{key:"addXaxisAnnotation",value:function(t,e,i){var a,s=this.w,r=this.helpers.getX1X2("x1",t),o=t.label.text,n=t.strokeDashArray;if(x.isNumber(r)){if(null===t.x2||void 0===t.x2){var l=this.annoCtx.graphics.drawLine(r+t.offsetX,0+t.offsetY,r+t.offsetX,s.globals.gridHeight+t.offsetY,t.borderColor,n,t.borderWidth);e.appendChild(l.node),t.id&&l.node.classList.add(t.id)}else{if((a=this.helpers.getX1X2("x2",t))o){var h=o;o=a,a=h}var c=this.annoCtx.graphics.drawRect(0+t.offsetX,a+t.offsetY,this._getYAxisAnnotationWidth(t),o-a,0,t.fillColor,t.opacity,1,t.borderColor,r);c.node.classList.add("apexcharts-annotation-rect"),c.attr("clip-path","url(#gridRectMask".concat(s.globals.cuid,")")),e.appendChild(c.node),t.id&&c.node.classList.add(t.id)}var d="right"===t.label.position?s.globals.gridWidth:"center"===t.label.position?s.globals.gridWidth/2:0,g=this.annoCtx.graphics.drawText({x:d+t.label.offsetX,y:(null!=a?a:o)+t.label.offsetY-3,text:n,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-yaxis-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});g.attr({rel:i}),e.appendChild(g.node)}},{key:"_getYAxisAnnotationWidth",value:function(t){var e=this.w;e.globals.gridWidth;return(t.width.indexOf("%")>-1?e.globals.gridWidth*parseInt(t.width,10)/100:parseInt(t.width,10))+t.offsetX}},{key:"drawYAxisAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-yaxis-annotations"});return e.config.annotations.yaxis.map((function(e,a){t.addYaxisAnnotation(e,i.node,a)})),i}}]),t}(),S=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e,this.helpers=new w(this.annoCtx)}return r(t,[{key:"addPointAnnotation",value:function(t,e,i){this.w;var a=this.helpers.getX1X2("x1",t),s=this.helpers.getY1Y2("y1",t);if(x.isNumber(a)){var r={pSize:t.marker.size,pointStrokeWidth:t.marker.strokeWidth,pointFillColor:t.marker.fillColor,pointStrokeColor:t.marker.strokeColor,shape:t.marker.shape,pRadius:t.marker.radius,class:"apexcharts-point-annotation-marker ".concat(t.marker.cssClass," ").concat(t.id?t.id:"")},o=this.annoCtx.graphics.drawMarker(a+t.marker.offsetX,s+t.marker.offsetY,r);e.appendChild(o.node);var n=t.label.text?t.label.text:"",l=this.annoCtx.graphics.drawText({x:a+t.label.offsetX,y:s+t.label.offsetY-t.marker.size-parseFloat(t.label.style.fontSize)/1.6,text:n,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-point-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});if(l.attr({rel:i}),e.appendChild(l.node),t.customSVG.SVG){var h=this.annoCtx.graphics.group({class:"apexcharts-point-annotations-custom-svg "+t.customSVG.cssClass});h.attr({transform:"translate(".concat(a+t.customSVG.offsetX,", ").concat(s+t.customSVG.offsetY,")")}),h.node.innerHTML=t.customSVG.SVG,e.appendChild(h.node)}if(t.image.path){var c=t.image.width?t.image.width:20,d=t.image.height?t.image.height:20;o=this.annoCtx.addImage({x:a+t.image.offsetX-c/2,y:s+t.image.offsetY-d/2,width:c,height:d,path:t.image.path,appendTo:".apexcharts-point-annotations"})}t.mouseEnter&&o.node.addEventListener("mouseenter",t.mouseEnter.bind(this,t)),t.mouseLeave&&o.node.addEventListener("mouseleave",t.mouseLeave.bind(this,t)),t.click&&o.node.addEventListener("click",t.click.bind(this,t))}}},{key:"drawPointAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-point-annotations"});return e.config.annotations.points.map((function(e,a){t.addPointAnnotation(e,i.node,a)})),i}}]),t}();var C={name:"en",options:{months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],toolbar:{exportToSVG:"Download SVG",exportToPNG:"Download PNG",exportToCSV:"Download CSV",menu:"Menu",selection:"Selection",selectionZoom:"Selection Zoom",zoomIn:"Zoom In",zoomOut:"Zoom Out",pan:"Panning",reset:"Reset Zoom"}}},L=function(){function t(){a(this,t),this.yAxis={show:!0,showAlways:!1,showForNullSeries:!0,seriesName:void 0,opposite:!1,reversed:!1,logarithmic:!1,logBase:10,tickAmount:void 0,forceNiceScale:!1,max:void 0,min:void 0,floating:!1,decimalsInFloat:void 0,labels:{show:!0,minWidth:0,maxWidth:160,offsetX:0,offsetY:0,align:void 0,rotate:0,padding:20,style:{colors:[],fontSize:"11px",fontWeight:400,fontFamily:void 0,cssClass:""},formatter:void 0},axisBorder:{show:!1,color:"#e0e0e0",width:1,offsetX:0,offsetY:0},axisTicks:{show:!1,color:"#e0e0e0",width:6,offsetX:0,offsetY:0},title:{text:void 0,rotate:-90,offsetY:0,offsetX:0,style:{color:void 0,fontSize:"11px",fontWeight:900,fontFamily:void 0,cssClass:""}},tooltip:{enabled:!1,offsetX:0},crosshairs:{show:!0,position:"front",stroke:{color:"#b6b6b6",width:1,dashArray:0}}},this.pointAnnotation={id:void 0,x:0,y:null,yAxisIndex:0,seriesIndex:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,marker:{size:4,fillColor:"#fff",strokeWidth:2,strokeColor:"#333",shape:"circle",offsetX:0,offsetY:0,radius:2,cssClass:""},label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}},customSVG:{SVG:void 0,cssClass:void 0,offsetX:0,offsetY:0},image:{path:void 0,width:20,height:20,offsetX:0,offsetY:0}},this.yAxisAnnotation={id:void 0,y:0,y2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,width:"100%",yAxisIndex:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"end",position:"right",offsetX:0,offsetY:-3,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.xAxisAnnotation={id:void 0,x:0,x2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",orientation:"vertical",position:"top",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.text={x:0,y:0,text:"",textAnchor:"start",foreColor:void 0,fontSize:"13px",fontFamily:void 0,fontWeight:400,appendTo:".apexcharts-annotations",backgroundColor:"transparent",borderColor:"#c2c2c2",borderRadius:0,borderWidth:0,paddingLeft:4,paddingRight:4,paddingTop:2,paddingBottom:2}}return r(t,[{key:"init",value:function(){return{annotations:{yaxis:[this.yAxisAnnotation],xaxis:[this.xAxisAnnotation],points:[this.pointAnnotation],texts:[],images:[],shapes:[]},chart:{animations:{enabled:!0,easing:"easeinout",speed:800,animateGradually:{delay:150,enabled:!0},dynamicAnimation:{enabled:!0,speed:350}},background:"transparent",locales:[C],defaultLocale:"en",dropShadow:{enabled:!1,enabledOnSeries:void 0,top:2,left:2,blur:4,color:"#000",opacity:.35},events:{animationEnd:void 0,beforeMount:void 0,mounted:void 0,updated:void 0,click:void 0,mouseMove:void 0,mouseLeave:void 0,xAxisLabelClick:void 0,legendClick:void 0,markerClick:void 0,selection:void 0,dataPointSelection:void 0,dataPointMouseEnter:void 0,dataPointMouseLeave:void 0,beforeZoom:void 0,beforeResetZoom:void 0,zoomed:void 0,scrolled:void 0,brushScrolled:void 0},foreColor:"#373d3f",fontFamily:"Helvetica, Arial, sans-serif",height:"auto",parentHeightOffset:15,redrawOnParentResize:!0,redrawOnWindowResize:!0,id:void 0,group:void 0,offsetX:0,offsetY:0,selection:{enabled:!1,type:"x",fill:{color:"#24292e",opacity:.1},stroke:{width:1,color:"#24292e",opacity:.4,dashArray:3},xaxis:{min:void 0,max:void 0},yaxis:{min:void 0,max:void 0}},sparkline:{enabled:!1},brush:{enabled:!1,autoScaleYaxis:!0,target:void 0},stacked:!1,stackType:"normal",toolbar:{show:!0,offsetX:0,offsetY:0,tools:{download:!0,selection:!0,zoom:!0,zoomin:!0,zoomout:!0,pan:!0,reset:!0,customIcons:[]},export:{csv:{filename:void 0,columnDelimiter:",",headerCategory:"category",headerValue:"value",dateFormatter:function(t){return new Date(t).toDateString()}},png:{filename:void 0},svg:{filename:void 0}},autoSelected:"zoom"},type:"line",width:"100%",zoom:{enabled:!0,type:"x",autoScaleYaxis:!1,zoomedArea:{fill:{color:"#90CAF9",opacity:.4},stroke:{color:"#0D47A1",opacity:.4,width:1}}}},plotOptions:{area:{fillTo:"origin"},bar:{horizontal:!1,columnWidth:"70%",barHeight:"70%",distributed:!1,borderRadius:0,borderRadiusApplication:"around",borderRadiusWhenStacked:"last",rangeBarOverlap:!0,rangeBarGroupRows:!1,hideZeroBarsWhenGrouped:!0,colors:{ranges:[],backgroundBarColors:[],backgroundBarOpacity:1,backgroundBarRadius:0},dataLabels:{position:"top",maxItems:100,hideOverflowingLabels:!0,orientation:"horizontal",total:{enabled:!1,formatter:void 0,offsetX:0,offsetY:0,style:{color:"#373d3f",fontSize:"12px",fontFamily:void 0,fontWeight:600}}}},bubble:{zScaling:!0,minBubbleRadius:void 0,maxBubbleRadius:void 0},candlestick:{colors:{upward:"#00B746",downward:"#EF403C"},wick:{useFillColor:!0}},boxPlot:{colors:{upper:"#00E396",lower:"#008FFB"}},heatmap:{radius:2,enableShades:!0,shadeIntensity:.5,reverseNegativeShade:!1,distributed:!1,useFillColorAsStroke:!1,colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0}},treemap:{enableShades:!0,shadeIntensity:.5,distributed:!1,reverseNegativeShade:!1,useFillColorAsStroke:!1,colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0}},radialBar:{inverseOrder:!1,startAngle:0,endAngle:360,offsetX:0,offsetY:0,hollow:{margin:5,size:"50%",background:"transparent",image:void 0,imageWidth:150,imageHeight:150,imageOffsetX:0,imageOffsetY:0,imageClipped:!0,position:"front",dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},track:{show:!0,startAngle:void 0,endAngle:void 0,background:"#f2f2f2",strokeWidth:"97%",opacity:1,margin:5,dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},dataLabels:{show:!0,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:0,formatter:function(t){return t}},value:{show:!0,fontSize:"14px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:16,formatter:function(t){return t+"%"}},total:{show:!1,label:"Total",fontSize:"16px",fontWeight:600,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)/t.globals.series.length+"%"}}}},pie:{customScale:1,offsetX:0,offsetY:0,startAngle:0,endAngle:360,expandOnClick:!0,dataLabels:{offset:0,minAngleToShowLabel:10},donut:{size:"65%",background:"transparent",labels:{show:!1,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:-10,formatter:function(t){return t}},value:{show:!0,fontSize:"20px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:10,formatter:function(t){return t}},total:{show:!1,showAlways:!1,label:"Total",fontSize:"16px",fontWeight:400,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)}}}}},polarArea:{rings:{strokeWidth:1,strokeColor:"#e8e8e8"},spokes:{strokeWidth:1,connectorColors:"#e8e8e8"}},radar:{size:void 0,offsetX:0,offsetY:0,polygons:{strokeWidth:1,strokeColors:"#e8e8e8",connectorColors:"#e8e8e8",fill:{colors:void 0}}}},colors:void 0,dataLabels:{enabled:!0,enabledOnSeries:void 0,formatter:function(t){return null!==t?t:""},textAnchor:"middle",distributed:!1,offsetX:0,offsetY:0,style:{fontSize:"12px",fontFamily:void 0,fontWeight:600,colors:void 0},background:{enabled:!0,foreColor:"#fff",borderRadius:2,padding:4,opacity:.9,borderWidth:1,borderColor:"#fff",dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.45}},dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.45}},fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]},image:{src:[],width:void 0,height:void 0},pattern:{style:"squares",width:6,height:6,strokeWidth:2}},forecastDataPoints:{count:0,fillOpacity:.5,strokeWidth:void 0,dashArray:4},grid:{show:!0,borderColor:"#e0e0e0",strokeDashArray:0,position:"back",xaxis:{lines:{show:!1}},yaxis:{lines:{show:!0}},row:{colors:void 0,opacity:.5},column:{colors:void 0,opacity:.5},padding:{top:0,right:10,bottom:0,left:12}},labels:[],legend:{show:!0,showForSingleSeries:!1,showForNullSeries:!0,showForZeroSeries:!0,floating:!1,position:"bottom",horizontalAlign:"center",inverseOrder:!1,fontSize:"12px",fontFamily:void 0,fontWeight:400,width:void 0,height:void 0,formatter:void 0,tooltipHoverFormatter:void 0,offsetX:-20,offsetY:4,customLegendItems:[],labels:{colors:void 0,useSeriesColors:!1},markers:{width:12,height:12,strokeWidth:0,fillColors:void 0,strokeColor:"#fff",radius:12,customHTML:void 0,offsetX:0,offsetY:0,onClick:void 0},itemMargin:{horizontal:5,vertical:2},onItemClick:{toggleDataSeries:!0},onItemHover:{highlightDataSeries:!0}},markers:{discrete:[],size:0,colors:void 0,strokeColors:"#fff",strokeWidth:2,strokeOpacity:.9,strokeDashArray:0,fillOpacity:1,shape:"circle",width:8,height:8,radius:2,offsetX:0,offsetY:0,onClick:void 0,onDblClick:void 0,showNullDataPoints:!0,hover:{size:void 0,sizeOffset:3}},noData:{text:void 0,align:"center",verticalAlign:"middle",offsetX:0,offsetY:0,style:{color:void 0,fontSize:"14px",fontFamily:void 0}},responsive:[],series:void 0,states:{normal:{filter:{type:"none",value:0}},hover:{filter:{type:"lighten",value:.1}},active:{allowMultipleDataPointsSelection:!1,filter:{type:"darken",value:.5}}},title:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:0,floating:!1,style:{fontSize:"14px",fontWeight:900,fontFamily:void 0,color:void 0}},subtitle:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:30,floating:!1,style:{fontSize:"12px",fontWeight:400,fontFamily:void 0,color:void 0}},stroke:{show:!0,curve:"smooth",lineCap:"butt",width:2,colors:void 0,dashArray:0,fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]}}},tooltip:{enabled:!0,enabledOnSeries:void 0,shared:!0,followCursor:!1,intersect:!1,inverseOrder:!1,custom:void 0,fillSeriesColor:!1,theme:"light",cssClass:"",style:{fontSize:"12px",fontFamily:void 0},onDatasetHover:{highlightDataSeries:!1},x:{show:!0,format:"dd MMM",formatter:void 0},y:{formatter:void 0,title:{formatter:function(t){return t?t+": ":""}}},z:{formatter:void 0,title:"Size: "},marker:{show:!0,fillColors:void 0},items:{display:"flex"},fixed:{enabled:!1,position:"topRight",offsetX:0,offsetY:0}},xaxis:{type:"category",categories:[],convertedCatToNumeric:!1,offsetX:0,offsetY:0,overwriteCategories:void 0,labels:{show:!0,rotate:-45,rotateAlways:!1,hideOverlappingLabels:!0,trim:!1,minHeight:void 0,maxHeight:120,showDuplicates:!0,style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""},offsetX:0,offsetY:0,format:void 0,formatter:void 0,datetimeUTC:!0,datetimeFormatter:{year:"yyyy",month:"MMM 'yy",day:"dd MMM",hour:"HH:mm",minute:"HH:mm:ss",second:"HH:mm:ss"}},group:{groups:[],style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""}},axisBorder:{show:!0,color:"#e0e0e0",width:"100%",height:1,offsetX:0,offsetY:0},axisTicks:{show:!0,color:"#e0e0e0",height:6,offsetX:0,offsetY:0},tickAmount:void 0,tickPlacement:"on",min:void 0,max:void 0,range:void 0,floating:!1,decimalsInFloat:void 0,position:"bottom",title:{text:void 0,offsetX:0,offsetY:0,style:{color:void 0,fontSize:"12px",fontWeight:900,fontFamily:void 0,cssClass:""}},crosshairs:{show:!0,width:1,position:"back",opacity:.9,stroke:{color:"#b6b6b6",width:1,dashArray:3},fill:{type:"solid",color:"#B1B9C4",gradient:{colorFrom:"#D8E3F0",colorTo:"#BED1E6",stops:[0,100],opacityFrom:.4,opacityTo:.5}},dropShadow:{enabled:!1,left:0,top:0,blur:1,opacity:.4}},tooltip:{enabled:!0,offsetY:0,formatter:void 0,style:{fontSize:"12px",fontFamily:void 0}}},yaxis:this.yAxis,theme:{mode:"light",palette:"palette1",monochrome:{enabled:!1,color:"#008FFB",shadeTo:"light",shadeIntensity:.65}}}}}]),t}(),P=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.graphics=new m(this.ctx),this.w.globals.isBarHorizontal&&(this.invertAxis=!0),this.helpers=new w(this),this.xAxisAnnotations=new k(this),this.yAxisAnnotations=new A(this),this.pointsAnnotations=new S(this),this.w.globals.isBarHorizontal&&this.w.config.yaxis[0].reversed&&(this.inversedReversedAxis=!0),this.xDivision=this.w.globals.gridWidth/this.w.globals.dataPoints}return r(t,[{key:"drawAxesAnnotations",value:function(){var t=this.w;if(t.globals.axisCharts){for(var e=this.yAxisAnnotations.drawYAxisAnnotations(),i=this.xAxisAnnotations.drawXAxisAnnotations(),a=this.pointsAnnotations.drawPointAnnotations(),s=t.config.chart.animations.enabled,r=[e,i,a],o=[i.node,e.node,a.node],n=0;n<3;n++)t.globals.dom.elGraphical.add(r[n]),!s||t.globals.resized||t.globals.dataChanged||"scatter"!==t.config.chart.type&&"bubble"!==t.config.chart.type&&t.globals.dataPoints>1&&o[n].classList.add("apexcharts-element-hidden"),t.globals.delayedElements.push({el:o[n],index:0});this.helpers.annotationsBackground()}}},{key:"drawImageAnnos",value:function(){var t=this;this.w.config.annotations.images.map((function(e,i){t.addImage(e,i)}))}},{key:"drawTextAnnos",value:function(){var t=this;this.w.config.annotations.texts.map((function(e,i){t.addText(e,i)}))}},{key:"addXaxisAnnotation",value:function(t,e,i){this.xAxisAnnotations.addXaxisAnnotation(t,e,i)}},{key:"addYaxisAnnotation",value:function(t,e,i){this.yAxisAnnotations.addYaxisAnnotation(t,e,i)}},{key:"addPointAnnotation",value:function(t,e,i){this.pointsAnnotations.addPointAnnotation(t,e,i)}},{key:"addText",value:function(t,e){var i=t.x,a=t.y,s=t.text,r=t.textAnchor,o=t.foreColor,n=t.fontSize,l=t.fontFamily,h=t.fontWeight,c=t.cssClass,d=t.backgroundColor,g=t.borderWidth,u=t.strokeDashArray,f=t.borderRadius,p=t.borderColor,x=t.appendTo,b=void 0===x?".apexcharts-annotations":x,v=t.paddingLeft,m=void 0===v?4:v,y=t.paddingRight,w=void 0===y?4:y,k=t.paddingBottom,A=void 0===k?2:k,S=t.paddingTop,C=void 0===S?2:S,L=this.w,P=this.graphics.drawText({x:i,y:a,text:s,textAnchor:r||"start",fontSize:n||"12px",fontWeight:h||"regular",fontFamily:l||L.config.chart.fontFamily,foreColor:o||L.config.chart.foreColor,cssClass:c}),T=L.globals.dom.baseEl.querySelector(b);T&&T.appendChild(P.node);var M=P.bbox();if(s){var I=this.graphics.drawRect(M.x-m,M.y-C,M.width+m+w,M.height+A+C,f,d||"transparent",1,g,p,u);T.insertBefore(I.node,P.node)}}},{key:"addImage",value:function(t,e){var i=this.w,a=t.path,s=t.x,r=void 0===s?0:s,o=t.y,n=void 0===o?0:o,l=t.width,h=void 0===l?20:l,c=t.height,d=void 0===c?20:c,g=t.appendTo,u=void 0===g?".apexcharts-annotations":g,f=i.globals.dom.Paper.image(a);f.size(h,d).move(r,n);var p=i.globals.dom.baseEl.querySelector(u);return p&&p.appendChild(f.node),f}},{key:"addXaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"xaxis",contextMethod:i.addXaxisAnnotation}),i}},{key:"addYaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"yaxis",contextMethod:i.addYaxisAnnotation}),i}},{key:"addPointAnnotationExternal",value:function(t,e,i){return void 0===this.invertAxis&&(this.invertAxis=i.w.globals.isBarHorizontal),this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"point",contextMethod:i.addPointAnnotation}),i}},{key:"addAnnotationExternal",value:function(t){var e=t.params,i=t.pushToMemory,a=t.context,s=t.type,r=t.contextMethod,o=a,n=o.w,l=n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations")),h=l.childNodes.length+1,c=new L,d=Object.assign({},"xaxis"===s?c.xAxisAnnotation:"yaxis"===s?c.yAxisAnnotation:c.pointAnnotation),g=x.extend(d,e);switch(s){case"xaxis":this.addXaxisAnnotation(g,l,h);break;case"yaxis":this.addYaxisAnnotation(g,l,h);break;case"point":this.addPointAnnotation(g,l,h)}var u=n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(h,"']")),f=this.helpers.addBackgroundToAnno(u,g);return f&&l.insertBefore(f.node,u),i&&n.globals.memory.methodsToExec.push({context:o,id:g.id?g.id:x.randomId(),method:r,label:"addAnnotation",params:e}),a}},{key:"clearAnnotations",value:function(t){var e=t.w,i=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations");e.globals.memory.methodsToExec.map((function(t,i){"addText"!==t.label&&"addAnnotation"!==t.label||e.globals.memory.methodsToExec.splice(i,1)})),i=x.listToArray(i),Array.prototype.forEach.call(i,(function(t){for(;t.firstChild;)t.removeChild(t.firstChild)}))}},{key:"removeAnnotation",value:function(t,e){var i=t.w,a=i.globals.dom.baseEl.querySelectorAll(".".concat(e));a&&(i.globals.memory.methodsToExec.map((function(t,a){t.id===e&&i.globals.memory.methodsToExec.splice(a,1)})),Array.prototype.forEach.call(a,(function(t){t.parentElement.removeChild(t)})))}}]),t}(),T=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.months31=[1,3,5,7,8,10,12],this.months30=[2,4,6,9,11],this.daysCntOfYear=[0,31,59,90,120,151,181,212,243,273,304,334]}return r(t,[{key:"isValidDate",value:function(t){return!isNaN(this.parseDate(t))}},{key:"getTimeStamp",value:function(t){return Date.parse(t)?this.w.config.xaxis.labels.datetimeUTC?new Date(new Date(t).toISOString().substr(0,25)).getTime():new Date(t).getTime():t}},{key:"getDate",value:function(t){return this.w.config.xaxis.labels.datetimeUTC?new Date(new Date(t).toUTCString()):new Date(t)}},{key:"parseDate",value:function(t){var e=Date.parse(t);if(!isNaN(e))return this.getTimeStamp(t);var i=Date.parse(t.replace(/-/g,"/").replace(/[a-z]+/gi," "));return i=this.getTimeStamp(i)}},{key:"parseDateWithTimezone",value:function(t){return Date.parse(t.replace(/-/g,"/").replace(/[a-z]+/gi," "))}},{key:"formatDate",value:function(t,e){var i=this.w.globals.locale,a=this.w.config.xaxis.labels.datetimeUTC,s=["\0"].concat(u(i.months)),r=["\x01"].concat(u(i.shortMonths)),o=["\x02"].concat(u(i.days)),n=["\x03"].concat(u(i.shortDays));function l(t,e){var i=t+"";for(e=e||2;i.length12?g-12:0===g?12:g;e=(e=(e=(e=e.replace(/(^|[^\\])HH+/g,"$1"+l(g))).replace(/(^|[^\\])H/g,"$1"+g)).replace(/(^|[^\\])hh+/g,"$1"+l(f))).replace(/(^|[^\\])h/g,"$1"+f);var p=a?t.getUTCMinutes():t.getMinutes();e=(e=e.replace(/(^|[^\\])mm+/g,"$1"+l(p))).replace(/(^|[^\\])m/g,"$1"+p);var x=a?t.getUTCSeconds():t.getSeconds();e=(e=e.replace(/(^|[^\\])ss+/g,"$1"+l(x))).replace(/(^|[^\\])s/g,"$1"+x);var b=a?t.getUTCMilliseconds():t.getMilliseconds();e=e.replace(/(^|[^\\])fff+/g,"$1"+l(b,3)),b=Math.round(b/10),e=e.replace(/(^|[^\\])ff/g,"$1"+l(b)),b=Math.round(b/10);var v=g<12?"AM":"PM";e=(e=(e=e.replace(/(^|[^\\])f/g,"$1"+b)).replace(/(^|[^\\])TT+/g,"$1"+v)).replace(/(^|[^\\])T/g,"$1"+v.charAt(0));var m=v.toLowerCase();e=(e=e.replace(/(^|[^\\])tt+/g,"$1"+m)).replace(/(^|[^\\])t/g,"$1"+m.charAt(0));var y=-t.getTimezoneOffset(),w=a||!y?"Z":y>0?"+":"-";if(!a){var k=(y=Math.abs(y))%60;w+=l(Math.floor(y/60))+":"+l(k)}e=e.replace(/(^|[^\\])K/g,"$1"+w);var A=(a?t.getUTCDay():t.getDay())+1;return e=(e=(e=(e=(e=e.replace(new RegExp(o[0],"g"),o[A])).replace(new RegExp(n[0],"g"),n[A])).replace(new RegExp(s[0],"g"),s[c])).replace(new RegExp(r[0],"g"),r[c])).replace(/\\(.)/g,"$1")}},{key:"getTimeUnitsfromTimestamp",value:function(t,e,i){var a=this.w;void 0!==a.config.xaxis.min&&(t=a.config.xaxis.min),void 0!==a.config.xaxis.max&&(e=a.config.xaxis.max);var s=this.getDate(t),r=this.getDate(e),o=this.formatDate(s,"yyyy MM dd HH mm ss fff").split(" "),n=this.formatDate(r,"yyyy MM dd HH mm ss fff").split(" ");return{minMillisecond:parseInt(o[6],10),maxMillisecond:parseInt(n[6],10),minSecond:parseInt(o[5],10),maxSecond:parseInt(n[5],10),minMinute:parseInt(o[4],10),maxMinute:parseInt(n[4],10),minHour:parseInt(o[3],10),maxHour:parseInt(n[3],10),minDate:parseInt(o[2],10),maxDate:parseInt(n[2],10),minMonth:parseInt(o[1],10)-1,maxMonth:parseInt(n[1],10)-1,minYear:parseInt(o[0],10),maxYear:parseInt(n[0],10)}}},{key:"isLeapYear",value:function(t){return t%4==0&&t%100!=0||t%400==0}},{key:"calculcateLastDaysOfMonth",value:function(t,e,i){return this.determineDaysOfMonths(t,e)-i}},{key:"determineDaysOfYear",value:function(t){var e=365;return this.isLeapYear(t)&&(e=366),e}},{key:"determineRemainingDaysOfYear",value:function(t,e,i){var a=this.daysCntOfYear[e]+i;return e>1&&this.isLeapYear()&&a++,a}},{key:"determineDaysOfMonths",value:function(t,e){var i=30;switch(t=x.monthMod(t),!0){case this.months30.indexOf(t)>-1:2===t&&(i=this.isLeapYear(e)?29:28);break;case this.months31.indexOf(t)>-1:default:i=31}return i}}]),t}(),M=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.tooltipKeyFormat="dd MMM"}return r(t,[{key:"xLabelFormat",value:function(t,e,i,a){var s=this.w;if("datetime"===s.config.xaxis.type&&void 0===s.config.xaxis.labels.formatter&&void 0===s.config.tooltip.x.formatter){var r=new T(this.ctx);return r.formatDate(r.getDate(e),s.config.tooltip.x.format)}return t(e,i,a)}},{key:"defaultGeneralFormatter",value:function(t){return Array.isArray(t)?t.map((function(t){return t})):t}},{key:"defaultYFormatter",value:function(t,e,i){var a=this.w;return x.isNumber(t)&&(t=0!==a.globals.yValueDecimal?t.toFixed(void 0!==e.decimalsInFloat?e.decimalsInFloat:a.globals.yValueDecimal):a.globals.maxYArr[i]-a.globals.minYArr[i]<5?t.toFixed(1):t.toFixed(0)),t}},{key:"setLabelFormatters",value:function(){var t=this,e=this.w;return e.globals.xaxisTooltipFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttKeyFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttZFormatter=function(t){return t},e.globals.legendFormatter=function(e){return t.defaultGeneralFormatter(e)},void 0!==e.config.xaxis.labels.formatter?e.globals.xLabelFormatter=e.config.xaxis.labels.formatter:e.globals.xLabelFormatter=function(t){if(x.isNumber(t)){if(!e.config.xaxis.convertedCatToNumeric&&"numeric"===e.config.xaxis.type){if(x.isNumber(e.config.xaxis.decimalsInFloat))return t.toFixed(e.config.xaxis.decimalsInFloat);var i=e.globals.maxX-e.globals.minX;return i>0&&i<100?t.toFixed(1):t.toFixed(0)}if(e.globals.isBarHorizontal)if(e.globals.maxY-e.globals.minYArr<4)return t.toFixed(1);return t.toFixed(0)}return t},"function"==typeof e.config.tooltip.x.formatter?e.globals.ttKeyFormatter=e.config.tooltip.x.formatter:e.globals.ttKeyFormatter=e.globals.xLabelFormatter,"function"==typeof e.config.xaxis.tooltip.formatter&&(e.globals.xaxisTooltipFormatter=e.config.xaxis.tooltip.formatter),(Array.isArray(e.config.tooltip.y)||void 0!==e.config.tooltip.y.formatter)&&(e.globals.ttVal=e.config.tooltip.y),void 0!==e.config.tooltip.z.formatter&&(e.globals.ttZFormatter=e.config.tooltip.z.formatter),void 0!==e.config.legend.formatter&&(e.globals.legendFormatter=e.config.legend.formatter),e.config.yaxis.forEach((function(i,a){void 0!==i.labels.formatter?e.globals.yLabelFormatters[a]=i.labels.formatter:e.globals.yLabelFormatters[a]=function(s){return e.globals.xyCharts?Array.isArray(s)?s.map((function(e){return t.defaultYFormatter(e,i,a)})):t.defaultYFormatter(s,i,a):s}})),e.globals}},{key:"heatmapLabelFormatters",value:function(){var t=this.w;if("heatmap"===t.config.chart.type){t.globals.yAxisScale[0].result=t.globals.seriesNames.slice();var e=t.globals.seriesNames.reduce((function(t,e){return t.length>e.length?t:e}),0);t.globals.yAxisScale[0].niceMax=e,t.globals.yAxisScale[0].niceMin=e}}}]),t}(),I=function(t){var e,i=t.isTimeline,a=t.ctx,s=t.seriesIndex,r=t.dataPointIndex,o=t.y1,n=t.y2,l=t.w,h=l.globals.seriesRangeStart[s][r],c=l.globals.seriesRangeEnd[s][r],d=l.globals.labels[r],g=l.config.series[s].name?l.config.series[s].name:"",u=l.globals.ttKeyFormatter,f=l.config.tooltip.y.title.formatter,p={w:l,seriesIndex:s,dataPointIndex:r,start:h,end:c};("function"==typeof f&&(g=f(g,p)),null!==(e=l.config.series[s].data[r])&&void 0!==e&&e.x&&(d=l.config.series[s].data[r].x),i)||"datetime"===l.config.xaxis.type&&(d=new M(a).xLabelFormat(l.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new T(a).formatDate,w:l}));"function"==typeof u&&(d=u(d,p)),Number.isFinite(o)&&Number.isFinite(n)&&(h=o,c=n);var x="",b="",v=l.globals.colors[s];if(void 0===l.config.tooltip.x.formatter)if("datetime"===l.config.xaxis.type){var m=new T(a);x=m.formatDate(m.getDate(h),l.config.tooltip.x.format),b=m.formatDate(m.getDate(c),l.config.tooltip.x.format)}else x=h,b=c;else x=l.config.tooltip.x.formatter(h),b=l.config.tooltip.x.formatter(c);return{start:h,end:c,startVal:x,endVal:b,ylabel:d,color:v,seriesName:g}},z=function(t){var e=t.color,i=t.seriesName,a=t.ylabel,s=t.start,r=t.end,o=t.seriesIndex,n=t.dataPointIndex,l=t.ctx.tooltip.tooltipLabels.getFormatters(o);s=l.yLbFormatter(s),r=l.yLbFormatter(r);var h=l.yLbFormatter(t.w.globals.series[o][n]),c='\n '.concat(s,'\n - \n ').concat(r,"\n ");return'
    '+(i||"")+'
    '+a+": "+(t.w.globals.comboCharts?"rangeArea"===t.w.config.series[o].type||"rangeBar"===t.w.config.series[o].type?c:"".concat(h,""):c)+"
    "},X=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"line",value:function(){return{chart:{animations:{easing:"swing"}},dataLabels:{enabled:!1},stroke:{width:5,curve:"straight"},markers:{size:0,hover:{sizeOffset:6}},xaxis:{crosshairs:{width:1}}}}},{key:"sparkline",value:function(t){this.opts.yaxis[0].show=!1,this.opts.yaxis[0].title.text="",this.opts.yaxis[0].axisBorder.show=!1,this.opts.yaxis[0].axisTicks.show=!1,this.opts.yaxis[0].floating=!0;return x.extend(t,{grid:{show:!1,padding:{left:0,right:0,top:0,bottom:0}},legend:{show:!1},xaxis:{labels:{show:!1},tooltip:{enabled:!1},axisBorder:{show:!1},axisTicks:{show:!1}},chart:{toolbar:{show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1}})}},{key:"bar",value:function(){return{chart:{stacked:!1,animations:{easing:"swing"}},plotOptions:{bar:{dataLabels:{position:"center"}}},dataLabels:{style:{colors:["#fff"]},background:{enabled:!1}},stroke:{width:0,lineCap:"round"},fill:{opacity:.85},legend:{markers:{shape:"square",radius:2,size:8}},tooltip:{shared:!1,intersect:!0},xaxis:{tooltip:{enabled:!1},tickPlacement:"between",crosshairs:{width:"barWidth",position:"back",fill:{type:"gradient"},dropShadow:{enabled:!1},stroke:{width:0}}}}}},{key:"candlestick",value:function(){var t=this;return{stroke:{width:1,colors:["#333"]},fill:{opacity:1},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Open","High","","Low","Close"],"candlestick")}},states:{active:{filter:{type:"none"}}},xaxis:{crosshairs:{width:1}}}}},{key:"boxPlot",value:function(){var t=this;return{chart:{animations:{dynamicAnimation:{enabled:!1}}},stroke:{width:1,colors:["#24292e"]},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Minimum","Q1","Median","Q3","Maximum"],"boxPlot")}},markers:{size:5,strokeWidth:1,strokeColors:"#111"},xaxis:{crosshairs:{width:1}}}}},{key:"rangeBar",value:function(){return{stroke:{width:0,lineCap:"square"},plotOptions:{bar:{borderRadius:0,dataLabels:{position:"center"}}},dataLabels:{enabled:!1,formatter:function(t,e){e.ctx;var i=e.seriesIndex,a=e.dataPointIndex,s=e.w,r=function(){var t=s.globals.seriesRangeStart[i][a];return s.globals.seriesRangeEnd[i][a]-t};return s.globals.comboCharts?"rangeBar"===s.config.series[i].type||"rangeArea"===s.config.series[i].type?r():t:r()},background:{enabled:!1},style:{colors:["#fff"]}},tooltip:{shared:!1,followCursor:!0,custom:function(t){return t.w.config.plotOptions&&t.w.config.plotOptions.bar&&t.w.config.plotOptions.bar.horizontal?function(t){var i=I(e(e({},t),{},{isTimeline:!0})),a=i.color,s=i.seriesName,r=i.ylabel,o=i.startVal,n=i.endVal;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t):function(t){var i=I(t),a=i.color,s=i.seriesName,r=i.ylabel,o=i.start,n=i.end;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t)}},xaxis:{tickPlacement:"between",tooltip:{enabled:!1},crosshairs:{stroke:{width:0}}}}}},{key:"area",value:function(){return{stroke:{width:4,fill:{type:"solid",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}}},fill:{type:"gradient",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}},markers:{size:0,hover:{sizeOffset:6}},tooltip:{followCursor:!1}}}},{key:"rangeArea",value:function(){return{stroke:{curve:"straight",width:0},fill:{type:"solid",opacity:.6},markers:{size:0},states:{hover:{filter:{type:"none"}},active:{filter:{type:"none"}}},tooltip:{intersect:!1,shared:!0,followCursor:!0,custom:function(t){return function(t){var i=I(t),a=i.color,s=i.seriesName,r=i.ylabel,o=i.start,n=i.end;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t)}}}}},{key:"brush",value:function(t){return x.extend(t,{chart:{toolbar:{autoSelected:"selection",show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1},stroke:{width:1},tooltip:{enabled:!1},xaxis:{tooltip:{enabled:!1}}})}},{key:"stacked100",value:function(t){t.dataLabels=t.dataLabels||{},t.dataLabels.formatter=t.dataLabels.formatter||void 0;var e=t.dataLabels.formatter;return t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})),"bar"===t.chart.type&&(t.dataLabels.formatter=e||function(t){return"number"==typeof t&&t?t.toFixed(0)+"%":t}),t}},{key:"stackedBars",value:function(){var t=this.bar();return e(e({},t),{},{plotOptions:e(e({},t.plotOptions),{},{bar:e(e({},t.plotOptions.bar),{},{borderRadiusApplication:"end",borderRadiusWhenStacked:"last"})})})}},{key:"convertCatToNumeric",value:function(t){return t.xaxis.convertedCatToNumeric=!0,t}},{key:"convertCatToNumericXaxis",value:function(t,e,i){t.xaxis.type="numeric",t.xaxis.labels=t.xaxis.labels||{},t.xaxis.labels.formatter=t.xaxis.labels.formatter||function(t){return x.isNumber(t)?Math.floor(t):t};var a=t.xaxis.labels.formatter,s=t.xaxis.categories&&t.xaxis.categories.length?t.xaxis.categories:t.labels;return i&&i.length&&(s=i.map((function(t){return Array.isArray(t)?t:String(t)}))),s&&s.length&&(t.xaxis.labels.formatter=function(t){return x.isNumber(t)?a(s[Math.floor(t)-1]):a(t)}),t.xaxis.categories=[],t.labels=[],t.xaxis.tickAmount=t.xaxis.tickAmount||"dataPoints",t}},{key:"bubble",value:function(){return{dataLabels:{style:{colors:["#fff"]}},tooltip:{shared:!1,intersect:!0},xaxis:{crosshairs:{width:0}},fill:{type:"solid",gradient:{shade:"light",inverse:!0,shadeIntensity:.55,opacityFrom:.4,opacityTo:.8}}}}},{key:"scatter",value:function(){return{dataLabels:{enabled:!1},tooltip:{shared:!1,intersect:!0},markers:{size:6,strokeWidth:1,hover:{sizeOffset:2}}}}},{key:"heatmap",value:function(){return{chart:{stacked:!1},fill:{opacity:1},dataLabels:{style:{colors:["#fff"]}},stroke:{colors:["#fff"]},tooltip:{followCursor:!0,marker:{show:!1},x:{show:!1}},legend:{position:"top",markers:{shape:"square",size:10,offsetY:2}},grid:{padding:{right:20}}}}},{key:"treemap",value:function(){return{chart:{zoom:{enabled:!1}},dataLabels:{style:{fontSize:14,fontWeight:600,colors:["#fff"]}},stroke:{show:!0,width:2,colors:["#fff"]},legend:{show:!1},fill:{gradient:{stops:[0,100]}},tooltip:{followCursor:!0,x:{show:!1}},grid:{padding:{left:0,right:0}},xaxis:{crosshairs:{show:!1},tooltip:{enabled:!1}}}}},{key:"pie",value:function(){return{chart:{toolbar:{show:!1}},plotOptions:{pie:{donut:{labels:{show:!1}}}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",stops:[0,100]}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"donut",value:function(){return{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",shadeIntensity:.35,stops:[80,100],opacityFrom:1,opacityTo:1}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"polarArea",value:function(){return this.opts.yaxis[0].tickAmount=this.opts.yaxis[0].tickAmount?this.opts.yaxis[0].tickAmount:6,{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},enabled:!1},stroke:{show:!0,width:2},fill:{opacity:.7},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"radar",value:function(){return this.opts.yaxis[0].labels.offsetY=this.opts.yaxis[0].labels.offsetY?this.opts.yaxis[0].labels.offsetY:6,{dataLabels:{enabled:!1,style:{fontSize:"11px"}},stroke:{width:2},markers:{size:3,strokeWidth:1,strokeOpacity:1},fill:{opacity:.2},tooltip:{shared:!1,intersect:!0,followCursor:!0},grid:{show:!1},xaxis:{labels:{formatter:function(t){return t},style:{colors:["#a8a8a8"],fontSize:"11px"}},tooltip:{enabled:!1},crosshairs:{show:!1}}}}},{key:"radialBar",value:function(){return{chart:{animations:{dynamicAnimation:{enabled:!0,speed:800}},toolbar:{show:!1}},fill:{gradient:{shade:"dark",shadeIntensity:.4,inverseColors:!1,type:"diagonal2",opacityFrom:1,opacityTo:1,stops:[70,98,100]}},legend:{show:!1,position:"right"},tooltip:{enabled:!1,fillSeriesColor:!0}}}},{key:"_getBoxTooltip",value:function(t,e,i,a,s){var r=t.globals.seriesCandleO[e][i],o=t.globals.seriesCandleH[e][i],n=t.globals.seriesCandleM[e][i],l=t.globals.seriesCandleL[e][i],h=t.globals.seriesCandleC[e][i];return t.config.series[e].type&&t.config.series[e].type!==s?'
    \n '.concat(t.config.series[e].name?t.config.series[e].name:"series-"+(e+1),": ").concat(t.globals.series[e][i],"\n
    "):'
    ')+"
    ".concat(a[0],': ')+r+"
    "+"
    ".concat(a[1],': ')+o+"
    "+(n?"
    ".concat(a[2],': ')+n+"
    ":"")+"
    ".concat(a[3],': ')+l+"
    "+"
    ".concat(a[4],': ')+h+"
    "}}]),t}(),E=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"init",value:function(t){var e=t.responsiveOverride,a=this.opts,s=new L,r=new X(a);this.chartType=a.chart.type,a=this.extendYAxis(a),a=this.extendAnnotations(a);var o=s.init(),n={};if(a&&"object"===i(a)){var l={};l=-1!==["line","area","bar","candlestick","boxPlot","rangeBar","rangeArea","bubble","scatter","heatmap","treemap","pie","polarArea","donut","radar","radialBar"].indexOf(a.chart.type)?r[a.chart.type]():r.line(),a.chart.stacked&&"bar"===a.chart.type&&(l=r.stackedBars()),a.chart.brush&&a.chart.brush.enabled&&(l=r.brush(l)),a.chart.stacked&&"100%"===a.chart.stackType&&(a=r.stacked100(a)),this.checkForDarkTheme(window.Apex),this.checkForDarkTheme(a),a.xaxis=a.xaxis||window.Apex.xaxis||{},e||(a.xaxis.convertedCatToNumeric=!1),((a=this.checkForCatToNumericXAxis(this.chartType,l,a)).chart.sparkline&&a.chart.sparkline.enabled||window.Apex.chart&&window.Apex.chart.sparkline&&window.Apex.chart.sparkline.enabled)&&(l=r.sparkline(l)),n=x.extend(o,l)}var h=x.extend(n,window.Apex);return o=x.extend(h,a),o=this.handleUserInputErrors(o)}},{key:"checkForCatToNumericXAxis",value:function(t,e,i){var a=new X(i),s=("bar"===t||"boxPlot"===t)&&i.plotOptions&&i.plotOptions.bar&&i.plotOptions.bar.horizontal,r="pie"===t||"polarArea"===t||"donut"===t||"radar"===t||"radialBar"===t||"heatmap"===t,o="datetime"!==i.xaxis.type&&"numeric"!==i.xaxis.type,n=i.xaxis.tickPlacement?i.xaxis.tickPlacement:e.xaxis&&e.xaxis.tickPlacement;return s||r||!o||"between"===n||(i=a.convertCatToNumeric(i)),i}},{key:"extendYAxis",value:function(t,e){var i=new L;(void 0===t.yaxis||!t.yaxis||Array.isArray(t.yaxis)&&0===t.yaxis.length)&&(t.yaxis={}),t.yaxis.constructor!==Array&&window.Apex.yaxis&&window.Apex.yaxis.constructor!==Array&&(t.yaxis=x.extend(t.yaxis,window.Apex.yaxis)),t.yaxis.constructor!==Array?t.yaxis=[x.extend(i.yAxis,t.yaxis)]:t.yaxis=x.extendArray(t.yaxis,i.yAxis);var a=!1;t.yaxis.forEach((function(t){t.logarithmic&&(a=!0)}));var s=t.series;return e&&!s&&(s=e.config.series),a&&s.length!==t.yaxis.length&&s.length&&(t.yaxis=s.map((function(e,a){if(e.name||(s[a].name="series-".concat(a+1)),t.yaxis[a])return t.yaxis[a].seriesName=s[a].name,t.yaxis[a];var r=x.extend(i.yAxis,t.yaxis[0]);return r.show=!1,r}))),a&&s.length>1&&s.length!==t.yaxis.length&&console.warn("A multi-series logarithmic chart should have equal number of series and y-axes. Please make sure to equalize both."),t}},{key:"extendAnnotations",value:function(t){return void 0===t.annotations&&(t.annotations={},t.annotations.yaxis=[],t.annotations.xaxis=[],t.annotations.points=[]),t=this.extendYAxisAnnotations(t),t=this.extendXAxisAnnotations(t),t=this.extendPointAnnotations(t)}},{key:"extendYAxisAnnotations",value:function(t){var e=new L;return t.annotations.yaxis=x.extendArray(void 0!==t.annotations.yaxis?t.annotations.yaxis:[],e.yAxisAnnotation),t}},{key:"extendXAxisAnnotations",value:function(t){var e=new L;return t.annotations.xaxis=x.extendArray(void 0!==t.annotations.xaxis?t.annotations.xaxis:[],e.xAxisAnnotation),t}},{key:"extendPointAnnotations",value:function(t){var e=new L;return t.annotations.points=x.extendArray(void 0!==t.annotations.points?t.annotations.points:[],e.pointAnnotation),t}},{key:"checkForDarkTheme",value:function(t){t.theme&&"dark"===t.theme.mode&&(t.tooltip||(t.tooltip={}),"light"!==t.tooltip.theme&&(t.tooltip.theme="dark"),t.chart.foreColor||(t.chart.foreColor="#f6f7f8"),t.chart.background||(t.chart.background="#424242"),t.theme.palette||(t.theme.palette="palette4"))}},{key:"handleUserInputErrors",value:function(t){var e=t;if(e.tooltip.shared&&e.tooltip.intersect)throw new Error("tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false.");if("bar"===e.chart.type&&e.plotOptions.bar.horizontal){if(e.yaxis.length>1)throw new Error("Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false");e.yaxis[0].reversed&&(e.yaxis[0].opposite=!0),e.xaxis.tooltip.enabled=!1,e.yaxis[0].tooltip.enabled=!1,e.chart.zoom.enabled=!1}return"bar"!==e.chart.type&&"rangeBar"!==e.chart.type||e.tooltip.shared&&"barWidth"===e.xaxis.crosshairs.width&&e.series.length>1&&(e.xaxis.crosshairs.width="tickWidth"),"candlestick"!==e.chart.type&&"boxPlot"!==e.chart.type||e.yaxis[0].reversed&&(console.warn("Reversed y-axis in ".concat(e.chart.type," chart is not supported.")),e.yaxis[0].reversed=!1),e}}]),t}(),Y=function(){function t(){a(this,t)}return r(t,[{key:"initGlobalVars",value:function(t){t.series=[],t.seriesCandleO=[],t.seriesCandleH=[],t.seriesCandleM=[],t.seriesCandleL=[],t.seriesCandleC=[],t.seriesRangeStart=[],t.seriesRangeEnd=[],t.seriesRange=[],t.seriesPercent=[],t.seriesGoals=[],t.seriesX=[],t.seriesZ=[],t.seriesNames=[],t.seriesTotals=[],t.seriesLog=[],t.seriesColors=[],t.stackedSeriesTotals=[],t.seriesXvalues=[],t.seriesYvalues=[],t.labels=[],t.hasGroups=!1,t.groups=[],t.categoryLabels=[],t.timescaleLabels=[],t.noLabelsProvided=!1,t.resizeTimer=null,t.selectionResizeTimer=null,t.delayedElements=[],t.pointsArray=[],t.dataLabelsRects=[],t.isXNumeric=!1,t.skipLastTimelinelabel=!1,t.skipFirstTimelinelabel=!1,t.isDataXYZ=!1,t.isMultiLineX=!1,t.isMultipleYAxis=!1,t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE,t.minYArr=[],t.maxYArr=[],t.maxX=-Number.MAX_VALUE,t.minX=Number.MAX_VALUE,t.initialMaxX=-Number.MAX_VALUE,t.initialMinX=Number.MAX_VALUE,t.maxDate=0,t.minDate=Number.MAX_VALUE,t.minZ=Number.MAX_VALUE,t.maxZ=-Number.MAX_VALUE,t.minXDiff=Number.MAX_VALUE,t.yAxisScale=[],t.xAxisScale=null,t.xAxisTicksPositions=[],t.yLabelsCoords=[],t.yTitleCoords=[],t.barPadForNumericAxis=0,t.padHorizontal=0,t.xRange=0,t.yRange=[],t.zRange=0,t.dataPoints=0,t.xTickAmount=0}},{key:"globalVars",value:function(t){return{chartID:null,cuid:null,events:{beforeMount:[],mounted:[],updated:[],clicked:[],selection:[],dataPointSelection:[],zoomed:[],scrolled:[]},colors:[],clientX:null,clientY:null,fill:{colors:[]},stroke:{colors:[]},dataLabels:{style:{colors:[]}},radarPolygons:{fill:{colors:[]}},markers:{colors:[],size:t.markers.size,largestSize:0},animationEnded:!1,isTouchDevice:"ontouchstart"in window||navigator.msMaxTouchPoints,isDirty:!1,isExecCalled:!1,initialConfig:null,initialSeries:[],lastXAxis:[],lastYAxis:[],columnSeries:null,labels:[],timescaleLabels:[],noLabelsProvided:!1,allSeriesCollapsed:!1,collapsedSeries:[],collapsedSeriesIndices:[],ancillaryCollapsedSeries:[],ancillaryCollapsedSeriesIndices:[],risingSeries:[],dataFormatXNumeric:!1,capturedSeriesIndex:-1,capturedDataPointIndex:-1,selectedDataPoints:[],goldenPadding:35,invalidLogScale:!1,ignoreYAxisIndexes:[],yAxisSameScaleIndices:[],maxValsInArrayIndex:0,radialSize:0,selection:void 0,zoomEnabled:"zoom"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.zoom&&t.chart.zoom.enabled,panEnabled:"pan"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.pan,selectionEnabled:"selection"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.selection,yaxis:null,mousedown:!1,lastClientPosition:{},visibleXRange:void 0,yValueDecimal:0,total:0,SVGNS:"http://www.w3.org/2000/svg",svgWidth:0,svgHeight:0,noData:!1,locale:{},dom:{},memory:{methodsToExec:[]},shouldAnimate:!0,skipLastTimelinelabel:!1,skipFirstTimelinelabel:!1,delayedElements:[],axisCharts:!0,isDataXYZ:!1,resized:!1,resizeTimer:null,comboCharts:!1,dataChanged:!1,previousPaths:[],allSeriesHasEqualX:!0,pointsArray:[],dataLabelsRects:[],lastDrawnDataLabelsIndexes:[],hasNullValues:!1,easing:null,zoomed:!1,gridWidth:0,gridHeight:0,rotateXLabels:!1,defaultLabels:!1,xLabelFormatter:void 0,yLabelFormatters:[],xaxisTooltipFormatter:void 0,ttKeyFormatter:void 0,ttVal:void 0,ttZFormatter:void 0,LINE_HEIGHT_RATIO:1.618,xAxisLabelsHeight:0,xAxisGroupLabelsHeight:0,xAxisLabelsWidth:0,yAxisLabelsWidth:0,scaleX:1,scaleY:1,translateX:0,translateY:0,translateYAxisX:[],yAxisWidths:[],translateXAxisY:0,translateXAxisX:0,tooltip:null}}},{key:"init",value:function(t){var e=this.globalVars(t);return this.initGlobalVars(e),e.initialConfig=x.extend({},t),e.initialSeries=x.clone(t.series),e.lastXAxis=x.clone(e.initialConfig.xaxis),e.lastYAxis=x.clone(e.initialConfig.yaxis),e}}]),t}(),F=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"init",value:function(){var t=new E(this.opts).init({responsiveOverride:!1});return{config:t,globals:(new Y).init(t)}}}]),t}(),R=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.opts=null,this.seriesIndex=0}return r(t,[{key:"clippedImgArea",value:function(t){var e=this.w,i=e.config,a=parseInt(e.globals.gridWidth,10),s=parseInt(e.globals.gridHeight,10),r=a>s?a:s,o=t.image,n=0,l=0;void 0===t.width&&void 0===t.height?void 0!==i.fill.image.width&&void 0!==i.fill.image.height?(n=i.fill.image.width+1,l=i.fill.image.height):(n=r+1,l=r):(n=t.width,l=t.height);var h=document.createElementNS(e.globals.SVGNS,"pattern");m.setAttrs(h,{id:t.patternID,patternUnits:t.patternUnits?t.patternUnits:"userSpaceOnUse",width:n+"px",height:l+"px"});var c=document.createElementNS(e.globals.SVGNS,"image");h.appendChild(c),c.setAttributeNS(window.SVG.xlink,"href",o),m.setAttrs(c,{x:0,y:0,preserveAspectRatio:"none",width:n+"px",height:l+"px"}),c.style.opacity=t.opacity,e.globals.dom.elDefs.node.appendChild(h)}},{key:"getSeriesIndex",value:function(t){var e=this.w;return("bar"===e.config.chart.type||"rangeBar"===e.config.chart.type)&&e.config.plotOptions.bar.distributed||"heatmap"===e.config.chart.type||"treemap"===e.config.chart.type?this.seriesIndex=t.seriesNumber:this.seriesIndex=t.seriesNumber%e.globals.series.length,this.seriesIndex}},{key:"fillPath",value:function(t){var e=this.w;this.opts=t;var i,a,s,r=this.w.config;this.seriesIndex=this.getSeriesIndex(t);var o=this.getFillColors()[this.seriesIndex];void 0!==e.globals.seriesColors[this.seriesIndex]&&(o=e.globals.seriesColors[this.seriesIndex]),"function"==typeof o&&(o=o({seriesIndex:this.seriesIndex,dataPointIndex:t.dataPointIndex,value:t.value,w:e}));var n=t.fillType?t.fillType:this.getFillType(this.seriesIndex),l=Array.isArray(r.fill.opacity)?r.fill.opacity[this.seriesIndex]:r.fill.opacity;t.color&&(o=t.color);var h=o;if(-1===o.indexOf("rgb")?o.length<9&&(h=x.hexToRgba(o,l)):o.indexOf("rgba")>-1&&(l=x.getOpacityFromRGBA(o)),t.opacity&&(l=t.opacity),"pattern"===n&&(a=this.handlePatternFill({fillConfig:t.fillConfig,patternFill:a,fillColor:o,fillOpacity:l,defaultColor:h})),"gradient"===n&&(s=this.handleGradientFill({fillConfig:t.fillConfig,fillColor:o,fillOpacity:l,i:this.seriesIndex})),"image"===n){var c=r.fill.image.src,d=t.patternID?t.patternID:"";this.clippedImgArea({opacity:l,image:Array.isArray(c)?t.seriesNumber-1&&(u=x.getOpacityFromRGBA(g));var f=void 0===o.gradient.opacityTo?a:Array.isArray(o.gradient.opacityTo)?o.gradient.opacityTo[r]:o.gradient.opacityTo;if(void 0===o.gradient.gradientToColors||0===o.gradient.gradientToColors.length)n="dark"===o.gradient.shade?c.shadeColor(-1*parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?x.rgb2hex(i):i):c.shadeColor(parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?x.rgb2hex(i):i);else if(o.gradient.gradientToColors[l.seriesNumber]){var p=o.gradient.gradientToColors[l.seriesNumber];n=p,p.indexOf("rgba")>-1&&(f=x.getOpacityFromRGBA(p))}else n=i;if(o.gradient.gradientFrom&&(g=o.gradient.gradientFrom),o.gradient.gradientTo&&(n=o.gradient.gradientTo),o.gradient.inverseColors){var b=g;g=n,n=b}return g.indexOf("rgb")>-1&&(g=x.rgb2hex(g)),n.indexOf("rgb")>-1&&(n=x.rgb2hex(n)),h.drawGradient(d,g,n,u,f,l.size,o.gradient.stops,o.gradient.colorStops,r)}}]),t}(),D=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"setGlobalMarkerSize",value:function(){var t=this.w;if(t.globals.markers.size=Array.isArray(t.config.markers.size)?t.config.markers.size:[t.config.markers.size],t.globals.markers.size.length>0){if(t.globals.markers.size.length4&&void 0!==arguments[4]&&arguments[4],o=this.w,n=e,l=t,h=null,c=new m(this.ctx),d=o.config.markers.discrete&&o.config.markers.discrete.length;if((o.globals.markers.size[e]>0||r||d)&&(h=c.group({class:r||d?"":"apexcharts-series-markers"})).attr("clip-path","url(#gridRectMarkerMask".concat(o.globals.cuid,")")),Array.isArray(l.x))for(var g=0;g0:o.config.markers.size>0;if(p||r||d){x.isNumber(l.y[g])?f+=" w".concat(x.randomId()):f="apexcharts-nullpoint";var b=this.getMarkerConfig({cssClass:f,seriesIndex:e,dataPointIndex:u});o.config.series[n].data[u]&&(o.config.series[n].data[u].fillColor&&(b.pointFillColor=o.config.series[n].data[u].fillColor),o.config.series[n].data[u].strokeColor&&(b.pointStrokeColor=o.config.series[n].data[u].strokeColor)),a&&(b.pSize=a),(s=c.drawMarker(l.x[g],l.y[g],b)).attr("rel",u),s.attr("j",u),s.attr("index",e),s.node.setAttribute("default-marker-size",b.pSize);var y=new v(this.ctx);y.setSelectionFilter(s,e,u),this.addEvents(s),h&&h.add(s)}else void 0===o.globals.pointsArray[e]&&(o.globals.pointsArray[e]=[]),o.globals.pointsArray[e].push([l.x[g],l.y[g]])}return h}},{key:"getMarkerConfig",value:function(t){var e=t.cssClass,i=t.seriesIndex,a=t.dataPointIndex,s=void 0===a?null:a,r=t.finishRadius,o=void 0===r?null:r,n=this.w,l=this.getMarkerStyle(i),h=n.globals.markers.size[i],c=n.config.markers;return null!==s&&c.discrete.length&&c.discrete.map((function(t){t.seriesIndex===i&&t.dataPointIndex===s&&(l.pointStrokeColor=t.strokeColor,l.pointFillColor=t.fillColor,h=t.size,l.pointShape=t.shape)})),{pSize:null===o?h:o,pRadius:c.radius,width:Array.isArray(c.width)?c.width[i]:c.width,height:Array.isArray(c.height)?c.height[i]:c.height,pointStrokeWidth:Array.isArray(c.strokeWidth)?c.strokeWidth[i]:c.strokeWidth,pointStrokeColor:l.pointStrokeColor,pointFillColor:l.pointFillColor,shape:l.pointShape||(Array.isArray(c.shape)?c.shape[i]:c.shape),class:e,pointStrokeOpacity:Array.isArray(c.strokeOpacity)?c.strokeOpacity[i]:c.strokeOpacity,pointStrokeDashArray:Array.isArray(c.strokeDashArray)?c.strokeDashArray[i]:c.strokeDashArray,pointFillOpacity:Array.isArray(c.fillOpacity)?c.fillOpacity[i]:c.fillOpacity,seriesIndex:i}}},{key:"addEvents",value:function(t){var e=this.w,i=new m(this.ctx);t.node.addEventListener("mouseenter",i.pathMouseEnter.bind(this.ctx,t)),t.node.addEventListener("mouseleave",i.pathMouseLeave.bind(this.ctx,t)),t.node.addEventListener("mousedown",i.pathMouseDown.bind(this.ctx,t)),t.node.addEventListener("click",e.config.markers.onClick),t.node.addEventListener("dblclick",e.config.markers.onDblClick),t.node.addEventListener("touchstart",i.pathMouseDown.bind(this.ctx,t),{passive:!0})}},{key:"getMarkerStyle",value:function(t){var e=this.w,i=e.globals.markers.colors,a=e.config.markers.strokeColor||e.config.markers.strokeColors;return{pointStrokeColor:Array.isArray(a)?a[t]:a,pointFillColor:Array.isArray(i)?i[t]:i}}}]),t}(),H=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.initialAnim=this.w.config.chart.animations.enabled,this.dynamicAnim=this.initialAnim&&this.w.config.chart.animations.dynamicAnimation.enabled}return r(t,[{key:"draw",value:function(t,e,i){var a=this.w,s=new m(this.ctx),r=i.realIndex,o=i.pointsPos,n=i.zRatio,l=i.elParent,h=s.group({class:"apexcharts-series-markers apexcharts-series-".concat(a.config.chart.type)});if(h.attr("clip-path","url(#gridRectMarkerMask".concat(a.globals.cuid,")")),Array.isArray(o.x))for(var c=0;cp.maxBubbleRadius&&(f=p.maxBubbleRadius)}a.config.chart.animations.enabled||(u=f);var x=o.x[c],b=o.y[c];if(u=u||0,null!==b&&void 0!==a.globals.series[r][d]||(g=!1),g){var v=this.drawPoint(x,b,u,f,r,d,e);h.add(v)}l.add(h)}}},{key:"drawPoint",value:function(t,e,i,a,s,r,o){var n=this.w,l=s,h=new b(this.ctx),c=new v(this.ctx),d=new R(this.ctx),g=new D(this.ctx),u=new m(this.ctx),f=g.getMarkerConfig({cssClass:"apexcharts-marker",seriesIndex:l,dataPointIndex:r,finishRadius:"bubble"===n.config.chart.type||n.globals.comboCharts&&n.config.series[s]&&"bubble"===n.config.series[s].type?a:null});a=f.pSize;var p,x=d.fillPath({seriesNumber:s,dataPointIndex:r,color:f.pointFillColor,patternUnits:"objectBoundingBox",value:n.globals.series[s][o]});if("circle"===f.shape?p=u.drawCircle(i):"square"!==f.shape&&"rect"!==f.shape||(p=u.drawRect(0,0,f.width-f.pointStrokeWidth/2,f.height-f.pointStrokeWidth/2,f.pRadius)),n.config.series[l].data[r]&&n.config.series[l].data[r].fillColor&&(x=n.config.series[l].data[r].fillColor),p.attr({x:t-f.width/2-f.pointStrokeWidth/2,y:e-f.height/2-f.pointStrokeWidth/2,cx:t,cy:e,fill:x,"fill-opacity":f.pointFillOpacity,stroke:f.pointStrokeColor,r:a,"stroke-width":f.pointStrokeWidth,"stroke-dasharray":f.pointStrokeDashArray,"stroke-opacity":f.pointStrokeOpacity}),n.config.chart.dropShadow.enabled){var y=n.config.chart.dropShadow;c.dropShadow(p,y,s)}if(!this.initialAnim||n.globals.dataChanged||n.globals.resized)n.globals.animationEnded=!0;else{var w=n.config.chart.animations.speed;h.animateMarker(p,0,"circle"===f.shape?a:{width:f.width,height:f.height},w,n.globals.easing,(function(){window.setTimeout((function(){h.animationCompleted(p)}),100)}))}if(n.globals.dataChanged&&"circle"===f.shape)if(this.dynamicAnim){var k,A,S,C,L=n.config.chart.animations.dynamicAnimation.speed;null!=(C=n.globals.previousPaths[s]&&n.globals.previousPaths[s][o])&&(k=C.x,A=C.y,S=void 0!==C.r?C.r:a);for(var P=0;Pn.globals.gridHeight+d&&(e=n.globals.gridHeight+d/2),void 0===n.globals.dataLabelsRects[a]&&(n.globals.dataLabelsRects[a]=[]),n.globals.dataLabelsRects[a].push({x:t,y:e,width:c,height:d});var g=n.globals.dataLabelsRects[a].length-2,u=void 0!==n.globals.lastDrawnDataLabelsIndexes[a]?n.globals.lastDrawnDataLabelsIndexes[a][n.globals.lastDrawnDataLabelsIndexes[a].length-1]:0;if(void 0!==n.globals.dataLabelsRects[a][g]){var f=n.globals.dataLabelsRects[a][u];(t>f.x+f.width+2||e>f.y+f.height+2||t+ce.globals.gridWidth+p.textRects.width+10)&&(n="");var x=e.globals.dataLabels.style.colors[r];(("bar"===e.config.chart.type||"rangeBar"===e.config.chart.type)&&e.config.plotOptions.bar.distributed||e.config.dataLabels.distributed)&&(x=e.globals.dataLabels.style.colors[o]),"function"==typeof x&&(x=x({series:e.globals.series,seriesIndex:r,dataPointIndex:o,w:e})),g&&(x=g);var b=d.offsetX,y=d.offsetY;if("bar"!==e.config.chart.type&&"rangeBar"!==e.config.chart.type||(b=0,y=0),p.drawnextLabel){var w=i.drawText({width:100,height:parseInt(d.style.fontSize,10),x:a+b,y:s+y,foreColor:x,textAnchor:l||d.textAnchor,text:n,fontSize:h||d.style.fontSize,fontFamily:d.style.fontFamily,fontWeight:d.style.fontWeight||"normal"});if(w.attr({class:"apexcharts-datalabel",cx:a,cy:s}),d.dropShadow.enabled){var k=d.dropShadow;new v(this.ctx).dropShadow(w,k)}c.add(w),void 0===e.globals.lastDrawnDataLabelsIndexes[r]&&(e.globals.lastDrawnDataLabelsIndexes[r]=[]),e.globals.lastDrawnDataLabelsIndexes[r].push(o)}}}},{key:"addBackgroundToDataLabel",value:function(t,e){var i=this.w,a=i.config.dataLabels.background,s=a.padding,r=a.padding/2,o=e.width,n=e.height,l=new m(this.ctx).drawRect(e.x-s,e.y-r/2,o+2*s,n+r,a.borderRadius,"transparent"===i.config.chart.background?"#fff":i.config.chart.background,a.opacity,a.borderWidth,a.borderColor);a.dropShadow.enabled&&new v(this.ctx).dropShadow(l,a.dropShadow);return l}},{key:"dataLabelsBackground",value:function(){var t=this.w;if("bubble"!==t.config.chart.type)for(var e=t.globals.dom.baseEl.querySelectorAll(".apexcharts-datalabels text"),i=0;i0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w,s=x.clone(a.globals.initialSeries);a.globals.previousPaths=[],i?(a.globals.collapsedSeries=[],a.globals.ancillaryCollapsedSeries=[],a.globals.collapsedSeriesIndices=[],a.globals.ancillaryCollapsedSeriesIndices=[]):s=this.emptyCollapsedSeries(s),a.config.series=s,t&&(e&&(a.globals.zoomed=!1,this.ctx.updateHelpers.revertDefaultAxisMinMax()),this.ctx.updateHelpers._updateSeries(s,a.config.chart.animations.dynamicAnimation.enabled))}},{key:"emptyCollapsedSeries",value:function(t){for(var e=this.w,i=0;i-1&&(t[i].data=[]);return t}},{key:"toggleSeriesOnHover",value:function(t,e){var i=this.w;e||(e=t.target);var a=i.globals.dom.baseEl.querySelectorAll(".apexcharts-series, .apexcharts-datalabels");if("mousemove"===t.type){var s=parseInt(e.getAttribute("rel"),10)-1,r=null,o=null;i.globals.axisCharts||"radialBar"===i.config.chart.type?i.globals.axisCharts?(r=i.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(s,"']")),o=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels[data\\:realIndex='".concat(s,"']"))):r=i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s+1,"']")):r=i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s+1,"'] path"));for(var n=0;n=t.from&&a<=t.to&&s[e].classList.remove(i.legendInactiveClass)}}(a.config.plotOptions.heatmap.colorScale.ranges[o])}else"mouseout"===t.type&&r("remove")}},{key:"getActiveConfigSeriesIndex",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"asc",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=this.w,a=0;if(i.config.series.length>1)for(var s=i.config.series.map((function(t,a){return t.data&&t.data.length>0&&-1===i.globals.collapsedSeriesIndices.indexOf(a)&&(!i.globals.comboCharts||0===e.length||e.length&&e.indexOf(i.config.series[a].type)>-1)?a:-1})),r="asc"===t?0:s.length-1;"asc"===t?r=0;"asc"===t?r++:r--)if(-1!==s[r]){a=s[r];break}return a}},{key:"getBarSeriesIndices",value:function(){return this.w.globals.comboCharts?this.w.config.series.map((function(t,e){return"bar"===t.type||"column"===t.type?e:-1})).filter((function(t){return-1!==t})):this.w.config.series.map((function(t,e){return e}))}},{key:"getPreviousPaths",value:function(){var t=this.w;function e(e,i,a){for(var s=e[i].childNodes,r={type:a,paths:[],realIndex:e[i].getAttribute("data:realIndex")},o=0;o0)for(var a=function(e){for(var i=t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t.config.chart.type," .apexcharts-series[data\\:realIndex='").concat(e,"'] rect")),a=[],s=function(t){var e=function(e){return i[t].getAttribute(e)},s={x:parseFloat(e("x")),y:parseFloat(e("y")),width:parseFloat(e("width")),height:parseFloat(e("height"))};a.push({rect:s,color:i[t].getAttribute("color")})},r=0;r0)for(var a=0;a0?t:[]}));return t}}]),t}(),W=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.twoDSeries=[],this.threeDSeries=[],this.twoDSeriesX=[],this.seriesGoals=[],this.coreUtils=new y(this.ctx)}return r(t,[{key:"isMultiFormat",value:function(){return this.isFormatXY()||this.isFormat2DArray()}},{key:"isFormatXY",value:function(){var t=this.w.config.series.slice(),e=new N(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&null!==t[this.activeSeriesIndex].data[0]&&void 0!==t[this.activeSeriesIndex].data[0].x&&null!==t[this.activeSeriesIndex].data[0])return!0}},{key:"isFormat2DArray",value:function(){var t=this.w.config.series.slice(),e=new N(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&void 0!==t[this.activeSeriesIndex].data[0]&&null!==t[this.activeSeriesIndex].data[0]&&t[this.activeSeriesIndex].data[0].constructor===Array)return!0}},{key:"handleFormat2DArray",value:function(t,e){for(var i=this.w.config,a=this.w.globals,s="boxPlot"===i.chart.type||"boxPlot"===i.series[e].type,r=0;r=5?this.twoDSeries.push(x.parseNumber(t[e].data[r][4])):this.twoDSeries.push(x.parseNumber(t[e].data[r][1])),a.dataFormatXNumeric=!0),"datetime"===i.xaxis.type){var o=new Date(t[e].data[r][0]);o=new Date(o).getTime(),this.twoDSeriesX.push(o)}else this.twoDSeriesX.push(t[e].data[r][0]);for(var n=0;n-1&&(r=this.activeSeriesIndex);for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:this.ctx,a=this.w.config,s=this.w.globals,r=new T(i),o=a.labels.length>0?a.labels.slice():a.xaxis.categories.slice();s.isRangeBar="rangeBar"===a.chart.type&&s.isBarHorizontal,s.hasGroups="category"===a.xaxis.type&&a.xaxis.group.groups.length>0,s.hasGroups&&(s.groups=a.xaxis.group.groups);for(var n=function(){for(var t=0;t0&&(this.twoDSeriesX=o,s.seriesX.push(this.twoDSeriesX))),s.labels.push(this.twoDSeriesX);var h=t[l].data.map((function(t){return x.parseNumber(t)}));s.series.push(h)}s.seriesZ.push(this.threeDSeries),void 0!==t[l].name?s.seriesNames.push(t[l].name):s.seriesNames.push("series-"+parseInt(l+1,10)),void 0!==t[l].color?s.seriesColors.push(t[l].color):s.seriesColors.push(void 0)}return this.w}},{key:"parseDataNonAxisCharts",value:function(t){var e=this.w.globals,i=this.w.config;e.series=t.slice(),e.seriesNames=i.labels.slice();for(var a=0;a0)i.labels=e.xaxis.categories;else if(e.labels.length>0)i.labels=e.labels.slice();else if(this.fallbackToCategory){if(i.labels=i.labels[0],i.seriesRange.length&&(i.seriesRange.map((function(t){t.forEach((function(t){i.labels.indexOf(t.x)<0&&t.x&&i.labels.push(t.x)}))})),i.labels=i.labels.filter((function(t,e,i){return i.indexOf(t)===e}))),e.xaxis.convertedCatToNumeric)new X(e).convertCatToNumericXaxis(e,this.ctx,i.seriesX[0]),this._generateExternalLabels(t)}else this._generateExternalLabels(t)}},{key:"_generateExternalLabels",value:function(t){var e=this.w.globals,i=this.w.config,a=[];if(e.axisCharts){if(e.series.length>0)if(this.isFormatXY())for(var s=i.series.map((function(t,e){return t.data.filter((function(t,e,i){return i.findIndex((function(e){return e.x===t.x}))===e}))})),r=s.reduce((function(t,e,i,a){return a[t].length>e.length?t:i}),0),o=0;o4&&void 0!==arguments[4]?arguments[4]:[],r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"12px",o=!(arguments.length>6&&void 0!==arguments[6])||arguments[6],n=this.w,l=void 0===t[a]?"":t[a],h=l,c=n.globals.xLabelFormatter,d=n.config.xaxis.labels.formatter,g=!1,u=new M(this.ctx),f=l;o&&(h=u.xLabelFormat(c,l,f,{i:a,dateFormatter:new T(this.ctx).formatDate,w:n}),void 0!==d&&(h=d(l,t[a],{i:a,dateFormatter:new T(this.ctx).formatDate,w:n})));var p=function(t){var i=null;return e.forEach((function(t){"month"===t.unit?i="year":"day"===t.unit?i="month":"hour"===t.unit?i="day":"minute"===t.unit&&(i="hour")})),i===t};e.length>0?(g=p(e[a].unit),i=e[a].position,h=e[a].value):"datetime"===n.config.xaxis.type&&void 0===d&&(h=""),void 0===h&&(h=""),h=Array.isArray(h)?h:h.toString();var x=new m(this.ctx),b={};b=n.globals.rotateXLabels&&o?x.getTextRects(h,parseInt(r,10),null,"rotate(".concat(n.config.xaxis.labels.rotate," 0 0)"),!1):x.getTextRects(h,parseInt(r,10));var v=!n.config.xaxis.labels.showDuplicates&&this.ctx.timeScale;return!Array.isArray(h)&&(0===h.indexOf("NaN")||0===h.toLowerCase().indexOf("invalid")||h.toLowerCase().indexOf("infinity")>=0||s.indexOf(h)>=0&&v)&&(h=""),{x:i,text:h,textRect:b,isBold:g}}},{key:"checkLabelBasedOnTickamount",value:function(t,e,i){var a=this.w,s=a.config.xaxis.tickAmount;return"dataPoints"===s&&(s=Math.round(a.globals.gridWidth/120)),s>i||t%Math.round(i/(s+1))==0||(e.text=""),e}},{key:"checkForOverflowingLabels",value:function(t,e,i,a,s){var r=this.w;if(0===t&&r.globals.skipFirstTimelinelabel&&(e.text=""),t===i-1&&r.globals.skipLastTimelinelabel&&(e.text=""),r.config.xaxis.labels.hideOverlappingLabels&&a.length>0){var o=s[s.length-1];e.x0){!0===n.config.yaxis[s].opposite&&(t+=a.width);for(var c=e;c>=0;c--){var d=h+e/10+n.config.yaxis[s].labels.offsetY-1;n.globals.isBarHorizontal&&(d=r*c),"heatmap"===n.config.chart.type&&(d+=r/2);var g=l.drawLine(t+i.offsetX-a.width+a.offsetX,d+a.offsetY,t+i.offsetX+a.offsetX,d+a.offsetY,a.color);o.add(g),h+=r}}}}]),t}(),G=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"scaleSvgNode",value:function(t,e){var i=parseFloat(t.getAttributeNS(null,"width")),a=parseFloat(t.getAttributeNS(null,"height"));t.setAttributeNS(null,"width",i*e),t.setAttributeNS(null,"height",a*e),t.setAttributeNS(null,"viewBox","0 0 "+i+" "+a)}},{key:"fixSvgStringForIe11",value:function(t){if(!x.isIE11())return t.replace(/ /g," ");var e=0,i=t.replace(/xmlns="http:\/\/www.w3.org\/2000\/svg"/g,(function(t){return 2===++e?'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev"':t}));return i=(i=i.replace(/xmlns:NS\d+=""/g,"")).replace(/NS\d+:(\w+:\w+=")/g,"$1")}},{key:"getSvgString",value:function(t){null==t&&(t=1);var e=this.w.globals.dom.Paper.svg();if(1!==t){var i=this.w.globals.dom.Paper.node.cloneNode(!0);this.scaleSvgNode(i,t),e=(new XMLSerializer).serializeToString(i)}return this.fixSvgStringForIe11(e)}},{key:"cleanup",value:function(){var t=this.w,e=t.globals.dom.baseEl.getElementsByClassName("apexcharts-xcrosshairs"),i=t.globals.dom.baseEl.getElementsByClassName("apexcharts-ycrosshairs"),a=t.globals.dom.baseEl.querySelectorAll(".apexcharts-zoom-rect, .apexcharts-selection-rect");Array.prototype.forEach.call(a,(function(t){t.setAttribute("width",0)})),e&&e[0]&&(e[0].setAttribute("x",-500),e[0].setAttribute("x1",-500),e[0].setAttribute("x2",-500)),i&&i[0]&&(i[0].setAttribute("y",-100),i[0].setAttribute("y1",-100),i[0].setAttribute("y2",-100))}},{key:"svgUrl",value:function(){this.cleanup();var t=this.getSvgString(),e=new Blob([t],{type:"image/svg+xml;charset=utf-8"});return URL.createObjectURL(e)}},{key:"dataURI",value:function(t){var e=this;return new Promise((function(i){var a=e.w,s=t?t.scale||t.width/a.globals.svgWidth:1;e.cleanup();var r=document.createElement("canvas");r.width=a.globals.svgWidth*s,r.height=parseInt(a.globals.dom.elWrap.style.height,10)*s;var o="transparent"===a.config.chart.background?"#fff":a.config.chart.background,n=r.getContext("2d");n.fillStyle=o,n.fillRect(0,0,r.width*s,r.height*s);var l=e.getSvgString(s);if(window.canvg&&x.isIE11()){var h=window.canvg.Canvg.fromString(n,l,{ignoreClear:!0,ignoreDimensions:!0});h.start();var c=r.msToBlob();h.stop(),i({blob:c})}else{var d="data:image/svg+xml,"+encodeURIComponent(l),g=new Image;g.crossOrigin="anonymous",g.onload=function(){if(n.drawImage(g,0,0),r.msToBlob){var t=r.msToBlob();i({blob:t})}else{var e=r.toDataURL("image/png");i({imgURI:e})}},g.src=d}}))}},{key:"exportToSVG",value:function(){this.triggerDownload(this.svgUrl(),this.w.config.chart.toolbar.export.svg.filename,".svg")}},{key:"exportToPng",value:function(){var t=this;this.dataURI().then((function(e){var i=e.imgURI,a=e.blob;a?navigator.msSaveOrOpenBlob(a,t.w.globals.chartID+".png"):t.triggerDownload(i,t.w.config.chart.toolbar.export.png.filename,".png")}))}},{key:"exportToCSV",value:function(t){var e=this,i=t.series,a=t.fileName,s=t.columnDelimiter,r=void 0===s?",":s,o=t.lineDelimiter,n=void 0===o?"\n":o,l=this.w;i||(i=l.config.series);var h=[],c=[],d="",g=l.globals.series.map((function(t,e){return-1===l.globals.collapsedSeriesIndices.indexOf(e)?t:[]})),f=Math.max.apply(Math,u(i.map((function(t){return t.data?t.data.length:0})))),p=new W(this.ctx),b=new B(this.ctx),v=function(t){var i="";if(l.globals.axisCharts){if("category"===l.config.xaxis.type||l.config.xaxis.convertedCatToNumeric)if(l.globals.isBarHorizontal){var a=l.globals.yLabelFormatters[0],s=new N(e.ctx).getActiveConfigSeriesIndex();i=a(l.globals.labels[t],{seriesIndex:s,dataPointIndex:t,w:l})}else i=b.getLabel(l.globals.labels,l.globals.timescaleLabels,0,t).text;"datetime"===l.config.xaxis.type&&(l.config.xaxis.categories.length?i=l.config.xaxis.categories[t]:l.config.labels.length&&(i=l.config.labels[t]))}else i=l.config.labels[t];return Array.isArray(i)&&(i=i.join(" ")),x.isNumber(i)?i:i.split(r).join("")},m=function(t,e){if(h.length&&0===e&&c.push(h.join(r)),t.data){t.data=t.data.length&&t.data||u(Array(f)).map((function(){return""}));for(var a=0;a=10?l.config.chart.toolbar.export.csv.dateFormatter(s):x.isNumber(s)?s:s.split(r).join("")));for(var o=0;o0&&!s.globals.isBarHorizontal&&(this.xaxisLabels=s.globals.timescaleLabels.slice()),s.config.xaxis.overwriteCategories&&(this.xaxisLabels=s.config.xaxis.overwriteCategories),this.drawnLabels=[],this.drawnLabelsRects=[],"top"===s.config.xaxis.position?this.offY=0:this.offY=s.globals.gridHeight+1,this.offY=this.offY+s.config.xaxis.axisBorder.offsetY,this.isCategoryBarHorizontal="bar"===s.config.chart.type&&s.config.plotOptions.bar.horizontal,this.xaxisFontSize=s.config.xaxis.labels.style.fontSize,this.xaxisFontFamily=s.config.xaxis.labels.style.fontFamily,this.xaxisForeColors=s.config.xaxis.labels.style.colors,this.xaxisBorderWidth=s.config.xaxis.axisBorder.width,this.isCategoryBarHorizontal&&(this.xaxisBorderWidth=s.config.yaxis[0].axisBorder.width.toString()),this.xaxisBorderWidth.indexOf("%")>-1?this.xaxisBorderWidth=s.globals.gridWidth*parseInt(this.xaxisBorderWidth,10)/100:this.xaxisBorderWidth=parseInt(this.xaxisBorderWidth,10),this.xaxisBorderHeight=s.config.xaxis.axisBorder.height,this.yaxis=s.config.yaxis[0]}return r(t,[{key:"drawXaxis",value:function(){var t=this.w,e=new m(this.ctx),i=e.group({class:"apexcharts-xaxis",transform:"translate(".concat(t.config.xaxis.offsetX,", ").concat(t.config.xaxis.offsetY,")")}),a=e.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(t.globals.translateXAxisX,", ").concat(t.globals.translateXAxisY,")")});i.add(a);for(var s=[],r=0;r6&&void 0!==arguments[6]?arguments[6]:{},h=[],c=[],d=this.w,g=l.xaxisFontSize||this.xaxisFontSize,u=l.xaxisFontFamily||this.xaxisFontFamily,f=l.xaxisForeColors||this.xaxisForeColors,p=l.fontWeight||d.config.xaxis.labels.style.fontWeight,x=l.cssClass||d.config.xaxis.labels.style.cssClass,b=d.globals.padHorizontal,v=a.length,m="category"===d.config.xaxis.type?d.globals.dataPoints:v;if(0===m&&v>m&&(m=v),s){var y=m>1?m-1:m;o=d.globals.gridWidth/y,b=b+r(0,o)/2+d.config.xaxis.labels.offsetX}else o=d.globals.gridWidth/m,b=b+r(0,o)+d.config.xaxis.labels.offsetX;for(var w=function(s){var l=b-r(s,o)/2+d.config.xaxis.labels.offsetX;0===s&&1===v&&o/2===b&&1===m&&(l=d.globals.gridWidth/2);var y=n.axesUtils.getLabel(a,d.globals.timescaleLabels,l,s,h,g,t),w=28;d.globals.rotateXLabels&&t&&(w=22),d.config.xaxis.title.text&&"top"===d.config.xaxis.position&&(w+=parseFloat(d.config.xaxis.title.style.fontSize)+2),t||(w=w+parseFloat(g)+(d.globals.xAxisLabelsHeight-d.globals.xAxisGroupLabelsHeight)+(d.globals.rotateXLabels?10:0)),y=void 0!==d.config.xaxis.tickAmount&&"dataPoints"!==d.config.xaxis.tickAmount&&"datetime"!==d.config.xaxis.type?n.axesUtils.checkLabelBasedOnTickamount(s,y,v):n.axesUtils.checkForOverflowingLabels(s,y,v,h,c);if(d.config.xaxis.labels.show){var k=e.drawText({x:y.x,y:n.offY+d.config.xaxis.labels.offsetY+w-("top"===d.config.xaxis.position?d.globals.xAxisHeight+d.config.xaxis.axisTicks.height-2:0),text:y.text,textAnchor:"middle",fontWeight:y.isBold?600:p,fontSize:g,fontFamily:u,foreColor:Array.isArray(f)?t&&d.config.xaxis.convertedCatToNumeric?f[d.globals.minX+s-1]:f[s]:f,isPlainText:!1,cssClass:(t?"apexcharts-xaxis-label ":"apexcharts-xaxis-group-label ")+x});if(i.add(k),k.on("click",(function(t){if("function"==typeof d.config.chart.events.xAxisLabelClick){var e=Object.assign({},d,{labelIndex:s});d.config.chart.events.xAxisLabelClick(t,n.ctx,e)}})),t){var A=document.createElementNS(d.globals.SVGNS,"title");A.textContent=Array.isArray(y.text)?y.text.join(" "):y.text,k.node.appendChild(A),""!==y.text&&(h.push(y.text),c.push(y))}}sa.globals.gridWidth)){var r=this.offY+a.config.xaxis.axisTicks.offsetY;if(e=e+r+a.config.xaxis.axisTicks.height,"top"===a.config.xaxis.position&&(e=r-a.config.xaxis.axisTicks.height),a.config.xaxis.axisTicks.show){var o=new m(this.ctx).drawLine(t+a.config.xaxis.axisTicks.offsetX,r+a.config.xaxis.offsetY,s+a.config.xaxis.axisTicks.offsetX,e+a.config.xaxis.offsetY,a.config.xaxis.axisTicks.color);i.add(o),o.node.classList.add("apexcharts-xaxis-tick")}}}},{key:"getXAxisTicksPositions",value:function(){var t=this.w,e=[],i=this.xaxisLabels.length,a=t.globals.padHorizontal;if(t.globals.timescaleLabels.length>0)for(var s=0;s0){var h=s[s.length-1].getBBox(),c=s[0].getBBox();h.x<-20&&s[s.length-1].parentNode.removeChild(s[s.length-1]),c.x+c.width>t.globals.gridWidth&&!t.globals.isBarHorizontal&&s[0].parentNode.removeChild(s[0]);for(var d=0;d0&&(this.xaxisLabels=i.globals.timescaleLabels.slice())}return r(t,[{key:"drawGridArea",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w,i=new m(this.ctx);null===t&&(t=i.group({class:"apexcharts-grid"}));var a=i.drawLine(e.globals.padHorizontal,1,e.globals.padHorizontal,e.globals.gridHeight,"transparent"),s=i.drawLine(e.globals.padHorizontal,e.globals.gridHeight,e.globals.gridWidth,e.globals.gridHeight,"transparent");return t.add(s),t.add(a),t}},{key:"drawGrid",value:function(){var t=null;return this.w.globals.axisCharts&&(t=this.renderGrid(),this.drawGridArea(t.el)),t}},{key:"createGridMask",value:function(){var t=this.w,e=t.globals,i=new m(this.ctx),a=Array.isArray(t.config.stroke.width)?0:t.config.stroke.width;if(Array.isArray(t.config.stroke.width)){var s=0;t.config.stroke.width.forEach((function(t){s=Math.max(s,t)})),a=s}e.dom.elGridRectMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elGridRectMask.setAttribute("id","gridRectMask".concat(e.cuid)),e.dom.elGridRectMarkerMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elGridRectMarkerMask.setAttribute("id","gridRectMarkerMask".concat(e.cuid)),e.dom.elForecastMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elForecastMask.setAttribute("id","forecastMask".concat(e.cuid)),e.dom.elNonForecastMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elNonForecastMask.setAttribute("id","nonForecastMask".concat(e.cuid));var r=t.config.chart.type,o=0,n=0;("bar"===r||"rangeBar"===r||"candlestick"===r||"boxPlot"===r||t.globals.comboBarCount>0)&&t.globals.isXNumeric&&!t.globals.isBarHorizontal&&(o=t.config.grid.padding.left,n=t.config.grid.padding.right,e.barPadForNumericAxis>o&&(o=e.barPadForNumericAxis,n=e.barPadForNumericAxis)),e.dom.elGridRect=i.drawRect(-a/2-o-2,-a/2,e.gridWidth+a+n+o+4,e.gridHeight+a,0,"#fff");var l=t.globals.markers.largestSize+1;e.dom.elGridRectMarker=i.drawRect(2*-l,2*-l,e.gridWidth+4*l,e.gridHeight+4*l,0,"#fff"),e.dom.elGridRectMask.appendChild(e.dom.elGridRect.node),e.dom.elGridRectMarkerMask.appendChild(e.dom.elGridRectMarker.node);var h=e.dom.baseEl.querySelector("defs");h.appendChild(e.dom.elGridRectMask),h.appendChild(e.dom.elForecastMask),h.appendChild(e.dom.elNonForecastMask),h.appendChild(e.dom.elGridRectMarkerMask)}},{key:"_drawGridLines",value:function(t){var e=t.i,i=t.x1,a=t.y1,s=t.x2,r=t.y2,o=t.xCount,n=t.parent,l=this.w;if(!(0===e&&l.globals.skipFirstTimelinelabel||e===o-1&&l.globals.skipLastTimelinelabel&&!l.config.xaxis.labels.formatter||"radar"===l.config.chart.type)){l.config.grid.xaxis.lines.show&&this._drawGridLine({i:e,x1:i,y1:a,x2:s,y2:r,xCount:o,parent:n});var h=0;if(l.globals.hasGroups&&"between"===l.config.xaxis.tickPlacement){var c=l.globals.groups;if(c){for(var d=0,g=0;d2));s++);return!t.globals.isBarHorizontal||this.isRangeBar?(i=this.xaxisLabels.length,this.isRangeBar&&(a=t.globals.labels.length,t.config.xaxis.tickAmount&&t.config.xaxis.labels.formatter&&(i=t.config.xaxis.tickAmount)),this._drawXYLines({xCount:i,tickAmount:a})):(i=a,a=t.globals.xTickAmount,this._drawInvertedXYLines({xCount:i,tickAmount:a})),this.drawGridBands(i,a),{el:this.elg,elGridBorders:this.elGridBorders,xAxisTickWidth:t.globals.gridWidth/i}}},{key:"drawGridBands",value:function(t,e){var i=this.w;if(void 0!==i.config.grid.row.colors&&i.config.grid.row.colors.length>0)for(var a=0,s=i.globals.gridHeight/e,r=i.globals.gridWidth,o=0,n=0;o=i.config.grid.row.colors.length&&(n=0),this._drawGridBandRect({c:n,x1:0,y1:a,x2:r,y2:s,type:"row"}),a+=i.globals.gridHeight/e;if(void 0!==i.config.grid.column.colors&&i.config.grid.column.colors.length>0)for(var l=i.globals.isBarHorizontal||"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric?t:t-1,h=i.globals.padHorizontal,c=i.globals.padHorizontal+i.globals.gridWidth/l,d=i.globals.gridHeight,g=0,u=0;g=i.config.grid.column.colors.length&&(u=0),this._drawGridBandRect({c:u,x1:h,y1:0,x2:c,y2:d,type:"column"}),h+=i.globals.gridWidth/l}}]),t}(),_=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"niceScale",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4?arguments[4]:void 0,r=this.w,o=Math.abs(e-t);if("dataPoints"===(i=this._adjustTicksForSmallRange(i,a,o))&&(i=r.globals.dataPoints-1),t===Number.MIN_VALUE&&0===e||!x.isNumber(t)&&!x.isNumber(e)||t===Number.MIN_VALUE&&e===-Number.MAX_VALUE){t=0,e=i;var n=this.linearScale(t,e,i);return n}t>e?(console.warn("axis.min cannot be greater than axis.max"),e=t+.1):t===e&&(t=0===t?0:t-.5,e=0===e?2:e+.5);var l=[];o<1&&s&&("candlestick"===r.config.chart.type||"candlestick"===r.config.series[a].type||"boxPlot"===r.config.chart.type||"boxPlot"===r.config.series[a].type||r.globals.isRangeData)&&(e*=1.01);var h=i+1;h<2?h=2:h>2&&(h-=2);var c=o/h,d=Math.floor(x.log10(c)),g=Math.pow(10,d),u=Math.round(c/g);u<1&&(u=1);var f=u*g,p=f*Math.floor(t/f),b=f*Math.ceil(e/f),v=p;if(s&&o>2){for(;l.push(v),!((v+=f)>b););return{result:l,niceMin:l[0],niceMax:l[l.length-1]}}var m=t;(l=[]).push(m);for(var y=Math.abs(e-t)/i,w=0;w<=i;w++)m+=y,l.push(m);return l[l.length-2]>=e&&l.pop(),{result:l,niceMin:l[0],niceMax:l[l.length-1]}}},{key:"linearScale",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,a=arguments.length>3?arguments[3]:void 0,s=Math.abs(e-t);"dataPoints"===(i=this._adjustTicksForSmallRange(i,a,s))&&(i=this.w.globals.dataPoints-1);var r=s/i;i===Number.MAX_VALUE&&(i=10,r=1);for(var o=[],n=t;i>=0;)o.push(n),n+=r,i-=1;return{result:o,niceMin:o[0],niceMax:o[o.length-1]}}},{key:"logarithmicScaleNice",value:function(t,e,i){e<=0&&(e=Math.max(t,i)),t<=0&&(t=Math.min(e,i));for(var a=[],s=Math.ceil(Math.log(e)/Math.log(i)+1),r=Math.floor(Math.log(t)/Math.log(i));r5)a.allSeriesCollapsed=!1,a.yAxisScale[t]=this.logarithmicScale(e,i,r.logBase),a.yAxisScale[t]=r.forceNiceScale?this.logarithmicScaleNice(e,i,r.logBase):this.logarithmicScale(e,i,r.logBase);else if(i!==-Number.MAX_VALUE&&x.isNumber(i))if(a.allSeriesCollapsed=!1,void 0===r.min&&void 0===r.max||r.forceNiceScale){var n=void 0===s.yaxis[t].max&&void 0===s.yaxis[t].min||s.yaxis[t].forceNiceScale;a.yAxisScale[t]=this.niceScale(e,i,r.tickAmount?r.tickAmount:o<5&&o>1?o+1:5,t,n)}else a.yAxisScale[t]=this.linearScale(e,i,r.tickAmount,t);else a.yAxisScale[t]=this.linearScale(0,5,5)}},{key:"setXScale",value:function(t,e){var i=this.w,a=i.globals,s=i.config.xaxis,r=Math.abs(e-t);return e!==-Number.MAX_VALUE&&x.isNumber(e)?a.xAxisScale=this.linearScale(t,e,s.tickAmount?s.tickAmount:r<5&&r>1?r+1:5,0):a.xAxisScale=this.linearScale(0,5,5),a.xAxisScale}},{key:"setMultipleYScales",value:function(){var t=this,e=this.w.globals,i=this.w.config,a=e.minYArr.concat([]),s=e.maxYArr.concat([]),r=[];i.yaxis.forEach((function(e,o){var n=o;i.series.forEach((function(t,i){t.name===e.seriesName&&(n=i,o!==i?r.push({index:i,similarIndex:o,alreadyExists:!0}):r.push({index:i}))}));var l=a[n],h=s[n];t.setYScaleForIndex(o,l,h)})),this.sameScaleInMultipleAxes(a,s,r)}},{key:"sameScaleInMultipleAxes",value:function(t,e,i){var a=this,s=this.w.config,r=this.w.globals,o=[];i.forEach((function(t){t.alreadyExists&&(void 0===o[t.index]&&(o[t.index]=[]),o[t.index].push(t.index),o[t.index].push(t.similarIndex))})),r.yAxisSameScaleIndices=o,o.forEach((function(t,e){o.forEach((function(i,a){var s,r;e!==a&&(s=t,r=i,s.filter((function(t){return-1!==r.indexOf(t)}))).length>0&&(o[e]=o[e].concat(o[a]))}))}));var n=o.map((function(t){return t.filter((function(e,i){return t.indexOf(e)===i}))})).map((function(t){return t.sort()}));o=o.filter((function(t){return!!t}));var l=n.slice(),h=l.map((function(t){return JSON.stringify(t)}));l=l.filter((function(t,e){return h.indexOf(JSON.stringify(t))===e}));var c=[],d=[];t.forEach((function(t,i){l.forEach((function(a,s){a.indexOf(i)>-1&&(void 0===c[s]&&(c[s]=[],d[s]=[]),c[s].push({key:i,value:t}),d[s].push({key:i,value:e[i]}))}))}));var g=Array.apply(null,Array(l.length)).map(Number.prototype.valueOf,Number.MIN_VALUE),u=Array.apply(null,Array(l.length)).map(Number.prototype.valueOf,-Number.MAX_VALUE);c.forEach((function(t,e){t.forEach((function(t,i){g[e]=Math.min(t.value,g[e])}))})),d.forEach((function(t,e){t.forEach((function(t,i){u[e]=Math.max(t.value,u[e])}))})),t.forEach((function(t,e){d.forEach((function(t,i){var o=g[i],n=u[i];s.chart.stacked&&(n=0,t.forEach((function(t,e){t.value!==-Number.MAX_VALUE&&(n+=t.value),o!==Number.MIN_VALUE&&(o+=c[i][e].value)}))),t.forEach((function(i,l){t[l].key===e&&(void 0!==s.yaxis[e].min&&(o="function"==typeof s.yaxis[e].min?s.yaxis[e].min(r.minY):s.yaxis[e].min),void 0!==s.yaxis[e].max&&(n="function"==typeof s.yaxis[e].max?s.yaxis[e].max(r.maxY):s.yaxis[e].max),a.setYScaleForIndex(e,o,n))}))}))}))}},{key:"autoScaleY",value:function(t,e,i){t||(t=this);var a=t.w;if(a.globals.isMultipleYAxis||a.globals.collapsedSeries.length)return console.warn("autoScaleYaxis is not supported in a multi-yaxis chart."),e;var s=a.globals.seriesX[0],r=a.config.chart.stacked;return e.forEach((function(t,o){for(var n=0,l=0;l=i.xaxis.min){n=l;break}var h,c,d=a.globals.minYArr[o],g=a.globals.maxYArr[o],u=a.globals.stackedSeriesTotals;a.globals.series.forEach((function(o,l){var f=o[n];r?(f=u[n],h=c=f,u.forEach((function(t,e){s[e]<=i.xaxis.max&&s[e]>=i.xaxis.min&&(t>c&&null!==t&&(c=t),o[e]=i.xaxis.min){var r=t,o=t;a.globals.series.forEach((function(i,a){null!==t&&(r=Math.min(i[e],r),o=Math.max(i[e],o))})),o>c&&null!==o&&(c=o),rd&&(h=d),e.length>1?(e[l].min=void 0===t.min?h:t.min,e[l].max=void 0===t.max?c:t.max):(e[0].min=void 0===t.min?h:t.min,e[0].max=void 0===t.max?c:t.max)}))})),e}}]),t}(),U=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.scales=new _(e)}return r(t,[{key:"init",value:function(){this.setYRange(),this.setXRange(),this.setZRange()}},{key:"getMinYMaxY",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Number.MAX_VALUE,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-Number.MAX_VALUE,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w.config,r=this.w.globals,o=-Number.MAX_VALUE,n=Number.MIN_VALUE;null===a&&(a=t+1);var l=r.series,h=l,c=l;"candlestick"===s.chart.type?(h=r.seriesCandleL,c=r.seriesCandleH):"boxPlot"===s.chart.type?(h=r.seriesCandleO,c=r.seriesCandleC):r.isRangeData&&(h=r.seriesRangeStart,c=r.seriesRangeEnd);for(var d=t;dh[d][g]&&h[d][g]<0&&(n=h[d][g])):r.hasNullValues=!0}}return"rangeBar"===s.chart.type&&r.seriesRangeStart.length&&r.isBarHorizontal&&(n=e),"bar"===s.chart.type&&(n<0&&o<0&&(o=0),n===Number.MIN_VALUE&&(n=0)),{minY:n,maxY:o,lowestY:e,highestY:i}}},{key:"setYRange",value:function(){var t=this.w.globals,e=this.w.config;t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE;var i=Number.MAX_VALUE;if(t.isMultipleYAxis)for(var a=0;a=0&&i<=10||void 0!==e.yaxis[0].min||void 0!==e.yaxis[0].max)&&(o=0),t.minY=i-5*o/100,i>0&&t.minY<0&&(t.minY=0),t.maxY=t.maxY+5*o/100}if(e.yaxis.forEach((function(e,i){void 0!==e.max&&("number"==typeof e.max?t.maxYArr[i]=e.max:"function"==typeof e.max&&(t.maxYArr[i]=e.max(t.isMultipleYAxis?t.maxYArr[i]:t.maxY)),t.maxY=t.maxYArr[i]),void 0!==e.min&&("number"==typeof e.min?t.minYArr[i]=e.min:"function"==typeof e.min&&(t.minYArr[i]=e.min(t.isMultipleYAxis?t.minYArr[i]===Number.MIN_VALUE?0:t.minYArr[i]:t.minY)),t.minY=t.minYArr[i])})),t.isBarHorizontal){["min","max"].forEach((function(i){void 0!==e.xaxis[i]&&"number"==typeof e.xaxis[i]&&("min"===i?t.minY=e.xaxis[i]:t.maxY=e.xaxis[i])}))}return t.isMultipleYAxis?(this.scales.setMultipleYScales(),t.minY=i,t.yAxisScale.forEach((function(e,i){t.minYArr[i]=e.niceMin,t.maxYArr[i]=e.niceMax}))):(this.scales.setYScaleForIndex(0,t.minY,t.maxY),t.minY=t.yAxisScale[0].niceMin,t.maxY=t.yAxisScale[0].niceMax,t.minYArr[0]=t.yAxisScale[0].niceMin,t.maxYArr[0]=t.yAxisScale[0].niceMax),{minY:t.minY,maxY:t.maxY,minYArr:t.minYArr,maxYArr:t.maxYArr,yAxisScale:t.yAxisScale}}},{key:"setXRange",value:function(){var t=this.w.globals,e=this.w.config,i="numeric"===e.xaxis.type||"datetime"===e.xaxis.type||"category"===e.xaxis.type&&!t.noLabelsProvided||t.noLabelsProvided||t.isXNumeric;if(t.isXNumeric&&function(){for(var e=0;et.dataPoints&&0!==t.dataPoints&&(a=t.dataPoints-1)):"dataPoints"===e.xaxis.tickAmount?(t.series.length>1&&(a=t.series[t.maxValsInArrayIndex].length-1),t.isXNumeric&&(a=t.maxX-t.minX-1)):a=e.xaxis.tickAmount,t.xTickAmount=a,void 0!==e.xaxis.max&&"number"==typeof e.xaxis.max&&(t.maxX=e.xaxis.max),void 0!==e.xaxis.min&&"number"==typeof e.xaxis.min&&(t.minX=e.xaxis.min),void 0!==e.xaxis.range&&(t.minX=t.maxX-e.xaxis.range),t.minX!==Number.MAX_VALUE&&t.maxX!==-Number.MAX_VALUE)if(e.xaxis.convertedCatToNumeric&&!t.dataFormatXNumeric){for(var s=[],r=t.minX-1;r0&&(t.xAxisScale=this.scales.linearScale(1,t.labels.length,a-1),t.seriesX=t.labels.slice());i&&(t.labels=t.xAxisScale.result.slice())}return t.isBarHorizontal&&t.labels.length&&(t.xTickAmount=t.labels.length),this._handleSingleDataPoint(),this._getMinXDiff(),{minX:t.minX,maxX:t.maxX}}},{key:"setZRange",value:function(){var t=this.w.globals;if(t.isDataXYZ)for(var e=0;e0){var s=e-a[i-1];s>0&&(t.minXDiff=Math.min(s,t.minXDiff))}})),1!==t.dataPoints&&t.minXDiff!==Number.MAX_VALUE||(t.minXDiff=.5)}))}},{key:"_setStackedMinMax",value:function(){var t=this.w.globals,e=[],i=[];if(t.series.length)for(var a=0;a0?s=s+parseFloat(t.series[o][a])+1e-4:r+=parseFloat(t.series[o][a])),o===t.series.length-1&&(e.push(s),i.push(r));for(var n=0;n=0;b--)x(b);if(void 0!==i.config.yaxis[t].title.text){var v=a.group({class:"apexcharts-yaxis-title"}),y=0;i.config.yaxis[t].opposite&&(y=i.globals.translateYAxisX[t]);var w=a.drawText({x:y,y:i.globals.gridHeight/2+i.globals.translateY+i.config.yaxis[t].title.offsetY,text:i.config.yaxis[t].title.text,textAnchor:"end",foreColor:i.config.yaxis[t].title.style.color,fontSize:i.config.yaxis[t].title.style.fontSize,fontWeight:i.config.yaxis[t].title.style.fontWeight,fontFamily:i.config.yaxis[t].title.style.fontFamily,cssClass:"apexcharts-yaxis-title-text "+i.config.yaxis[t].title.style.cssClass});v.add(w),l.add(v)}var k=i.config.yaxis[t].axisBorder,A=31+k.offsetX;if(i.config.yaxis[t].opposite&&(A=-31-k.offsetX),k.show){var S=a.drawLine(A,i.globals.translateY+k.offsetY-2,A,i.globals.gridHeight+i.globals.translateY+k.offsetY+2,k.color,0,k.width);l.add(S)}return i.config.yaxis[t].axisTicks.show&&this.axesUtils.drawYAxisTicks(A,c,k,i.config.yaxis[t].axisTicks,t,d,l),l}},{key:"drawYaxisInversed",value:function(t){var e=this.w,i=new m(this.ctx),a=i.group({class:"apexcharts-xaxis apexcharts-yaxis-inversed"}),s=i.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(e.globals.translateXAxisX,", ").concat(e.globals.translateXAxisY,")")});a.add(s);var r=e.globals.yAxisScale[t].result.length-1,o=e.globals.gridWidth/r+.1,n=o+e.config.xaxis.labels.offsetX,l=e.globals.xLabelFormatter,h=e.globals.yAxisScale[t].result.slice(),c=e.globals.timescaleLabels;c.length>0&&(this.xaxisLabels=c.slice(),r=(h=c.slice()).length),h=this.axesUtils.checkForReversedLabels(t,h);var d=c.length;if(e.config.xaxis.labels.show)for(var g=d?0:r;d?g=0;d?g++:g--){var u=h[g];u=l(u,g,e);var f=e.globals.gridWidth+e.globals.padHorizontal-(n-o+e.config.xaxis.labels.offsetX);if(c.length){var p=this.axesUtils.getLabel(h,c,f,g,this.drawnLabels,this.xaxisFontSize);f=p.x,u=p.text,this.drawnLabels.push(p.text),0===g&&e.globals.skipFirstTimelinelabel&&(u=""),g===h.length-1&&e.globals.skipLastTimelinelabel&&(u="")}var x=i.drawText({x:f,y:this.xAxisoffX+e.config.xaxis.labels.offsetY+30-("top"===e.config.xaxis.position?e.globals.xAxisHeight+e.config.xaxis.axisTicks.height-2:0),text:u,textAnchor:"middle",foreColor:Array.isArray(this.xaxisForeColors)?this.xaxisForeColors[t]:this.xaxisForeColors,fontSize:this.xaxisFontSize,fontFamily:this.xaxisFontFamily,fontWeight:e.config.xaxis.labels.style.fontWeight,isPlainText:!1,cssClass:"apexcharts-xaxis-label "+e.config.xaxis.labels.style.cssClass});s.add(x),x.tspan(u);var b=document.createElementNS(e.globals.SVGNS,"title");b.textContent=u,x.node.appendChild(b),n+=o}return this.inversedYAxisTitleText(a),this.inversedYAxisBorder(a),a}},{key:"inversedYAxisBorder",value:function(t){var e=this.w,i=new m(this.ctx),a=e.config.xaxis.axisBorder;if(a.show){var s=0;"bar"===e.config.chart.type&&e.globals.isXNumeric&&(s-=15);var r=i.drawLine(e.globals.padHorizontal+s+a.offsetX,this.xAxisoffX,e.globals.gridWidth,this.xAxisoffX,a.color,0,a.height);this.elgrid&&this.elgrid.elGridBorders?this.elgrid.elGridBorders.add(r):t.add(r)}}},{key:"inversedYAxisTitleText",value:function(t){var e=this.w,i=new m(this.ctx);if(void 0!==e.config.xaxis.title.text){var a=i.group({class:"apexcharts-xaxis-title apexcharts-yaxis-title-inversed"}),s=i.drawText({x:e.globals.gridWidth/2+e.config.xaxis.title.offsetX,y:this.xAxisoffX+parseFloat(this.xaxisFontSize)+parseFloat(e.config.xaxis.title.style.fontSize)+e.config.xaxis.title.offsetY+20,text:e.config.xaxis.title.text,textAnchor:"middle",fontSize:e.config.xaxis.title.style.fontSize,fontFamily:e.config.xaxis.title.style.fontFamily,fontWeight:e.config.xaxis.title.style.fontWeight,foreColor:e.config.xaxis.title.style.color,cssClass:"apexcharts-xaxis-title-text "+e.config.xaxis.title.style.cssClass});a.add(s),t.add(a)}}},{key:"yAxisTitleRotate",value:function(t,e){var i=this.w,a=new m(this.ctx),s={width:0,height:0},r={width:0,height:0},o=i.globals.dom.baseEl.querySelector(" .apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-texts-g"));null!==o&&(s=o.getBoundingClientRect());var n=i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-title text"));if(null!==n&&(r=n.getBoundingClientRect()),null!==n){var l=this.xPaddingForYAxisTitle(t,s,r,e);n.setAttribute("x",l.xPos-(e?10:0))}if(null!==n){var h=a.rotateAroundCenter(n);n.setAttribute("transform","rotate(".concat(e?-1*i.config.yaxis[t].title.rotate:i.config.yaxis[t].title.rotate," ").concat(h.x," ").concat(h.y,")"))}}},{key:"xPaddingForYAxisTitle",value:function(t,e,i,a){var s=this.w,r=0,o=0,n=10;return void 0===s.config.yaxis[t].title.text||t<0?{xPos:o,padd:0}:(a?(o=e.width+s.config.yaxis[t].title.offsetX+i.width/2+n/2,0===(r+=1)&&(o-=n/2)):(o=-1*e.width+s.config.yaxis[t].title.offsetX+n/2+i.width/2,s.globals.isBarHorizontal&&(n=25,o=-1*e.width-s.config.yaxis[t].title.offsetX-n)),{xPos:o,padd:n})}},{key:"setYAxisXPosition",value:function(t,e){var i=this.w,a=0,s=0,r=18,o=1;i.config.yaxis.length>1&&(this.multipleYs=!0),i.config.yaxis.map((function(n,l){var h=i.globals.ignoreYAxisIndexes.indexOf(l)>-1||!n.show||n.floating||0===t[l].width,c=t[l].width+e[l].width;n.opposite?i.globals.isBarHorizontal?(s=i.globals.gridWidth+i.globals.translateX-1,i.globals.translateYAxisX[l]=s-n.labels.offsetX):(s=i.globals.gridWidth+i.globals.translateX+o,h||(o=o+c+20),i.globals.translateYAxisX[l]=s-n.labels.offsetX+20):(a=i.globals.translateX-r,h||(r=r+c+20),i.globals.translateYAxisX[l]=a+n.labels.offsetX)}))}},{key:"setYAxisTextAlignments",value:function(){var t=this.w,e=t.globals.dom.baseEl.getElementsByClassName("apexcharts-yaxis");(e=x.listToArray(e)).forEach((function(e,i){var a=t.config.yaxis[i];if(a&&!a.floating&&void 0!==a.labels.align){var s=t.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-texts-g")),r=t.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-label"));r=x.listToArray(r);var o=s.getBoundingClientRect();"left"===a.labels.align?(r.forEach((function(t,e){t.setAttribute("text-anchor","start")})),a.opposite||s.setAttribute("transform","translate(-".concat(o.width,", 0)"))):"center"===a.labels.align?(r.forEach((function(t,e){t.setAttribute("text-anchor","middle")})),s.setAttribute("transform","translate(".concat(o.width/2*(a.opposite?1:-1),", 0)"))):"right"===a.labels.align&&(r.forEach((function(t,e){t.setAttribute("text-anchor","end")})),a.opposite&&s.setAttribute("transform","translate(".concat(o.width,", 0)")))}}))}}]),t}(),Z=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.documentEvent=x.bind(this.documentEvent,this)}return r(t,[{key:"addEventListener",value:function(t,e){var i=this.w;i.globals.events.hasOwnProperty(t)?i.globals.events[t].push(e):i.globals.events[t]=[e]}},{key:"removeEventListener",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){var a=i.globals.events[t].indexOf(e);-1!==a&&i.globals.events[t].splice(a,1)}}},{key:"fireEvent",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){e&&e.length||(e=[]);for(var a=i.globals.events[t],s=a.length,r=0;r0&&(e=this.w.config.chart.locales.concat(window.Apex.chart.locales));var i=e.filter((function(e){return e.name===t}))[0];if(!i)throw new Error("Wrong locale name provided. Please make sure you set the correct locale name in options");var a=x.extend(C,i);this.w.globals.locale=a.options}}]),t}(),J=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"drawAxis",value:function(t,e){var i,a,s=this,r=this.w.globals,o=this.w.config,n=new V(this.ctx,e),l=new q(this.ctx,e);r.axisCharts&&"radar"!==t&&(r.isBarHorizontal?(a=l.drawYaxisInversed(0),i=n.drawXaxisInversed(0),r.dom.elGraphical.add(i),r.dom.elGraphical.add(a)):(i=n.drawXaxis(),r.dom.elGraphical.add(i),o.yaxis.map((function(t,e){if(-1===r.ignoreYAxisIndexes.indexOf(e)&&(a=l.drawYaxis(e),r.dom.Paper.add(a),"back"===s.w.config.grid.position)){var i=r.dom.Paper.children()[1];i.remove(),r.dom.Paper.add(i)}}))))}}]),t}(),Q=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"drawXCrosshairs",value:function(){var t=this.w,e=new m(this.ctx),i=new v(this.ctx),a=t.config.xaxis.crosshairs.fill.gradient,s=t.config.xaxis.crosshairs.dropShadow,r=t.config.xaxis.crosshairs.fill.type,o=a.colorFrom,n=a.colorTo,l=a.opacityFrom,h=a.opacityTo,c=a.stops,d=s.enabled,g=s.left,u=s.top,f=s.blur,p=s.color,b=s.opacity,y=t.config.xaxis.crosshairs.fill.color;if(t.config.xaxis.crosshairs.show){"gradient"===r&&(y=e.drawGradient("vertical",o,n,l,h,null,c,null));var w=e.drawRect();1===t.config.xaxis.crosshairs.width&&(w=e.drawLine());var k=t.globals.gridHeight;(!x.isNumber(k)||k<0)&&(k=0);var A=t.config.xaxis.crosshairs.width;(!x.isNumber(A)||A<0)&&(A=0),w.attr({class:"apexcharts-xcrosshairs",x:0,y:0,y2:k,width:A,height:k,fill:y,filter:"none","fill-opacity":t.config.xaxis.crosshairs.opacity,stroke:t.config.xaxis.crosshairs.stroke.color,"stroke-width":t.config.xaxis.crosshairs.stroke.width,"stroke-dasharray":t.config.xaxis.crosshairs.stroke.dashArray}),d&&(w=i.dropShadow(w,{left:g,top:u,blur:f,color:p,opacity:b})),t.globals.dom.elGraphical.add(w)}}},{key:"drawYCrosshairs",value:function(){var t=this.w,e=new m(this.ctx),i=t.config.yaxis[0].crosshairs,a=t.globals.barPadForNumericAxis;if(t.config.yaxis[0].crosshairs.show){var s=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,i.stroke.dashArray,i.stroke.width);s.attr({class:"apexcharts-ycrosshairs"}),t.globals.dom.elGraphical.add(s)}var r=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,0,0);r.attr({class:"apexcharts-ycrosshairs-hidden"}),t.globals.dom.elGraphical.add(r)}}]),t}(),K=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"checkResponsiveConfig",value:function(t){var e=this,i=this.w,a=i.config;if(0!==a.responsive.length){var s=a.responsive.slice();s.sort((function(t,e){return t.breakpoint>e.breakpoint?1:e.breakpoint>t.breakpoint?-1:0})).reverse();var r=new E({}),o=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=s[0].breakpoint,o=window.innerWidth>0?window.innerWidth:screen.width;if(o>a){var n=y.extendArrayProps(r,i.globals.initialConfig,i);t=x.extend(n,t),t=x.extend(i.config,t),e.overrideResponsiveOptions(t)}else for(var l=0;l0&&"function"==typeof e.config.colors[0]&&(e.globals.colors=e.config.series.map((function(i,a){var s=e.config.colors[a];return s||(s=e.config.colors[0]),"function"==typeof s?(t.isColorFn=!0,s({value:e.globals.axisCharts?e.globals.series[a][0]?e.globals.series[a][0]:0:e.globals.series[a],seriesIndex:a,dataPointIndex:a,w:e})):s})))),e.globals.seriesColors.map((function(t,i){t&&(e.globals.colors[i]=t)})),e.config.theme.monochrome.enabled){var a=[],s=e.globals.series.length;(this.isBarDistributed||this.isHeatmapDistributed)&&(s=e.globals.series[0].length*e.globals.series.length);for(var r=e.config.theme.monochrome.color,o=1/(s/e.config.theme.monochrome.shadeIntensity),n=e.config.theme.monochrome.shadeTo,l=0,h=0;h2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=e||a.globals.series.length;if(null===i&&(i=this.isBarDistributed||this.isHeatmapDistributed||"heatmap"===a.config.chart.type&&a.config.plotOptions.heatmap.colorScale.inverse),i&&a.globals.series.length&&(s=a.globals.series[a.globals.maxValsInArrayIndex].length*a.globals.series.length),t.lengtht.globals.svgWidth&&(this.dCtx.lgRect.width=t.globals.svgWidth/1.5),this.dCtx.lgRect}},{key:"getLargestStringFromMultiArr",value:function(t,e){var i=t;if(this.w.globals.isMultiLineX){var a=e.map((function(t,e){return Array.isArray(t)?t.length:1})),s=Math.max.apply(Math,u(a));i=e[a.indexOf(s)]}return i}}]),t}(),at=function(){function t(e){a(this,t),this.w=e.w,this.dCtx=e}return r(t,[{key:"getxAxisLabelsCoords",value:function(){var t,e=this.w,i=e.globals.labels.slice();if(e.config.xaxis.convertedCatToNumeric&&0===i.length&&(i=e.globals.categoryLabels),e.globals.timescaleLabels.length>0){var a=this.getxAxisTimeScaleLabelsCoords();t={width:a.width,height:a.height},e.globals.rotateXLabels=!1}else{this.dCtx.lgWidthForSideLegends="left"!==e.config.legend.position&&"right"!==e.config.legend.position||e.config.legend.floating?0:this.dCtx.lgRect.width;var s=e.globals.xLabelFormatter,r=x.getLargestStringFromArr(i),o=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,i);e.globals.isBarHorizontal&&(o=r=e.globals.yAxisScale[0].result.reduce((function(t,e){return t.length>e.length?t:e}),0));var n=new M(this.dCtx.ctx),l=r;r=n.xLabelFormat(s,r,l,{i:void 0,dateFormatter:new T(this.dCtx.ctx).formatDate,w:e}),o=n.xLabelFormat(s,o,l,{i:void 0,dateFormatter:new T(this.dCtx.ctx).formatDate,w:e}),(e.config.xaxis.convertedCatToNumeric&&void 0===r||""===String(r).trim())&&(o=r="1");var h=new m(this.dCtx.ctx),c=h.getTextRects(r,e.config.xaxis.labels.style.fontSize),d=c;if(r!==o&&(d=h.getTextRects(o,e.config.xaxis.labels.style.fontSize)),(t={width:c.width>=d.width?c.width:d.width,height:c.height>=d.height?c.height:d.height}).width*i.length>e.globals.svgWidth-this.dCtx.lgWidthForSideLegends-this.dCtx.yAxisWidth-this.dCtx.gridPad.left-this.dCtx.gridPad.right&&0!==e.config.xaxis.labels.rotate||e.config.xaxis.labels.rotateAlways){if(!e.globals.isBarHorizontal){e.globals.rotateXLabels=!0;var g=function(t){return h.getTextRects(t,e.config.xaxis.labels.style.fontSize,e.config.xaxis.labels.style.fontFamily,"rotate(".concat(e.config.xaxis.labels.rotate," 0 0)"),!1)};c=g(r),r!==o&&(d=g(o)),t.height=(c.height>d.height?c.height:d.height)/1.5,t.width=c.width>d.width?c.width:d.width}}else e.globals.rotateXLabels=!1}return e.config.xaxis.labels.show||(t={width:0,height:0}),{width:t.width,height:t.height}}},{key:"getxAxisGroupLabelsCoords",value:function(){var t,e=this.w;if(!e.globals.hasGroups)return{width:0,height:0};var i,a=(null===(t=e.config.xaxis.group.style)||void 0===t?void 0:t.fontSize)||e.config.xaxis.labels.style.fontSize,s=e.globals.groups.map((function(t){return t.title})),r=x.getLargestStringFromArr(s),o=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,s),n=new m(this.dCtx.ctx),l=n.getTextRects(r,a),h=l;return r!==o&&(h=n.getTextRects(o,a)),i={width:l.width>=h.width?l.width:h.width,height:l.height>=h.height?l.height:h.height},e.config.xaxis.labels.show||(i={width:0,height:0}),{width:i.width,height:i.height}}},{key:"getxAxisTitleCoords",value:function(){var t=this.w,e=0,i=0;if(void 0!==t.config.xaxis.title.text){var a=new m(this.dCtx.ctx).getTextRects(t.config.xaxis.title.text,t.config.xaxis.title.style.fontSize);e=a.width,i=a.height}return{width:e,height:i}}},{key:"getxAxisTimeScaleLabelsCoords",value:function(){var t,e=this.w;this.dCtx.timescaleLabels=e.globals.timescaleLabels.slice();var i=this.dCtx.timescaleLabels.map((function(t){return t.value})),a=i.reduce((function(t,e){return void 0===t?(console.error("You have possibly supplied invalid Date format. Please supply a valid JavaScript Date"),0):t.length>e.length?t:e}),0);return 1.05*(t=new m(this.dCtx.ctx).getTextRects(a,e.config.xaxis.labels.style.fontSize)).width*i.length>e.globals.gridWidth&&0!==e.config.xaxis.labels.rotate&&(e.globals.overlappingXLabels=!0),t}},{key:"additionalPaddingXLabels",value:function(t){var e=this,i=this.w,a=i.globals,s=i.config,r=s.xaxis.type,o=t.width;a.skipLastTimelinelabel=!1,a.skipFirstTimelinelabel=!1;var n=i.config.yaxis[0].opposite&&i.globals.isBarHorizontal,l=function(t,n){(function(t){return-1!==a.collapsedSeriesIndices.indexOf(t)})(n)||function(t){if(e.dCtx.timescaleLabels&&e.dCtx.timescaleLabels.length){var n=e.dCtx.timescaleLabels[0],l=e.dCtx.timescaleLabels[e.dCtx.timescaleLabels.length-1].position+o/1.75-e.dCtx.yAxisWidthRight,h=n.position-o/1.75+e.dCtx.yAxisWidthLeft,c="right"===i.config.legend.position&&e.dCtx.lgRect.width>0?e.dCtx.lgRect.width:0;l>a.svgWidth-a.translateX-c&&(a.skipLastTimelinelabel=!0),h<-(t.show&&!t.floating||"bar"!==s.chart.type&&"candlestick"!==s.chart.type&&"rangeBar"!==s.chart.type&&"boxPlot"!==s.chart.type?10:o/1.75)&&(a.skipFirstTimelinelabel=!0)}else"datetime"===r?e.dCtx.gridPad.rightString(n.niceMax).length?c:n.niceMax,g=h(d,{seriesIndex:o,dataPointIndex:-1,w:e}),u=g;if(void 0!==g&&0!==g.length||(g=d),e.globals.isBarHorizontal){a=0;var f=e.globals.labels.slice();g=h(g=x.getLargestStringFromArr(f),{seriesIndex:o,dataPointIndex:-1,w:e}),u=t.dCtx.dimHelpers.getLargestStringFromMultiArr(g,f)}var p=new m(t.dCtx.ctx),b="rotate(".concat(r.labels.rotate," 0 0)"),v=p.getTextRects(g,r.labels.style.fontSize,r.labels.style.fontFamily,b,!1),y=v;g!==u&&(y=p.getTextRects(u,r.labels.style.fontSize,r.labels.style.fontFamily,b,!1)),i.push({width:(l>y.width||l>v.width?l:y.width>v.width?y.width:v.width)+a,height:y.height>v.height?y.height:v.height})}else i.push({width:0,height:0})})),i}},{key:"getyAxisTitleCoords",value:function(){var t=this,e=this.w,i=[];return e.config.yaxis.map((function(e,a){if(e.show&&void 0!==e.title.text){var s=new m(t.dCtx.ctx),r="rotate(".concat(e.title.rotate," 0 0)"),o=s.getTextRects(e.title.text,e.title.style.fontSize,e.title.style.fontFamily,r,!1);i.push({width:o.width,height:o.height})}else i.push({width:0,height:0})})),i}},{key:"getTotalYAxisWidth",value:function(){var t=this.w,e=0,i=0,a=0,s=t.globals.yAxisScale.length>1?10:0,r=new B(this.dCtx.ctx),o=function(o,n){var l=t.config.yaxis[n].floating,h=0;o.width>0&&!l?(h=o.width+s,function(e){return t.globals.ignoreYAxisIndexes.indexOf(e)>-1}(n)&&(h=h-o.width-s)):h=l||r.isYAxisHidden(n)?0:5,t.config.yaxis[n].opposite?a+=h:i+=h,e+=h};return t.globals.yLabelsCoords.map((function(t,e){o(t,e)})),t.globals.yTitleCoords.map((function(t,e){o(t,e)})),t.globals.isBarHorizontal&&!t.config.yaxis[0].floating&&(e=t.globals.yLabelsCoords[0].width+t.globals.yTitleCoords[0].width+15),this.dCtx.yAxisWidthLeft=i,this.dCtx.yAxisWidthRight=a,e}}]),t}(),rt=function(){function t(e){a(this,t),this.w=e.w,this.dCtx=e}return r(t,[{key:"gridPadForColumnsInNumericAxis",value:function(t){var e=this.w;if(e.globals.noData||e.globals.allSeriesCollapsed)return 0;var i=function(t){return"bar"===t||"rangeBar"===t||"candlestick"===t||"boxPlot"===t},a=e.config.chart.type,s=0,r=i(a)?e.config.series.length:1;if(e.globals.comboBarCount>0&&(r=e.globals.comboBarCount),e.globals.collapsedSeries.forEach((function(t){i(t.type)&&(r-=1)})),e.config.chart.stacked&&(r=1),(i(a)||e.globals.comboBarCount>0)&&e.globals.isXNumeric&&!e.globals.isBarHorizontal&&r>0){var o,n,l=Math.abs(e.globals.initialMaxX-e.globals.initialMinX);l<=3&&(l=e.globals.dataPoints),o=l/t,e.globals.minXDiff&&e.globals.minXDiff/o>0&&(n=e.globals.minXDiff/o),n>t/2&&(n/=2),(s=n/r*parseInt(e.config.plotOptions.bar.columnWidth,10)/100)<1&&(s=1),s=s/(r>1?1:1.5)+5,e.globals.barPadForNumericAxis=s}return s}},{key:"gridPadFortitleSubtitle",value:function(){var t=this,e=this.w,i=e.globals,a=this.dCtx.isSparkline||!e.globals.axisCharts?0:10;["title","subtitle"].forEach((function(i){void 0!==e.config[i].text?a+=e.config[i].margin:a+=t.dCtx.isSparkline||!e.globals.axisCharts?0:5})),!e.config.legend.show||"bottom"!==e.config.legend.position||e.config.legend.floating||e.globals.axisCharts||(a+=10);var s=this.dCtx.dimHelpers.getTitleSubtitleCoords("title"),r=this.dCtx.dimHelpers.getTitleSubtitleCoords("subtitle");i.gridHeight=i.gridHeight-s.height-r.height-a,i.translateY=i.translateY+s.height+r.height+a}},{key:"setGridXPosForDualYAxis",value:function(t,e){var i=this.w,a=new B(this.dCtx.ctx);i.config.yaxis.map((function(s,r){-1!==i.globals.ignoreYAxisIndexes.indexOf(r)||s.floating||a.isYAxisHidden(r)||(s.opposite&&(i.globals.translateX=i.globals.translateX-(e[r].width+t[r].width)-parseInt(i.config.yaxis[r].labels.style.fontSize,10)/1.2-12),i.globals.translateX<2&&(i.globals.translateX=2))}))}}]),t}(),ot=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.lgRect={},this.yAxisWidth=0,this.yAxisWidthLeft=0,this.yAxisWidthRight=0,this.xAxisHeight=0,this.isSparkline=this.w.config.chart.sparkline.enabled,this.dimHelpers=new it(this),this.dimYAxis=new st(this),this.dimXAxis=new at(this),this.dimGrid=new rt(this),this.lgWidthForSideLegends=0,this.gridPad=this.w.config.grid.padding,this.xPadRight=0,this.xPadLeft=0}return r(t,[{key:"plotCoords",value:function(){var t=this,e=this.w,i=e.globals;this.lgRect=this.dimHelpers.getLegendsRect(),this.isSparkline&&(e.config.markers.discrete.length>0||e.config.markers.size>0)&&Object.entries(this.gridPad).forEach((function(e){var i=g(e,2),a=i[0],s=i[1];t.gridPad[a]=Math.max(s,t.w.globals.markers.largestSize/1.5)})),i.axisCharts?this.setDimensionsForAxisCharts():this.setDimensionsForNonAxisCharts(),this.dimGrid.gridPadFortitleSubtitle(),i.gridHeight=i.gridHeight-this.gridPad.top-this.gridPad.bottom,i.gridWidth=i.gridWidth-this.gridPad.left-this.gridPad.right-this.xPadRight-this.xPadLeft;var a=this.dimGrid.gridPadForColumnsInNumericAxis(i.gridWidth);i.gridWidth=i.gridWidth-2*a,i.translateX=i.translateX+this.gridPad.left+this.xPadLeft+(a>0?a+4:0),i.translateY=i.translateY+this.gridPad.top}},{key:"setDimensionsForAxisCharts",value:function(){var t=this,e=this.w,i=e.globals,a=this.dimYAxis.getyAxisLabelsCoords(),s=this.dimYAxis.getyAxisTitleCoords();e.globals.yLabelsCoords=[],e.globals.yTitleCoords=[],e.config.yaxis.map((function(t,i){e.globals.yLabelsCoords.push({width:a[i].width,index:i}),e.globals.yTitleCoords.push({width:s[i].width,index:i})})),this.yAxisWidth=this.dimYAxis.getTotalYAxisWidth();var r=this.dimXAxis.getxAxisLabelsCoords(),o=this.dimXAxis.getxAxisGroupLabelsCoords(),n=this.dimXAxis.getxAxisTitleCoords();this.conditionalChecksForAxisCoords(r,n,o),i.translateXAxisY=e.globals.rotateXLabels?this.xAxisHeight/8:-4,i.translateXAxisX=e.globals.rotateXLabels&&e.globals.isXNumeric&&e.config.xaxis.labels.rotate<=-45?-this.xAxisWidth/4:0,e.globals.isBarHorizontal&&(i.rotateXLabels=!1,i.translateXAxisY=parseInt(e.config.xaxis.labels.style.fontSize,10)/1.5*-1),i.translateXAxisY=i.translateXAxisY+e.config.xaxis.labels.offsetY,i.translateXAxisX=i.translateXAxisX+e.config.xaxis.labels.offsetX;var l=this.yAxisWidth,h=this.xAxisHeight;i.xAxisLabelsHeight=this.xAxisHeight-n.height,i.xAxisGroupLabelsHeight=i.xAxisLabelsHeight-r.height,i.xAxisLabelsWidth=this.xAxisWidth,i.xAxisHeight=this.xAxisHeight;var c=10;("radar"===e.config.chart.type||this.isSparkline)&&(l=0,h=i.goldenPadding),this.isSparkline&&(this.lgRect={height:0,width:0}),(this.isSparkline||"treemap"===e.config.chart.type)&&(l=0,h=0,c=0),this.isSparkline||this.dimXAxis.additionalPaddingXLabels(r);var d=function(){i.translateX=l,i.gridHeight=i.svgHeight-t.lgRect.height-h-(t.isSparkline||"treemap"===e.config.chart.type?0:e.globals.rotateXLabels?10:15),i.gridWidth=i.svgWidth-l};switch("top"===e.config.xaxis.position&&(c=i.xAxisHeight-e.config.xaxis.axisTicks.height-5),e.config.legend.position){case"bottom":i.translateY=c,d();break;case"top":i.translateY=this.lgRect.height+c,d();break;case"left":i.translateY=c,i.translateX=this.lgRect.width+l,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l;break;case"right":i.translateY=c,i.translateX=l,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l-5;break;default:throw new Error("Legend position not supported")}this.dimGrid.setGridXPosForDualYAxis(s,a),new q(this.ctx).setYAxisXPosition(a,s)}},{key:"setDimensionsForNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=t.config,a=0;t.config.legend.show&&!t.config.legend.floating&&(a=20);var s="pie"===i.chart.type||"polarArea"===i.chart.type||"donut"===i.chart.type?"pie":"radialBar",r=i.plotOptions[s].offsetY,o=i.plotOptions[s].offsetX;if(!i.legend.show||i.legend.floating)return e.gridHeight=e.svgHeight-i.grid.padding.left+i.grid.padding.right,e.gridWidth=e.gridHeight,e.translateY=r,void(e.translateX=o+(e.svgWidth-e.gridWidth)/2);switch(i.legend.position){case"bottom":e.gridHeight=e.svgHeight-this.lgRect.height-e.goldenPadding,e.gridWidth=e.svgWidth,e.translateY=r-10,e.translateX=o+(e.svgWidth-e.gridWidth)/2;break;case"top":e.gridHeight=e.svgHeight-this.lgRect.height-e.goldenPadding,e.gridWidth=e.svgWidth,e.translateY=this.lgRect.height+r+10,e.translateX=o+(e.svgWidth-e.gridWidth)/2;break;case"left":e.gridWidth=e.svgWidth-this.lgRect.width-a,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=o+this.lgRect.width+a;break;case"right":e.gridWidth=e.svgWidth-this.lgRect.width-a-5,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=o+10;break;default:throw new Error("Legend position not supported")}}},{key:"conditionalChecksForAxisCoords",value:function(t,e,i){var a=this.w,s=a.globals.hasGroups?2:1,r=i.height+t.height+e.height,o=a.globals.isMultiLineX?1.2:a.globals.LINE_HEIGHT_RATIO,n=a.globals.rotateXLabels?22:10,l=a.globals.rotateXLabels&&"bottom"===a.config.legend.position?10:0;this.xAxisHeight=r*o+s*n+l,this.xAxisWidth=t.width,this.xAxisHeight-e.height>a.config.xaxis.labels.maxHeight&&(this.xAxisHeight=a.config.xaxis.labels.maxHeight),a.config.xaxis.labels.minHeight&&this.xAxisHeightc&&(this.yAxisWidth=c)}}]),t}(),nt=function(){function t(e){a(this,t),this.w=e.w,this.lgCtx=e}return r(t,[{key:"getLegendBBox",value:function(){var t=this.w.globals.dom.baseEl.querySelector(".apexcharts-legend").getBoundingClientRect(),e=t.width;return{clwh:t.height,clww:e}}},{key:"toggleDataSeries",value:function(t,e){var i=this,a=this.w;if(a.globals.axisCharts||"radialBar"===a.config.chart.type){a.globals.resized=!0;var s=null,r=null;if(a.globals.risingSeries=[],a.globals.axisCharts?(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(t,"']")),r=parseInt(s.getAttribute("data:realIndex"),10)):(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(t+1,"']")),r=parseInt(s.getAttribute("rel"),10)-1),e)[{cs:a.globals.collapsedSeries,csi:a.globals.collapsedSeriesIndices},{cs:a.globals.ancillaryCollapsedSeries,csi:a.globals.ancillaryCollapsedSeriesIndices}].forEach((function(t){i.riseCollapsedSeries(t.cs,t.csi,r)}));else this.hideSeries({seriesEl:s,realIndex:r})}else{var o=a.globals.dom.Paper.select(" .apexcharts-series[rel='".concat(t+1,"'] path")),n=a.config.chart.type;if("pie"===n||"polarArea"===n||"donut"===n){var l=a.config.plotOptions.pie.donut.labels;new m(this.lgCtx.ctx).pathMouseDown(o.members[0],null),this.lgCtx.ctx.pie.printDataLabelsInner(o.members[0].node,l)}o.fire("click")}}},{key:"hideSeries",value:function(t){var e=t.seriesEl,i=t.realIndex,a=this.w,s=x.clone(a.config.series);if(a.globals.axisCharts){var r=!1;if(a.config.yaxis[i]&&a.config.yaxis[i].show&&a.config.yaxis[i].showAlways&&(r=!0,a.globals.ancillaryCollapsedSeriesIndices.indexOf(i)<0&&(a.globals.ancillaryCollapsedSeries.push({index:i,data:s[i].data.slice(),type:e.parentNode.className.baseVal.split("-")[1]}),a.globals.ancillaryCollapsedSeriesIndices.push(i))),!r){a.globals.collapsedSeries.push({index:i,data:s[i].data.slice(),type:e.parentNode.className.baseVal.split("-")[1]}),a.globals.collapsedSeriesIndices.push(i);var o=a.globals.risingSeries.indexOf(i);a.globals.risingSeries.splice(o,1)}}else a.globals.collapsedSeries.push({index:i,data:s[i]}),a.globals.collapsedSeriesIndices.push(i);for(var n=e.childNodes,l=0;l0){for(var r=0;r-1&&(t[a].data=[])})):t.forEach((function(i,a){e.globals.collapsedSeriesIndices.indexOf(a)>-1&&(t[a]=0)})),t}}]),t}(),lt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.onLegendClick=this.onLegendClick.bind(this),this.onLegendHovered=this.onLegendHovered.bind(this),this.isBarsDistributed="bar"===this.w.config.chart.type&&this.w.config.plotOptions.bar.distributed&&1===this.w.config.series.length,this.legendHelpers=new nt(this)}return r(t,[{key:"init",value:function(){var t=this.w,e=t.globals,i=t.config;if((i.legend.showForSingleSeries&&1===e.series.length||this.isBarsDistributed||e.series.length>1||!e.axisCharts)&&i.legend.show){for(;e.dom.elLegendWrap.firstChild;)e.dom.elLegendWrap.removeChild(e.dom.elLegendWrap.firstChild);this.drawLegends(),"bottom"===i.legend.position||"top"===i.legend.position?this.legendAlignHorizontal():"right"!==i.legend.position&&"left"!==i.legend.position||this.legendAlignVertical()}}},{key:"drawLegends",value:function(){var t=this,e=this.w,i=e.config.legend.fontFamily,a=e.globals.seriesNames,s=e.globals.colors.slice();if("heatmap"===e.config.chart.type){var r=e.config.plotOptions.heatmap.colorScale.ranges;a=r.map((function(t){return t.name?t.name:t.from+" - "+t.to})),s=r.map((function(t){return t.color}))}else this.isBarsDistributed&&(a=e.globals.labels.slice());e.config.legend.customLegendItems.length&&(a=e.config.legend.customLegendItems);for(var o=e.globals.legendFormatter,n=e.config.legend.inverseOrder,l=n?a.length-1:0;n?l>=0:l<=a.length-1;n?l--:l++){var h=o(a[l],{seriesIndex:l,w:e}),c=!1,d=!1;if(e.globals.collapsedSeries.length>0)for(var g=0;g0)for(var u=0;u0?l-10:0)+(h>0?h-10:0)}a.style.position="absolute",r=r+t+i.config.legend.offsetX,o=o+e+i.config.legend.offsetY,a.style.left=r+"px",a.style.top=o+"px","bottom"===i.config.legend.position?(a.style.top="auto",a.style.bottom=5-i.config.legend.offsetY+"px"):"right"===i.config.legend.position&&(a.style.left="auto",a.style.right=25+i.config.legend.offsetX+"px");["width","height"].forEach((function(t){a.style[t]&&(a.style[t]=parseInt(i.config.legend[t],10)+"px")}))}},{key:"legendAlignHorizontal",value:function(){var t=this.w;t.globals.dom.elLegendWrap.style.right=0;var e=this.legendHelpers.getLegendBBox(),i=new ot(this.ctx),a=i.dimHelpers.getTitleSubtitleCoords("title"),s=i.dimHelpers.getTitleSubtitleCoords("subtitle"),r=0;"bottom"===t.config.legend.position?r=-e.clwh/1.8:"top"===t.config.legend.position&&(r=a.height+s.height+t.config.title.margin+t.config.subtitle.margin-10),this.setLegendWrapXY(20,r)}},{key:"legendAlignVertical",value:function(){var t=this.w,e=this.legendHelpers.getLegendBBox(),i=0;"left"===t.config.legend.position&&(i=20),"right"===t.config.legend.position&&(i=t.globals.svgWidth-e.clww-10),this.setLegendWrapXY(i,20)}},{key:"onLegendHovered",value:function(t){var e=this.w,i=t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker");if("heatmap"===e.config.chart.type||this.isBarsDistributed){if(i){var a=parseInt(t.target.getAttribute("rel"),10)-1;this.ctx.events.fireEvent("legendHover",[this.ctx,a,this.w]),new N(this.ctx).highlightRangeInSeries(t,t.target)}}else!t.target.classList.contains("apexcharts-inactive-legend")&&i&&new N(this.ctx).toggleSeriesOnHover(t,t.target)}},{key:"onLegendClick",value:function(t){var e=this.w;if(!e.config.legend.customLegendItems.length&&(t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker"))){var i=parseInt(t.target.getAttribute("rel"),10)-1,a="true"===t.target.getAttribute("data:collapsed"),s=this.w.config.chart.events.legendClick;"function"==typeof s&&s(this.ctx,i,this.w),this.ctx.events.fireEvent("legendClick",[this.ctx,i,this.w]);var r=this.w.config.legend.markers.onClick;"function"==typeof r&&t.target.classList.contains("apexcharts-legend-marker")&&(r(this.ctx,i,this.w),this.ctx.events.fireEvent("legendMarkerClick",[this.ctx,i,this.w])),"treemap"!==e.config.chart.type&&"heatmap"!==e.config.chart.type&&!this.isBarsDistributed&&e.config.legend.onItemClick.toggleDataSeries&&this.legendHelpers.toggleDataSeries(i,a)}}}]),t}(),ht=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w;var i=this.w;this.ev=this.w.config.chart.events,this.selectedClass="apexcharts-selected",this.localeValues=this.w.globals.locale.toolbar,this.minX=i.globals.minX,this.maxX=i.globals.maxX}return r(t,[{key:"createToolbar",value:function(){var t=this,e=this.w,i=function(){return document.createElement("div")},a=i();if(a.setAttribute("class","apexcharts-toolbar"),a.style.top=e.config.chart.toolbar.offsetY+"px",a.style.right=3-e.config.chart.toolbar.offsetX+"px",e.globals.dom.elWrap.appendChild(a),this.elZoom=i(),this.elZoomIn=i(),this.elZoomOut=i(),this.elPan=i(),this.elSelection=i(),this.elZoomReset=i(),this.elMenuIcon=i(),this.elMenu=i(),this.elCustomIcons=[],this.t=e.config.chart.toolbar.tools,Array.isArray(this.t.customIcons))for(var s=0;s\n \n \n\n'),o("zoomOut",this.elZoomOut,'\n \n \n\n');var n=function(i){t.t[i]&&e.config.chart[i].enabled&&r.push({el:"zoom"===i?t.elZoom:t.elSelection,icon:"string"==typeof t.t[i]?t.t[i]:"zoom"===i?'\n \n \n \n':'\n \n \n',title:t.localeValues["zoom"===i?"selectionZoom":"selection"],class:e.globals.isTouchDevice?"apexcharts-element-hidden":"apexcharts-".concat(i,"-icon")})};n("zoom"),n("selection"),this.t.pan&&e.config.chart.zoom.enabled&&r.push({el:this.elPan,icon:"string"==typeof this.t.pan?this.t.pan:'\n \n \n \n \n \n \n \n',title:this.localeValues.pan,class:e.globals.isTouchDevice?"apexcharts-element-hidden":"apexcharts-pan-icon"}),o("reset",this.elZoomReset,'\n \n \n'),this.t.download&&r.push({el:this.elMenuIcon,icon:"string"==typeof this.t.download?this.t.download:'',title:this.localeValues.menu,class:"apexcharts-menu-icon"});for(var l=0;l0&&e.height>0&&this.slDraggableRect.selectize({points:"l, r",pointSize:8,pointType:"rect"}).resize({constraint:{minX:0,minY:0,maxX:t.globals.gridWidth,maxY:t.globals.gridHeight}}).on("resizing",this.selectionDragging.bind(this,"resizing"))}}},{key:"preselectedSelection",value:function(){var t=this.w,e=this.xyRatios;if(!t.globals.zoomEnabled)if(void 0!==t.globals.selection&&null!==t.globals.selection)this.drawSelectionRect(t.globals.selection);else if(void 0!==t.config.chart.selection.xaxis.min&&void 0!==t.config.chart.selection.xaxis.max){var i=(t.config.chart.selection.xaxis.min-t.globals.minX)/e.xRatio,a={x:i,y:0,width:t.globals.gridWidth-(t.globals.maxX-t.config.chart.selection.xaxis.max)/e.xRatio-i,height:t.globals.gridHeight,translateX:0,translateY:0,selectionEnabled:!0};this.drawSelectionRect(a),this.makeSelectionRectDraggable(),"function"==typeof t.config.chart.events.selection&&t.config.chart.events.selection(this.ctx,{xaxis:{min:t.config.chart.selection.xaxis.min,max:t.config.chart.selection.xaxis.max},yaxis:{}})}}},{key:"drawSelectionRect",value:function(t){var e=t.x,i=t.y,a=t.width,s=t.height,r=t.translateX,o=void 0===r?0:r,n=t.translateY,l=void 0===n?0:n,h=this.w,c=this.zoomRect,d=this.selectionRect;if(this.dragged||null!==h.globals.selection){var g={transform:"translate("+o+", "+l+")"};h.globals.zoomEnabled&&this.dragged&&(a<0&&(a=1),c.attr({x:e,y:i,width:a,height:s,fill:h.config.chart.zoom.zoomedArea.fill.color,"fill-opacity":h.config.chart.zoom.zoomedArea.fill.opacity,stroke:h.config.chart.zoom.zoomedArea.stroke.color,"stroke-width":h.config.chart.zoom.zoomedArea.stroke.width,"stroke-opacity":h.config.chart.zoom.zoomedArea.stroke.opacity}),m.setAttrs(c.node,g)),h.globals.selectionEnabled&&(d.attr({x:e,y:i,width:a>0?a:0,height:s>0?s:0,fill:h.config.chart.selection.fill.color,"fill-opacity":h.config.chart.selection.fill.opacity,stroke:h.config.chart.selection.stroke.color,"stroke-width":h.config.chart.selection.stroke.width,"stroke-dasharray":h.config.chart.selection.stroke.dashArray,"stroke-opacity":h.config.chart.selection.stroke.opacity}),m.setAttrs(d.node,g))}}},{key:"hideSelectionRect",value:function(t){t&&t.attr({x:0,y:0,width:0,height:0})}},{key:"selectionDrawing",value:function(t){var e=t.context,i=t.zoomtype,a=this.w,s=e,r=this.gridRect.getBoundingClientRect(),o=s.startX-1,n=s.startY,l=!1,h=!1,c=s.clientX-r.left-o,d=s.clientY-r.top-n,g={};return Math.abs(c+o)>a.globals.gridWidth?c=a.globals.gridWidth-o:s.clientX-r.left<0&&(c=o),o>s.clientX-r.left&&(l=!0,c=Math.abs(c)),n>s.clientY-r.top&&(h=!0,d=Math.abs(d)),g="x"===i?{x:l?o-c:o,y:0,width:c,height:a.globals.gridHeight}:"y"===i?{x:0,y:h?n-d:n,width:a.globals.gridWidth,height:d}:{x:l?o-c:o,y:h?n-d:n,width:c,height:d},s.drawSelectionRect(g),s.selectionDragging("resizing"),g}},{key:"selectionDragging",value:function(t,e){var i=this,a=this.w,s=this.xyRatios,r=this.selectionRect,o=0;"resizing"===t&&(o=30);var n=function(t){return parseFloat(r.node.getAttribute(t))},l={x:n("x"),y:n("y"),width:n("width"),height:n("height")};a.globals.selection=l,"function"==typeof a.config.chart.events.selection&&a.globals.selectionEnabled&&(clearTimeout(this.w.globals.selectionResizeTimer),this.w.globals.selectionResizeTimer=window.setTimeout((function(){var t=i.gridRect.getBoundingClientRect(),e=r.node.getBoundingClientRect(),o={xaxis:{min:a.globals.xAxisScale.niceMin+(e.left-t.left)*s.xRatio,max:a.globals.xAxisScale.niceMin+(e.right-t.left)*s.xRatio},yaxis:{min:a.globals.yAxisScale[0].niceMin+(t.bottom-e.bottom)*s.yRatio[0],max:a.globals.yAxisScale[0].niceMax-(e.top-t.top)*s.yRatio[0]}};a.config.chart.events.selection(i.ctx,o),a.config.chart.brush.enabled&&void 0!==a.config.chart.events.brushScrolled&&a.config.chart.events.brushScrolled(i.ctx,o)}),o))}},{key:"selectionDrawn",value:function(t){var e=t.context,i=t.zoomtype,a=this.w,s=e,r=this.xyRatios,o=this.ctx.toolbar;if(s.startX>s.endX){var n=s.startX;s.startX=s.endX,s.endX=n}if(s.startY>s.endY){var l=s.startY;s.startY=s.endY,s.endY=l}var h=void 0,c=void 0;a.globals.isRangeBar?(h=a.globals.yAxisScale[0].niceMin+s.startX*r.invertedYRatio,c=a.globals.yAxisScale[0].niceMin+s.endX*r.invertedYRatio):(h=a.globals.xAxisScale.niceMin+s.startX*r.xRatio,c=a.globals.xAxisScale.niceMin+s.endX*r.xRatio);var d=[],g=[];if(a.config.yaxis.forEach((function(t,e){d.push(a.globals.yAxisScale[e].niceMax-r.yRatio[e]*s.startY),g.push(a.globals.yAxisScale[e].niceMax-r.yRatio[e]*s.endY)})),s.dragged&&(s.dragX>10||s.dragY>10)&&h!==c)if(a.globals.zoomEnabled){var u=x.clone(a.globals.initialConfig.yaxis),f=x.clone(a.globals.initialConfig.xaxis);if(a.globals.zoomed=!0,a.config.xaxis.convertedCatToNumeric&&(h=Math.floor(h),c=Math.floor(c),h<1&&(h=1,c=a.globals.dataPoints),c-h<2&&(c=h+1)),"xy"!==i&&"x"!==i||(f={min:h,max:c}),"xy"!==i&&"y"!==i||u.forEach((function(t,e){u[e].min=g[e],u[e].max=d[e]})),a.config.chart.zoom.autoScaleYaxis){var p=new _(s.ctx);u=p.autoScaleY(s.ctx,u,{xaxis:f})}if(o){var b=o.getBeforeZoomRange(f,u);b&&(f=b.xaxis?b.xaxis:f,u=b.yaxis?b.yaxis:u)}var v={xaxis:f};a.config.chart.group||(v.yaxis=u),s.ctx.updateHelpers._updateOptions(v,!1,s.w.config.chart.animations.dynamicAnimation.enabled),"function"==typeof a.config.chart.events.zoomed&&o.zoomCallback(f,u)}else if(a.globals.selectionEnabled){var m,y=null;m={min:h,max:c},"xy"!==i&&"y"!==i||(y=x.clone(a.config.yaxis)).forEach((function(t,e){y[e].min=g[e],y[e].max=d[e]})),a.globals.selection=s.selection,"function"==typeof a.config.chart.events.selection&&a.config.chart.events.selection(s.ctx,{xaxis:m,yaxis:y})}}},{key:"panDragging",value:function(t){var e=t.context,i=this.w,a=e;if(void 0!==i.globals.lastClientPosition.x){var s=i.globals.lastClientPosition.x-a.clientX,r=i.globals.lastClientPosition.y-a.clientY;Math.abs(s)>Math.abs(r)&&s>0?this.moveDirection="left":Math.abs(s)>Math.abs(r)&&s<0?this.moveDirection="right":Math.abs(r)>Math.abs(s)&&r>0?this.moveDirection="up":Math.abs(r)>Math.abs(s)&&r<0&&(this.moveDirection="down")}i.globals.lastClientPosition={x:a.clientX,y:a.clientY};var o=i.globals.isRangeBar?i.globals.minY:i.globals.minX,n=i.globals.isRangeBar?i.globals.maxY:i.globals.maxX;i.config.xaxis.convertedCatToNumeric||a.panScrolled(o,n)}},{key:"delayedPanScrolled",value:function(){var t=this.w,e=t.globals.minX,i=t.globals.maxX,a=(t.globals.maxX-t.globals.minX)/2;"left"===this.moveDirection?(e=t.globals.minX+a,i=t.globals.maxX+a):"right"===this.moveDirection&&(e=t.globals.minX-a,i=t.globals.maxX-a),e=Math.floor(e),i=Math.floor(i),this.updateScrolledChart({xaxis:{min:e,max:i}},e,i)}},{key:"panScrolled",value:function(t,e){var i=this.w,a=this.xyRatios,s=x.clone(i.globals.initialConfig.yaxis),r=a.xRatio,o=i.globals.minX,n=i.globals.maxX;i.globals.isRangeBar&&(r=a.invertedYRatio,o=i.globals.minY,n=i.globals.maxY),"left"===this.moveDirection?(t=o+i.globals.gridWidth/15*r,e=n+i.globals.gridWidth/15*r):"right"===this.moveDirection&&(t=o-i.globals.gridWidth/15*r,e=n-i.globals.gridWidth/15*r),i.globals.isRangeBar||(ti.globals.initialMaxX)&&(t=o,e=n);var l={min:t,max:e};i.config.chart.zoom.autoScaleYaxis&&(s=new _(this.ctx).autoScaleY(this.ctx,s,{xaxis:l}));var h={xaxis:{min:t,max:e}};i.config.chart.group||(h.yaxis=s),this.updateScrolledChart(h,t,e)}},{key:"updateScrolledChart",value:function(t,e,i){var a=this.w;this.ctx.updateHelpers._updateOptions(t,!1,!1),"function"==typeof a.config.chart.events.scrolled&&a.config.chart.events.scrolled(this.ctx,{xaxis:{min:e,max:i}})}}]),i}(),dt=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx}return r(t,[{key:"getNearestValues",value:function(t){var e=t.hoverArea,i=t.elGrid,a=t.clientX,s=t.clientY,r=this.w,o=i.getBoundingClientRect(),n=o.width,l=o.height,h=n/(r.globals.dataPoints-1),c=l/r.globals.dataPoints,d=this.hasBars();!r.globals.comboCharts&&!d||r.config.xaxis.convertedCatToNumeric||(h=n/r.globals.dataPoints);var g=a-o.left-r.globals.barPadForNumericAxis,u=s-o.top;g<0||u<0||g>n||u>l?(e.classList.remove("hovering-zoom"),e.classList.remove("hovering-pan")):r.globals.zoomEnabled?(e.classList.remove("hovering-pan"),e.classList.add("hovering-zoom")):r.globals.panEnabled&&(e.classList.remove("hovering-zoom"),e.classList.add("hovering-pan"));var f=Math.round(g/h),p=Math.floor(u/c);d&&!r.config.xaxis.convertedCatToNumeric&&(f=Math.ceil(g/h),f-=1);var b=null,v=null,m=[],y=[];if(r.globals.seriesXvalues.forEach((function(t){m.push([t[0]+1e-6].concat(t))})),r.globals.seriesYvalues.forEach((function(t){y.push([t[0]+1e-6].concat(t))})),m=m.map((function(t){return t.filter((function(t){return x.isNumber(t)}))})),y=y.map((function(t){return t.filter((function(t){return x.isNumber(t)}))})),r.globals.isXNumeric){var w=this.ttCtx.getElGrid().getBoundingClientRect(),k=g*(w.width/n),A=u*(w.height/l);b=(v=this.closestInMultiArray(k,A,m,y)).index,f=v.j,null!==b&&(m=r.globals.seriesXvalues[b],f=(v=this.closestInArray(k,m)).index)}return r.globals.capturedSeriesIndex=null===b?-1:b,(!f||f<1)&&(f=0),r.globals.isBarHorizontal?r.globals.capturedDataPointIndex=p:r.globals.capturedDataPointIndex=f,{capturedSeries:b,j:r.globals.isBarHorizontal?p:f,hoverX:g,hoverY:u}}},{key:"closestInMultiArray",value:function(t,e,i,a){var s=this.w,r=0,o=null,n=-1;s.globals.series.length>1?r=this.getFirstActiveXArray(i):o=0;var l=i[r][0],h=Math.abs(t-l);if(i.forEach((function(e){e.forEach((function(e,i){var a=Math.abs(t-e);a0?e:-1})),s=0;s0)for(var a=0;ai?-1:0}));var e=[];return t.forEach((function(t){e.push(t.querySelector(".apexcharts-marker"))})),e}},{key:"hasMarkers",value:function(){return this.getElMarkers().length>0}},{key:"getElBars",value:function(){return this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-bar-series, .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series")}},{key:"hasBars",value:function(){return this.getElBars().length>0}},{key:"getHoverMarkerSize",value:function(t){var e=this.w,i=e.config.markers.hover.size;return void 0===i&&(i=e.globals.markers.size[t]+e.config.markers.hover.sizeOffset),i}},{key:"toggleAllTooltipSeriesGroups",value:function(t){var e=this.w,i=this.ttCtx;0===i.allTooltipSeriesGroups.length&&(i.allTooltipSeriesGroups=e.globals.dom.baseEl.querySelectorAll(".apexcharts-tooltip-series-group"));for(var a=i.allTooltipSeriesGroups,s=0;s ').concat(i.attrs.name,"
    "),e+="
    ".concat(i.val,"
    ")})),v.innerHTML=t+"
    ",m.innerHTML=e+"
    "};o?l.globals.seriesGoals[e][i]&&Array.isArray(l.globals.seriesGoals[e][i])?y():(v.innerHTML="",m.innerHTML=""):y()}else v.innerHTML="",m.innerHTML="";null!==f&&(a[e].querySelector(".apexcharts-tooltip-text-z-label").innerHTML=l.config.tooltip.z.title,a[e].querySelector(".apexcharts-tooltip-text-z-value").innerHTML=void 0!==f?f:"");o&&p[0]&&(null==c||l.globals.ancillaryCollapsedSeriesIndices.indexOf(e)>-1||l.globals.collapsedSeriesIndices.indexOf(e)>-1?p[0].parentNode.style.display="none":p[0].parentNode.style.display=l.config.tooltip.items.display)}},{key:"toggleActiveInactiveSeries",value:function(t){var e=this.w;if(t)this.tooltipUtil.toggleAllTooltipSeriesGroups("enable");else{this.tooltipUtil.toggleAllTooltipSeriesGroups("disable");var i=e.globals.dom.baseEl.querySelector(".apexcharts-tooltip-series-group");i&&(i.classList.add("apexcharts-active"),i.style.display=e.config.tooltip.items.display)}}},{key:"getValuesToPrint",value:function(t){var e=t.i,i=t.j,a=this.w,s=this.ctx.series.filteredSeriesX(),r="",o="",n=null,l=null,h={series:a.globals.series,seriesIndex:e,dataPointIndex:i,w:a},c=a.globals.ttZFormatter;null===i?l=a.globals.series[e]:a.globals.isXNumeric&&"treemap"!==a.config.chart.type?(r=s[e][i],0===s[e].length&&(r=s[this.tooltipUtil.getFirstActiveXArray(s)][i])):r=void 0!==a.globals.labels[i]?a.globals.labels[i]:"";var d=r;a.globals.isXNumeric&&"datetime"===a.config.xaxis.type?r=new M(this.ctx).xLabelFormat(a.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new T(this.ctx).formatDate,w:this.w}):r=a.globals.isBarHorizontal?a.globals.yLabelFormatters[0](d,h):a.globals.xLabelFormatter(d,h);return void 0!==a.config.tooltip.x.formatter&&(r=a.globals.ttKeyFormatter(d,h)),a.globals.seriesZ.length>0&&a.globals.seriesZ[e].length>0&&(n=c(a.globals.seriesZ[e][i],a)),o="function"==typeof a.config.xaxis.tooltip.formatter?a.globals.xaxisTooltipFormatter(d,h):r,{val:Array.isArray(l)?l.join(" "):l,xVal:Array.isArray(r)?r.join(" "):r,xAxisTTVal:Array.isArray(o)?o.join(" "):o,zVal:n}}},{key:"handleCustomTooltip",value:function(t){var e=t.i,i=t.j,a=t.y1,s=t.y2,r=t.w,o=this.ttCtx.getElTooltip(),n=r.config.tooltip.custom;Array.isArray(n)&&n[e]&&(n=n[e]),o.innerHTML=n({ctx:this.ctx,series:r.globals.series,seriesIndex:e,dataPointIndex:i,y1:a,y2:s,w:r})}}]),t}(),ut=function(){function t(e){a(this,t),this.ttCtx=e,this.ctx=e.ctx,this.w=e.w}return r(t,[{key:"moveXCrosshairs",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.ttCtx,a=this.w,s=i.getElXCrosshairs(),r=t-i.xcrosshairsWidth/2,o=a.globals.labels.slice().length;if(null!==e&&(r=a.globals.gridWidth/o*e),null===s||a.globals.isBarHorizontal||(s.setAttribute("x",r),s.setAttribute("x1",r),s.setAttribute("x2",r),s.setAttribute("y2",a.globals.gridHeight),s.classList.add("apexcharts-active")),r<0&&(r=0),r>a.globals.gridWidth&&(r=a.globals.gridWidth),i.isXAxisTooltipEnabled){var n=r;"tickWidth"!==a.config.xaxis.crosshairs.width&&"barWidth"!==a.config.xaxis.crosshairs.width||(n=r+i.xcrosshairsWidth/2),this.moveXAxisTooltip(n)}}},{key:"moveYCrosshairs",value:function(t){var e=this.ttCtx;null!==e.ycrosshairs&&m.setAttrs(e.ycrosshairs,{y1:t,y2:t}),null!==e.ycrosshairsHidden&&m.setAttrs(e.ycrosshairsHidden,{y1:t,y2:t})}},{key:"moveXAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;if(null!==i.xaxisTooltip&&0!==i.xcrosshairsWidth){i.xaxisTooltip.classList.add("apexcharts-active");var a=i.xaxisOffY+e.config.xaxis.tooltip.offsetY+e.globals.translateY+1+e.config.xaxis.offsetY;if(t-=i.xaxisTooltip.getBoundingClientRect().width/2,!isNaN(t)){t+=e.globals.translateX;var s;s=new m(this.ctx).getTextRects(i.xaxisTooltipText.innerHTML),i.xaxisTooltipText.style.minWidth=s.width+"px",i.xaxisTooltip.style.left=t+"px",i.xaxisTooltip.style.top=a+"px"}}}},{key:"moveYAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;null===i.yaxisTTEls&&(i.yaxisTTEls=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip"));var a=parseInt(i.ycrosshairsHidden.getAttribute("y1"),10),s=e.globals.translateY+a,r=i.yaxisTTEls[t].getBoundingClientRect().height,o=e.globals.translateYAxisX[t]-2;e.config.yaxis[t].opposite&&(o-=26),s-=r/2,-1===e.globals.ignoreYAxisIndexes.indexOf(t)?(i.yaxisTTEls[t].classList.add("apexcharts-active"),i.yaxisTTEls[t].style.top=s+"px",i.yaxisTTEls[t].style.left=o+e.config.yaxis[t].tooltip.offsetX+"px"):i.yaxisTTEls[t].classList.remove("apexcharts-active")}},{key:"moveTooltip",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=this.ttCtx,r=s.getElTooltip(),o=s.tooltipRect,n=null!==i?parseFloat(i):1,l=parseFloat(t)+n+5,h=parseFloat(e)+n/2;if(l>a.globals.gridWidth/2&&(l=l-o.ttWidth-n-10),l>a.globals.gridWidth-o.ttWidth-10&&(l=a.globals.gridWidth-o.ttWidth),l<-20&&(l=-20),a.config.tooltip.followCursor){var c=s.getElGrid(),d=c.getBoundingClientRect();h=s.e.clientY+a.globals.translateY-d.top-o.ttHeight/2}else a.globals.isBarHorizontal||o.ttHeight/2+h>a.globals.gridHeight&&(h=a.globals.gridHeight-o.ttHeight+a.globals.translateY);isNaN(l)||(l+=a.globals.translateX,r.style.left=l+"px",r.style.top=h+"px")}},{key:"moveMarkers",value:function(t,e){var i=this.w,a=this.ttCtx;if(i.globals.markers.size[t]>0)for(var s=i.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(t,"'] .apexcharts-marker")),r=0;r0&&(h.setAttribute("r",n),h.setAttribute("cx",i),h.setAttribute("cy",a)),this.moveXCrosshairs(i),r.fixedTooltip||this.moveTooltip(i,a,n)}}},{key:"moveDynamicPointsOnHover",value:function(t){var e,i=this.ttCtx,a=i.w,s=0,r=0,o=a.globals.pointsArray;e=new N(this.ctx).getActiveConfigSeriesIndex("asc",["line","area","scatter","bubble"]);var n=i.tooltipUtil.getHoverMarkerSize(e);o[e]&&(s=o[e][t][0],r=o[e][t][1]);var l=i.tooltipUtil.getAllMarkers();if(null!==l)for(var h=0;h0?(l[h]&&l[h].setAttribute("r",n),l[h]&&l[h].setAttribute("cy",d)):l[h]&&l[h].setAttribute("r",0)}}if(this.moveXCrosshairs(s),!i.fixedTooltip){var f=r||a.globals.gridHeight;this.moveTooltip(s,f,n)}}},{key:"moveStickyTooltipOverBars",value:function(t){var e=this.w,i=this.ttCtx,a=e.globals.columnSeries?e.globals.columnSeries.length:e.globals.series.length,s=a>=2&&a%2==0?Math.floor(a/2):Math.floor(a/2)+1;e.globals.isBarHorizontal&&(s=new N(this.ctx).getActiveConfigSeriesIndex("desc")+1);var r=e.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(s,"'] path[j='").concat(t,"'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"']")),o=r?parseFloat(r.getAttribute("cx")):0,n=r?parseFloat(r.getAttribute("cy")):0,l=r?parseFloat(r.getAttribute("barWidth")):0,h=i.getElGrid().getBoundingClientRect(),c=r.classList.contains("apexcharts-candlestick-area")||r.classList.contains("apexcharts-boxPlot-area");if(e.globals.isXNumeric?(r&&!c&&(o-=a%2!=0?l/2:0),r&&c&&e.globals.comboCharts&&(o-=l/2)):e.globals.isBarHorizontal||(o=i.xAxisTicksPositions[t-1]+i.dataPointsDividedWidth/2,isNaN(o)&&(o=i.xAxisTicksPositions[t]-i.dataPointsDividedWidth/2)),e.globals.isBarHorizontal?n-=i.tooltipRect.ttHeight:e.config.tooltip.followCursor?n=i.e.clientY-h.top-i.tooltipRect.ttHeight/2:n+i.tooltipRect.ttHeight+15>e.globals.gridHeight&&(n=e.globals.gridHeight),e.globals.isBarHorizontal||this.moveXCrosshairs(o),!i.fixedTooltip){var d=n||e.globals.gridHeight;this.moveTooltip(o,d)}}}]),t}(),ft=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx,this.tooltipPosition=new ut(e)}return r(t,[{key:"drawDynamicPoints",value:function(){var t=this.w,e=new m(this.ctx),i=new D(this.ctx),a=t.globals.dom.baseEl.querySelectorAll(".apexcharts-series");a=u(a),t.config.chart.stacked&&a.sort((function(t,e){return parseFloat(t.getAttribute("data:realIndex"))-parseFloat(e.getAttribute("data:realIndex"))}));for(var s=0;s2&&void 0!==arguments[2]?arguments[2]:null,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w;"bubble"!==s.config.chart.type&&this.newPointSize(t,e);var r=e.getAttribute("cx"),o=e.getAttribute("cy");if(null!==i&&null!==a&&(r=i,o=a),this.tooltipPosition.moveXCrosshairs(r),!this.fixedTooltip){if("radar"===s.config.chart.type){var n=this.ttCtx.getElGrid(),l=n.getBoundingClientRect();r=this.ttCtx.e.clientX-l.left}this.tooltipPosition.moveTooltip(r,o,s.config.markers.hover.size)}}},{key:"enlargePoints",value:function(t){for(var e=this.w,i=this,a=this.ttCtx,s=t,r=e.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"),o=e.config.markers.hover.size,n=0;n=0?t[e].setAttribute("r",i):t[e].setAttribute("r",0)}}}]),t}(),pt=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e}return r(t,[{key:"getAttr",value:function(t,e){return parseFloat(t.target.getAttribute(e))}},{key:"handleHeatTreeTooltip",value:function(t){var e=t.e,i=t.opt,a=t.x,s=t.y,r=t.type,o=this.ttCtx,n=this.w;if(e.target.classList.contains("apexcharts-".concat(r,"-rect"))){var l=this.getAttr(e,"i"),h=this.getAttr(e,"j"),c=this.getAttr(e,"cx"),d=this.getAttr(e,"cy"),g=this.getAttr(e,"width"),u=this.getAttr(e,"height");if(o.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:l,j:h,shared:!1,e:e}),n.globals.capturedSeriesIndex=l,n.globals.capturedDataPointIndex=h,a=c+o.tooltipRect.ttWidth/2+g,s=d+o.tooltipRect.ttHeight/2-u/2,o.tooltipPosition.moveXCrosshairs(c+g/2),a>n.globals.gridWidth/2&&(a=c-o.tooltipRect.ttWidth/2+g),o.w.config.tooltip.followCursor){var f=n.globals.dom.elWrap.getBoundingClientRect();a=n.globals.clientX-f.left-(a>n.globals.gridWidth/2?o.tooltipRect.ttWidth:0),s=n.globals.clientY-f.top-(s>n.globals.gridHeight/2?o.tooltipRect.ttHeight:0)}}return{x:a,y:s}}},{key:"handleMarkerTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=t.x,o=t.y,n=this.w,l=this.ttCtx;if(a.target.classList.contains("apexcharts-marker")){var h=parseInt(s.paths.getAttribute("cx"),10),c=parseInt(s.paths.getAttribute("cy"),10),d=parseFloat(s.paths.getAttribute("val"));if(i=parseInt(s.paths.getAttribute("rel"),10),e=parseInt(s.paths.parentNode.parentNode.parentNode.getAttribute("rel"),10)-1,l.intersect){var g=x.findAncestor(s.paths,"apexcharts-series");g&&(e=parseInt(g.getAttribute("data:realIndex"),10))}if(l.tooltipLabels.drawSeriesTexts({ttItems:s.ttItems,i:e,j:i,shared:!l.showOnIntersect&&n.config.tooltip.shared,e:a}),"mouseup"===a.type&&l.markerClick(a,e,i),n.globals.capturedSeriesIndex=e,n.globals.capturedDataPointIndex=i,r=h,o=c+n.globals.translateY-1.4*l.tooltipRect.ttHeight,l.w.config.tooltip.followCursor){var u=l.getElGrid().getBoundingClientRect();o=l.e.clientY+n.globals.translateY-u.top}d<0&&(o=c),l.marker.enlargeCurrentPoint(i,s.paths,r,o)}return{x:r,y:o}}},{key:"handleBarTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,o=this.ttCtx,n=o.getElTooltip(),l=0,h=0,c=0,d=this.getBarTooltipXY({e:a,opt:s});e=d.i;var g=d.barHeight,u=d.j;r.globals.capturedSeriesIndex=e,r.globals.capturedDataPointIndex=u,r.globals.isBarHorizontal&&o.tooltipUtil.hasBars()||!r.config.tooltip.shared?(h=d.x,c=d.y,i=Array.isArray(r.config.stroke.width)?r.config.stroke.width[e]:r.config.stroke.width,l=h):r.globals.comboCharts||r.config.tooltip.shared||(l/=2),isNaN(c)&&(c=r.globals.svgHeight-o.tooltipRect.ttHeight);var f=parseInt(s.paths.parentNode.getAttribute("data:realIndex"),10),p=r.globals.isMultipleYAxis?r.config.yaxis[f]&&r.config.yaxis[f].reversed:r.config.yaxis[0].reversed;if(h+o.tooltipRect.ttWidth>r.globals.gridWidth&&!p?h-=o.tooltipRect.ttWidth:h<0&&(h=0),o.w.config.tooltip.followCursor){var x=o.getElGrid().getBoundingClientRect();c=o.e.clientY-x.top}null===o.tooltip&&(o.tooltip=r.globals.dom.baseEl.querySelector(".apexcharts-tooltip")),r.config.tooltip.shared||(r.globals.comboBarCount>0?o.tooltipPosition.moveXCrosshairs(l+i/2):o.tooltipPosition.moveXCrosshairs(l)),!o.fixedTooltip&&(!r.config.tooltip.shared||r.globals.isBarHorizontal&&o.tooltipUtil.hasBars())&&(p&&(h-=o.tooltipRect.ttWidth)<0&&(h=0),!p||r.globals.isBarHorizontal&&o.tooltipUtil.hasBars()||(c=c+g-2*(r.globals.series[e][u]<0?g:0)),c=c+r.globals.translateY-o.tooltipRect.ttHeight/2,n.style.left=h+r.globals.translateX+"px",n.style.top=c+"px")}},{key:"getBarTooltipXY",value:function(t){var e=t.e,i=t.opt,a=this.w,s=null,r=this.ttCtx,o=0,n=0,l=0,h=0,c=0,d=e.target.classList;if(d.contains("apexcharts-bar-area")||d.contains("apexcharts-candlestick-area")||d.contains("apexcharts-boxPlot-area")||d.contains("apexcharts-rangebar-area")){var g=e.target,u=g.getBoundingClientRect(),f=i.elGrid.getBoundingClientRect(),p=u.height;c=u.height;var x=u.width,b=parseInt(g.getAttribute("cx"),10),v=parseInt(g.getAttribute("cy"),10);h=parseFloat(g.getAttribute("barWidth"));var m="touchmove"===e.type?e.touches[0].clientX:e.clientX;s=parseInt(g.getAttribute("j"),10),o=parseInt(g.parentNode.getAttribute("rel"),10)-1;var y=g.getAttribute("data-range-y1"),w=g.getAttribute("data-range-y2");a.globals.comboCharts&&(o=parseInt(g.parentNode.getAttribute("data:realIndex"),10)),r.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:o,j:s,y1:y?parseInt(y,10):null,y2:w?parseInt(w,10):null,shared:!r.showOnIntersect&&a.config.tooltip.shared,e:e}),a.config.tooltip.followCursor?a.globals.isBarHorizontal?(n=m-f.left+15,l=v-r.dataPointsDividedHeight+p/2-r.tooltipRect.ttHeight/2):(n=a.globals.isXNumeric?b-x/2:b-r.dataPointsDividedWidth+x/2,l=e.clientY-f.top-r.tooltipRect.ttHeight/2-15):a.globals.isBarHorizontal?((n=b)0&&i.setAttribute("width",e.xcrosshairsWidth)}},{key:"handleYCrosshair",value:function(){var t=this.w,e=this.ttCtx;e.ycrosshairs=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs"),e.ycrosshairsHidden=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs-hidden")}},{key:"drawYaxisTooltipText",value:function(t,e,i){var a=this.ttCtx,s=this.w,r=s.globals.yLabelFormatters[t];if(a.yaxisTooltips[t]){var o=a.getElGrid().getBoundingClientRect(),n=(e-o.top)*i.yRatio[t],l=s.globals.maxYArr[t]-s.globals.minYArr[t],h=s.globals.minYArr[t]+(l-n);a.tooltipPosition.moveYCrosshairs(e-o.top),a.yaxisTooltipText[t].innerHTML=r(h),a.tooltipPosition.moveYAxisTooltip(t)}}}]),t}(),bt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w;var i=this.w;this.tConfig=i.config.tooltip,this.tooltipUtil=new dt(this),this.tooltipLabels=new gt(this),this.tooltipPosition=new ut(this),this.marker=new ft(this),this.intersect=new pt(this),this.axesTooltip=new xt(this),this.showOnIntersect=this.tConfig.intersect,this.showTooltipTitle=this.tConfig.x.show,this.fixedTooltip=this.tConfig.fixed.enabled,this.xaxisTooltip=null,this.yaxisTTEls=null,this.isBarShared=!i.globals.isBarHorizontal&&this.tConfig.shared,this.lastHoverTime=Date.now()}return r(t,[{key:"getElTooltip",value:function(t){return t||(t=this),t.w.globals.dom.baseEl?t.w.globals.dom.baseEl.querySelector(".apexcharts-tooltip"):null}},{key:"getElXCrosshairs",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-xcrosshairs")}},{key:"getElGrid",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-grid")}},{key:"drawTooltip",value:function(t){var e=this.w;this.xyRatios=t,this.isXAxisTooltipEnabled=e.config.xaxis.tooltip.enabled&&e.globals.axisCharts,this.yaxisTooltips=e.config.yaxis.map((function(t,i){return!!(t.show&&t.tooltip.enabled&&e.globals.axisCharts)})),this.allTooltipSeriesGroups=[],e.globals.axisCharts||(this.showTooltipTitle=!1);var i=document.createElement("div");if(i.classList.add("apexcharts-tooltip"),e.config.tooltip.cssClass&&i.classList.add(e.config.tooltip.cssClass),i.classList.add("apexcharts-theme-".concat(this.tConfig.theme)),e.globals.dom.elWrap.appendChild(i),e.globals.axisCharts){this.axesTooltip.drawXaxisTooltip(),this.axesTooltip.drawYaxisTooltip(),this.axesTooltip.setXCrosshairWidth(),this.axesTooltip.handleYCrosshair();var a=new V(this.ctx);this.xAxisTicksPositions=a.getXAxisTicksPositions()}if(!e.globals.comboCharts&&!this.tConfig.intersect&&"rangeBar"!==e.config.chart.type||this.tConfig.shared||(this.showOnIntersect=!0),0!==e.config.markers.size&&0!==e.globals.markers.largestSize||this.marker.drawDynamicPoints(this),e.globals.collapsedSeries.length!==e.globals.series.length){this.dataPointsDividedHeight=e.globals.gridHeight/e.globals.dataPoints,this.dataPointsDividedWidth=e.globals.gridWidth/e.globals.dataPoints,this.showTooltipTitle&&(this.tooltipTitle=document.createElement("div"),this.tooltipTitle.classList.add("apexcharts-tooltip-title"),this.tooltipTitle.style.fontFamily=this.tConfig.style.fontFamily||e.config.chart.fontFamily,this.tooltipTitle.style.fontSize=this.tConfig.style.fontSize,i.appendChild(this.tooltipTitle));var s=e.globals.series.length;(e.globals.xyCharts||e.globals.comboCharts)&&this.tConfig.shared&&(s=this.showOnIntersect?1:e.globals.series.length),this.legendLabels=e.globals.dom.baseEl.querySelectorAll(".apexcharts-legend-text"),this.ttItems=this.createTTElements(s),this.addSVGEvents()}}},{key:"createTTElements",value:function(t){for(var e=this,i=this.w,a=[],s=this.getElTooltip(),r=function(r){var o=document.createElement("div");o.classList.add("apexcharts-tooltip-series-group"),o.style.order=i.config.tooltip.inverseOrder?t-r:r+1,e.tConfig.shared&&e.tConfig.enabledOnSeries&&Array.isArray(e.tConfig.enabledOnSeries)&&e.tConfig.enabledOnSeries.indexOf(r)<0&&o.classList.add("apexcharts-tooltip-series-group-hidden");var n=document.createElement("span");n.classList.add("apexcharts-tooltip-marker"),n.style.backgroundColor=i.globals.colors[r],o.appendChild(n);var l=document.createElement("div");l.classList.add("apexcharts-tooltip-text"),l.style.fontFamily=e.tConfig.style.fontFamily||i.config.chart.fontFamily,l.style.fontSize=e.tConfig.style.fontSize,["y","goals","z"].forEach((function(t){var e=document.createElement("div");e.classList.add("apexcharts-tooltip-".concat(t,"-group"));var i=document.createElement("span");i.classList.add("apexcharts-tooltip-text-".concat(t,"-label")),e.appendChild(i);var a=document.createElement("span");a.classList.add("apexcharts-tooltip-text-".concat(t,"-value")),e.appendChild(a),l.appendChild(e)})),o.appendChild(l),s.appendChild(o),a.push(o)},o=0;o0&&this.addPathsEventListeners(u,c),this.tooltipUtil.hasBars()&&!this.tConfig.shared&&this.addDatapointEventsListeners(c)}}},{key:"drawFixedTooltipRect",value:function(){var t=this.w,e=this.getElTooltip(),i=e.getBoundingClientRect(),a=i.width+10,s=i.height+10,r=this.tConfig.fixed.offsetX,o=this.tConfig.fixed.offsetY,n=this.tConfig.fixed.position.toLowerCase();return n.indexOf("right")>-1&&(r=r+t.globals.svgWidth-a+10),n.indexOf("bottom")>-1&&(o=o+t.globals.svgHeight-s-10),e.style.left=r+"px",e.style.top=o+"px",{x:r,y:o,ttWidth:a,ttHeight:s}}},{key:"addDatapointEventsListeners",value:function(t){var e=this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area");this.addPathsEventListeners(e,t)}},{key:"addPathsEventListeners",value:function(t,e){for(var i=this,a=function(a){var s={paths:t[a],tooltipEl:e.tooltipEl,tooltipY:e.tooltipY,tooltipX:e.tooltipX,elGrid:e.elGrid,hoverArea:e.hoverArea,ttItems:e.ttItems};["mousemove","mouseup","touchmove","mouseout","touchend"].map((function(e){return t[a].addEventListener(e,i.onSeriesHover.bind(i,s),{capture:!1,passive:!0})}))},s=0;s=100?this.seriesHover(t,e):(clearTimeout(this.seriesHoverTimeout),this.seriesHoverTimeout=setTimeout((function(){i.seriesHover(t,e)}),100-a))}},{key:"seriesHover",value:function(t,e){var i=this;this.lastHoverTime=Date.now();var a=[],s=this.w;s.config.chart.group&&(a=this.ctx.getGroupedCharts()),s.globals.axisCharts&&(s.globals.minX===-1/0&&s.globals.maxX===1/0||0===s.globals.dataPoints)||(a.length?a.forEach((function(a){var s=i.getElTooltip(a),r={paths:t.paths,tooltipEl:s,tooltipY:t.tooltipY,tooltipX:t.tooltipX,elGrid:t.elGrid,hoverArea:t.hoverArea,ttItems:a.w.globals.tooltip.ttItems};a.w.globals.minX===i.w.globals.minX&&a.w.globals.maxX===i.w.globals.maxX&&a.w.globals.tooltip.seriesHoverByContext({chartCtx:a,ttCtx:a.w.globals.tooltip,opt:r,e:e})})):this.seriesHoverByContext({chartCtx:this.ctx,ttCtx:this.w.globals.tooltip,opt:t,e:e}))}},{key:"seriesHoverByContext",value:function(t){var e=t.chartCtx,i=t.ttCtx,a=t.opt,s=t.e,r=e.w,o=this.getElTooltip();if(o){if(i.tooltipRect={x:0,y:0,ttWidth:o.getBoundingClientRect().width,ttHeight:o.getBoundingClientRect().height},i.e=s,i.tooltipUtil.hasBars()&&!r.globals.comboCharts&&!i.isBarShared)if(this.tConfig.onDatasetHover.highlightDataSeries)new N(e).toggleSeriesOnHover(s,s.target.parentNode);i.fixedTooltip&&i.drawFixedTooltipRect(),r.globals.axisCharts?i.axisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}):i.nonAxisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect})}}},{key:"axisChartsTooltips",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,o=s.elGrid.getBoundingClientRect(),n="touchmove"===a.type?a.touches[0].clientX:a.clientX,l="touchmove"===a.type?a.touches[0].clientY:a.clientY;if(this.clientY=l,this.clientX=n,r.globals.capturedSeriesIndex=-1,r.globals.capturedDataPointIndex=-1,lo.top+o.height)this.handleMouseOut(s);else{if(Array.isArray(this.tConfig.enabledOnSeries)&&!r.config.tooltip.shared){var h=parseInt(s.paths.getAttribute("index"),10);if(this.tConfig.enabledOnSeries.indexOf(h)<0)return void this.handleMouseOut(s)}var c=this.getElTooltip(),d=this.getElXCrosshairs(),g=r.globals.xyCharts||"bar"===r.config.chart.type&&!r.globals.isBarHorizontal&&this.tooltipUtil.hasBars()&&this.tConfig.shared||r.globals.comboCharts&&this.tooltipUtil.hasBars();if("mousemove"===a.type||"touchmove"===a.type||"mouseup"===a.type){if(r.globals.collapsedSeries.length+r.globals.ancillaryCollapsedSeries.length===r.globals.series.length)return;null!==d&&d.classList.add("apexcharts-active");var u=this.yaxisTooltips.filter((function(t){return!0===t}));if(null!==this.ycrosshairs&&u.length&&this.ycrosshairs.classList.add("apexcharts-active"),g&&!this.showOnIntersect)this.handleStickyTooltip(a,n,l,s);else if("heatmap"===r.config.chart.type||"treemap"===r.config.chart.type){var f=this.intersect.handleHeatTreeTooltip({e:a,opt:s,x:e,y:i,type:r.config.chart.type});e=f.x,i=f.y,c.style.left=e+"px",c.style.top=i+"px"}else this.tooltipUtil.hasBars()&&this.intersect.handleBarTooltip({e:a,opt:s}),this.tooltipUtil.hasMarkers()&&this.intersect.handleMarkerTooltip({e:a,opt:s,x:e,y:i});if(this.yaxisTooltips.length)for(var p=0;pl.width?this.handleMouseOut(a):null!==n?this.handleStickyCapturedSeries(t,n,a,o):(this.tooltipUtil.isXoverlap(o)||s.globals.isBarHorizontal)&&this.create(t,this,0,o,a.ttItems)}},{key:"handleStickyCapturedSeries",value:function(t,e,i,a){var s=this.w;if(!this.tConfig.shared&&null===s.globals.series[e][a])return void this.handleMouseOut(i);void 0!==s.globals.series[e][a]?this.tConfig.shared&&this.tooltipUtil.isXoverlap(a)&&this.tooltipUtil.isInitialSeriesSameLen()?this.create(t,this,e,a,i.ttItems):this.create(t,this,e,a,i.ttItems,!1):this.tooltipUtil.isXoverlap(a)&&this.create(t,this,0,a,i.ttItems)}},{key:"deactivateHoverFilter",value:function(){for(var t=this.w,e=new m(this.ctx),i=t.globals.dom.Paper.select(".apexcharts-bar-area"),a=0;a5&&void 0!==arguments[5]?arguments[5]:null,S=this.w,C=i;"mouseup"===t.type&&this.markerClick(t,a,s),null===A&&(A=this.tConfig.shared);var L=this.tooltipUtil.hasMarkers(),P=this.tooltipUtil.getElBars();if(S.config.legend.tooltipHoverFormatter){var T=S.config.legend.tooltipHoverFormatter,M=Array.from(this.legendLabels);M.forEach((function(t){var e=t.getAttribute("data:default-text");t.innerHTML=decodeURIComponent(e)}));for(var I=0;I0?C.marker.enlargePoints(s):C.tooltipPosition.moveDynamicPointsOnHover(s)),this.tooltipUtil.hasBars()&&(this.barSeriesHeight=this.tooltipUtil.getBarsHeight(P),this.barSeriesHeight>0)){var R=new m(this.ctx),D=S.globals.dom.Paper.select(".apexcharts-bar-area[j='".concat(s,"']"));this.deactivateHoverFilter(),this.tooltipPosition.moveStickyTooltipOverBars(s);for(var H=0;Hs.globals.gridHeight&&(u=s.globals.gridHeight-b)),{bcx:h,bcy:l,dataLabelsX:e,dataLabelsY:u,totalDataLabelsX:a,totalDataLabelsY:i,totalDataLabelsAnchor:"middle"}}},{key:"calculateBarsDataLabelsPosition",value:function(t){var e=this.w,i=t.x,a=t.i,s=t.j,r=t.realIndex,o=t.bcy,n=t.barHeight,l=t.barWidth,h=t.textRects,c=t.dataLabelsX,d=t.strokeWidth,g=t.dataLabelsConfig,u=t.barDataLabelsConfig,f=t.barTotalDataLabelsConfig,p=t.offX,x=t.offY,b=e.globals.gridHeight/e.globals.dataPoints;l=Math.abs(l);var v,y,w=o-(this.barCtx.isRangeBar?0:b)+n/2+h.height/2+x-3,k="start",A=this.barCtx.series[a][s]<0,S=i;switch(this.barCtx.isReversed&&(S=i+l-(A?2*l:0),i=e.globals.gridWidth-l),u.position){case"center":c=A?S+l/2-p:Math.max(h.width/2,S-l/2)+p;break;case"bottom":c=A?S+l-d-Math.round(h.width/2)-p:S-l+d+Math.round(h.width/2)+p;break;case"top":c=A?S-d+Math.round(h.width/2)-p:S-d-Math.round(h.width/2)+p}if(this.barCtx.lastActiveBarSerieIndex===r&&f.enabled){var C=new m(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({realIndex:r,j:s}),g.fontSize);A?(v=S-d+Math.round(C.width/2)-p-f.offsetX-15,k="end"):v=S-d-Math.round(C.width/2)+p+f.offsetX+15,y=w+f.offsetY}return e.config.chart.stacked||(c<0?c=c+h.width+d:c+h.width/2>e.globals.gridWidth&&(c=e.globals.gridWidth-h.width-d)),{bcx:i,bcy:o,dataLabelsX:c,dataLabelsY:w,totalDataLabelsX:v,totalDataLabelsY:y,totalDataLabelsAnchor:k}}},{key:"drawCalculatedDataLabels",value:function(t){var i=t.x,a=t.y,s=t.val,r=t.i,o=t.j,n=t.textRects,l=t.barHeight,h=t.barWidth,c=t.dataLabelsConfig,d=this.w,g="rotate(0)";"vertical"===d.config.plotOptions.bar.dataLabels.orientation&&(g="rotate(-90, ".concat(i,", ").concat(a,")"));var u=new O(this.barCtx.ctx),f=new m(this.barCtx.ctx),p=c.formatter,x=null,b=d.globals.collapsedSeriesIndices.indexOf(r)>-1;if(c.enabled&&!b){x=f.group({class:"apexcharts-data-labels",transform:g});var v="";void 0!==s&&(v=p(s,e(e({},d),{},{seriesIndex:r,dataPointIndex:o,w:d})));var y=d.globals.series[r][o]<0,w=d.config.plotOptions.bar.dataLabels.position;if("vertical"===d.config.plotOptions.bar.dataLabels.orientation&&("top"===w&&(c.textAnchor=y?"end":"start"),"center"===w&&(c.textAnchor="middle"),"bottom"===w&&(c.textAnchor=y?"end":"start")),this.barCtx.isRangeBar&&this.barCtx.barOptions.dataLabels.hideOverflowingLabels)hMath.abs(h)&&(v=""):n.height/1.6>Math.abs(l)&&(v=""));var k=e({},c);this.barCtx.isHorizontal&&s<0&&("start"===c.textAnchor?k.textAnchor="end":"end"===c.textAnchor&&(k.textAnchor="start")),u.plotDataLabelsText({x:i,y:a,text:v,i:r,j:o,parent:x,dataLabelsConfig:k,alwaysDrawDataLabel:!0,offsetCorrection:!0})}return x}},{key:"drawTotalDataLabels",value:function(t){var e,i=t.x,a=t.y,s=t.val,r=t.realIndex,o=t.textAnchor,n=t.barTotalDataLabelsConfig,l=new m(this.barCtx.ctx);return n.enabled&&void 0!==i&&void 0!==a&&this.barCtx.lastActiveBarSerieIndex===r&&(e=l.drawText({x:i,y:a,foreColor:n.style.color,text:s,textAnchor:o,fontFamily:n.style.fontFamily,fontSize:n.style.fontSize,fontWeight:n.style.fontWeight})),e}}]),t}(),mt=function(){function t(e){a(this,t),this.w=e.w,this.barCtx=e}return r(t,[{key:"initVariables",value:function(t){var e=this.w;this.barCtx.series=t,this.barCtx.totalItems=0,this.barCtx.seriesLen=0,this.barCtx.visibleI=-1,this.barCtx.visibleItems=1;for(var i=0;i0&&(this.barCtx.seriesLen=this.barCtx.seriesLen+1,this.barCtx.totalItems+=t[i].length),e.globals.isXNumeric)for(var a=0;ae.globals.minX&&e.globals.seriesX[i][a]0&&(a=l.globals.minXDiff/d),(r=a/this.barCtx.seriesLen*parseInt(this.barCtx.barOptions.columnWidth,10)/100)<1&&(r=1)}o=l.globals.gridHeight-this.barCtx.baseLineY[this.barCtx.yaxisIndex]-(this.barCtx.isReversed?l.globals.gridHeight:0)+(this.barCtx.isReversed?2*this.barCtx.baseLineY[this.barCtx.yaxisIndex]:0),t=l.globals.padHorizontal+(a-r*this.barCtx.seriesLen)/2}return{x:t,y:e,yDivision:i,xDivision:a,barHeight:s,barWidth:r,zeroH:o,zeroW:n}}},{key:"getPathFillColor",value:function(t,e,i,a){var s,r,o,n,l=this.w,h=new R(this.barCtx.ctx),c=null,d=this.barCtx.barOptions.distributed?i:e;this.barCtx.barOptions.colors.ranges.length>0&&this.barCtx.barOptions.colors.ranges.map((function(a){t[e][i]>=a.from&&t[e][i]<=a.to&&(c=a.color)}));return l.config.series[e].data[i]&&l.config.series[e].data[i].fillColor&&(c=l.config.series[e].data[i].fillColor),h.fillPath({seriesNumber:this.barCtx.barOptions.distributed?d:a,dataPointIndex:i,color:c,value:t[e][i],fillConfig:null===(s=l.config.series[e].data[i])||void 0===s?void 0:s.fill,fillType:null!==(r=l.config.series[e].data[i])&&void 0!==r&&null!==(o=r.fill)&&void 0!==o&&o.type?null===(n=l.config.series[e].data[i])||void 0===n?void 0:n.fill.type:l.config.fill.type})}},{key:"getStrokeWidth",value:function(t,e,i){var a=0,s=this.w;return this.barCtx.series[t][e]?this.barCtx.isNullValue=!1:this.barCtx.isNullValue=!0,s.config.stroke.show&&(this.barCtx.isNullValue||(a=Array.isArray(this.barCtx.strokeWidth)?this.barCtx.strokeWidth[i]:this.barCtx.strokeWidth)),a}},{key:"shouldApplyRadius",value:function(t){var e=this.w,i=!1;return e.config.plotOptions.bar.borderRadius>0&&(e.config.chart.stacked&&"last"===e.config.plotOptions.bar.borderRadiusWhenStacked?this.barCtx.lastActiveBarSerieIndex===t&&(i=!0):i=!0),i}},{key:"barBackground",value:function(t){var e=t.j,i=t.i,a=t.x1,s=t.x2,r=t.y1,o=t.y2,n=t.elSeries,l=this.w,h=new m(this.barCtx.ctx),c=new N(this.barCtx.ctx).getActiveConfigSeriesIndex();if(this.barCtx.barOptions.colors.backgroundBarColors.length>0&&c===i){e>=this.barCtx.barOptions.colors.backgroundBarColors.length&&(e%=this.barCtx.barOptions.colors.backgroundBarColors.length);var d=this.barCtx.barOptions.colors.backgroundBarColors[e],g=h.drawRect(void 0!==a?a:0,void 0!==r?r:0,void 0!==s?s:l.globals.gridWidth,void 0!==o?o:l.globals.gridHeight,this.barCtx.barOptions.colors.backgroundBarRadius,d,this.barCtx.barOptions.colors.backgroundBarOpacity);n.add(g),g.node.classList.add("apexcharts-backgroundBar")}}},{key:"getColumnPaths",value:function(t){var e,i=t.barWidth,a=t.barXPosition,s=t.y1,r=t.y2,o=t.strokeWidth,n=t.realIndex,l=t.i,h=t.j,c=t.w,d=new m(this.barCtx.ctx);(o=Array.isArray(o)?o[n]:o)||(o=0);var g=i,u=a;null!==(e=c.config.series[n].data[h])&&void 0!==e&&e.columnWidthOffset&&(u=a-c.config.series[n].data[h].columnWidthOffset/2,g=i+c.config.series[n].data[h].columnWidthOffset);var f=u,p=u+g;s+=.001,r+=.001;var x=d.move(f,s),b=d.move(f,s),v=d.line(p-o,s);return c.globals.previousPaths.length>0&&(b=this.barCtx.getPreviousPath(n,h,!1)),x=x+d.line(f,r)+d.line(p-o,r)+d.line(p-o,s)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),b=b+d.line(f,s)+v+v+v+v+v+d.line(f,s)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(n)&&(x=d.roundPathCorners(x,c.config.plotOptions.bar.borderRadius)),c.config.chart.stacked&&(this.barCtx.yArrj.push(r),this.barCtx.yArrjF.push(Math.abs(s-r)),this.barCtx.yArrjVal.push(this.barCtx.series[l][h])),{pathTo:x,pathFrom:b}}},{key:"getBarpaths",value:function(t){var e,i=t.barYPosition,a=t.barHeight,s=t.x1,r=t.x2,o=t.strokeWidth,n=t.realIndex,l=t.i,h=t.j,c=t.w,d=new m(this.barCtx.ctx);(o=Array.isArray(o)?o[n]:o)||(o=0);var g=i,u=a;null!==(e=c.config.series[n].data[h])&&void 0!==e&&e.barHeightOffset&&(g=i-c.config.series[n].data[h].barHeightOffset/2,u=a+c.config.series[n].data[h].barHeightOffset);var f=g,p=g+u;s+=.001,r+=.001;var x=d.move(s,f),b=d.move(s,f);c.globals.previousPaths.length>0&&(b=this.barCtx.getPreviousPath(n,h,!1));var v=d.line(s,p-o);return x=x+d.line(r,f)+d.line(r,p-o)+v+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),b=b+d.line(s,f)+v+v+v+v+v+d.line(s,f)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(n)&&(x=d.roundPathCorners(x,c.config.plotOptions.bar.borderRadius)),c.config.chart.stacked&&(this.barCtx.xArrj.push(r),this.barCtx.xArrjF.push(Math.abs(s-r)),this.barCtx.xArrjVal.push(this.barCtx.series[l][h])),{pathTo:x,pathFrom:b}}},{key:"checkZeroSeries",value:function(t){for(var e=t.series,i=this.w,a=0;a=0;o--)this.barCtx.zeroSerieses.indexOf(o)>-1&&o===this.radiusOnSeriesNumber&&(this.barCtx.radiusOnSeriesNumber-=1);for(var n=e.length-1;n>=0;n--)i.globals.collapsedSeriesIndices.indexOf(this.barCtx.radiusOnSeriesNumber)>-1&&(this.barCtx.radiusOnSeriesNumber-=1)}},{key:"getXForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e+t/this.barCtx.invertedYRatio-2*(this.barCtx.isReversed?t/this.barCtx.invertedYRatio:0)),a}},{key:"getYForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e-t/this.barCtx.yRatio[this.barCtx.yaxisIndex]+2*(this.barCtx.isReversed?t/this.barCtx.yRatio[this.barCtx.yaxisIndex]:0)),a}},{key:"getGoalValues",value:function(t,e,i,a,s){var r=this,n=this.w,l=[];return n.globals.seriesGoals[a]&&n.globals.seriesGoals[a][s]&&Array.isArray(n.globals.seriesGoals[a][s])&&n.globals.seriesGoals[a][s].forEach((function(a){var s;l.push((o(s={},t,"x"===t?r.getXForValue(a.value,e,!1):r.getYForValue(a.value,i,!1)),o(s,"attrs",a),s))})),l}},{key:"drawGoalLine",value:function(t){var e=t.barXPosition,i=t.barYPosition,a=t.goalX,s=t.goalY,r=t.barWidth,o=t.barHeight,n=new m(this.barCtx.ctx),l=n.group({className:"apexcharts-bar-goals-groups"}),h=null;return this.barCtx.isHorizontal?Array.isArray(a)&&a.forEach((function(t){var e=void 0!==t.attrs.strokeHeight?t.attrs.strokeHeight:o/2,a=i+e+o/2;h=n.drawLine(t.x,a-2*e,t.x,a,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeWidth?t.attrs.strokeWidth:2,t.attrs.strokeLineCap),l.add(h)})):Array.isArray(s)&&s.forEach((function(t){var i=void 0!==t.attrs.strokeWidth?t.attrs.strokeWidth:r/2,a=e+i+r/2;h=n.drawLine(a-2*i,t.y,a,t.y,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeHeight?t.attrs.strokeHeight:2,t.attrs.strokeLineCap),l.add(h)})),l}}]),t}(),yt=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w;var s=this.w;this.barOptions=s.config.plotOptions.bar,this.isHorizontal=this.barOptions.horizontal,this.strokeWidth=s.config.stroke.width,this.isNullValue=!1,this.isRangeBar=s.globals.seriesRange.length&&this.isHorizontal,this.xyRatios=i,null!==this.xyRatios&&(this.xRatio=i.xRatio,this.initialXRatio=i.initialXRatio,this.yRatio=i.yRatio,this.invertedXRatio=i.invertedXRatio,this.invertedYRatio=i.invertedYRatio,this.baseLineY=i.baseLineY,this.baseLineInvertedY=i.baseLineInvertedY),this.yaxisIndex=0,this.seriesLen=0;var r=new N(this.ctx);this.lastActiveBarSerieIndex=r.getActiveConfigSeriesIndex("desc",["bar","column"]);var o=r.getBarSeriesIndices(),n=new y(this.ctx);this.stackedSeriesTotals=n.getStackedSeriesTotals(this.w.config.series.map((function(t,e){return-1===o.indexOf(e)?e:-1})).filter((function(t){return-1!==t}))),this.barHelpers=new mt(this)}return r(t,[{key:"draw",value:function(t,i){var a=this.w,s=new m(this.ctx),r=new y(this.ctx,a);t=r.getLogSeries(t),this.series=t,this.yRatio=r.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);var o=s.group({class:"apexcharts-bar-series apexcharts-plot-series"});a.config.dataLabels.enabled&&this.totalItems>this.barOptions.dataLabels.maxItems&&console.warn("WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering.");for(var n=0,l=0;n0&&(this.visibleI=this.visibleI+1);var k=0,A=0;this.yRatio.length>1&&(this.yaxisIndex=v),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed;var S=this.barHelpers.initialPositions();f=S.y,k=S.barHeight,c=S.yDivision,g=S.zeroW,u=S.x,A=S.barWidth,h=S.xDivision,d=S.zeroH,this.horizontal||b.push(u+A/2);for(var C=s.group({class:"apexcharts-datalabels","data:realIndex":v}),L=s.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),P=0;P0&&b.push(u+A/2),p.push(f);var X=this.barHelpers.getPathFillColor(t,n,P,v);this.renderSeries({realIndex:v,pathFill:X,j:P,i:n,pathFrom:M.pathFrom,pathTo:M.pathTo,strokeWidth:T,elSeries:w,x:u,y:f,series:t,barHeight:k,barWidth:A,elDataLabelsWrap:C,elGoalsMarkers:L,visibleSeries:this.visibleI,type:"bar"})}a.globals.seriesXvalues[v]=b,a.globals.seriesYvalues[v]=p,o.add(w)}return o}},{key:"renderSeries",value:function(t){var e=t.realIndex,i=t.pathFill,a=t.lineFill,s=t.j,r=t.i,o=t.pathFrom,n=t.pathTo,l=t.strokeWidth,h=t.elSeries,c=t.x,d=t.y,g=t.y1,u=t.y2,f=t.series,p=t.barHeight,x=t.barWidth,b=t.barYPosition,y=t.elDataLabelsWrap,w=t.elGoalsMarkers,k=t.visibleSeries,A=t.type,S=this.w,C=new m(this.ctx);a||(a=this.barOptions.distributed?S.globals.stroke.colors[s]:S.globals.stroke.colors[e]),S.config.series[r].data[s]&&S.config.series[r].data[s].strokeColor&&(a=S.config.series[r].data[s].strokeColor),this.isNullValue&&(i="none");var L=s/S.config.chart.animations.animateGradually.delay*(S.config.chart.animations.speed/S.globals.dataPoints)/2.4,P=C.renderPaths({i:r,j:s,realIndex:e,pathFrom:o,pathTo:n,stroke:a,strokeWidth:l,strokeLineCap:S.config.stroke.lineCap,fill:i,animationDelay:L,initialSpeed:S.config.chart.animations.speed,dataChangeSpeed:S.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(A,"-area")});P.attr("clip-path","url(#gridRectMask".concat(S.globals.cuid,")"));var T=S.config.forecastDataPoints;T.count>0&&s>=S.globals.dataPoints-T.count&&(P.node.setAttribute("stroke-dasharray",T.dashArray),P.node.setAttribute("stroke-width",T.strokeWidth),P.node.setAttribute("fill-opacity",T.fillOpacity)),void 0!==g&&void 0!==u&&(P.attr("data-range-y1",g),P.attr("data-range-y2",u)),new v(this.ctx).setSelectionFilter(P,e,s),h.add(P);var M=new vt(this).handleBarDataLabels({x:c,y:d,y1:g,y2:u,i:r,j:s,series:f,realIndex:e,barHeight:p,barWidth:x,barYPosition:b,renderedPath:P,visibleSeries:k});return null!==M.dataLabels&&y.add(M.dataLabels),M.totalDataLabels&&y.add(M.totalDataLabels),h.add(y),w&&h.add(w),h}},{key:"drawBarPaths",value:function(t){var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,o=t.x,n=t.y,l=t.yDivision,h=t.elSeries,c=this.w,d=i.i,g=i.j;if(c.globals.isXNumeric)e=(n=(c.globals.seriesX[d][g]-c.globals.minX)/this.invertedXRatio-a)+a*this.visibleI;else if(c.config.plotOptions.bar.hideZeroBarsWhenGrouped){var u=0,f=0;c.globals.seriesPercent.forEach((function(t,e){t[g]&&u++,e0&&parseInt(r.realIndex,10)===parseInt(t,10)&&void 0!==a.globals.previousPaths[s].paths[e]&&(i=a.globals.previousPaths[s].paths[e].d)}return i}}]),t}(),wt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this,s=this.w;this.graphics=new m(this.ctx),this.bar=new yt(this.ctx,this.xyRatios);var r=new y(this.ctx,s);t=r.getLogSeries(t),this.yRatio=r.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t),"100%"===s.config.chart.stackType&&(t=s.globals.seriesPercent.slice()),this.series=t,this.totalItems=0,this.prevY=[],this.prevX=[],this.prevYF=[],this.prevXF=[],this.prevYVal=[],this.prevXVal=[],this.xArrj=[],this.xArrjF=[],this.xArrjVal=[],this.yArrj=[],this.yArrjF=[],this.yArrjVal=[];for(var o=0;o0&&(this.totalItems+=t[o].length);for(var n=this.graphics.group({class:"apexcharts-bar-series apexcharts-plot-series"}),l=0,h=0,c=function(r,o){var c=void 0,d=void 0,g=void 0,u=void 0,f=[],p=[],b=s.globals.comboCharts?i[r]:r;a.yRatio.length>1&&(a.yaxisIndex=b),a.isReversed=s.config.yaxis[a.yaxisIndex]&&s.config.yaxis[a.yaxisIndex].reversed;var v=a.graphics.group({class:"apexcharts-series",seriesName:x.escapeString(s.globals.seriesNames[b]),rel:r+1,"data:realIndex":b});a.ctx.series.addCollapsedClassToSeries(v,b);var m=a.graphics.group({class:"apexcharts-datalabels","data:realIndex":b}),y=a.graphics.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),w=0,k=0,A=a.initialPositions(l,h,c,d,g,u);h=A.y,w=A.barHeight,d=A.yDivision,u=A.zeroW,l=A.x,k=A.barWidth,c=A.xDivision,g=A.zeroH,a.yArrj=[],a.yArrjF=[],a.yArrjVal=[],a.xArrj=[],a.xArrjF=[],a.xArrjVal=[],1===a.prevY.length&&a.prevY[0].every((function(t){return isNaN(t)}))&&(a.prevY[0]=a.prevY[0].map((function(t){return g})),a.prevYF[0]=a.prevYF[0].map((function(t){return 0})));for(var S=0;S1?(i=l.globals.minXDiff/this.xRatio)*parseInt(this.barOptions.columnWidth,10)/100:n*parseInt(l.config.plotOptions.bar.columnWidth,10)/100,s=l.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?l.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),t=l.globals.padHorizontal+(i-n)/2),{x:t,y:e,yDivision:a,xDivision:i,barHeight:o,barWidth:n,zeroH:s,zeroW:r}}},{key:"drawStackedBarPaths",value:function(t){for(var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,o=t.x,n=t.y,l=t.yDivision,h=t.elSeries,c=this.w,d=n,g=i.i,u=i.j,f=0,p=0;p0){var x=r;this.prevXVal[g-1][u]<0?x=this.series[g][u]>=0?this.prevX[g-1][u]+f-2*(this.isReversed?f:0):this.prevX[g-1][u]:this.prevXVal[g-1][u]>=0&&(x=this.series[g][u]>=0?this.prevX[g-1][u]:this.prevX[g-1][u]-f+2*(this.isReversed?f:0)),e=x}else e=r;o=null===this.series[g][u]?e:e+this.series[g][u]/this.invertedYRatio-2*(this.isReversed?this.series[g][u]/this.invertedYRatio:0);var b=this.barHelpers.getBarpaths({barYPosition:d,barHeight:a,x1:e,x2:o,strokeWidth:s,series:this.series,realIndex:i.realIndex,i:g,j:u,w:c});return this.barHelpers.barBackground({j:u,i:g,y1:d,y2:a,elSeries:h}),n+=l,{pathTo:b.pathTo,pathFrom:b.pathFrom,goalX:this.barHelpers.getGoalValues("x",r,null,g,u),barYPosition:d,x:o,y:n}}},{key:"drawStackedColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=t.y,s=t.xDivision,r=t.barWidth,o=t.zeroH;t.strokeWidth;var n=t.elSeries,l=this.w,h=e.i,c=e.j,d=e.bc;if(l.globals.isXNumeric){var g=l.globals.seriesX[h][c];g||(g=0),i=(g-l.globals.minX)/this.xRatio-r/2}for(var u,f=i,p=0,x=0;x0&&!l.globals.isXNumeric||h>0&&l.globals.isXNumeric&&l.globals.seriesX[h-1][c]===l.globals.seriesX[h][c]){var b,v,m=Math.min(this.yRatio.length+1,h+1);if(void 0!==this.prevY[h-1])for(var y=1;y=0?v-p+2*(this.isReversed?p:0):v;break}if(this.prevYVal[h-w][c]>=0){b=this.series[h][c]>=0?v:v+p-2*(this.isReversed?p:0);break}}void 0===b&&(b=l.globals.gridHeight),u=this.prevYF[0].every((function(t){return 0===t}))&&this.prevYF.slice(1,h).every((function(t){return t.every((function(t){return isNaN(t)}))}))?o:b}else u=o;a=this.series[h][c]?u-this.series[h][c]/this.yRatio[this.yaxisIndex]+2*(this.isReversed?this.series[h][c]/this.yRatio[this.yaxisIndex]:0):u;var k=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:r,y1:u,y2:a,yRatio:this.yRatio[this.yaxisIndex],strokeWidth:this.strokeWidth,series:this.series,realIndex:e.realIndex,i:h,j:c,w:l});return this.barHelpers.barBackground({bc:d,j:c,i:h,x1:f,x2:r,elSeries:n}),i+=s,{pathTo:k.pathTo,pathFrom:k.pathFrom,goalY:this.barHelpers.getGoalValues("y",null,o,h,c),barXPosition:f,x:l.globals.isXNumeric?i-s:i,y:a}}}]),s}(),kt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this,s=this.w,r=new m(this.ctx),o=new R(this.ctx);this.candlestickOptions=this.w.config.plotOptions.candlestick,this.boxOptions=this.w.config.plotOptions.boxPlot,this.isHorizontal=s.config.plotOptions.bar.horizontal;var n=new y(this.ctx,s);t=n.getLogSeries(t),this.series=t,this.yRatio=n.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);for(var l=r.group({class:"apexcharts-".concat(s.config.chart.type,"-series apexcharts-plot-series")}),h=function(n){a.isBoxPlot="boxPlot"===s.config.chart.type||"boxPlot"===s.config.series[n].type;var h,c,d,g,u=void 0,f=void 0,p=[],b=[],v=s.globals.comboCharts?i[n]:n,m=r.group({class:"apexcharts-series",seriesName:x.escapeString(s.globals.seriesNames[v]),rel:n+1,"data:realIndex":v});a.ctx.series.addCollapsedClassToSeries(m,v),t[n].length>0&&(a.visibleI=a.visibleI+1);var y,w;a.yRatio.length>1&&(a.yaxisIndex=v);var k=a.barHelpers.initialPositions();f=k.y,y=k.barHeight,c=k.yDivision,g=k.zeroW,u=k.x,w=k.barWidth,h=k.xDivision,d=k.zeroH,b.push(u+w/2);for(var A=r.group({class:"apexcharts-datalabels","data:realIndex":v}),S=function(i){var r=a.barHelpers.getStrokeWidth(n,i,v),l=null,x={indexes:{i:n,j:i,realIndex:v},x:u,y:f,strokeWidth:r,elSeries:m};l=a.isHorizontal?a.drawHorizontalBoxPaths(e(e({},x),{},{yDivision:c,barHeight:y,zeroW:g})):a.drawVerticalBoxPaths(e(e({},x),{},{xDivision:h,barWidth:w,zeroH:d})),f=l.y,u=l.x,i>0&&b.push(u+w/2),p.push(f),l.pathTo.forEach((function(e,h){var c=!a.isBoxPlot&&a.candlestickOptions.wick.useFillColor?l.color[h]:s.globals.stroke.colors[n],d=o.fillPath({seriesNumber:v,dataPointIndex:i,color:l.color[h],value:t[n][i]});a.renderSeries({realIndex:v,pathFill:d,lineFill:c,j:i,i:n,pathFrom:l.pathFrom,pathTo:e,strokeWidth:r,elSeries:m,x:u,y:f,series:t,barHeight:y,barWidth:w,elDataLabelsWrap:A,visibleSeries:a.visibleI,type:s.config.chart.type})}))},C=0;Cb.c&&(d=!1);var w=Math.min(b.o,b.c),k=Math.max(b.o,b.c),A=b.m;n.globals.isXNumeric&&(i=(n.globals.seriesX[x][c]-n.globals.minX)/this.xRatio-s/2);var S=i+s*this.visibleI;void 0===this.series[h][c]||null===this.series[h][c]?(w=r,k=r):(w=r-w/p,k=r-k/p,v=r-b.h/p,y=r-b.l/p,A=r-b.m/p);var C=l.move(S,r),L=l.move(S+s/2,w);return n.globals.previousPaths.length>0&&(L=this.getPreviousPath(x,c,!0)),C=this.isBoxPlot?[l.move(S,w)+l.line(S+s/2,w)+l.line(S+s/2,v)+l.line(S+s/4,v)+l.line(S+s-s/4,v)+l.line(S+s/2,v)+l.line(S+s/2,w)+l.line(S+s,w)+l.line(S+s,A)+l.line(S,A)+l.line(S,w+o/2),l.move(S,A)+l.line(S+s,A)+l.line(S+s,k)+l.line(S+s/2,k)+l.line(S+s/2,y)+l.line(S+s-s/4,y)+l.line(S+s/4,y)+l.line(S+s/2,y)+l.line(S+s/2,k)+l.line(S,k)+l.line(S,A)+"z"]:[l.move(S,k)+l.line(S+s/2,k)+l.line(S+s/2,v)+l.line(S+s/2,k)+l.line(S+s,k)+l.line(S+s,w)+l.line(S+s/2,w)+l.line(S+s/2,y)+l.line(S+s/2,w)+l.line(S,w)+l.line(S,k-o/2)],L+=l.move(S,w),n.globals.isXNumeric||(i+=a),{pathTo:C,pathFrom:L,x:i,y:k,barXPosition:S,color:this.isBoxPlot?f:d?[g]:[u]}}},{key:"drawHorizontalBoxPaths",value:function(t){var e=t.indexes;t.x;var i=t.y,a=t.yDivision,s=t.barHeight,r=t.zeroW,o=t.strokeWidth,n=this.w,l=new m(this.ctx),h=e.i,c=e.j,d=this.boxOptions.colors.lower;this.isBoxPlot&&(d=[this.boxOptions.colors.lower,this.boxOptions.colors.upper]);var g=this.invertedYRatio,u=e.realIndex,f=this.getOHLCValue(u,c),p=r,x=r,b=Math.min(f.o,f.c),v=Math.max(f.o,f.c),y=f.m;n.globals.isXNumeric&&(i=(n.globals.seriesX[u][c]-n.globals.minX)/this.invertedXRatio-s/2);var w=i+s*this.visibleI;void 0===this.series[h][c]||null===this.series[h][c]?(b=r,v=r):(b=r+b/g,v=r+v/g,p=r+f.h/g,x=r+f.l/g,y=r+f.m/g);var k=l.move(r,w),A=l.move(b,w+s/2);return n.globals.previousPaths.length>0&&(A=this.getPreviousPath(u,c,!0)),k=[l.move(b,w)+l.line(b,w+s/2)+l.line(p,w+s/2)+l.line(p,w+s/2-s/4)+l.line(p,w+s/2+s/4)+l.line(p,w+s/2)+l.line(b,w+s/2)+l.line(b,w+s)+l.line(y,w+s)+l.line(y,w)+l.line(b+o/2,w),l.move(y,w)+l.line(y,w+s)+l.line(v,w+s)+l.line(v,w+s/2)+l.line(x,w+s/2)+l.line(x,w+s-s/4)+l.line(x,w+s/4)+l.line(x,w+s/2)+l.line(v,w+s/2)+l.line(v,w)+l.line(y,w)+"z"],A+=l.move(b,w),n.globals.isXNumeric||(i+=a),{pathTo:k,pathFrom:A,x:v,y:i,barYPosition:w,color:d}}},{key:"getOHLCValue",value:function(t,e){var i=this.w;return{o:this.isBoxPlot?i.globals.seriesCandleH[t][e]:i.globals.seriesCandleO[t][e],h:this.isBoxPlot?i.globals.seriesCandleO[t][e]:i.globals.seriesCandleH[t][e],m:i.globals.seriesCandleM[t][e],l:this.isBoxPlot?i.globals.seriesCandleC[t][e]:i.globals.seriesCandleL[t][e],c:this.isBoxPlot?i.globals.seriesCandleL[t][e]:i.globals.seriesCandleC[t][e]}}}]),s}(),At=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"checkColorRange",value:function(){var t=this.w,e=!1,i=t.config.plotOptions[t.config.chart.type];return i.colorScale.ranges.length>0&&i.colorScale.ranges.map((function(t,i){t.from<=0&&(e=!0)})),e}},{key:"getShadeColor",value:function(t,e,i,a){var s=this.w,r=1,o=s.config.plotOptions[t].shadeIntensity,n=this.determineColor(t,e,i);s.globals.hasNegs||a?r=s.config.plotOptions[t].reverseNegativeShade?n.percent<0?n.percent/100*(1.25*o):(1-n.percent/100)*(1.25*o):n.percent<=0?1-(1+n.percent/100)*o:(1-n.percent/100)*o:(r=1-n.percent/100,"treemap"===t&&(r=(1-n.percent/100)*(1.25*o)));var l=n.color,h=new x;return s.config.plotOptions[t].enableShades&&(l="dark"===this.w.config.theme.mode?x.hexToRgba(h.shadeColor(-1*r,n.color),s.config.fill.opacity):x.hexToRgba(h.shadeColor(r,n.color),s.config.fill.opacity)),{color:l,colorProps:n}}},{key:"determineColor",value:function(t,e,i){var a=this.w,s=a.globals.series[e][i],r=a.config.plotOptions[t],o=r.colorScale.inverse?i:e;r.distributed&&"treemap"===a.config.chart.type&&(o=i);var n=a.globals.colors[o],l=null,h=Math.min.apply(Math,u(a.globals.series[e])),c=Math.max.apply(Math,u(a.globals.series[e]));r.distributed||"heatmap"!==t||(h=a.globals.minY,c=a.globals.maxY),void 0!==r.colorScale.min&&(h=r.colorScale.mina.globals.maxY?r.colorScale.max:a.globals.maxY);var d=Math.abs(c)+Math.abs(h),g=100*s/(0===d?d-1e-6:d);r.colorScale.ranges.length>0&&r.colorScale.ranges.map((function(t,e){if(s>=t.from&&s<=t.to){n=t.color,l=t.foreColor?t.foreColor:null,h=t.from,c=t.to;var i=Math.abs(c)+Math.abs(h);g=100*s/(0===i?i-1e-6:i)}}));return{color:n,foreColor:l,percent:g}}},{key:"calculateDataLabels",value:function(t){var e=t.text,i=t.x,a=t.y,s=t.i,r=t.j,o=t.colorProps,n=t.fontSize,l=this.w.config.dataLabels,h=new m(this.ctx),c=new O(this.ctx),d=null;if(l.enabled){d=h.group({class:"apexcharts-data-labels"});var g=l.offsetX,u=l.offsetY,f=i+g,p=a+parseFloat(l.style.fontSize)/3+u;c.plotDataLabelsText({x:f,y:p,text:e,i:s,j:r,color:o.foreColor,parent:d,fontSize:n,dataLabelsConfig:l})}return d}},{key:"addListeners",value:function(t){var e=new m(this.ctx);t.node.addEventListener("mouseenter",e.pathMouseEnter.bind(this,t)),t.node.addEventListener("mouseleave",e.pathMouseLeave.bind(this,t)),t.node.addEventListener("mousedown",e.pathMouseDown.bind(this,t))}}]),t}(),St=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w,this.xRatio=i.xRatio,this.yRatio=i.yRatio,this.dynamicAnim=this.w.config.chart.animations.dynamicAnimation,this.helpers=new At(e),this.rectRadius=this.w.config.plotOptions.heatmap.radius,this.strokeWidth=this.w.config.stroke.show?this.w.config.stroke.width:0}return r(t,[{key:"draw",value:function(t){var e=this.w,i=new m(this.ctx),a=i.group({class:"apexcharts-heatmap"});a.attr("clip-path","url(#gridRectMask".concat(e.globals.cuid,")"));var s=e.globals.gridWidth/e.globals.dataPoints,r=e.globals.gridHeight/e.globals.series.length,o=0,n=!1;this.negRange=this.helpers.checkColorRange();var l=t.slice();e.config.yaxis[0].reversed&&(n=!0,l.reverse());for(var h=n?0:l.length-1;n?h=0;n?h++:h--){var c=i.group({class:"apexcharts-series apexcharts-heatmap-series",seriesName:x.escapeString(e.globals.seriesNames[h]),rel:h+1,"data:realIndex":h});if(this.ctx.series.addCollapsedClassToSeries(c,h),e.config.chart.dropShadow.enabled){var d=e.config.chart.dropShadow;new v(this.ctx).dropShadow(c,d,h)}for(var g=0,u=e.config.plotOptions.heatmap.shadeIntensity,f=0;f-1&&this.pieClicked(d),i.config.dataLabels.enabled){var A=w.x,S=w.y,C=100*u/this.fullAngle+"%";if(0!==u&&i.config.plotOptions.pie.dataLabels.minAngleToShowLabelthis.fullAngle?e.endAngle=e.endAngle-(a+o):a+o=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle&&(n=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle-.01),Math.ceil(n)>this.fullAngle&&(n-=this.fullAngle);var l=Math.PI*(n-90)/180,h=e.centerX+s*Math.cos(o),c=e.centerY+s*Math.sin(o),d=e.centerX+s*Math.cos(l),g=e.centerY+s*Math.sin(l),u=x.polarToCartesian(e.centerX,e.centerY,e.donutSize,n),f=x.polarToCartesian(e.centerX,e.centerY,e.donutSize,r),p=a>180?1:0,b=["M",h,c,"A",s,s,0,p,1,d,g];return"donut"===e.chartType?[].concat(b,["L",u.x,u.y,"A",e.donutSize,e.donutSize,0,p,0,f.x,f.y,"L",h,c,"z"]).join(" "):"pie"===e.chartType||"polarArea"===e.chartType?[].concat(b,["L",e.centerX,e.centerY,"L",h,c]).join(" "):[].concat(b).join(" ")}},{key:"drawPolarElements",value:function(t){var e=this.w,i=new _(this.ctx),a=new m(this.ctx),s=new Ct(this.ctx),r=a.group(),o=a.group(),n=i.niceScale(0,Math.ceil(this.maxY),e.config.yaxis[0].tickAmount,0,!0),l=n.result.reverse(),h=n.result.length;this.maxY=n.niceMax;for(var c=e.globals.radialSize,d=c/(h-1),g=0;g1&&t.total.show&&(s=t.total.color);var o=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-label"),n=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-value");i=(0,t.value.formatter)(i,r),a||"function"!=typeof t.total.formatter||(i=t.total.formatter(r));var l=e===t.total.label;e=t.name.formatter(e,l,r),null!==o&&(o.textContent=e),null!==n&&(n.textContent=i),null!==o&&(o.style.fill=s)}},{key:"printDataLabelsInner",value:function(t,e){var i=this.w,a=t.getAttribute("data:value"),s=i.globals.seriesNames[parseInt(t.parentNode.getAttribute("rel"),10)-1];i.globals.series.length>1&&this.printInnerLabels(e,s,a,t);var r=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group");null!==r&&(r.style.opacity=1)}},{key:"drawSpokes",value:function(t){var e=this,i=this.w,a=new m(this.ctx),s=i.config.plotOptions.polarArea.spokes;if(0!==s.strokeWidth){for(var r=[],o=360/i.globals.series.length,n=0;n1)o&&!e.total.showAlways?l({makeSliceOut:!1,printLabel:!0}):this.printInnerLabels(e,e.total.label,e.total.formatter(s));else if(l({makeSliceOut:!1,printLabel:!0}),!o)if(s.globals.selectedDataPoints.length&&s.globals.series.length>1)if(s.globals.selectedDataPoints[0].length>0){var h=s.globals.selectedDataPoints[0],c=s.globals.dom.baseEl.querySelector(".apexcharts-".concat(this.chartType.toLowerCase(),"-slice-").concat(h));this.printDataLabelsInner(c,e)}else r&&s.globals.selectedDataPoints.length&&0===s.globals.selectedDataPoints[0].length&&(r.style.opacity=0);else r&&s.globals.series.length>1&&(r.style.opacity=0)}}]),t}(),Pt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.chartType=this.w.config.chart.type,this.initialAnim=this.w.config.chart.animations.enabled,this.dynamicAnim=this.initialAnim&&this.w.config.chart.animations.dynamicAnimation.enabled,this.animDur=0;var i=this.w;this.graphics=new m(this.ctx),this.lineColorArr=void 0!==i.globals.stroke.colors?i.globals.stroke.colors:i.globals.colors,this.defaultSize=i.globals.svgHeight0&&(p=i.getPreviousPath(n));for(var b=0;b=10?t.x>0?(i="start",a+=10):t.x<0&&(i="end",a-=10):i="middle",Math.abs(t.y)>=e-10&&(t.y<0?s-=10:t.y>0&&(s+=10)),{textAnchor:i,newX:a,newY:s}}},{key:"getPreviousPath",value:function(t){for(var e=this.w,i=null,a=0;a0&&parseInt(s.realIndex,10)===parseInt(t,10)&&void 0!==e.globals.previousPaths[a].paths[0]&&(i=e.globals.previousPaths[a].paths[0].d)}return i}},{key:"getDataPointsPos",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.dataPointsLen;t=t||[],e=e||[];for(var a=[],s=0;s=360&&(g=360-Math.abs(this.startAngle)-.1);var u=i.drawPath({d:"",stroke:c,strokeWidth:o*parseInt(h.strokeWidth,10)/100,fill:"none",strokeOpacity:h.opacity,classes:"apexcharts-radialbar-area"});if(h.dropShadow.enabled){var f=h.dropShadow;s.dropShadow(u,f)}l.add(u),u.attr("id","apexcharts-radialbarTrack-"+n),this.animatePaths(u,{centerX:t.centerX,centerY:t.centerY,endAngle:g,startAngle:d,size:t.size,i:n,totalItems:2,animBeginArr:0,dur:0,isTrack:!0,easing:e.globals.easing})}return a}},{key:"drawArcs",value:function(t){var e=this.w,i=new m(this.ctx),a=new R(this.ctx),s=new v(this.ctx),r=i.group(),o=this.getStrokeWidth(t);t.size=t.size-o/2;var n=e.config.plotOptions.radialBar.hollow.background,l=t.size-o*t.series.length-this.margin*t.series.length-o*parseInt(e.config.plotOptions.radialBar.track.strokeWidth,10)/100/2,h=l-e.config.plotOptions.radialBar.hollow.margin;void 0!==e.config.plotOptions.radialBar.hollow.image&&(n=this.drawHollowImage(t,r,l,n));var c=this.drawHollow({size:h,centerX:t.centerX,centerY:t.centerY,fill:n||"transparent"});if(e.config.plotOptions.radialBar.hollow.dropShadow.enabled){var d=e.config.plotOptions.radialBar.hollow.dropShadow;s.dropShadow(c,d)}var g=1;!this.radialDataLabels.total.show&&e.globals.series.length>1&&(g=0);var u=null;this.radialDataLabels.show&&(u=this.renderInnerDataLabels(this.radialDataLabels,{hollowSize:l,centerX:t.centerX,centerY:t.centerY,opacity:g})),"back"===e.config.plotOptions.radialBar.hollow.position&&(r.add(c),u&&r.add(u));var f=!1;e.config.plotOptions.radialBar.inverseOrder&&(f=!0);for(var p=f?t.series.length-1:0;f?p>=0:p100?100:t.series[p])/100,S=Math.round(this.totalAngle*A)+this.startAngle,C=void 0;e.globals.dataChanged&&(k=this.startAngle,C=Math.round(this.totalAngle*x.negToZero(e.globals.previousPaths[p])/100)+k),Math.abs(S)+Math.abs(w)>=360&&(S-=.01),Math.abs(C)+Math.abs(k)>=360&&(C-=.01);var L=S-w,P=Array.isArray(e.config.stroke.dashArray)?e.config.stroke.dashArray[p]:e.config.stroke.dashArray,T=i.drawPath({d:"",stroke:y,strokeWidth:o,fill:"none",fillOpacity:e.config.fill.opacity,classes:"apexcharts-radialbar-area apexcharts-radialbar-slice-"+p,strokeDashArray:P});if(m.setAttrs(T.node,{"data:angle":L,"data:value":t.series[p]}),e.config.chart.dropShadow.enabled){var M=e.config.chart.dropShadow;s.dropShadow(T,M,p)}s.setSelectionFilter(T,0,p),this.addListeners(T,this.radialDataLabels),b.add(T),T.attr({index:0,j:p});var I=0;!this.initialAnim||e.globals.resized||e.globals.dataChanged||(I=e.config.chart.animations.speed),e.globals.dataChanged&&(I=e.config.chart.animations.dynamicAnimation.speed),this.animDur=I/(1.2*t.series.length)+this.animDur,this.animBeginArr.push(this.animDur),this.animatePaths(T,{centerX:t.centerX,centerY:t.centerY,endAngle:S,startAngle:w,prevEndAngle:C,prevStartAngle:k,size:t.size,i:p,totalItems:2,animBeginArr:this.animBeginArr,dur:I,shouldSetPrevPaths:!0,easing:e.globals.easing})}return{g:r,elHollow:c,dataLabels:u}}},{key:"drawHollow",value:function(t){var e=new m(this.ctx).drawCircle(2*t.size);return e.attr({class:"apexcharts-radialbar-hollow",cx:t.centerX,cy:t.centerY,r:t.size,fill:t.fill}),e}},{key:"drawHollowImage",value:function(t,e,i,a){var s=this.w,r=new R(this.ctx),o=x.randomId(),n=s.config.plotOptions.radialBar.hollow.image;if(s.config.plotOptions.radialBar.hollow.imageClipped)r.clippedImgArea({width:i,height:i,image:n,patternID:"pattern".concat(s.globals.cuid).concat(o)}),a="url(#pattern".concat(s.globals.cuid).concat(o,")");else{var l=s.config.plotOptions.radialBar.hollow.imageWidth,h=s.config.plotOptions.radialBar.hollow.imageHeight;if(void 0===l&&void 0===h){var c=s.globals.dom.Paper.image(n).loaded((function(e){this.move(t.centerX-e.width/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-e.height/2+s.config.plotOptions.radialBar.hollow.imageOffsetY)}));e.add(c)}else{var d=s.globals.dom.Paper.image(n).loaded((function(e){this.move(t.centerX-l/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-h/2+s.config.plotOptions.radialBar.hollow.imageOffsetY),this.size(l,h)}));e.add(d)}}return a}},{key:"getStrokeWidth",value:function(t){var e=this.w;return t.size*(100-parseInt(e.config.plotOptions.radialBar.hollow.size,10))/100/(t.series.length+1)-this.margin}}]),i}(),Mt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this.w,s=new m(this.ctx);this.rangeBarOptions=this.w.config.plotOptions.rangeBar,this.series=t,this.seriesRangeStart=a.globals.seriesRangeStart,this.seriesRangeEnd=a.globals.seriesRangeEnd,this.barHelpers.initVariables(t);for(var r=s.group({class:"apexcharts-rangebar-series apexcharts-plot-series"}),o=0;o0&&(this.visibleI=this.visibleI+1);var p=0,b=0;this.yRatio.length>1&&(this.yaxisIndex=u);var v=this.barHelpers.initialPositions();d=v.y,h=v.zeroW,c=v.x,b=v.barWidth,n=v.xDivision,l=v.zeroH;for(var y=s.group({class:"apexcharts-datalabels","data:realIndex":u}),w=s.group({class:"apexcharts-rangebar-goals-markers",style:"pointer-events: none"}),k=0;k0}));return a=l.config.plotOptions.bar.rangeBarGroupRows?s+o*g:s+r*this.visibleI+o*g,u>-1&&!l.config.plotOptions.bar.rangeBarOverlap&&(h=l.globals.seriesRange[e][u].overlaps).indexOf(c)>-1&&(a=(r=n.barHeight/h.length)*this.visibleI+o*(100-parseInt(this.barOptions.barHeight,10))/100/2+r*(this.visibleI+h.indexOf(c))+o*g),{barYPosition:a,barHeight:r}}},{key:"drawRangeColumnPaths",value:function(t){var e=t.indexes,i=t.x;t.strokeWidth;var a=t.xDivision,s=t.barWidth,r=t.zeroH,o=this.w,n=e.i,l=e.j,h=this.yRatio[this.yaxisIndex],c=e.realIndex,d=this.getRangeValue(c,l),g=Math.min(d.start,d.end),u=Math.max(d.start,d.end);o.globals.isXNumeric&&(i=(o.globals.seriesX[n][l]-o.globals.minX)/this.xRatio-s/2);var f=i+s*this.visibleI;void 0===this.series[n][l]||null===this.series[n][l]?g=r:(g=r-g/h,u=r-u/h);var p=Math.abs(u-g),x=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:s,y1:g,y2:u,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,realIndex:e.realIndex,i:c,j:l,w:o});return o.globals.isXNumeric||(i+=a),{pathTo:x.pathTo,pathFrom:x.pathFrom,barHeight:p,x:i,y:u,goalY:this.barHelpers.getGoalValues("y",null,r,n,l),barXPosition:f}}},{key:"drawRangeBarPaths",value:function(t){var e=t.indexes,i=t.y,a=t.y1,s=t.y2,r=t.yDivision,o=t.barHeight,n=t.barYPosition,l=t.zeroW,h=this.w,c=l+a/this.invertedYRatio,d=l+s/this.invertedYRatio,g=Math.abs(d-c),u=this.barHelpers.getBarpaths({barYPosition:n,barHeight:o,x1:c,x2:d,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,i:e.realIndex,realIndex:e.realIndex,j:e.j,w:h});return h.globals.isXNumeric||(i+=r),{pathTo:u.pathTo,pathFrom:u.pathFrom,barWidth:g,x:d,goalX:this.barHelpers.getGoalValues("x",l,null,e.realIndex,e.j),y:i}}},{key:"getRangeValue",value:function(t,e){var i=this.w;return{start:i.globals.seriesRangeStart[t][e],end:i.globals.seriesRangeEnd[t][e]}}}]),s}(),It=function(){function t(e){a(this,t),this.w=e.w,this.lineCtx=e}return r(t,[{key:"sameValueSeriesFix",value:function(t,e){var i=this.w;if(("gradient"===i.config.fill.type||"gradient"===i.config.fill.type[t])&&new y(this.lineCtx.ctx,i).seriesHaveSameValues(t)){var a=e[t].slice();a[a.length-1]=a[a.length-1]+1e-6,e[t]=a}return e}},{key:"calculatePoints",value:function(t){var e=t.series,i=t.realIndex,a=t.x,s=t.y,r=t.i,o=t.j,n=t.prevY,l=this.w,h=[],c=[];if(0===o){var d=this.lineCtx.categoryAxisCorrection+l.config.markers.offsetX;l.globals.isXNumeric&&(d=(l.globals.seriesX[i][0]-l.globals.minX)/this.lineCtx.xRatio+l.config.markers.offsetX),h.push(d),c.push(x.isNumber(e[r][0])?n+l.config.markers.offsetY:null),h.push(a+l.config.markers.offsetX),c.push(x.isNumber(e[r][o+1])?s+l.config.markers.offsetY:null)}else h.push(a+l.config.markers.offsetX),c.push(x.isNumber(e[r][o+1])?s+l.config.markers.offsetY:null);return{x:h,y:c}}},{key:"checkPreviousPaths",value:function(t){for(var e=t.pathFromLine,i=t.pathFromArea,a=t.realIndex,s=this.w,r=0;r0&&parseInt(o.realIndex,10)===parseInt(a,10)&&("line"===o.type?(this.lineCtx.appendPathFrom=!1,e=s.globals.previousPaths[r].paths[0].d):"area"===o.type&&(this.lineCtx.appendPathFrom=!1,i=s.globals.previousPaths[r].paths[0].d,s.config.stroke.show&&s.globals.previousPaths[r].paths[1]&&(e=s.globals.previousPaths[r].paths[1].d)))}return{pathFromLine:e,pathFromArea:i}}},{key:"determineFirstPrevY",value:function(t){var e,i=t.i,a=t.series,s=t.prevY,r=t.lineYPosition,o=this.w;if(void 0!==(null===(e=a[i])||void 0===e?void 0:e[0]))s=(r=o.config.chart.stacked&&i>0?this.lineCtx.prevSeriesY[i-1][0]:this.lineCtx.zeroY)-a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]+2*(this.lineCtx.isReversed?a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]:0);else if(o.config.chart.stacked&&i>0&&void 0===a[i][0])for(var n=i-1;n>=0;n--)if(null!==a[n][0]&&void 0!==a[n][0]){s=r=this.lineCtx.prevSeriesY[n][0];break}return{prevY:s,lineYPosition:r}}}]),t}(),zt=function(){function t(e,i,s){a(this,t),this.ctx=e,this.w=e.w,this.xyRatios=i,this.pointsChart=!("bubble"!==this.w.config.chart.type&&"scatter"!==this.w.config.chart.type)||s,this.scatter=new H(this.ctx),this.noNegatives=this.w.globals.minX===Number.MAX_VALUE,this.lineHelpers=new It(this),this.markers=new D(this.ctx),this.prevSeriesY=[],this.categoryAxisCorrection=0,this.yaxisIndex=0}return r(t,[{key:"draw",value:function(t,i,a,s){var r=this.w,o=new m(this.ctx),n=r.globals.comboCharts?i:r.config.chart.type,l=o.group({class:"apexcharts-".concat(n,"-series apexcharts-plot-series")}),h=new y(this.ctx,r);this.yRatio=this.xyRatios.yRatio,this.zRatio=this.xyRatios.zRatio,this.xRatio=this.xyRatios.xRatio,this.baseLineY=this.xyRatios.baseLineY,t=h.getLogSeries(t),this.yRatio=h.getLogYRatios(this.yRatio);for(var c=[],d=0;d0&&(p=(r.globals.seriesX[g][0]-r.globals.minX)/this.xRatio),f.push(p);var x,b=p,v=void 0,w=b,k=this.zeroY,A=this.zeroY;k=this.lineHelpers.determineFirstPrevY({i:d,series:t,prevY:k,lineYPosition:0}).prevY,u.push(k),x=k;"rangeArea"===n&&(v=A=this.lineHelpers.determineFirstPrevY({i:d,series:s,prevY:A,lineYPosition:0}).prevY);var S={type:n,series:t,realIndex:g,i:d,x:p,y:1,pX:b,pY:x,pathsFrom:this._calculatePathsFrom({type:n,series:t,i:d,realIndex:g,prevX:w,prevY:k,prevY2:A}),linePaths:[],areaPaths:[],seriesIndex:a,lineYPosition:0,xArrj:f,yArrj:u,seriesRangeEnd:s},C=this._iterateOverDataPoints(e(e({},S),{},{iterations:"rangeArea"===n?t[d].length-1:void 0,isRangeStart:!0}));if("rangeArea"===n){var L=this._calculatePathsFrom({series:s,i:d,realIndex:g,prevX:w,prevY:A}),P=this._iterateOverDataPoints(e(e({},S),{},{series:s,pY:v,pathsFrom:L,iterations:s[d].length-1,isRangeStart:!1}));C.linePaths[0]=P.linePath+C.linePath,C.pathFromLine=P.pathFromLine+C.pathFromLine}this._handlePaths({type:n,realIndex:g,i:d,paths:C}),this.elSeries.add(this.elPointsMain),this.elSeries.add(this.elDataLabelsWrap),c.push(this.elSeries)}if(r.config.chart.stacked)for(var T=c.length;T>0;T--)l.add(c[T-1]);else for(var M=0;M1&&(this.yaxisIndex=i),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed,this.zeroY=a.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?a.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),this.areaBottomY=this.zeroY,(this.zeroY>a.globals.gridHeight||"end"===a.config.plotOptions.area.fillTo)&&(this.areaBottomY=a.globals.gridHeight),this.categoryAxisCorrection=this.xDivision/2,this.elSeries=s.group({class:"apexcharts-series",seriesName:x.escapeString(a.globals.seriesNames[i])}),this.elPointsMain=s.group({class:"apexcharts-series-markers-wrap","data:realIndex":i}),this.elDataLabelsWrap=s.group({class:"apexcharts-datalabels","data:realIndex":i});var r=t[e].length===a.globals.dataPoints;this.elSeries.attr({"data:longestSeries":r,rel:e+1,"data:realIndex":i}),this.appendPathFrom=!0}},{key:"_calculatePathsFrom",value:function(t){var e,i,a,s,r=t.type,o=t.series,n=t.i,l=t.realIndex,h=t.prevX,c=t.prevY,d=t.prevY2,g=this.w,u=new m(this.ctx);if(null===o[n][0]){for(var f=0;f0){var p=this.lineHelpers.checkPreviousPaths({pathFromLine:a,pathFromArea:s,realIndex:l});a=p.pathFromLine,s=p.pathFromArea}return{prevX:h,prevY:c,linePath:e,areaPath:i,pathFromLine:a,pathFromArea:s}}},{key:"_handlePaths",value:function(t){var i=t.type,a=t.realIndex,s=t.i,r=t.paths,o=this.w,n=new m(this.ctx),l=new R(this.ctx);this.prevSeriesY.push(r.yArrj),o.globals.seriesXvalues[a]=r.xArrj,o.globals.seriesYvalues[a]=r.yArrj;var h=o.config.forecastDataPoints;if(h.count>0&&"rangeArea"!==i){var c=o.globals.seriesXvalues[a][o.globals.seriesXvalues[a].length-h.count-1],d=n.drawRect(c,0,o.globals.gridWidth,o.globals.gridHeight,0);o.globals.dom.elForecastMask.appendChild(d.node);var g=n.drawRect(0,0,c,o.globals.gridHeight,0);o.globals.dom.elNonForecastMask.appendChild(g.node)}this.pointsChart||o.globals.delayedElements.push({el:this.elPointsMain.node,index:a});var u={i:s,realIndex:a,animationDelay:s,initialSpeed:o.config.chart.animations.speed,dataChangeSpeed:o.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(i)};if("area"===i)for(var f=l.fillPath({seriesNumber:a}),p=0;p0&&"rangeArea"!==i){var S=n.renderPaths(k);S.node.setAttribute("stroke-dasharray",h.dashArray),h.strokeWidth&&S.node.setAttribute("stroke-width",h.strokeWidth),this.elSeries.add(S),S.attr("clip-path","url(#forecastMask".concat(o.globals.cuid,")")),A.attr("clip-path","url(#nonForecastMask".concat(o.globals.cuid,")"))}}}}},{key:"_iterateOverDataPoints",value:function(t){var e=t.type,i=t.series,a=t.iterations,s=t.realIndex,r=t.i,o=t.x,n=t.y,l=t.pX,h=t.pY,c=t.pathsFrom,d=t.linePaths,g=t.areaPaths,u=t.seriesIndex,f=t.lineYPosition,p=t.xArrj,b=t.yArrj,v=t.isRangeStart,y=t.seriesRangeEnd,w=this.w,k=new m(this.ctx),A=this.yRatio,S=c.prevY,C=c.linePath,L=c.areaPath,P=c.pathFromLine,T=c.pathFromArea,M=x.isNumber(w.globals.minYArr[s])?w.globals.minYArr[s]:w.globals.minY;a||(a=w.globals.dataPoints>1?w.globals.dataPoints-1:w.globals.dataPoints);for(var I=n,z=0;z0&&w.globals.collapsedSeries.length-1){e--;break}return e>=0?e:0}(r-1)][z+1]}else f=this.zeroY;else f=this.zeroY;X?n=f-M/A[this.yaxisIndex]+2*(this.isReversed?M/A[this.yaxisIndex]:0):(n=f-i[r][z+1]/A[this.yaxisIndex]+2*(this.isReversed?i[r][z+1]/A[this.yaxisIndex]:0),"rangeArea"===e&&(I=f-y[r][z+1]/A[this.yaxisIndex]+2*(this.isReversed?y[r][z+1]/A[this.yaxisIndex]:0))),p.push(o),b.push(n);var Y=this.lineHelpers.calculatePoints({series:i,x:o,y:n,realIndex:s,i:r,j:z,prevY:S}),F=this._createPaths({type:e,series:i,i:r,realIndex:s,j:z,x:o,y:n,y2:I,pX:l,pY:h,linePath:C,areaPath:L,linePaths:d,areaPaths:g,seriesIndex:u,isRangeStart:v});g=F.areaPaths,d=F.linePaths,l=F.pX,h=F.pY,L=F.areaPath,C=F.linePath,this.appendPathFrom&&(P+=k.line(o,this.zeroY),T+=k.line(o,this.zeroY)),this.handleNullDataPoints(i,Y,r,z,s),this._handleMarkersAndLabels({type:e,pointsPos:Y,i:r,j:z,realIndex:s,isRangeStart:v})}return{yArrj:b,xArrj:p,pathFromArea:T,areaPaths:g,pathFromLine:P,linePaths:d,linePath:C,areaPath:L}}},{key:"_handleMarkersAndLabels",value:function(t){var e=t.type,i=t.pointsPos,a=t.isRangeStart,s=t.i,r=t.j,o=t.realIndex,n=this.w,l=new O(this.ctx);if(this.pointsChart)this.scatter.draw(this.elSeries,r,{realIndex:o,pointsPos:i,zRatio:this.zRatio,elParent:this.elPointsMain});else{n.globals.series[s].length>1&&this.elPointsMain.node.classList.add("apexcharts-element-hidden");var h=this.markers.plotChartMarkers(i,o,r+1);null!==h&&this.elPointsMain.add(h)}var c=l.drawDataLabel({type:e,isRangeStart:a,pos:i,i:o,j:r+1});null!==c&&this.elDataLabelsWrap.add(c)}},{key:"_createPaths",value:function(t){var e=t.type,i=t.series,a=t.i,s=t.realIndex,r=t.j,o=t.x,n=t.y,l=t.y2,h=t.pX,c=t.pY,d=t.linePath,g=t.areaPath,u=t.linePaths,f=t.areaPaths,p=t.seriesIndex,x=t.isRangeStart,b=this.w,v=new m(this.ctx),y=b.config.stroke.curve,w=this.areaBottomY;if(Array.isArray(b.config.stroke.curve)&&(y=Array.isArray(p)?b.config.stroke.curve[p[a]]:b.config.stroke.curve[a]),"smooth"===y){var k=.35*(o-h);b.globals.hasNullValues?(null!==i[a][r]&&(null!==i[a][r+1]?(d=v.move(h,c)+v.curve(h+k,c,o-k,n,o+1,n),g=v.move(h+1,c)+v.curve(h+k,c,o-k,n,o+1,n)+v.line(o,w)+v.line(h,w)+"z"):(d=v.move(h,c),g=v.move(h,c)+"z")),u.push(d),f.push(g)):(d+=v.curve(h+k,c,o-k,n,o,n),g+=v.curve(h+k,c,o-k,n,o,n)),h=o,c=n,r===i[a].length-2&&(g=g+v.curve(h,c,o,n,o,w)+v.move(o,n)+"z","rangeArea"===e&&x?d=d+v.curve(h,c,o,n,o,l)+v.move(o,l)+"z":b.globals.hasNullValues||(u.push(d),f.push(g)))}else{if(null===i[a][r+1]){d+=v.move(o,n);var A=b.globals.isXNumeric?(b.globals.seriesX[s][r]-b.globals.minX)/this.xRatio:o-this.xDivision;g=g+v.line(A,w)+v.move(o,n)+"z"}null===i[a][r]&&(d+=v.move(o,n),g+=v.move(o,w)),"stepline"===y?(d=d+v.line(o,null,"H")+v.line(null,n,"V"),g=g+v.line(o,null,"H")+v.line(null,n,"V")):"straight"===y&&(d+=v.line(o,n),g+=v.line(o,n)),r===i[a].length-2&&(g=g+v.line(o,w)+v.move(o,n)+"z","rangeArea"===e&&x?d=d+v.line(o,l)+v.move(o,l)+"z":(u.push(d),f.push(g)))}return{linePaths:u,areaPaths:f,pX:h,pY:c,linePath:d,areaPath:g}}},{key:"handleNullDataPoints",value:function(t,e,i,a,s){var r=this.w;if(null===t[i][a]&&r.config.markers.showNullDataPoints||1===t[i].length){var o=this.markers.plotChartMarkers(e,s,a+1,this.strokeWidth-r.config.markers.strokeWidth/2,!0);null!==o&&this.elPointsMain.add(o)}}}]),t}();window.TreemapSquared={},window.TreemapSquared.generate=function(){function t(e,i,a,s){this.xoffset=e,this.yoffset=i,this.height=s,this.width=a,this.shortestEdge=function(){return Math.min(this.height,this.width)},this.getCoordinates=function(t){var e,i=[],a=this.xoffset,s=this.yoffset,o=r(t)/this.height,n=r(t)/this.width;if(this.width>=this.height)for(e=0;e=this.height){var a=e/this.height,s=this.width-a;i=new t(this.xoffset+a,this.yoffset,s,this.height)}else{var r=e/this.width,o=this.height-r;i=new t(this.xoffset,this.yoffset+r,this.width,o)}return i}}function e(e,a,s,o,n){o=void 0===o?0:o,n=void 0===n?0:n;var l=i(function(t,e){var i,a=[],s=e/r(t);for(i=0;i=o}(e,l=t[0],n)?(e.push(l),i(t.slice(1),e,s,o)):(h=s.cutArea(r(e),o),o.push(s.getCoordinates(e)),i(t,[],h,o)),o;o.push(s.getCoordinates(e))}function a(t,e){var i=Math.min.apply(Math,t),a=Math.max.apply(Math,t),s=r(t);return Math.max(Math.pow(e,2)*a/Math.pow(s,2),Math.pow(s,2)/(Math.pow(e,2)*i))}function s(t){return t&&t.constructor===Array}function r(t){var e,i=0;for(e=0;er-a&&l.width<=o-s){var h=n.rotateAroundCenter(t.node);t.node.setAttribute("transform","rotate(-90 ".concat(h.x," ").concat(h.y,")"))}}},{key:"animateTreemap",value:function(t,e,i,a){var s=new b(this.ctx);s.animateRect(t,{x:e.x,y:e.y,width:e.width,height:e.height},{x:i.x,y:i.y,width:i.width,height:i.height},a,(function(){s.animationCompleted(t)}))}}]),t}(),Ft=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.timeScaleArray=[],this.utc=this.w.config.xaxis.labels.datetimeUTC}return r(t,[{key:"calculateTimeScaleTicks",value:function(t,i){var a=this,s=this.w;if(s.globals.allSeriesCollapsed)return s.globals.labels=[],s.globals.timescaleLabels=[],[];var r=new T(this.ctx),o=(i-t)/864e5;this.determineInterval(o),s.globals.disableZoomIn=!1,s.globals.disableZoomOut=!1,o<.00011574074074074075?s.globals.disableZoomIn=!0:o>5e4&&(s.globals.disableZoomOut=!0);var n=r.getTimeUnitsfromTimestamp(t,i,this.utc),l=s.globals.gridWidth/o,h=l/24,c=h/60,d=c/60,g=Math.floor(24*o),u=Math.floor(1440*o),f=Math.floor(86400*o),p=Math.floor(o),x=Math.floor(o/30),b=Math.floor(o/365),v={minMillisecond:n.minMillisecond,minSecond:n.minSecond,minMinute:n.minMinute,minHour:n.minHour,minDate:n.minDate,minMonth:n.minMonth,minYear:n.minYear},m={firstVal:v,currentMillisecond:v.minMillisecond,currentSecond:v.minSecond,currentMinute:v.minMinute,currentHour:v.minHour,currentMonthDate:v.minDate,currentDate:v.minDate,currentMonth:v.minMonth,currentYear:v.minYear,daysWidthOnXAxis:l,hoursWidthOnXAxis:h,minutesWidthOnXAxis:c,secondsWidthOnXAxis:d,numberOfSeconds:f,numberOfMinutes:u,numberOfHours:g,numberOfDays:p,numberOfMonths:x,numberOfYears:b};switch(this.tickInterval){case"years":this.generateYearScale(m);break;case"months":case"half_year":this.generateMonthScale(m);break;case"months_days":case"months_fortnight":case"days":case"week_days":this.generateDayScale(m);break;case"hours":this.generateHourScale(m);break;case"minutes_fives":case"minutes":this.generateMinuteScale(m);break;case"seconds_tens":case"seconds_fives":case"seconds":this.generateSecondScale(m)}var y=this.timeScaleArray.map((function(t){var i={position:t.position,unit:t.unit,year:t.year,day:t.day?t.day:1,hour:t.hour?t.hour:0,month:t.month+1};return"month"===t.unit?e(e({},i),{},{day:1,value:t.value+1}):"day"===t.unit||"hour"===t.unit?e(e({},i),{},{value:t.value}):"minute"===t.unit?e(e({},i),{},{value:t.value,minute:t.value}):"second"===t.unit?e(e({},i),{},{value:t.value,minute:t.minute,second:t.second}):t}));return y.filter((function(t){var e=1,i=Math.ceil(s.globals.gridWidth/120),r=t.value;void 0!==s.config.xaxis.tickAmount&&(i=s.config.xaxis.tickAmount),y.length>i&&(e=Math.floor(y.length/i));var o=!1,n=!1;switch(a.tickInterval){case"years":"year"===t.unit&&(o=!0);break;case"half_year":e=7,"year"===t.unit&&(o=!0);break;case"months":e=1,"year"===t.unit&&(o=!0);break;case"months_fortnight":e=15,"year"!==t.unit&&"month"!==t.unit||(o=!0),30===r&&(n=!0);break;case"months_days":e=10,"month"===t.unit&&(o=!0),30===r&&(n=!0);break;case"week_days":e=8,"month"===t.unit&&(o=!0);break;case"days":e=1,"month"===t.unit&&(o=!0);break;case"hours":"day"===t.unit&&(o=!0);break;case"minutes_fives":case"seconds_fives":r%5!=0&&(n=!0);break;case"seconds_tens":r%10!=0&&(n=!0)}if("hours"===a.tickInterval||"minutes_fives"===a.tickInterval||"seconds_tens"===a.tickInterval||"seconds_fives"===a.tickInterval){if(!n)return!0}else if((r%e==0||o)&&!n)return!0}))}},{key:"recalcDimensionsBasedOnFormat",value:function(t,e){var i=this.w,a=this.formatDates(t),s=this.removeOverlappingTS(a);i.globals.timescaleLabels=s.slice(),new ot(this.ctx).plotCoords()}},{key:"determineInterval",value:function(t){var e=24*t,i=60*e;switch(!0){case t/365>5:this.tickInterval="years";break;case t>800:this.tickInterval="half_year";break;case t>180:this.tickInterval="months";break;case t>90:this.tickInterval="months_fortnight";break;case t>60:this.tickInterval="months_days";break;case t>30:this.tickInterval="week_days";break;case t>2:this.tickInterval="days";break;case e>2.4:this.tickInterval="hours";break;case i>15:this.tickInterval="minutes_fives";break;case i>5:this.tickInterval="minutes";break;case i>1:this.tickInterval="seconds_tens";break;case 60*i>20:this.tickInterval="seconds_fives";break;default:this.tickInterval="seconds"}}},{key:"generateYearScale",value:function(t){var e=t.firstVal,i=t.currentMonth,a=t.currentYear,s=t.daysWidthOnXAxis,r=t.numberOfYears,o=e.minYear,n=0,l=new T(this.ctx),h="year";if(e.minDate>1||e.minMonth>0){var c=l.determineRemainingDaysOfYear(e.minYear,e.minMonth,e.minDate);n=(l.determineDaysOfYear(e.minYear)-c+1)*s,o=e.minYear+1,this.timeScaleArray.push({position:n,value:o,unit:h,year:o,month:x.monthMod(i+1)})}else 1===e.minDate&&0===e.minMonth&&this.timeScaleArray.push({position:n,value:o,unit:h,year:a,month:x.monthMod(i+1)});for(var d=o,g=n,u=0;u1){l=(h.determineDaysOfMonths(a+1,e.minYear)-i+1)*r,n=x.monthMod(a+1);var g=s+d,u=x.monthMod(n),f=n;0===n&&(c="year",f=g,u=1,g+=d+=1),this.timeScaleArray.push({position:l,value:f,unit:c,year:g,month:u})}else this.timeScaleArray.push({position:l,value:n,unit:c,year:s,month:x.monthMod(a)});for(var p=n+1,b=l,v=0,m=1;vo.determineDaysOfMonths(e+1,i)?(h=1,n="month",g=e+=1,e):e},d=(24-e.minHour)*s,g=l,u=c(h,i,a);0===e.minHour&&1===e.minDate?(d=0,g=x.monthMod(e.minMonth),n="month",h=e.minDate,r++):1!==e.minDate&&0===e.minHour&&0===e.minMinute&&(d=0,l=e.minDate,g=l,u=c(h=l,i,a)),this.timeScaleArray.push({position:d,value:g,unit:n,year:this._getYear(a,u,0),month:x.monthMod(u),day:h});for(var f=d,p=0;pn.determineDaysOfMonths(e+1,s)&&(p=1,e+=1),{month:e,date:p}},c=function(t,e){return t>n.determineDaysOfMonths(e+1,s)?e+=1:e},d=60-(e.minMinute+e.minSecond/60),g=d*r,u=e.minHour+1,f=u+1;60===d&&(g=0,f=(u=e.minHour)+1);var p=i,b=c(p,a);this.timeScaleArray.push({position:g,value:u,unit:l,day:p,hour:f,year:s,month:x.monthMod(b)});for(var v=g,m=0;m=24)f=0,l="day",b=h(p+=1,b).month,b=c(p,b);var y=this._getYear(s,b,0);v=60*r+v;var w=0===f?p:f;this.timeScaleArray.push({position:v,value:w,unit:l,hour:f,day:p,year:y,month:x.monthMod(b)}),f++}}},{key:"generateMinuteScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,n=t.currentYear,l=t.minutesWidthOnXAxis,h=t.secondsWidthOnXAxis,c=t.numberOfMinutes,d=a+1,g=r,u=o,f=n,p=s,b=(60-i-e/1e3)*h,v=0;v=60&&(d=0,24===(p+=1)&&(p=0)),this.timeScaleArray.push({position:b,value:d,unit:"minute",hour:p,minute:d,day:g,year:this._getYear(f,u,0),month:x.monthMod(u)}),b+=l,d++}},{key:"generateSecondScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,n=t.currentYear,l=t.secondsWidthOnXAxis,h=t.numberOfSeconds,c=i+1,d=a,g=r,u=o,f=n,p=s,b=(1e3-e)/1e3*l,v=0;v=60&&(c=0,++d>=60&&(d=0,24===++p&&(p=0))),this.timeScaleArray.push({position:b,value:c,unit:"second",hour:p,minute:d,second:c,day:g,year:this._getYear(f,u,0),month:x.monthMod(u)}),b+=l,c++}},{key:"createRawDateString",value:function(t,e){var i=t.year;return 0===t.month&&(t.month=1),i+="-"+("0"+t.month.toString()).slice(-2),"day"===t.unit?i+="day"===t.unit?"-"+("0"+e).slice(-2):"-01":i+="-"+("0"+(t.day?t.day:"1")).slice(-2),"hour"===t.unit?i+="hour"===t.unit?"T"+("0"+e).slice(-2):"T00":i+="T"+("0"+(t.hour?t.hour:"0")).slice(-2),"minute"===t.unit?i+=":"+("0"+e).slice(-2):i+=":"+(t.minute?("0"+t.minute).slice(-2):"00"),"second"===t.unit?i+=":"+("0"+e).slice(-2):i+=":00",this.utc&&(i+=".000Z"),i}},{key:"formatDates",value:function(t){var e=this,i=this.w;return t.map((function(t){var a=t.value.toString(),s=new T(e.ctx),r=e.createRawDateString(t,a),o=s.getDate(s.parseDate(r));if(e.utc||(o=s.getDate(s.parseDateWithTimezone(r))),void 0===i.config.xaxis.labels.format){var n="dd MMM",l=i.config.xaxis.labels.datetimeFormatter;"year"===t.unit&&(n=l.year),"month"===t.unit&&(n=l.month),"day"===t.unit&&(n=l.day),"hour"===t.unit&&(n=l.hour),"minute"===t.unit&&(n=l.minute),"second"===t.unit&&(n=l.second),a=s.formatDate(o,n)}else a=s.formatDate(o,i.config.xaxis.labels.format);return{dateString:r,position:t.position,value:a,unit:t.unit,year:t.year,month:t.month}}))}},{key:"removeOverlappingTS",value:function(t){var e,i=this,a=new m(this.ctx),s=!1;t.length>0&&t[0].value&&t.every((function(e){return e.value.length===t[0].value.length}))&&(s=!0,e=a.getTextRects(t[0].value).width);var r=0,o=t.map((function(o,n){if(n>0&&i.w.config.xaxis.labels.hideOverlappingLabels){var l=s?e:a.getTextRects(t[r].value).width,h=t[r].position;return o.position>h+l+10?(r=n,o):null}return o}));return o=o.filter((function(t){return null!==t}))}},{key:"_getYear",value:function(t,e,i){return t+Math.floor(e/12)+i}}]),t}(),Rt=function(){function t(e,i){a(this,t),this.ctx=i,this.w=i.w,this.el=e}return r(t,[{key:"setupElements",value:function(){var t=this.w.globals,e=this.w.config,i=e.chart.type;t.axisCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble","radar","heatmap","treemap"].indexOf(i)>-1,t.xyCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble"].indexOf(i)>-1,t.isBarHorizontal=("bar"===e.chart.type||"rangeBar"===e.chart.type||"boxPlot"===e.chart.type)&&e.plotOptions.bar.horizontal,t.chartClass=".apexcharts"+t.chartID,t.dom.baseEl=this.el,t.dom.elWrap=document.createElement("div"),m.setAttrs(t.dom.elWrap,{id:t.chartClass.substring(1),class:"apexcharts-canvas "+t.chartClass.substring(1)}),this.el.appendChild(t.dom.elWrap),t.dom.Paper=new window.SVG.Doc(t.dom.elWrap),t.dom.Paper.attr({class:"apexcharts-svg","xmlns:data":"ApexChartsNS",transform:"translate(".concat(e.chart.offsetX,", ").concat(e.chart.offsetY,")")}),t.dom.Paper.node.style.background=e.chart.background,this.setSVGDimensions(),t.dom.elGraphical=t.dom.Paper.group().attr({class:"apexcharts-inner apexcharts-graphical"}),t.dom.elAnnotations=t.dom.Paper.group().attr({class:"apexcharts-annotations"}),t.dom.elDefs=t.dom.Paper.defs(),t.dom.elLegendWrap=document.createElement("div"),t.dom.elLegendWrap.classList.add("apexcharts-legend"),t.dom.elWrap.appendChild(t.dom.elLegendWrap),t.dom.Paper.add(t.dom.elGraphical),t.dom.elGraphical.add(t.dom.elDefs)}},{key:"plotChartType",value:function(t,e){var i=this.w,a=i.config,s=i.globals,r={series:[],i:[]},o={series:[],i:[]},n={series:[],i:[]},l={series:[],i:[]},h={series:[],i:[]},c={series:[],i:[]},d={series:[],i:[]},g={series:[],i:[]},u={series:[],seriesRangeEnd:[],i:[]};s.series.map((function(e,f){var p=0;void 0!==t[f].type?("column"===t[f].type||"bar"===t[f].type?(s.series.length>1&&a.plotOptions.bar.horizontal&&console.warn("Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"),h.series.push(e),h.i.push(f),p++,i.globals.columnSeries=h.series):"area"===t[f].type?(o.series.push(e),o.i.push(f),p++):"line"===t[f].type?(r.series.push(e),r.i.push(f),p++):"scatter"===t[f].type?(n.series.push(e),n.i.push(f)):"bubble"===t[f].type?(l.series.push(e),l.i.push(f),p++):"candlestick"===t[f].type?(c.series.push(e),c.i.push(f),p++):"boxPlot"===t[f].type?(d.series.push(e),d.i.push(f),p++):"rangeBar"===t[f].type?(g.series.push(e),g.i.push(f),p++):"rangeArea"===t[f].type?(u.series.push(s.seriesRangeStart[f]),u.seriesRangeEnd.push(s.seriesRangeEnd[f]),u.i.push(f),p++):console.warn("You have specified an unrecognized chart type. Available types for this property are line/area/column/bar/scatter/bubble"),p>1&&(s.comboCharts=!0)):(r.series.push(e),r.i.push(f))}));var f=new zt(this.ctx,e),p=new kt(this.ctx,e);this.ctx.pie=new Lt(this.ctx);var x=new Tt(this.ctx);this.ctx.rangeBar=new Mt(this.ctx,e);var b=new Pt(this.ctx),v=[];if(s.comboCharts){if(o.series.length>0&&v.push(f.draw(o.series,"area",o.i)),h.series.length>0)if(i.config.chart.stacked){var m=new wt(this.ctx,e);v.push(m.draw(h.series,h.i))}else this.ctx.bar=new yt(this.ctx,e),v.push(this.ctx.bar.draw(h.series,h.i));if(u.series.length>0&&v.push(f.draw(u.series,"rangeArea",u.i,u.seriesRangeEnd)),r.series.length>0&&v.push(f.draw(r.series,"line",r.i)),c.series.length>0&&v.push(p.draw(c.series,c.i)),d.series.length>0&&v.push(p.draw(d.series,d.i)),g.series.length>0&&v.push(this.ctx.rangeBar.draw(g.series,g.i)),n.series.length>0){var y=new zt(this.ctx,e,!0);v.push(y.draw(n.series,"scatter",n.i))}if(l.series.length>0){var w=new zt(this.ctx,e,!0);v.push(w.draw(l.series,"bubble",l.i))}}else switch(a.chart.type){case"line":v=f.draw(s.series,"line");break;case"area":v=f.draw(s.series,"area");break;case"bar":if(a.chart.stacked)v=new wt(this.ctx,e).draw(s.series);else this.ctx.bar=new yt(this.ctx,e),v=this.ctx.bar.draw(s.series);break;case"candlestick":v=new kt(this.ctx,e).draw(s.series);break;case"boxPlot":v=new kt(this.ctx,e).draw(s.series);break;case"rangeBar":v=this.ctx.rangeBar.draw(s.series);break;case"rangeArea":v=f.draw(s.seriesRangeStart,"rangeArea",void 0,s.seriesRangeEnd);break;case"heatmap":v=new St(this.ctx,e).draw(s.series);break;case"treemap":v=new Yt(this.ctx,e).draw(s.series);break;case"pie":case"donut":case"polarArea":v=this.ctx.pie.draw(s.series);break;case"radialBar":v=x.draw(s.series);break;case"radar":v=b.draw(s.series);break;default:v=f.draw(s.series)}return v}},{key:"setSVGDimensions",value:function(){var t=this.w.globals,e=this.w.config;t.svgWidth=e.chart.width,t.svgHeight=e.chart.height;var i=x.getDimensions(this.el),a=e.chart.width.toString().split(/[0-9]+/g).pop();"%"===a?x.isNumber(i[0])&&(0===i[0].width&&(i=x.getDimensions(this.el.parentNode)),t.svgWidth=i[0]*parseInt(e.chart.width,10)/100):"px"!==a&&""!==a||(t.svgWidth=parseInt(e.chart.width,10));var s=e.chart.height.toString().split(/[0-9]+/g).pop();if("auto"!==t.svgHeight&&""!==t.svgHeight)if("%"===s){var r=x.getDimensions(this.el.parentNode);t.svgHeight=r[1]*parseInt(e.chart.height,10)/100}else t.svgHeight=parseInt(e.chart.height,10);else t.axisCharts?t.svgHeight=t.svgWidth/1.61:t.svgHeight=t.svgWidth/1.2;if(t.svgWidth<0&&(t.svgWidth=0),t.svgHeight<0&&(t.svgHeight=0),m.setAttrs(t.dom.Paper.node,{width:t.svgWidth,height:t.svgHeight}),"%"!==s){var o=e.chart.sparkline.enabled?0:t.axisCharts?e.chart.parentHeightOffset:0;t.dom.Paper.node.parentNode.parentNode.style.minHeight=t.svgHeight+o+"px"}t.dom.elWrap.style.width=t.svgWidth+"px",t.dom.elWrap.style.height=t.svgHeight+"px"}},{key:"shiftGraphPosition",value:function(){var t=this.w.globals,e=t.translateY,i={transform:"translate("+t.translateX+", "+e+")"};m.setAttrs(t.dom.elGraphical.node,i)}},{key:"resizeNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=0,a=t.config.chart.sparkline.enabled?1:15;a+=t.config.grid.padding.bottom,"top"!==t.config.legend.position&&"bottom"!==t.config.legend.position||!t.config.legend.show||t.config.legend.floating||(i=new lt(this.ctx).legendHelpers.getLegendBBox().clwh+10);var s=t.globals.dom.baseEl.querySelector(".apexcharts-radialbar, .apexcharts-pie"),r=2.05*t.globals.radialSize;if(s&&!t.config.chart.sparkline.enabled&&0!==t.config.plotOptions.radialBar.startAngle){var o=x.getBoundingClientRect(s);r=o.bottom;var n=o.bottom-o.top;r=Math.max(2.05*t.globals.radialSize,n)}var l=r+e.translateY+i+a;e.dom.elLegendForeign&&e.dom.elLegendForeign.setAttribute("height",l),t.config.chart.height&&String(t.config.chart.height).indexOf("%")>0||(e.dom.elWrap.style.height=l+"px",m.setAttrs(e.dom.Paper.node,{height:l}),e.dom.Paper.node.parentNode.parentNode.style.minHeight=l+"px")}},{key:"coreCalculations",value:function(){new U(this.ctx).init()}},{key:"resetGlobals",value:function(){var t=this,e=function(){return t.w.config.series.map((function(t){return[]}))},i=new Y,a=this.w.globals;i.initGlobalVars(a),a.seriesXvalues=e(),a.seriesYvalues=e()}},{key:"isMultipleY",value:function(){if(this.w.config.yaxis.constructor===Array&&this.w.config.yaxis.length>1)return this.w.globals.isMultipleYAxis=!0,!0}},{key:"xySettings",value:function(){var t=null,e=this.w;if(e.globals.axisCharts){if("back"===e.config.xaxis.crosshairs.position)new Q(this.ctx).drawXCrosshairs();if("back"===e.config.yaxis[0].crosshairs.position)new Q(this.ctx).drawYCrosshairs();if("datetime"===e.config.xaxis.type&&void 0===e.config.xaxis.labels.formatter){this.ctx.timeScale=new Ft(this.ctx);var i=[];isFinite(e.globals.minX)&&isFinite(e.globals.maxX)&&!e.globals.isBarHorizontal?i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minX,e.globals.maxX):e.globals.isBarHorizontal&&(i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minY,e.globals.maxY)),this.ctx.timeScale.recalcDimensionsBasedOnFormat(i)}t=new y(this.ctx).getCalculatedRatios()}return t}},{key:"updateSourceChart",value:function(t){this.ctx.w.globals.selection=void 0,this.ctx.updateHelpers._updateOptions({chart:{selection:{xaxis:{min:t.w.globals.minX,max:t.w.globals.maxX}}}},!1,!1)}},{key:"setupBrushHandler",value:function(){var t=this,i=this.w;if(i.config.chart.brush.enabled&&"function"!=typeof i.config.chart.events.selection){var a=i.config.chart.brush.targets||[i.config.chart.brush.target];a.forEach((function(e){var i=ApexCharts.getChartByID(e);i.w.globals.brushSource=t.ctx,"function"!=typeof i.w.config.chart.events.zoomed&&(i.w.config.chart.events.zoomed=function(){t.updateSourceChart(i)}),"function"!=typeof i.w.config.chart.events.scrolled&&(i.w.config.chart.events.scrolled=function(){t.updateSourceChart(i)})})),i.config.chart.events.selection=function(t,s){a.forEach((function(t){var a=ApexCharts.getChartByID(t),r=x.clone(i.config.yaxis);if(i.config.chart.brush.autoScaleYaxis&&1===a.w.globals.series.length){var o=new _(a);r=o.autoScaleY(a,r,s)}var n=a.w.config.yaxis.reduce((function(t,i,s){return[].concat(u(t),[e(e({},a.w.config.yaxis[s]),{},{min:r[0].min,max:r[0].max})])}),[]);a.ctx.updateHelpers._updateOptions({xaxis:{min:s.xaxis.min,max:s.xaxis.max},yaxis:n},!1,!1,!1,!1)}))}}}}]),t}(),Dt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"_updateOptions",value:function(t){var e=this,a=arguments.length>1&&void 0!==arguments[1]&&arguments[1],s=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return new Promise((function(n){var l=[e.ctx];r&&(l=e.ctx.getSyncedCharts()),e.ctx.w.globals.isExecCalled&&(l=[e.ctx],e.ctx.w.globals.isExecCalled=!1),l.forEach((function(r,h){var c=r.w;if(c.globals.shouldAnimate=s,a||(c.globals.resized=!0,c.globals.dataChanged=!0,s&&r.series.getPreviousPaths()),t&&"object"===i(t)&&(r.config=new E(t),t=y.extendArrayProps(r.config,t,c),r.w.globals.chartID!==e.ctx.w.globals.chartID&&delete t.series,c.config=x.extend(c.config,t),o&&(c.globals.lastXAxis=t.xaxis?x.clone(t.xaxis):[],c.globals.lastYAxis=t.yaxis?x.clone(t.yaxis):[],c.globals.initialConfig=x.extend({},c.config),c.globals.initialSeries=x.clone(c.config.series),t.series))){for(var d=0;d2&&void 0!==arguments[2]&&arguments[2];return new Promise((function(s){var r,o=i.w;return o.globals.shouldAnimate=e,o.globals.dataChanged=!0,e&&i.ctx.series.getPreviousPaths(),o.globals.axisCharts?(0===(r=t.map((function(t,e){return i._extendSeries(t,e)}))).length&&(r=[{data:[]}]),o.config.series=r):o.config.series=t.slice(),a&&(o.globals.initialConfig.series=x.clone(o.config.series),o.globals.initialSeries=x.clone(o.config.series)),i.ctx.update().then((function(){s(i.ctx)}))}))}},{key:"_extendSeries",value:function(t,i){var a=this.w,s=a.config.series[i];return e(e({},a.config.series[i]),{},{name:t.name?t.name:s&&s.name,color:t.color?t.color:s&&s.color,type:t.type?t.type:s&&s.type,data:t.data?t.data:s&&s.data})}},{key:"toggleDataPointSelection",value:function(t,e){var i=this.w,a=null,s=".apexcharts-series[data\\:realIndex='".concat(t,"']");return i.globals.axisCharts?a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(e,"'], ").concat(s," circle[j='").concat(e,"'], ").concat(s," rect[j='").concat(e,"']")).members[0]:void 0===e&&(a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(t,"']")).members[0],"pie"!==i.config.chart.type&&"polarArea"!==i.config.chart.type&&"donut"!==i.config.chart.type||this.ctx.pie.pieClicked(t)),a?(new m(this.ctx).pathMouseDown(a,null),a.node?a.node:null):(console.warn("toggleDataPointSelection: Element not found"),null)}},{key:"forceXAxisUpdate",value:function(t){var e=this.w;if(["min","max"].forEach((function(i){void 0!==t.xaxis[i]&&(e.config.xaxis[i]=t.xaxis[i],e.globals.lastXAxis[i]=t.xaxis[i])})),t.xaxis.categories&&t.xaxis.categories.length&&(e.config.xaxis.categories=t.xaxis.categories),e.config.xaxis.convertedCatToNumeric){var i=new X(t);t=i.convertCatToNumericXaxis(t,this.ctx)}return t}},{key:"forceYAxisUpdate",value:function(t){return t.chart&&t.chart.stacked&&"100%"===t.chart.stackType&&(Array.isArray(t.yaxis)?t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})):(t.yaxis.min=0,t.yaxis.max=100)),t}},{key:"revertDefaultAxisMinMax",value:function(t){var e=this,i=this.w,a=i.globals.lastXAxis,s=i.globals.lastYAxis;t&&t.xaxis&&(a=t.xaxis),t&&t.yaxis&&(s=t.yaxis),i.config.xaxis.min=a.min,i.config.xaxis.max=a.max;var r=function(t){void 0!==s[t]&&(i.config.yaxis[t].min=s[t].min,i.config.yaxis[t].max=s[t].max)};i.config.yaxis.map((function(t,a){i.globals.zoomed||void 0!==s[a]?r(a):void 0!==e.ctx.opts.yaxis[a]&&(t.min=e.ctx.opts.yaxis[a].min,t.max=e.ctx.opts.yaxis[a].max)}))}}]),t}();Xt="undefined"!=typeof window?window:void 0,Et=function(t,e){var a=(void 0!==this?this:t).SVG=function(t){if(a.supported)return t=new a.Doc(t),a.parser.draw||a.prepare(),t};if(a.ns="http://www.w3.org/2000/svg",a.xmlns="http://www.w3.org/2000/xmlns/",a.xlink="http://www.w3.org/1999/xlink",a.svgjs="http://svgjs.dev",a.supported=!0,!a.supported)return!1;a.did=1e3,a.eid=function(t){return"Svgjs"+d(t)+a.did++},a.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},a.extend=function(){var t,e;e=(t=[].slice.call(arguments)).pop();for(var i=t.length-1;i>=0;i--)if(t[i])for(var s in e)t[i].prototype[s]=e[s];a.Set&&a.Set.inherit&&a.Set.inherit()},a.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,a.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&a.extend(e,t.extend),t.construct&&a.extend(t.parent||a.Container,t.construct),e},a.adopt=function(e){return e?e.instance?e.instance:((i="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new a.Nested:new a.Doc:"linearGradient"==e.nodeName?new a.Gradient("linear"):"radialGradient"==e.nodeName?new a.Gradient("radial"):a[d(e.nodeName)]?new(a[d(e.nodeName)]):new a.Element(e)).type=e.nodeName,i.node=e,e.instance=i,i instanceof a.Doc&&i.namespace().defs(),i.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),i):null;var i},a.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new a.Doc(t):a.adopt(e.documentElement).nested()).size(2,0);a.parser={body:t||e.documentElement,draw:i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden").node,poly:i.polyline().node,path:i.path().node,native:a.create("svg")}},a.parser={native:a.create("svg")},e.addEventListener("DOMContentLoaded",(function(){a.parser.draw||a.prepare()}),!1),a.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},a.utils={map:function(t,e){for(var i=t.length,a=[],s=0;s1?1:t,new a.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),a.Color.test=function(t){return t+="",a.regex.isHex.test(t)||a.regex.isRgb.test(t)},a.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},a.Color.isColor=function(t){return a.Color.isRgb(t)||a.Color.test(t)},a.Array=function(t,e){0==(t=(t||[]).valueOf()).length&&e&&(t=e.valueOf()),this.value=this.parse(t)},a.extend(a.Array,{toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:this.split(t)}}),a.PointArray=function(t,e){a.Array.call(this,t,e||[[0,0]])},a.PointArray.prototype=new a.Array,a.PointArray.prototype.constructor=a.PointArray;for(var s={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]}},r="mlhvqtcsaz".split(""),o=0,n=r.length;ol);return r},bbox:function(){return a.parser.draw||a.prepare(),a.parser.path.setAttribute("d",this.toString()),a.parser.path.getBBox()}}),a.Number=a.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(a.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof a.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new a.Number(t),new a.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new a.Number(t),new a.Number(this-t,this.unit||t.unit)},times:function(t){return t=new a.Number(t),new a.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new a.Number(t),new a.Number(this/t,this.unit||t.unit)},to:function(t){var e=new a.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new a.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new a.Number(this.destination).minus(this).times(t).plus(this):this}}}),a.Element=a.invent({create:function(t){this._stroke=a.defaults.attrs.stroke,this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this,this._stroke=t.getAttribute("stroke")||this._stroke)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=u(this,t,e);return this.width(new a.Number(i.width)).height(new a.Number(i.height))},clone:function(t){this.writeDataToDom();var e=x(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return"none"!=this.style("display")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(a.regex.delimiter)},hasClass:function(t){return-1!=this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter((function(e){return e!=t})).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return a.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=a.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;if(!i.node.parentNode||"#document"==i.node.parentNode.nodeName)return null;i=a.adopt(i.node.parentNode)}},doc:function(){return this instanceof a.Doc?this:this.parent(a.Doc)},parents:function(t){var e=[],i=this;do{if(!(i=i.parent(t))||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return function(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}(this.node,t)},native:function(){return this.node},svg:function(t){var i=e.createElement("svg");if(!(t&&this instanceof a.Parent))return i.appendChild(t=e.createElement("svg")),this.writeDataToDom(),t.appendChild(this.node.cloneNode(!0)),i.innerHTML.replace(/^/,"").replace(/<\/svg>$/,"");i.innerHTML=""+t.replace(/\n/,"").replace(/<([\w:-]+)([^<]+?)\/>/g,"<$1$2>")+"";for(var s=0,r=i.firstChild.childNodes.length;s":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},a.morph=function(t){return function(e,i){return new a.MorphObj(e,i).at(t)}},a.Situation=a.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new a.Number(t.duration).valueOf(),this.delay=new a.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),a.FX=a.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,s){"object"===i(t)&&(e=t.ease,s=t.delay,t=t.duration);var r=new a.Situation({duration:t||1e3,delay:s||0,ease:a.easing[e||"-"]||e});return this.queue(r),this},target:function(t){return t&&t instanceof a.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof a.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof a.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e=this.situation;if(e.init)return this;for(var i in e.animations){t=this.target()[i](),Array.isArray(t)||(t=[t]),Array.isArray(e.animations[i])||(e.animations[i]=[e.animations[i]]);for(var s=t.length;s--;)e.animations[i][s]instanceof a.Number&&(t[s]=new a.Number(t[s])),e.animations[i][s]=t[s].morph(e.animations[i][s])}for(var i in e.attrs)e.attrs[i]=new a.MorphObj(this.target().attr(i),e.attrs[i]);for(var i in e.styles)e.styles[i]=new a.MorphObj(this.target().style(i),e.styles[i]);return e.initialTransformation=this.target().matrixify(),e.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},after:function(t){var e=this.last();return this.target().on("finished.fx",(function i(a){a.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))})),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,a.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after((function(){this.off("during.fx",i)})),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){var e,i,a;t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops?(e=Math.max(this.absPos,0),i=Math.floor(e),!0===this.situation.loops||ithis.lastPos&&r<=s&&(this.situation.once[r].call(this.target(),this.pos,s),delete this.situation.once[r]);return this.active&&this.target().fire("during",{pos:this.pos,eased:s,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=s,this):this},eachAt:function(){var t,e=this,i=this.target(),s=this.situation;for(var r in s.animations)t=[].concat(s.animations[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i[r].apply(i,t);for(var r in s.attrs)t=[r].concat(s.attrs[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i.attr.apply(i,t);for(var r in s.styles)t=[r].concat(s.styles[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i.style.apply(i,t);if(s.transforms.length){t=s.initialTransformation,r=0;for(var o=s.transforms.length;r=0;--s)this[m[s]]=null!=t[m[s]]?t[m[s]]:e[m[s]]},extend:{extract:function(){var t=f(this,0,1);f(this,1,0);var e=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(e*Math.PI/180)+this.f*Math.sin(e*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(e*Math.PI/180)+this.e*Math.sin(-e*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),rotation:e,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new a.Matrix(this)}},clone:function(){return new a.Matrix(this)},morph:function(t){return this.destination=new a.Matrix(t),this},multiply:function(t){return new a.Matrix(this.native().multiply(function(t){return t instanceof a.Matrix||(t=new a.Matrix(t)),t}(t).native()))},inverse:function(){return new a.Matrix(this.native().inverse())},translate:function(t,e){return new a.Matrix(this.native().translate(t||0,e||0))},native:function(){for(var t=a.parser.native.createSVGMatrix(),e=m.length-1;e>=0;e--)t[m[e]]=this[m[e]];return t},toString:function(){return"matrix("+v(this.a)+","+v(this.b)+","+v(this.c)+","+v(this.d)+","+v(this.e)+","+v(this.f)+")"}},parent:a.Element,construct:{ctm:function(){return new a.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof a.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new a.Matrix(e)}return new a.Matrix(this.node.getScreenCTM())}}}),a.Point=a.invent({create:function(t,e){var a;a=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===i(t)?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:{x:0,y:0},this.x=a.x,this.y=a.y},extend:{clone:function(){return new a.Point(this)},morph:function(t,e){return this.destination=new a.Point(t,e),this}}}),a.extend(a.Element,{point:function(t,e){return new a.Point(t,e).transform(this.screenCTM().inverse())}}),a.extend(a.Element,{attr:function(t,e,s){if(null==t){for(t={},s=(e=this.node.attributes).length-1;s>=0;s--)t[e[s].nodeName]=a.regex.isNumber.test(e[s].nodeValue)?parseFloat(e[s].nodeValue):e[s].nodeValue;return t}if("object"===i(t))for(var r in t)this.attr(r,t[r]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?a.defaults.attrs[t]:a.regex.isNumber.test(e)?parseFloat(e):e;"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),"fill"!=t&&"stroke"!=t||(a.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof a.Image&&(e=this.doc().defs().pattern(0,0,(function(){this.add(e)})))),"number"==typeof e?e=new a.Number(e):a.Color.isColor(e)?e=new a.Color(e):Array.isArray(e)&&(e=new a.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof s?this.node.setAttributeNS(s,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),a.extend(a.Element,{transform:function(t,e){var s;return"object"!==i(t)?(s=new a.Matrix(this).extract(),"string"==typeof t?s[t]:s):(s=new a.Matrix(this),e=!!e||!!t.relative,null!=t.a&&(s=e?s.multiply(new a.Matrix(t)):new a.Matrix(t)),this.attr("transform",s))}}),a.extend(a.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(a.regex.transforms).slice(0,-1).map((function(t){var e=t.trim().split("(");return[e[0],e[1].split(a.regex.delimiter).map((function(t){return parseFloat(t)}))]})).reduce((function(t,e){return"matrix"==e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])}),new a.Matrix)},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),a.Transformation=a.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var a=0,s=this.arguments.length;a=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return a.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){for(var i=this.children(),s=0,r=i.length;s=0;i--)e.childNodes[i]instanceof t.SVGElement&&x(e.childNodes[i]);return a.adopt(e).id(a.eid(e.nodeName))}function b(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function v(t){return Math.abs(t)>1e-37?t:0}["fill","stroke"].forEach((function(t){var e={};e[t]=function(e){if(void 0===e)return this;if("string"==typeof e||a.Color.isRgb(e)||e&&"function"==typeof e.fill)this.attr(t,e);else for(var i=l[t].length-1;i>=0;i--)null!=e[l[t][i]]&&this.attr(l.prefix(t,l[t][i]),e[l[t][i]]);return this},a.extend(a.Element,a.FX,e)})),a.extend(a.Element,a.FX,{translate:function(t,e){return this.transform({x:t,y:e})},matrix:function(t){return this.attr("transform",new a.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new a.Number(t).plus(this instanceof a.FX?0:this.x()),!0)},dy:function(t){return this.y(new a.Number(t).plus(this instanceof a.FX?0:this.y()),!0)}}),a.extend(a.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return this.node.getPointAtLength(t)}}),a.Set=a.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){for(var t=[].slice.call(arguments),e=0,i=t.length;e-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members}},construct:{set:function(t){return new a.Set(t)}}}),a.FX.Set=a.invent({create:function(t){this.set=t}}),a.Set.inherit=function(){var t=[];for(var e in a.Shape.prototype)"function"==typeof a.Shape.prototype[e]&&"function"!=typeof a.Set.prototype[e]&&t.push(e);for(var e in t.forEach((function(t){a.Set.prototype[t]=function(){for(var e=0,i=this.members.length;e=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),a.get=function(t){var i=e.getElementById(function(t){var e=(t||"").toString().match(a.regex.reference);if(e)return e[1]}(t)||t);return a.adopt(i)},a.select=function(t,i){return new a.Set(a.utils.map((i||e).querySelectorAll(t),(function(t){return a.adopt(t)})))},a.extend(a.Parent,{select:function(t){return a.select(t,this.node)}});var m="abcdef".split("");if("function"!=typeof t.CustomEvent){var y=function(t,i){i=i||{bubbles:!1,cancelable:!1,detail:void 0};var a=e.createEvent("CustomEvent");return a.initCustomEvent(t,i.bubbles,i.cancelable,i.detail),a};y.prototype=t.Event.prototype,a.CustomEvent=y}else a.CustomEvent=t.CustomEvent;return a},"function"==typeof define&&define.amd?define((function(){return Et(Xt,Xt.document)})):"object"===("undefined"==typeof exports?"undefined":i(exports))&&"undefined"!=typeof module?module.exports=Xt.document?Et(Xt,Xt.document):function(t){return Et(t,t.document)}:Xt.SVG=Et(Xt,Xt.document), /*! svg.filter.js - v2.0.2 - 2016-02-24 * https://github.com/wout/svg.filter.js * Copyright (c) 2016 Wout Fierens; Licensed MIT */ function(){SVG.Filter=SVG.invent({create:"filter",inherit:SVG.Parent,extend:{source:"SourceGraphic",sourceAlpha:"SourceAlpha",background:"BackgroundImage",backgroundAlpha:"BackgroundAlpha",fill:"FillPaint",stroke:"StrokePaint",autoSetIn:!0,put:function(t,e){return this.add(t,e),!t.attr("in")&&this.autoSetIn&&t.attr("in",this.source),t.attr("result")||t.attr("result",t),t},blend:function(t,e,i){return this.put(new SVG.BlendEffect(t,e,i))},colorMatrix:function(t,e){return this.put(new SVG.ColorMatrixEffect(t,e))},convolveMatrix:function(t){return this.put(new SVG.ConvolveMatrixEffect(t))},componentTransfer:function(t){return this.put(new SVG.ComponentTransferEffect(t))},composite:function(t,e,i){return this.put(new SVG.CompositeEffect(t,e,i))},flood:function(t,e){return this.put(new SVG.FloodEffect(t,e))},offset:function(t,e){return this.put(new SVG.OffsetEffect(t,e))},image:function(t){return this.put(new SVG.ImageEffect(t))},merge:function(){var t=[void 0];for(var e in arguments)t.push(arguments[e]);return this.put(new(SVG.MergeEffect.bind.apply(SVG.MergeEffect,t)))},gaussianBlur:function(t,e){return this.put(new SVG.GaussianBlurEffect(t,e))},morphology:function(t,e){return this.put(new SVG.MorphologyEffect(t,e))},diffuseLighting:function(t,e,i){return this.put(new SVG.DiffuseLightingEffect(t,e,i))},displacementMap:function(t,e,i,a,s){return this.put(new SVG.DisplacementMapEffect(t,e,i,a,s))},specularLighting:function(t,e,i,a){return this.put(new SVG.SpecularLightingEffect(t,e,i,a))},tile:function(){return this.put(new SVG.TileEffect)},turbulence:function(t,e,i,a,s){return this.put(new SVG.TurbulenceEffect(t,e,i,a,s))},toString:function(){return"url(#"+this.attr("id")+")"}}}),SVG.extend(SVG.Defs,{filter:function(t){var e=this.put(new SVG.Filter);return"function"==typeof t&&t.call(e,e),e}}),SVG.extend(SVG.Container,{filter:function(t){return this.defs().filter(t)}}),SVG.extend(SVG.Element,SVG.G,SVG.Nested,{filter:function(t){return this.filterer=t instanceof SVG.Element?t:this.doc().filter(t),this.doc()&&this.filterer.doc()!==this.doc()&&this.doc().defs().add(this.filterer),this.attr("filter",this.filterer),this.filterer},unfilter:function(t){return this.filterer&&!0===t&&this.filterer.remove(),delete this.filterer,this.attr("filter",null)}}),SVG.Effect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Element,extend:{in:function(t){return null==t?this.parent()&&this.parent().select('[result="'+this.attr("in")+'"]').get(0)||this.attr("in"):this.attr("in",t)},result:function(t){return null==t?this.attr("result"):this.attr("result",t)},toString:function(){return this.result()}}}),SVG.ParentEffect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Parent,extend:{in:function(t){return null==t?this.parent()&&this.parent().select('[result="'+this.attr("in")+'"]').get(0)||this.attr("in"):this.attr("in",t)},result:function(t){return null==t?this.attr("result"):this.attr("result",t)},toString:function(){return this.result()}}});var t={blend:function(t,e){return this.parent()&&this.parent().blend(this,t,e)},colorMatrix:function(t,e){return this.parent()&&this.parent().colorMatrix(t,e).in(this)},convolveMatrix:function(t){return this.parent()&&this.parent().convolveMatrix(t).in(this)},componentTransfer:function(t){return this.parent()&&this.parent().componentTransfer(t).in(this)},composite:function(t,e){return this.parent()&&this.parent().composite(this,t,e)},flood:function(t,e){return this.parent()&&this.parent().flood(t,e)},offset:function(t,e){return this.parent()&&this.parent().offset(t,e).in(this)},image:function(t){return this.parent()&&this.parent().image(t)},merge:function(){return this.parent()&&this.parent().merge.apply(this.parent(),[this].concat(arguments))},gaussianBlur:function(t,e){return this.parent()&&this.parent().gaussianBlur(t,e).in(this)},morphology:function(t,e){return this.parent()&&this.parent().morphology(t,e).in(this)},diffuseLighting:function(t,e,i){return this.parent()&&this.parent().diffuseLighting(t,e,i).in(this)},displacementMap:function(t,e,i,a){return this.parent()&&this.parent().displacementMap(this,t,e,i,a)},specularLighting:function(t,e,i,a){return this.parent()&&this.parent().specularLighting(t,e,i,a).in(this)},tile:function(){return this.parent()&&this.parent().tile().in(this)},turbulence:function(t,e,i,a,s){return this.parent()&&this.parent().turbulence(t,e,i,a,s).in(this)}};SVG.extend(SVG.Effect,t),SVG.extend(SVG.ParentEffect,t),SVG.ChildEffect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Element,extend:{in:function(t){this.attr("in",t)}}});var e={blend:function(t,e,i){this.attr({in:t,in2:e,mode:i||"normal"})},colorMatrix:function(t,e){"matrix"==t&&(e=s(e)),this.attr({type:t,values:void 0===e?null:e})},convolveMatrix:function(t){t=s(t),this.attr({order:Math.sqrt(t.split(" ").length),kernelMatrix:t})},composite:function(t,e,i){this.attr({in:t,in2:e,operator:i})},flood:function(t,e){this.attr("flood-color",t),null!=e&&this.attr("flood-opacity",e)},offset:function(t,e){this.attr({dx:t,dy:e})},image:function(t){this.attr("href",t,SVG.xlink)},displacementMap:function(t,e,i,a,s){this.attr({in:t,in2:e,scale:i,xChannelSelector:a,yChannelSelector:s})},gaussianBlur:function(t,e){null!=t||null!=e?this.attr("stdDeviation",r(Array.prototype.slice.call(arguments))):this.attr("stdDeviation","0 0")},morphology:function(t,e){this.attr({operator:t,radius:e})},tile:function(){},turbulence:function(t,e,i,a,s){this.attr({numOctaves:e,seed:i,stitchTiles:a,baseFrequency:t,type:s})}},i={merge:function(){var t;if(arguments[0]instanceof SVG.Set){var e=this;arguments[0].each((function(t){this instanceof SVG.MergeNode?e.put(this):(this instanceof SVG.Effect||this instanceof SVG.ParentEffect)&&e.put(new SVG.MergeNode(this))}))}else{t=Array.isArray(arguments[0])?arguments[0]:arguments;for(var i=0;i1&&(T*=a=Math.sqrt(a),M*=a);s=(new SVG.Matrix).rotate(I).scale(1/T,1/M).rotate(-I),F=F.transform(s),R=R.transform(s),r=[R.x-F.x,R.y-F.y],n=r[0]*r[0]+r[1]*r[1],o=Math.sqrt(n),r[0]/=o,r[1]/=o,l=n<4?Math.sqrt(1-n/4):0,z===X&&(l*=-1);h=new SVG.Point((R.x+F.x)/2+l*-r[1],(R.y+F.y)/2+l*r[0]),c=new SVG.Point(F.x-h.x,F.y-h.y),d=new SVG.Point(R.x-h.x,R.y-h.y),g=Math.acos(c.x/Math.sqrt(c.x*c.x+c.y*c.y)),c.y<0&&(g*=-1);u=Math.acos(d.x/Math.sqrt(d.x*d.x+d.y*d.y)),d.y<0&&(u*=-1);X&&g>u&&(u+=2*Math.PI);!X&&gr.maxX-e.width&&(o=(a=r.maxX-e.width)-this.startPoints.box.x),null!=r.minY&&sr.maxY-e.height&&(n=(s=r.maxY-e.height)-this.startPoints.box.y),null!=r.snapToGrid&&(a-=a%r.snapToGrid,s-=s%r.snapToGrid,o-=o%r.snapToGrid,n-=n%r.snapToGrid),this.el instanceof SVG.G?this.el.matrix(this.startPoints.transform).transform({x:o,y:n},!0):this.el.move(a,s));return i},t.prototype.end=function(t){var e=this.drag(t);this.el.fire("dragend",{event:t,p:e,m:this.m,handler:this}),SVG.off(window,"mousemove.drag"),SVG.off(window,"touchmove.drag"),SVG.off(window,"mouseup.drag"),SVG.off(window,"touchend.drag")},SVG.extend(SVG.Element,{draggable:function(e,i){"function"!=typeof e&&"object"!=typeof e||(i=e,e=!0);var a=this.remember("_draggable")||new t(this);return(e=void 0===e||e)?a.init(i||{},e):(this.off("mousedown.drag"),this.off("touchstart.drag")),this}})}.call(void 0),function(){function t(t){this.el=t,t.remember("_selectHandler",this),this.pointSelection={isSelected:!1},this.rectSelection={isSelected:!1},this.pointsList={lt:[0,0],rt:["width",0],rb:["width","height"],lb:[0,"height"],t:["width",0],r:["width","height"],b:["width","height"],l:[0,"height"]},this.pointCoord=function(t,e,i){var a="string"!=typeof t?t:e[t];return i?a/2:a},this.pointCoords=function(t,e){var i=this.pointsList[t];return{x:this.pointCoord(i[0],e,"t"===t||"b"===t),y:this.pointCoord(i[1],e,"r"===t||"l"===t)}}}t.prototype.init=function(t,e){var i=this.el.bbox();this.options={};var a=this.el.selectize.defaults.points;for(var s in this.el.selectize.defaults)this.options[s]=this.el.selectize.defaults[s],void 0!==e[s]&&(this.options[s]=e[s]);var r=["points","pointsExclude"];for(var s in r){var o=this.options[r[s]];"string"==typeof o?o=o.length>0?o.split(/\s*,\s*/i):[]:"boolean"==typeof o&&"points"===r[s]&&(o=o?a:[]),this.options[r[s]]=o}this.options.points=[a,this.options.points].reduce((function(t,e){return t.filter((function(t){return e.indexOf(t)>-1}))})),this.options.points=[this.options.points,this.options.pointsExclude].reduce((function(t,e){return t.filter((function(t){return e.indexOf(t)<0}))})),this.parent=this.el.parent(),this.nested=this.nested||this.parent.group(),this.nested.matrix(new SVG.Matrix(this.el).translate(i.x,i.y)),this.options.deepSelect&&-1!==["line","polyline","polygon"].indexOf(this.el.type)?this.selectPoints(t):this.selectRect(t),this.observe(),this.cleanup()},t.prototype.selectPoints=function(t){return this.pointSelection.isSelected=t,this.pointSelection.set||(this.pointSelection.set=this.parent.set(),this.drawPoints()),this},t.prototype.getPointArray=function(){var t=this.el.bbox();return this.el.array().valueOf().map((function(e){return[e[0]-t.x,e[1]-t.y]}))},t.prototype.drawPoints=function(){for(var t=this,e=this.getPointArray(),i=0,a=e.length;i0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y+i[1]).size(this.parameters.box.width-i[0],this.parameters.box.height-i[1])}};break;case"rt":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).size(this.parameters.box.width+i[0],this.parameters.box.height-i[1])}};break;case"rb":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x,this.parameters.box.y).size(this.parameters.box.width+i[0],this.parameters.box.height+i[1])}};break;case"lb":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).size(this.parameters.box.width-i[0],this.parameters.box.height+i[1])}};break;case"t":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).height(this.parameters.box.height-i[1])}};break;case"r":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).width(this.parameters.box.width+i[0])}};break;case"b":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).height(this.parameters.box.height+i[1])}};break;case"l":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).width(this.parameters.box.width-i[0])}};break;case"rot":this.calc=function(t,e){var i=t+this.parameters.p.x,a=e+this.parameters.p.y,s=Math.atan2(this.parameters.p.y-this.parameters.box.y-this.parameters.box.height/2,this.parameters.p.x-this.parameters.box.x-this.parameters.box.width/2),r=Math.atan2(a-this.parameters.box.y-this.parameters.box.height/2,i-this.parameters.box.x-this.parameters.box.width/2),o=this.parameters.rotation+180*(r-s)/Math.PI+this.options.snapToAngle/2;this.el.center(this.parameters.box.cx,this.parameters.box.cy).rotate(o-o%this.options.snapToAngle,this.parameters.box.cx,this.parameters.box.cy)};break;case"point":this.calc=function(t,e){var i=this.snapToGrid(t,e,this.parameters.pointCoords[0],this.parameters.pointCoords[1]),a=this.el.array().valueOf();a[this.parameters.i][0]=this.parameters.pointCoords[0]+i[0],a[this.parameters.i][1]=this.parameters.pointCoords[1]+i[1],this.el.plot(a)}}this.el.fire("resizestart",{dx:this.parameters.x,dy:this.parameters.y,event:t}),SVG.on(window,"touchmove.resize",(function(t){e.update(t||window.event)})),SVG.on(window,"touchend.resize",(function(){e.done()})),SVG.on(window,"mousemove.resize",(function(t){e.update(t||window.event)})),SVG.on(window,"mouseup.resize",(function(){e.done()}))},t.prototype.update=function(t){if(t){var e=this._extractPosition(t),i=this.transformPoint(e.x,e.y),a=i.x-this.parameters.p.x,s=i.y-this.parameters.p.y;this.lastUpdateCall=[a,s],this.calc(a,s),this.el.fire("resizing",{dx:a,dy:s,event:t})}else this.lastUpdateCall&&this.calc(this.lastUpdateCall[0],this.lastUpdateCall[1])},t.prototype.done=function(){this.lastUpdateCall=null,SVG.off(window,"mousemove.resize"),SVG.off(window,"mouseup.resize"),SVG.off(window,"touchmove.resize"),SVG.off(window,"touchend.resize"),this.el.fire("resizedone")},t.prototype.snapToGrid=function(t,e,i,a){var s;return void 0!==a?s=[(i+t)%this.options.snapToGrid,(a+e)%this.options.snapToGrid]:(i=null==i?3:i,s=[(this.parameters.box.x+t+(1&i?0:this.parameters.box.width))%this.options.snapToGrid,(this.parameters.box.y+e+(2&i?0:this.parameters.box.height))%this.options.snapToGrid]),t<0&&(s[0]-=this.options.snapToGrid),e<0&&(s[1]-=this.options.snapToGrid),t-=Math.abs(s[0])o.maxX&&(t=o.maxX-s),void 0!==o.minY&&r+eo.maxY&&(e=o.maxY-r),[t,e]},t.prototype.checkAspectRatio=function(t,e){if(!this.options.saveAspectRatio)return t;var i=t.slice(),a=this.parameters.box.width/this.parameters.box.height,s=this.parameters.box.width+t[0],r=this.parameters.box.height-t[1],o=s/r;return oa&&(i[0]=this.parameters.box.width-r*a,e&&(i[0]=-i[0])),i},SVG.extend(SVG.Element,{resize:function(e){return(this.remember("_resizeHandler")||new t(this)).init(e||{}),this}}),SVG.Element.prototype.resize.defaults={snapToAngle:.1,snapToGrid:1,constraint:{},saveAspectRatio:!1}}).call(this)}(),void 0===window.Apex&&(window.Apex={});var Ht=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"initModules",value:function(){this.ctx.publicMethods=["updateOptions","updateSeries","appendData","appendSeries","toggleSeries","showSeries","hideSeries","setLocale","resetSeries","zoomX","toggleDataPointSelection","dataURI","exportToCSV","addXaxisAnnotation","addYaxisAnnotation","addPointAnnotation","clearAnnotations","removeAnnotation","paper","destroy"],this.ctx.eventList=["click","mousedown","mousemove","mouseleave","touchstart","touchmove","touchleave","mouseup","touchend"],this.ctx.animations=new b(this.ctx),this.ctx.axes=new J(this.ctx),this.ctx.core=new Rt(this.ctx.el,this.ctx),this.ctx.config=new E({}),this.ctx.data=new W(this.ctx),this.ctx.grid=new j(this.ctx),this.ctx.graphics=new m(this.ctx),this.ctx.coreUtils=new y(this.ctx),this.ctx.crosshairs=new Q(this.ctx),this.ctx.events=new Z(this.ctx),this.ctx.exports=new G(this.ctx),this.ctx.localization=new $(this.ctx),this.ctx.options=new L,this.ctx.responsive=new K(this.ctx),this.ctx.series=new N(this.ctx),this.ctx.theme=new tt(this.ctx),this.ctx.formatters=new M(this.ctx),this.ctx.titleSubtitle=new et(this.ctx),this.ctx.legend=new lt(this.ctx),this.ctx.toolbar=new ht(this.ctx),this.ctx.tooltip=new bt(this.ctx),this.ctx.dimensions=new ot(this.ctx),this.ctx.updateHelpers=new Dt(this.ctx),this.ctx.zoomPanSelection=new ct(this.ctx),this.ctx.w.globals.tooltip=new bt(this.ctx)}}]),t}(),Ot=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"clear",value:function(t){var e=t.isUpdating;this.ctx.zoomPanSelection&&this.ctx.zoomPanSelection.destroy(),this.ctx.toolbar&&this.ctx.toolbar.destroy(),this.ctx.animations=null,this.ctx.axes=null,this.ctx.annotations=null,this.ctx.core=null,this.ctx.data=null,this.ctx.grid=null,this.ctx.series=null,this.ctx.responsive=null,this.ctx.theme=null,this.ctx.formatters=null,this.ctx.titleSubtitle=null,this.ctx.legend=null,this.ctx.dimensions=null,this.ctx.options=null,this.ctx.crosshairs=null,this.ctx.zoomPanSelection=null,this.ctx.updateHelpers=null,this.ctx.toolbar=null,this.ctx.localization=null,this.ctx.w.globals.tooltip=null,this.clearDomElements({isUpdating:e})}},{key:"killSVG",value:function(t){t.each((function(t,e){this.removeClass("*"),this.off(),this.stop()}),!0),t.ungroup(),t.clear()}},{key:"clearDomElements",value:function(t){var e=this,i=t.isUpdating,a=this.w.globals.dom.Paper.node;a.parentNode&&a.parentNode.parentNode&&!i&&(a.parentNode.parentNode.style.minHeight="unset");var s=this.w.globals.dom.baseEl;s&&this.ctx.eventList.forEach((function(t){s.removeEventListener(t,e.ctx.events.documentEvent)}));var r=this.w.globals.dom;if(null!==this.ctx.el)for(;this.ctx.el.firstChild;)this.ctx.el.removeChild(this.ctx.el.firstChild);this.killSVG(r.Paper),r.Paper.remove(),r.elWrap=null,r.elGraphical=null,r.elAnnotations=null,r.elLegendWrap=null,r.baseEl=null,r.elGridRect=null,r.elGridRectMask=null,r.elGridRectMarkerMask=null,r.elForecastMask=null,r.elNonForecastMask=null,r.elDefs=null}}]),t}(),Nt=new WeakMap;var Wt=function(){function t(e,i){a(this,t),this.opts=i,this.ctx=this,this.w=new F(i).init(),this.el=e,this.w.globals.cuid=x.randomId(),this.w.globals.chartID=this.w.config.chart.id?x.escapeString(this.w.config.chart.id):this.w.globals.cuid,new Ht(this).initModules(),this.create=x.bind(this.create,this),this.windowResizeHandler=this._windowResizeHandler.bind(this),this.parentResizeHandler=this._parentResizeCallback.bind(this)}return r(t,[{key:"render",value:function(){var t=this;return new Promise((function(e,i){if(null!==t.el){void 0===Apex._chartInstances&&(Apex._chartInstances=[]),t.w.config.chart.id&&Apex._chartInstances.push({id:t.w.globals.chartID,group:t.w.config.chart.group,chart:t}),t.setLocale(t.w.config.chart.defaultLocale);var a=t.w.config.chart.events.beforeMount;if("function"==typeof a&&a(t,t.w),t.events.fireEvent("beforeMount",[t,t.w]),window.addEventListener("resize",t.windowResizeHandler),function(t,e){var i=!1;if(t.nodeType!==Node.DOCUMENT_FRAGMENT_NODE){var a=t.getBoundingClientRect();"none"!==t.style.display&&0!==a.width||(i=!0)}var s=new ResizeObserver((function(a){i&&e.call(t,a),i=!0}));t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?Array.from(t.children).forEach((function(t){return s.observe(t)})):s.observe(t),Nt.set(e,s)}(t.el.parentNode,t.parentResizeHandler),!t.css){var s=t.el.getRootNode&&t.el.getRootNode(),r=x.is("ShadowRoot",s),o=t.el.ownerDocument,n=o.getElementById("apexcharts-css");!r&&n||(t.css=document.createElement("style"),t.css.id="apexcharts-css",t.css.textContent='@keyframes opaque {\n 0% {\n opacity: 0\n }\n\n to {\n opacity: 1\n }\n}\n\n@keyframes resizeanim {\n 0%,to {\n opacity: 0\n }\n}\n\n.apexcharts-canvas {\n position: relative;\n user-select: none\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n -webkit-appearance: none;\n width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n border-radius: 4px;\n background-color: rgba(0,0,0,.5);\n box-shadow: 0 0 1px rgba(255,255,255,.5);\n -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)\n}\n\n.apexcharts-inner {\n position: relative\n}\n\n.apexcharts-text tspan {\n font-family: inherit\n}\n\n.legend-mouseover-inactive {\n transition: .15s ease all;\n opacity: .2\n}\n\n.apexcharts-legend-text {\n padding-left: 15px;\n margin-left: -15px;\n}\n\n.apexcharts-series-collapsed {\n opacity: 0\n}\n\n.apexcharts-tooltip {\n border-radius: 5px;\n box-shadow: 2px 2px 6px -4px #999;\n cursor: default;\n font-size: 14px;\n left: 62px;\n opacity: 0;\n pointer-events: none;\n position: absolute;\n top: 20px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n white-space: nowrap;\n z-index: 12;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n border: 1px solid #e3e3e3;\n background: rgba(255,255,255,.96)\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n color: #fff;\n background: rgba(30,30,30,.8)\n}\n\n.apexcharts-tooltip * {\n font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n padding: 6px;\n font-size: 15px;\n margin-bottom: 4px\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {\n background: #eceff1;\n border-bottom: 1px solid #ddd\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n background: rgba(0,0,0,.7);\n border-bottom: 1px solid #333\n}\n\n.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {\n display: inline-block;\n margin-left: 5px;\n font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {\n display: none\n}\n\n.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {\n margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n width: 12px;\n height: 12px;\n position: relative;\n top: 0;\n margin-right: 10px;\n border-radius: 50%\n}\n\n.apexcharts-tooltip-series-group {\n padding: 0 10px;\n display: none;\n text-align: left;\n justify-content: left;\n align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {\n padding-bottom: 4px\n}\n\n.apexcharts-tooltip-series-group-hidden {\n opacity: 0;\n height: 0;\n line-height: 0;\n padding: 0!important\n}\n\n.apexcharts-tooltip-y-group {\n padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,.apexcharts-tooltip-box {\n padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n display: flex;\n flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_boundingRect,.svg_select_points_rot {\n pointer-events: none;\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {\n cursor: ew-resize;\n opacity: 1;\n visibility: visible\n}\n\n.svg_select_points {\n fill: #efefef;\n stroke: #333;\n rx: 2\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0,0,0,.7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {\n opacity: 0\n}\n\n.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-legend {\t\n display: flex;\t\n overflow: auto;\t\n padding: 0 10px;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\t\n flex-wrap: wrap\t\n}\t\n.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n flex-direction: column;\t\n bottom: 0;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n justify-content: flex-start;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\t\n justify-content: center; \t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\t\n justify-content: flex-end;\t\n}\t\n.apexcharts-legend-series {\t\n cursor: pointer;\t\n line-height: normal;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{\t\n display: flex;\t\n align-items: center;\t\n}\t\n.apexcharts-legend-text {\t\n position: relative;\t\n font-size: 14px;\t\n}\t\n.apexcharts-legend-text *, .apexcharts-legend-marker * {\t\n pointer-events: none;\t\n}\t\n.apexcharts-legend-marker {\t\n position: relative;\t\n display: inline-block;\t\n cursor: pointer;\t\n margin-right: 3px;\t\n border-style: solid;\n}\t\n \n.apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{\t\n display: inline-block;\t\n}\t\n.apexcharts-legend-series.apexcharts-no-click {\t\n cursor: auto;\t\n}\t\n.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\t\n display: none !important;\t\n}\t\n.apexcharts-inactive-legend {\t\n opacity: 0.45;\t\n}\n\n.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {\n pointer-events: none\n}\n\n.apexcharts-marker {\n transition: .15s ease all\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,.resize-triggers,.resize-triggers>div {\n content: " ";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n',r?s.prepend(t.css):o.head.appendChild(t.css))}var l=t.create(t.w.config.series,{});if(!l)return e(t);t.mount(l).then((function(){"function"==typeof t.w.config.chart.events.mounted&&t.w.config.chart.events.mounted(t,t.w),t.events.fireEvent("mounted",[t,t.w]),e(l)})).catch((function(t){i(t)}))}else i(new Error("Element not found"))}))}},{key:"create",value:function(t,e){var i=this.w;new Ht(this).initModules();var a=this.w.globals;(a.noData=!1,a.animationEnded=!1,this.responsive.checkResponsiveConfig(e),i.config.xaxis.convertedCatToNumeric)&&new X(i.config).convertCatToNumericXaxis(i.config,this.ctx);if(null===this.el)return a.animationEnded=!0,null;if(this.core.setupElements(),"treemap"===i.config.chart.type&&(i.config.grid.show=!1,i.config.yaxis[0].show=!1),0===a.svgWidth)return a.animationEnded=!0,null;var s=y.checkComboSeries(t);a.comboCharts=s.comboCharts,a.comboBarCount=s.comboBarCount;var r=t.every((function(t){return t.data&&0===t.data.length}));(0===t.length||r)&&this.series.handleNoData(),this.events.setupEventHandlers(),this.data.parseData(t),this.theme.init(),new D(this).setGlobalMarkerSize(),this.formatters.setLabelFormatters(),this.titleSubtitle.draw(),a.noData&&a.collapsedSeries.length!==a.series.length&&!i.config.legend.showForSingleSeries||this.legend.init(),this.series.hasAllSeriesEqualX(),a.axisCharts&&(this.core.coreCalculations(),"category"!==i.config.xaxis.type&&this.formatters.setLabelFormatters(),this.ctx.toolbar.minX=i.globals.minX,this.ctx.toolbar.maxX=i.globals.maxX),this.formatters.heatmapLabelFormatters(),new y(this).getLargestMarkerSize(),this.dimensions.plotCoords();var o=this.core.xySettings();this.grid.createGridMask();var n=this.core.plotChartType(t,o),l=new O(this);l.bringForward(),i.config.dataLabels.background.enabled&&l.dataLabelsBackground(),this.core.shiftGraphPosition();var h={plot:{left:i.globals.translateX,top:i.globals.translateY,width:i.globals.gridWidth,height:i.globals.gridHeight}};return{elGraph:n,xyRatios:o,elInner:i.globals.dom.elGraphical,dimensions:h}}},{key:"mount",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,i=this,a=i.w;return new Promise((function(s,r){if(null===i.el)return r(new Error("Not enough data to display or target element not found"));(null===e||a.globals.allSeriesCollapsed)&&i.series.handleNoData(),i.grid=new j(i);var o=i.grid.drawGrid();if(i.annotations=new P(i),i.annotations.drawImageAnnos(),i.annotations.drawTextAnnos(),"back"===a.config.grid.position&&o&&(a.globals.dom.elGraphical.add(o.el),o&&o.elGridBorders&&o.elGridBorders.node&&a.globals.dom.elGraphical.add(o.elGridBorders)),Array.isArray(e.elGraph))for(var n=0;n0&&a.globals.memory.methodsToExec.forEach((function(t){t.method(t.params,!1,t.context)})),a.globals.axisCharts||a.globals.noData||i.core.resizeNonAxisCharts(),s(i)}))}},{key:"destroy",value:function(){var t,e;window.removeEventListener("resize",this.windowResizeHandler),this.el.parentNode,t=this.parentResizeHandler,(e=Nt.get(t))&&(e.disconnect(),Nt.delete(t));var i=this.w.config.chart.id;i&&Apex._chartInstances.forEach((function(t,e){t.id===x.escapeString(i)&&Apex._chartInstances.splice(e,1)})),new Ot(this.ctx).clear({isUpdating:!1})}},{key:"updateOptions",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=this.w;return o.globals.selection=void 0,t.series&&(this.series.resetSeries(!1,!0,!1),t.series.length&&t.series[0].data&&(t.series=t.series.map((function(t,i){return e.updateHelpers._extendSeries(t,i)}))),this.updateHelpers.revertDefaultAxisMinMax()),t.xaxis&&(t=this.updateHelpers.forceXAxisUpdate(t)),t.yaxis&&(t=this.updateHelpers.forceYAxisUpdate(t)),o.globals.collapsedSeriesIndices.length>0&&this.series.clearPreviousPaths(),t.theme&&(t=this.theme.updateThemeOptions(t)),this.updateHelpers._updateOptions(t,i,a,s,r)}},{key:"updateSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(t,e,i)}},{key:"appendSeries",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w.config.series.slice();return a.push(t),this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(a,e,i)}},{key:"appendData",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this;i.w.globals.dataChanged=!0,i.series.getPreviousPaths();for(var a=i.w.config.series.slice(),s=0;s0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.series.resetSeries(t,e)}},{key:"addEventListener",value:function(t,e){this.events.addEventListener(t,e)}},{key:"removeEventListener",value:function(t,e){this.events.removeEventListener(t,e)}},{key:"addXaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addXaxisAnnotationExternal(t,e,a)}},{key:"addYaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addYaxisAnnotationExternal(t,e,a)}},{key:"addPointAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addPointAnnotationExternal(t,e,a)}},{key:"clearAnnotations",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,e=this;t&&(e=t),e.annotations.clearAnnotations(e)}},{key:"removeAnnotation",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=this;e&&(i=e),i.annotations.removeAnnotation(i,t)}},{key:"getChartArea",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner")}},{key:"getSeriesTotalXRange",value:function(t,e){return this.coreUtils.getSeriesTotalsXRange(t,e)}},{key:"getHighestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new U(this.ctx);return e.getMinYMaxY(t).highestY}},{key:"getLowestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new U(this.ctx);return e.getMinYMaxY(t).lowestY}},{key:"getSeriesTotal",value:function(){return this.w.globals.seriesTotals}},{key:"toggleDataPointSelection",value:function(t,e){return this.updateHelpers.toggleDataPointSelection(t,e)}},{key:"zoomX",value:function(t,e){this.ctx.toolbar.zoomUpdateOptions(t,e)}},{key:"setLocale",value:function(t){this.localization.setCurrentLocaleValues(t)}},{key:"dataURI",value:function(t){return new G(this.ctx).dataURI(t)}},{key:"exportToCSV",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=new G(this.ctx);return e.exportToCSV(t)}},{key:"paper",value:function(){return this.w.globals.dom.Paper}},{key:"_parentResizeCallback",value:function(){this.w.globals.animationEnded&&this.w.config.chart.redrawOnParentResize&&this._windowResize()}},{key:"_windowResize",value:function(){var t=this;clearTimeout(this.w.globals.resizeTimer),this.w.globals.resizeTimer=window.setTimeout((function(){t.w.globals.resized=!0,t.w.globals.dataChanged=!1,t.ctx.update()}),150)}},{key:"_windowResizeHandler",value:function(){var t=this.w.config.chart.redrawOnWindowResize;"function"==typeof t&&(t=t()),t&&this._windowResize()}}],[{key:"getChartByID",value:function(t){var e=x.escapeString(t),i=Apex._chartInstances.filter((function(t){return t.id===e}))[0];return i&&i.chart}},{key:"initOnLoad",value:function(){for(var e=document.querySelectorAll("[data-apexcharts]"),i=0;i2?s-2:0),o=2;odiv { margin: 4px 0 } .apexcharts-tooltip-box span.value { font-weight: 700 } .apexcharts-tooltip-rangebar { padding: 5px 8px } .apexcharts-tooltip-rangebar .category { font-weight: 600; color: #777 } .apexcharts-tooltip-rangebar .series-name { font-weight: 700; display: block; margin-bottom: 5px } .apexcharts-xaxistooltip,.apexcharts-yaxistooltip { opacity: 0; pointer-events: none; color: #373d3f; font-size: 13px; text-align: center; border-radius: 2px; position: absolute; z-index: 10; background: #eceff1; border: 1px solid #90a4ae } .apexcharts-xaxistooltip { padding: 9px 10px; transition: .15s ease all } .apexcharts-xaxistooltip.apexcharts-theme-dark { background: rgba(0,0,0,.7); border: 1px solid rgba(0,0,0,.5); color: #fff } .apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before { left: 50%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none } .apexcharts-xaxistooltip:after { border-color: transparent; border-width: 6px; margin-left: -6px } .apexcharts-xaxistooltip:before { border-color: transparent; border-width: 7px; margin-left: -7px } .apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before { bottom: 100% } .apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before { top: 100% } .apexcharts-xaxistooltip-bottom:after { border-bottom-color: #eceff1 } .apexcharts-xaxistooltip-bottom:before { border-bottom-color: #90a4ae } .apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before { border-bottom-color: rgba(0,0,0,.5) } .apexcharts-xaxistooltip-top:after { border-top-color: #eceff1 } .apexcharts-xaxistooltip-top:before { border-top-color: #90a4ae } .apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before { border-top-color: rgba(0,0,0,.5) } .apexcharts-xaxistooltip.apexcharts-active { opacity: 1; transition: .15s ease all } .apexcharts-yaxistooltip { padding: 4px 10px } .apexcharts-yaxistooltip.apexcharts-theme-dark { background: rgba(0,0,0,.7); border: 1px solid rgba(0,0,0,.5); color: #fff } .apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before { top: 50%; border: solid transparent; content: " "; height: 0; width: 0; position: absolute; pointer-events: none } .apexcharts-yaxistooltip:after { border-color: transparent; border-width: 6px; margin-top: -6px } .apexcharts-yaxistooltip:before { border-color: transparent; border-width: 7px; margin-top: -7px } .apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before { left: 100% } .apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before { right: 100% } .apexcharts-yaxistooltip-left:after { border-left-color: #eceff1 } .apexcharts-yaxistooltip-left:before { border-left-color: #90a4ae } .apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before { border-left-color: rgba(0,0,0,.5) } .apexcharts-yaxistooltip-right:after { border-right-color: #eceff1 } .apexcharts-yaxistooltip-right:before { border-right-color: #90a4ae } .apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before { border-right-color: rgba(0,0,0,.5) } .apexcharts-yaxistooltip.apexcharts-active { opacity: 1 } .apexcharts-yaxistooltip-hidden { display: none } .apexcharts-xcrosshairs,.apexcharts-ycrosshairs { pointer-events: none; opacity: 0; transition: .15s ease all } .apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active { opacity: 1; transition: .15s ease all } .apexcharts-ycrosshairs-hidden { opacity: 0 } .apexcharts-selection-rect { cursor: move } .svg_select_boundingRect,.svg_select_points_rot { pointer-events: none; opacity: 0; visibility: hidden } .apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot { opacity: 0; visibility: hidden } .apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r { cursor: ew-resize; opacity: 1; visibility: visible } .svg_select_points { fill: #efefef; stroke: #333; rx: 2 } .apexcharts-svg.apexcharts-zoomable.hovering-zoom { cursor: crosshair } .apexcharts-svg.apexcharts-zoomable.hovering-pan { cursor: move } .apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon { cursor: pointer; width: 20px; height: 20px; line-height: 24px; color: #6e8192; text-align: center } .apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg { fill: #6e8192 } .apexcharts-selection-icon svg { fill: #444; transform: scale(.76) } .apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg { fill: #f3f4f5 } .apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg { fill: #008ffb } .apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg { fill: #333 } .apexcharts-menu-icon,.apexcharts-selection-icon { position: relative } .apexcharts-reset-icon { margin-left: 5px } .apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon { transform: scale(.85) } .apexcharts-zoomin-icon,.apexcharts-zoomout-icon { transform: scale(.7) } .apexcharts-zoomout-icon { margin-right: 3px } .apexcharts-pan-icon { transform: scale(.62); position: relative; left: 1px; top: 0 } .apexcharts-pan-icon svg { fill: #fff; stroke: #6e8192; stroke-width: 2 } .apexcharts-pan-icon.apexcharts-selected svg { stroke: #008ffb } .apexcharts-pan-icon:not(.apexcharts-selected):hover svg { stroke: #333 } .apexcharts-toolbar { position: absolute; z-index: 11; max-width: 176px; text-align: right; border-radius: 3px; padding: 0 6px 2px; display: flex; justify-content: space-between; align-items: center } .apexcharts-menu { background: #fff; position: absolute; top: 100%; border: 1px solid #ddd; border-radius: 3px; padding: 3px; right: 10px; opacity: 0; min-width: 110px; transition: .15s ease all; pointer-events: none } .apexcharts-menu.apexcharts-menu-open { opacity: 1; pointer-events: all; transition: .15s ease all } .apexcharts-menu-item { padding: 6px 7px; font-size: 12px; cursor: pointer } .apexcharts-theme-light .apexcharts-menu-item:hover { background: #eee } .apexcharts-theme-dark .apexcharts-menu { background: rgba(0,0,0,.7); color: #fff } @media screen and (min-width:768px) { .apexcharts-canvas:hover .apexcharts-toolbar { opacity: 1 } } .apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points { opacity: 0 } .apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label { cursor: default; pointer-events: none } .apexcharts-pie-label-delay { opacity: 0; animation-name: opaque; animation-duration: .3s; animation-fill-mode: forwards; animation-timing-function: ease } .apexcharts-legend { display: flex; overflow: auto; padding: 0 10px; } .apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top { flex-wrap: wrap } .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left { flex-direction: column; bottom: 0; } .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left { justify-content: flex-start; } .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center { justify-content: center; } .apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right { justify-content: flex-end; } .apexcharts-legend-series { cursor: pointer; line-height: normal; } .apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{ display: flex; align-items: center; } .apexcharts-legend-text { position: relative; font-size: 14px; } .apexcharts-legend-text *, .apexcharts-legend-marker * { pointer-events: none; } .apexcharts-legend-marker { position: relative; display: inline-block; cursor: pointer; margin-right: 3px; border-style: solid; } .apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{ display: inline-block; } .apexcharts-legend-series.apexcharts-no-click { cursor: auto; } .apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series { display: none !important; } .apexcharts-inactive-legend { opacity: 0.45; } .apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect { pointer-events: none } .apexcharts-marker { transition: .15s ease all } .resize-triggers { animation: 1ms resizeanim; visibility: hidden; opacity: 0; height: 100%; width: 100%; overflow: hidden } .contract-trigger:before,.resize-triggers,.resize-triggers>div { content: " "; display: block; position: absolute; top: 0; left: 0 } .resize-triggers>div { height: 100%; width: 100%; background: #eee; overflow: auto } .contract-trigger:before { overflow: hidden; width: 200%; height: 200% } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/apexcharts.esm.js ================================================ /*! * ApexCharts v3.37.1 * (c) 2018-2023 ApexCharts * Released under the MIT License. */ function t(t,e){var i=Object.keys(t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(t);e&&(a=a.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),i.push.apply(i,a)}return i}function e(e){for(var i=1;it.length)&&(e=t.length);for(var i=0,a=new Array(e);i>16,o=i>>8&255,n=255&i;return"#"+(16777216+65536*(Math.round((a-r)*s)+r)+256*(Math.round((a-o)*s)+o)+(Math.round((a-n)*s)+n)).toString(16).slice(1)}},{key:"shadeColor",value:function(e,i){return t.isColorHex(i)?this.shadeHexColor(e,i):this.shadeRGBColor(e,i)}}],[{key:"bind",value:function(t,e){return function(){return t.apply(e,arguments)}}},{key:"isObject",value:function(t){return t&&"object"===i(t)&&!Array.isArray(t)&&null!=t}},{key:"is",value:function(t,e){return Object.prototype.toString.call(e)==="[object "+t+"]"}},{key:"listToArray",value:function(t){var e,i=[];for(e=0;ee.length?t:e}))),t.length>e.length?t:e}),0)}},{key:"hexToRgba",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"#999999",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:.6;"#"!==t.substring(0,1)&&(t="#999999");var i=t.replace("#","");i=i.match(new RegExp("(.{"+i.length/3+"})","g"));for(var a=0;a1&&void 0!==arguments[1]?arguments[1]:"x",i=t.toString().slice();return i=i.replace(/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi,e)}},{key:"negToZero",value:function(t){return t<0?0:t}},{key:"moveIndexInArray",value:function(t,e,i){if(i>=t.length)for(var a=i-t.length+1;a--;)t.push(void 0);return t.splice(i,0,t.splice(e,1)[0]),t}},{key:"extractNumber",value:function(t){return parseFloat(t.replace(/[^\d.]*/g,""))}},{key:"findAncestor",value:function(t,e){for(;(t=t.parentElement)&&!t.classList.contains(e););return t}},{key:"setELstyles",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&(t.style.key=e[i])}},{key:"isNumber",value:function(t){return!isNaN(t)&&parseFloat(Number(t))===t&&!isNaN(parseInt(t,10))}},{key:"isFloat",value:function(t){return Number(t)===t&&t%1!=0}},{key:"isSafari",value:function(){return/^((?!chrome|android).)*safari/i.test(navigator.userAgent)}},{key:"isFirefox",value:function(){return navigator.userAgent.toLowerCase().indexOf("firefox")>-1}},{key:"isIE11",value:function(){if(-1!==window.navigator.userAgent.indexOf("MSIE")||window.navigator.appVersion.indexOf("Trident/")>-1)return!0}},{key:"isIE",value:function(){var t=window.navigator.userAgent,e=t.indexOf("MSIE ");if(e>0)return parseInt(t.substring(e+5,t.indexOf(".",e)),10);if(t.indexOf("Trident/")>0){var i=t.indexOf("rv:");return parseInt(t.substring(i+3,t.indexOf(".",i)),10)}var a=t.indexOf("Edge/");return a>0&&parseInt(t.substring(a+5,t.indexOf(".",a)),10)}}]),t}(),b=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.setEasingFunctions()}return r(t,[{key:"setEasingFunctions",value:function(){var t;if(!this.w.globals.easing){switch(this.w.config.chart.animations.easing){case"linear":t="-";break;case"easein":t="<";break;case"easeout":t=">";break;case"easeinout":default:t="<>";break;case"swing":t=function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1};break;case"bounce":t=function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375};break;case"elastic":t=function(t){return t===!!t?t:Math.pow(2,-10*t)*Math.sin((t-.075)*(2*Math.PI)/.3)+1}}this.w.globals.easing=t}}},{key:"animateLine",value:function(t,e,i,a){t.attr(e).animate(a).attr(i)}},{key:"animateMarker",value:function(t,e,i,a,s,r){e||(e=0),t.attr({r:e,width:e,height:e}).animate(a,s).attr({r:i,width:i.width,height:i.height}).afterAll((function(){r()}))}},{key:"animateCircle",value:function(t,e,i,a,s){t.attr({r:e.r,cx:e.cx,cy:e.cy}).animate(a,s).attr({r:i.r,cx:i.cx,cy:i.cy})}},{key:"animateRect",value:function(t,e,i,a,s){t.attr(e).animate(a).attr(i).afterAll((function(){return s()}))}},{key:"animatePathsGradually",value:function(t){var e=t.el,i=t.realIndex,a=t.j,s=t.fill,r=t.pathFrom,o=t.pathTo,n=t.speed,l=t.delay,h=this.w,c=0;h.config.chart.animations.animateGradually.enabled&&(c=h.config.chart.animations.animateGradually.delay),h.config.chart.animations.dynamicAnimation.enabled&&h.globals.dataChanged&&"bar"!==h.config.chart.type&&(c=0),this.morphSVG(e,i,a,"line"!==h.config.chart.type||h.globals.comboCharts?s:"stroke",r,o,n,l*c)}},{key:"showDelayedElements",value:function(){this.w.globals.delayedElements.forEach((function(t){t.el.classList.remove("apexcharts-element-hidden")}))}},{key:"animationCompleted",value:function(t){var e=this.w;e.globals.animationEnded||(e.globals.animationEnded=!0,this.showDelayedElements(),"function"==typeof e.config.chart.events.animationEnd&&e.config.chart.events.animationEnd(this.ctx,{el:t,w:e}))}},{key:"morphSVG",value:function(t,e,i,a,s,r,o,n){var l=this,h=this.w;s||(s=t.attr("pathFrom")),r||(r=t.attr("pathTo"));var c=function(t){return"radar"===h.config.chart.type&&(o=1),"M 0 ".concat(h.globals.gridHeight)};(!s||s.indexOf("undefined")>-1||s.indexOf("NaN")>-1)&&(s=c()),(!r||r.indexOf("undefined")>-1||r.indexOf("NaN")>-1)&&(r=c()),h.globals.shouldAnimate||(o=1),t.plot(s).animate(1,h.globals.easing,n).plot(s).animate(o,h.globals.easing,n).plot(r).afterAll((function(){x.isNumber(i)?i===h.globals.series[h.globals.maxValsInArrayIndex].length-2&&h.globals.shouldAnimate&&l.animationCompleted(t):"none"!==a&&h.globals.shouldAnimate&&(!h.globals.comboCharts&&e===h.globals.series.length-1||h.globals.comboCharts)&&l.animationCompleted(t),l.showDelayedElements()}))}}]),t}(),v=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"getDefaultFilter",value:function(t,e){var i=this.w;t.unfilter(!0),(new window.SVG.Filter).size("120%","180%","-5%","-40%"),"none"!==i.config.states.normal.filter?this.applyFilter(t,e,i.config.states.normal.filter.type,i.config.states.normal.filter.value):i.config.chart.dropShadow.enabled&&this.dropShadow(t,i.config.chart.dropShadow,e)}},{key:"addNormalFilter",value:function(t,e){var i=this.w;i.config.chart.dropShadow.enabled&&!t.node.classList.contains("apexcharts-marker")&&this.dropShadow(t,i.config.chart.dropShadow,e)}},{key:"addLightenFilter",value:function(t,e,i){var a=this,s=this.w,r=i.intensity;t.unfilter(!0);new window.SVG.Filter;t.filter((function(t){var i=s.config.chart.dropShadow;(i.enabled?a.addShadow(t,e,i):t).componentTransfer({rgb:{type:"linear",slope:1.5,intercept:r}})})),t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)}},{key:"addDarkenFilter",value:function(t,e,i){var a=this,s=this.w,r=i.intensity;t.unfilter(!0);new window.SVG.Filter;t.filter((function(t){var i=s.config.chart.dropShadow;(i.enabled?a.addShadow(t,e,i):t).componentTransfer({rgb:{type:"linear",slope:r}})})),t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)}},{key:"applyFilter",value:function(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:.5;switch(i){case"none":this.addNormalFilter(t,e);break;case"lighten":this.addLightenFilter(t,e,{intensity:a});break;case"darken":this.addDarkenFilter(t,e,{intensity:a})}}},{key:"addShadow",value:function(t,e,i){var a=i.blur,s=i.top,r=i.left,o=i.color,n=i.opacity,l=t.flood(Array.isArray(o)?o[e]:o,n).composite(t.sourceAlpha,"in").offset(r,s).gaussianBlur(a).merge(t.source);return t.blend(t.source,l)}},{key:"dropShadow",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=e.top,s=e.left,r=e.blur,o=e.color,n=e.opacity,l=e.noUserSpaceOnUse,h=this.w;return t.unfilter(!0),x.isIE()&&"radialBar"===h.config.chart.type||(o=Array.isArray(o)?o[i]:o,t.filter((function(t){var e=null;e=x.isSafari()||x.isFirefox()||x.isIE()?t.flood(o,n).composite(t.sourceAlpha,"in").offset(s,a).gaussianBlur(r):t.flood(o,n).composite(t.sourceAlpha,"in").offset(s,a).gaussianBlur(r).merge(t.source),t.blend(t.source,e)})),l||t.filterer.node.setAttribute("filterUnits","userSpaceOnUse"),this._scaleFilterSize(t.filterer.node)),t}},{key:"setSelectionFilter",value:function(t,e,i){var a=this.w;if(void 0!==a.globals.selectedDataPoints[e]&&a.globals.selectedDataPoints[e].indexOf(i)>-1){t.node.setAttribute("selected",!0);var s=a.config.states.active.filter;"none"!==s&&this.applyFilter(t,e,s.type,s.value)}}},{key:"_scaleFilterSize",value:function(t){!function(e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}({width:"200%",height:"200%",x:"-50%",y:"-50%"})}}]),t}(),m=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"roundPathCorners",value:function(t,e){function i(t,e,i){var s=e.x-t.x,r=e.y-t.y,o=Math.sqrt(s*s+r*r);return a(t,e,Math.min(1,i/o))}function a(t,e,i){return{x:t.x+(e.x-t.x)*i,y:t.y+(e.y-t.y)*i}}function s(t,e){t.length>2&&(t[t.length-2]=e.x,t[t.length-1]=e.y)}function r(t){return{x:parseFloat(t[t.length-2]),y:parseFloat(t[t.length-1])}}var o=t.split(/[,\s]/).reduce((function(t,e){var i=e.match("([a-zA-Z])(.+)");return i?(t.push(i[1]),t.push(i[2])):t.push(e),t}),[]).reduce((function(t,e){return parseFloat(e)==e&&t.length?t[t.length-1].push(e):t.push([e]),t}),[]),n=[];if(o.length>1){var l=r(o[0]),h=null;"Z"==o[o.length-1][0]&&o[0].length>2&&(h=["L",l.x,l.y],o[o.length-1]=h),n.push(o[0]);for(var c=1;c2&&"L"==g[0]&&u.length>2&&"L"==u[0]){var f,p,x=r(d),b=r(g),v=r(u);f=i(b,x,e),p=i(b,v,e),s(g,f),g.origPoint=b,n.push(g);var m=a(f,b,.5),y=a(b,p,.5),w=["C",m.x,m.y,y.x,y.y,p.x,p.y];w.origPoint=b,n.push(w)}else n.push(g)}if(h){var k=r(n[n.length-1]);n.push(["Z"]),s(n[0],k)}}else n=o;return n.reduce((function(t,e){return t+e.join(" ")+" "}),"")}},{key:"drawLine",value:function(t,e,i,a){var s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"#a8a8a8",r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,o=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,n=arguments.length>7&&void 0!==arguments[7]?arguments[7]:"butt",l=this.w,h=l.globals.dom.Paper.line().attr({x1:t,y1:e,x2:i,y2:a,stroke:s,"stroke-dasharray":r,"stroke-width":o,"stroke-linecap":n});return h}},{key:"drawRect",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"#fefefe",o=arguments.length>6&&void 0!==arguments[6]?arguments[6]:1,n=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,l=arguments.length>8&&void 0!==arguments[8]?arguments[8]:null,h=arguments.length>9&&void 0!==arguments[9]?arguments[9]:0,c=this.w,d=c.globals.dom.Paper.rect();return d.attr({x:t,y:e,width:i>0?i:0,height:a>0?a:0,rx:s,ry:s,opacity:o,"stroke-width":null!==n?n:0,stroke:null!==l?l:"none","stroke-dasharray":h}),d.node.setAttribute("fill",r),d}},{key:"drawPolygon",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"#e1e1e1",i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"none",s=this.w,r=s.globals.dom.Paper.polygon(t).attr({fill:a,stroke:e,"stroke-width":i});return r}},{key:"drawCircle",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.w;t<0&&(t=0);var a=i.globals.dom.Paper.circle(2*t);return null!==e&&a.attr(e),a}},{key:"drawPath",value:function(t){var e=t.d,i=void 0===e?"":e,a=t.stroke,s=void 0===a?"#a8a8a8":a,r=t.strokeWidth,o=void 0===r?1:r,n=t.fill,l=t.fillOpacity,h=void 0===l?1:l,c=t.strokeOpacity,d=void 0===c?1:c,g=t.classes,u=t.strokeLinecap,f=void 0===u?null:u,p=t.strokeDashArray,x=void 0===p?0:p,b=this.w;return null===f&&(f=b.config.stroke.lineCap),(i.indexOf("undefined")>-1||i.indexOf("NaN")>-1)&&(i="M 0 ".concat(b.globals.gridHeight)),b.globals.dom.Paper.path(i).attr({fill:n,"fill-opacity":h,stroke:s,"stroke-opacity":d,"stroke-linecap":f,"stroke-width":o,"stroke-dasharray":x,class:g})}},{key:"group",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w,i=e.globals.dom.Paper.group();return null!==t&&i.attr(t),i}},{key:"move",value:function(t,e){var i=["M",t,e].join(" ");return i}},{key:"line",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=null;return null===i?a=[" L",t,e].join(" "):"H"===i?a=[" H",t].join(" "):"V"===i&&(a=[" V",e].join(" ")),a}},{key:"curve",value:function(t,e,i,a,s,r){var o=["C",t,e,i,a,s,r].join(" ");return o}},{key:"quadraticCurve",value:function(t,e,i,a){return["Q",t,e,i,a].join(" ")}},{key:"arc",value:function(t,e,i,a,s,r,o){var n=arguments.length>7&&void 0!==arguments[7]&&arguments[7],l="A";n&&(l="a");var h=[l,t,e,i,a,s,r,o].join(" ");return h}},{key:"renderPaths",value:function(t){var i,a=t.j,s=t.realIndex,r=t.pathFrom,o=t.pathTo,n=t.stroke,l=t.strokeWidth,h=t.strokeLinecap,c=t.fill,d=t.animationDelay,g=t.initialSpeed,u=t.dataChangeSpeed,f=t.className,p=t.shouldClipToGrid,x=void 0===p||p,m=t.bindEventsOnPaths,y=void 0===m||m,w=t.drawShadow,k=void 0===w||w,A=this.w,S=new v(this.ctx),C=new b(this.ctx),L=this.w.config.chart.animations.enabled,P=L&&this.w.config.chart.animations.dynamicAnimation.enabled,T=!!(L&&!A.globals.resized||P&&A.globals.dataChanged&&A.globals.shouldAnimate);T?i=r:(i=o,A.globals.animationEnded=!0);var M=A.config.stroke.dashArray,I=0;I=Array.isArray(M)?M[s]:A.config.stroke.dashArray;var z=this.drawPath({d:i,stroke:n,strokeWidth:l,fill:c,fillOpacity:1,classes:f,strokeLinecap:h,strokeDashArray:I});if(z.attr("index",s),x&&z.attr({"clip-path":"url(#gridRectMask".concat(A.globals.cuid,")")}),"none"!==A.config.states.normal.filter.type)S.getDefaultFilter(z,s);else if(A.config.chart.dropShadow.enabled&&k&&(!A.config.chart.dropShadow.enabledOnSeries||A.config.chart.dropShadow.enabledOnSeries&&-1!==A.config.chart.dropShadow.enabledOnSeries.indexOf(s))){var X=A.config.chart.dropShadow;S.dropShadow(z,X,s)}y&&(z.node.addEventListener("mouseenter",this.pathMouseEnter.bind(this,z)),z.node.addEventListener("mouseleave",this.pathMouseLeave.bind(this,z)),z.node.addEventListener("mousedown",this.pathMouseDown.bind(this,z))),z.attr({pathTo:o,pathFrom:r});var E={el:z,j:a,realIndex:s,pathFrom:r,pathTo:o,fill:c,strokeWidth:l,delay:d};return!L||A.globals.resized||A.globals.dataChanged?!A.globals.resized&&A.globals.dataChanged||C.showDelayedElements():C.animatePathsGradually(e(e({},E),{},{speed:g})),A.globals.dataChanged&&P&&T&&C.animatePathsGradually(e(e({},E),{},{speed:u})),z}},{key:"drawPattern",value:function(t,e,i){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"#a8a8a8",s=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,r=this.w,o=r.globals.dom.Paper.pattern(e,i,(function(r){"horizontalLines"===t?r.line(0,0,i,0).stroke({color:a,width:s+1}):"verticalLines"===t?r.line(0,0,0,e).stroke({color:a,width:s+1}):"slantedLines"===t?r.line(0,0,e,i).stroke({color:a,width:s}):"squares"===t?r.rect(e,i).fill("none").stroke({color:a,width:s}):"circles"===t&&r.circle(e).fill("none").stroke({color:a,width:s})}));return o}},{key:"drawGradient",value:function(t,e,i,a,s){var r,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:null,n=arguments.length>6&&void 0!==arguments[6]?arguments[6]:null,l=arguments.length>7&&void 0!==arguments[7]?arguments[7]:null,h=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0,c=this.w;e.length<9&&0===e.indexOf("#")&&(e=x.hexToRgba(e,a)),i.length<9&&0===i.indexOf("#")&&(i=x.hexToRgba(i,s));var d=0,g=1,u=1,f=null;null!==n&&(d=void 0!==n[0]?n[0]/100:0,g=void 0!==n[1]?n[1]/100:1,u=void 0!==n[2]?n[2]/100:1,f=void 0!==n[3]?n[3]/100:null);var p=!("donut"!==c.config.chart.type&&"pie"!==c.config.chart.type&&"polarArea"!==c.config.chart.type&&"bubble"!==c.config.chart.type);if(r=null===l||0===l.length?c.globals.dom.Paper.gradient(p?"radial":"linear",(function(t){t.at(d,e,a),t.at(g,i,s),t.at(u,i,s),null!==f&&t.at(f,e,a)})):c.globals.dom.Paper.gradient(p?"radial":"linear",(function(t){(Array.isArray(l[h])?l[h]:l).forEach((function(e){t.at(e.offset/100,e.color,e.opacity)}))})),p){var b=c.globals.gridWidth/2,v=c.globals.gridHeight/2;"bubble"!==c.config.chart.type?r.attr({gradientUnits:"userSpaceOnUse",cx:b,cy:v,r:o}):r.attr({cx:.5,cy:.5,r:.8,fx:.2,fy:.2})}else"vertical"===t?r.from(0,0).to(0,1):"diagonal"===t?r.from(0,0).to(1,1):"horizontal"===t?r.from(0,1).to(1,1):"diagonal2"===t&&r.from(1,0).to(0,1);return r}},{key:"getTextBasedOnMaxWidth",value:function(t){var e=t.text,i=t.maxWidth,a=t.fontSize,s=t.fontFamily,r=this.getTextRects(e,a,s),o=r.width/e.length,n=Math.floor(i/o);return i-1){var n=i.globals.selectedDataPoints[s].indexOf(r);i.globals.selectedDataPoints[s].splice(n,1)}}else{if(!i.config.states.active.allowMultipleDataPointsSelection&&i.globals.selectedDataPoints.length>0){i.globals.selectedDataPoints=[];var l=i.globals.dom.Paper.select(".apexcharts-series path").members,h=i.globals.dom.Paper.select(".apexcharts-series circle, .apexcharts-series rect").members,c=function(t){Array.prototype.forEach.call(t,(function(t){t.node.setAttribute("selected","false"),a.getDefaultFilter(t,s)}))};c(l),c(h)}t.node.setAttribute("selected","true"),o="true",void 0===i.globals.selectedDataPoints[s]&&(i.globals.selectedDataPoints[s]=[]),i.globals.selectedDataPoints[s].push(r)}if("true"===o){var d=i.config.states.active.filter;if("none"!==d)a.applyFilter(t,s,d.type,d.value);else if("none"!==i.config.states.hover.filter&&!i.globals.isTouchDevice){var g=i.config.states.hover.filter;a.applyFilter(t,s,g.type,g.value)}}else if("none"!==i.config.states.active.filter.type)if("none"===i.config.states.hover.filter.type||i.globals.isTouchDevice)a.getDefaultFilter(t,s);else{g=i.config.states.hover.filter;a.applyFilter(t,s,g.type,g.value)}"function"==typeof i.config.chart.events.dataPointSelection&&i.config.chart.events.dataPointSelection(e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}),e&&this.ctx.events.fireEvent("dataPointSelection",[e,this.ctx,{selectedDataPoints:i.globals.selectedDataPoints,seriesIndex:s,dataPointIndex:r,w:i}])}},{key:"rotateAroundCenter",value:function(t){var e={};return t&&"function"==typeof t.getBBox&&(e=t.getBBox()),{x:e.x+e.width/2,y:e.y+e.height/2}}},{key:"getTextRects",value:function(t,e,i,a){var s=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],r=this.w,o=this.drawText({x:-200,y:-200,text:t,textAnchor:"start",fontSize:e,fontFamily:i,foreColor:"#fff",opacity:0});a&&o.attr("transform",a),r.globals.dom.Paper.add(o);var n=o.bbox();return s||(n=o.node.getBoundingClientRect()),o.remove(),{width:n.width,height:n.height}}},{key:"placeTextWithEllipsis",value:function(t,e,i){if("function"==typeof t.getComputedTextLength&&(t.textContent=e,e.length>0&&t.getComputedTextLength()>=i/1.1)){for(var a=e.length-3;a>0;a-=3)if(t.getSubStringLength(0,a)<=i/1.1)return void(t.textContent=e.substring(0,a)+"...");t.textContent="."}}}],[{key:"setAttrs",value:function(t,e){for(var i in e)e.hasOwnProperty(i)&&t.setAttribute(i,e[i])}}]),t}(),y=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"getStackedSeriesTotals",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=this.w,i=[];if(0===e.globals.series.length)return i;for(var a=0;a0&&void 0!==arguments[0]?arguments[0]:null;return null===t?this.w.config.series.reduce((function(t,e){return t+e}),0):this.w.globals.series[t].reduce((function(t,e){return t+e}),0)}},{key:"isSeriesNull",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;return 0===(null===t?this.w.config.series.filter((function(t){return null!==t})):this.w.config.series[t].data.filter((function(t){return null!==t}))).length}},{key:"seriesHaveSameValues",value:function(t){return this.w.globals.series[t].every((function(t,e,i){return t===i[0]}))}},{key:"getCategoryLabels",value:function(t){var e=this.w,i=t.slice();return e.config.xaxis.convertedCatToNumeric&&(i=t.map((function(t,i){return e.config.xaxis.labels.formatter(t-e.globals.minX+1)}))),i}},{key:"getLargestSeries",value:function(){var t=this.w;t.globals.maxValsInArrayIndex=t.globals.series.map((function(t){return t.length})).indexOf(Math.max.apply(Math,t.globals.series.map((function(t){return t.length}))))}},{key:"getLargestMarkerSize",value:function(){var t=this.w,e=0;return t.globals.markers.size.forEach((function(t){e=Math.max(e,t)})),t.config.markers.discrete&&t.config.markers.discrete.length&&t.config.markers.discrete.forEach((function(t){e=Math.max(e,t.size)})),e>0&&(e+=t.config.markers.hover.sizeOffset+1),t.globals.markers.largestSize=e,e}},{key:"getSeriesTotals",value:function(){var t=this.w;t.globals.seriesTotals=t.globals.series.map((function(t,e){var i=0;if(Array.isArray(t))for(var a=0;at&&i.globals.seriesX[s][o]0&&(e=!0),{comboBarCount:i,comboCharts:e}}},{key:"extendArrayProps",value:function(t,e,i){return e.yaxis&&(e=t.extendYAxis(e,i)),e.annotations&&(e.annotations.yaxis&&(e=t.extendYAxisAnnotations(e)),e.annotations.xaxis&&(e=t.extendXAxisAnnotations(e)),e.annotations.points&&(e=t.extendPointAnnotations(e))),e}}]),t}(),w=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e}return r(t,[{key:"setOrientations",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.w;if("vertical"===t.label.orientation){var a=null!==e?e:0,s=i.globals.dom.baseEl.querySelector(".apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='".concat(a,"']"));if(null!==s){var r=s.getBoundingClientRect();s.setAttribute("x",parseFloat(s.getAttribute("x"))-r.height+4),"top"===t.label.position?s.setAttribute("y",parseFloat(s.getAttribute("y"))+r.width):s.setAttribute("y",parseFloat(s.getAttribute("y"))-r.width);var o=this.annoCtx.graphics.rotateAroundCenter(s),n=o.x,l=o.y;s.setAttribute("transform","rotate(-90 ".concat(n," ").concat(l,")"))}}}},{key:"addBackgroundToAnno",value:function(t,e){var i=this.w;if(!t||void 0===e.label.text||void 0!==e.label.text&&!String(e.label.text).trim())return null;var a=i.globals.dom.baseEl.querySelector(".apexcharts-grid").getBoundingClientRect(),s=t.getBoundingClientRect(),r=e.label.style.padding.left,o=e.label.style.padding.right,n=e.label.style.padding.top,l=e.label.style.padding.bottom;"vertical"===e.label.orientation&&(n=e.label.style.padding.left,l=e.label.style.padding.right,r=e.label.style.padding.top,o=e.label.style.padding.bottom);var h=s.left-a.left-r,c=s.top-a.top-n,d=this.annoCtx.graphics.drawRect(h-i.globals.barPadForNumericAxis,c,s.width+r+o,s.height+n+l,e.label.borderRadius,e.label.style.background,1,e.label.borderWidth,e.label.borderColor,0);return e.id&&d.node.classList.add(e.id),d}},{key:"annotationsBackground",value:function(){var t=this,e=this.w,i=function(i,a,s){var r=e.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(a,"']"));if(r){var o=r.parentNode,n=t.addBackgroundToAnno(r,i);n&&(o.insertBefore(n.node,r),i.label.mouseEnter&&n.node.addEventListener("mouseenter",i.label.mouseEnter.bind(t,i)),i.label.mouseLeave&&n.node.addEventListener("mouseleave",i.label.mouseLeave.bind(t,i)),i.label.click&&n.node.addEventListener("click",i.label.click.bind(t,i)))}};e.config.annotations.xaxis.map((function(t,e){i(t,e,"xaxis")})),e.config.annotations.yaxis.map((function(t,e){i(t,e,"yaxis")})),e.config.annotations.points.map((function(t,e){i(t,e,"point")}))}},{key:"getY1Y2",value:function(t,e){var i,a="y1"===t?e.y:e.y2,s=this.w;if(this.annoCtx.invertAxis){var r=s.globals.labels.indexOf(a);s.config.xaxis.convertedCatToNumeric&&(r=s.globals.categoryLabels.indexOf(a));var o=s.globals.dom.baseEl.querySelector(".apexcharts-yaxis-texts-g text:nth-child("+(r+1)+")");o&&(i=parseFloat(o.getAttribute("y")))}else{var n;if(s.config.yaxis[e.yAxisIndex].logarithmic)n=(a=new y(this.annoCtx.ctx).getLogVal(a,e.yAxisIndex))/s.globals.yLogRatio[e.yAxisIndex];else n=(a-s.globals.minYArr[e.yAxisIndex])/(s.globals.yRange[e.yAxisIndex]/s.globals.gridHeight);i=s.globals.gridHeight-n,!e.marker||void 0!==e.y&&null!==e.y||(i=0),s.config.yaxis[e.yAxisIndex]&&s.config.yaxis[e.yAxisIndex].reversed&&(i=n)}return"string"==typeof a&&a.indexOf("px")>-1&&(i=parseFloat(a)),i}},{key:"getX1X2",value:function(t,e){var i=this.w,a=this.annoCtx.invertAxis?i.globals.minY:i.globals.minX,s=this.annoCtx.invertAxis?i.globals.maxY:i.globals.maxX,r=this.annoCtx.invertAxis?i.globals.yRange[0]:i.globals.xRange,o=(e.x-a)/(r/i.globals.gridWidth);this.annoCtx.inversedReversedAxis&&(o=(s-e.x)/(r/i.globals.gridWidth)),"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric||this.annoCtx.invertAxis||i.globals.dataFormatXNumeric||(o=this.getStringX(e.x));var n=(e.x2-a)/(r/i.globals.gridWidth);return this.annoCtx.inversedReversedAxis&&(n=(s-e.x2)/(r/i.globals.gridWidth)),"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric||this.annoCtx.invertAxis||i.globals.dataFormatXNumeric||(n=this.getStringX(e.x2)),void 0!==e.x&&null!==e.x||!e.marker||(o=i.globals.gridWidth),"x1"===t&&"string"==typeof e.x&&e.x.indexOf("px")>-1&&(o=parseFloat(e.x)),"x2"===t&&"string"==typeof e.x2&&e.x2.indexOf("px")>-1&&(n=parseFloat(e.x2)),"x1"===t?o:n}},{key:"getStringX",value:function(t){var e=this.w,i=t;e.config.xaxis.convertedCatToNumeric&&e.globals.categoryLabels.length&&(t=e.globals.categoryLabels.indexOf(t)+1);var a=e.globals.labels.indexOf(t),s=e.globals.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g text:nth-child("+(a+1)+")");return s&&(i=parseFloat(s.getAttribute("x"))),i}}]),t}(),k=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e,this.invertAxis=this.annoCtx.invertAxis,this.helpers=new w(this.annoCtx)}return r(t,[{key:"addXaxisAnnotation",value:function(t,e,i){var a,s=this.w,r=this.helpers.getX1X2("x1",t),o=t.label.text,n=t.strokeDashArray;if(x.isNumber(r)){if(null===t.x2||void 0===t.x2){var l=this.annoCtx.graphics.drawLine(r+t.offsetX,0+t.offsetY,r+t.offsetX,s.globals.gridHeight+t.offsetY,t.borderColor,n,t.borderWidth);e.appendChild(l.node),t.id&&l.node.classList.add(t.id)}else{if((a=this.helpers.getX1X2("x2",t))o){var h=o;o=a,a=h}var c=this.annoCtx.graphics.drawRect(0+t.offsetX,a+t.offsetY,this._getYAxisAnnotationWidth(t),o-a,0,t.fillColor,t.opacity,1,t.borderColor,r);c.node.classList.add("apexcharts-annotation-rect"),c.attr("clip-path","url(#gridRectMask".concat(s.globals.cuid,")")),e.appendChild(c.node),t.id&&c.node.classList.add(t.id)}var d="right"===t.label.position?s.globals.gridWidth:"center"===t.label.position?s.globals.gridWidth/2:0,g=this.annoCtx.graphics.drawText({x:d+t.label.offsetX,y:(null!=a?a:o)+t.label.offsetY-3,text:n,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-yaxis-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});g.attr({rel:i}),e.appendChild(g.node)}},{key:"_getYAxisAnnotationWidth",value:function(t){var e=this.w;e.globals.gridWidth;return(t.width.indexOf("%")>-1?e.globals.gridWidth*parseInt(t.width,10)/100:parseInt(t.width,10))+t.offsetX}},{key:"drawYAxisAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-yaxis-annotations"});return e.config.annotations.yaxis.map((function(e,a){t.addYaxisAnnotation(e,i.node,a)})),i}}]),t}(),S=function(){function t(e){a(this,t),this.w=e.w,this.annoCtx=e,this.helpers=new w(this.annoCtx)}return r(t,[{key:"addPointAnnotation",value:function(t,e,i){this.w;var a=this.helpers.getX1X2("x1",t),s=this.helpers.getY1Y2("y1",t);if(x.isNumber(a)){var r={pSize:t.marker.size,pointStrokeWidth:t.marker.strokeWidth,pointFillColor:t.marker.fillColor,pointStrokeColor:t.marker.strokeColor,shape:t.marker.shape,pRadius:t.marker.radius,class:"apexcharts-point-annotation-marker ".concat(t.marker.cssClass," ").concat(t.id?t.id:"")},o=this.annoCtx.graphics.drawMarker(a+t.marker.offsetX,s+t.marker.offsetY,r);e.appendChild(o.node);var n=t.label.text?t.label.text:"",l=this.annoCtx.graphics.drawText({x:a+t.label.offsetX,y:s+t.label.offsetY-t.marker.size-parseFloat(t.label.style.fontSize)/1.6,text:n,textAnchor:t.label.textAnchor,fontSize:t.label.style.fontSize,fontFamily:t.label.style.fontFamily,fontWeight:t.label.style.fontWeight,foreColor:t.label.style.color,cssClass:"apexcharts-point-annotation-label ".concat(t.label.style.cssClass," ").concat(t.id?t.id:"")});if(l.attr({rel:i}),e.appendChild(l.node),t.customSVG.SVG){var h=this.annoCtx.graphics.group({class:"apexcharts-point-annotations-custom-svg "+t.customSVG.cssClass});h.attr({transform:"translate(".concat(a+t.customSVG.offsetX,", ").concat(s+t.customSVG.offsetY,")")}),h.node.innerHTML=t.customSVG.SVG,e.appendChild(h.node)}if(t.image.path){var c=t.image.width?t.image.width:20,d=t.image.height?t.image.height:20;o=this.annoCtx.addImage({x:a+t.image.offsetX-c/2,y:s+t.image.offsetY-d/2,width:c,height:d,path:t.image.path,appendTo:".apexcharts-point-annotations"})}t.mouseEnter&&o.node.addEventListener("mouseenter",t.mouseEnter.bind(this,t)),t.mouseLeave&&o.node.addEventListener("mouseleave",t.mouseLeave.bind(this,t)),t.click&&o.node.addEventListener("click",t.click.bind(this,t))}}},{key:"drawPointAnnotations",value:function(){var t=this,e=this.w,i=this.annoCtx.graphics.group({class:"apexcharts-point-annotations"});return e.config.annotations.points.map((function(e,a){t.addPointAnnotation(e,i.node,a)})),i}}]),t}();var C={name:"en",options:{months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],toolbar:{exportToSVG:"Download SVG",exportToPNG:"Download PNG",exportToCSV:"Download CSV",menu:"Menu",selection:"Selection",selectionZoom:"Selection Zoom",zoomIn:"Zoom In",zoomOut:"Zoom Out",pan:"Panning",reset:"Reset Zoom"}}},L=function(){function t(){a(this,t),this.yAxis={show:!0,showAlways:!1,showForNullSeries:!0,seriesName:void 0,opposite:!1,reversed:!1,logarithmic:!1,logBase:10,tickAmount:void 0,forceNiceScale:!1,max:void 0,min:void 0,floating:!1,decimalsInFloat:void 0,labels:{show:!0,minWidth:0,maxWidth:160,offsetX:0,offsetY:0,align:void 0,rotate:0,padding:20,style:{colors:[],fontSize:"11px",fontWeight:400,fontFamily:void 0,cssClass:""},formatter:void 0},axisBorder:{show:!1,color:"#e0e0e0",width:1,offsetX:0,offsetY:0},axisTicks:{show:!1,color:"#e0e0e0",width:6,offsetX:0,offsetY:0},title:{text:void 0,rotate:-90,offsetY:0,offsetX:0,style:{color:void 0,fontSize:"11px",fontWeight:900,fontFamily:void 0,cssClass:""}},tooltip:{enabled:!1,offsetX:0},crosshairs:{show:!0,position:"front",stroke:{color:"#b6b6b6",width:1,dashArray:0}}},this.pointAnnotation={id:void 0,x:0,y:null,yAxisIndex:0,seriesIndex:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,marker:{size:4,fillColor:"#fff",strokeWidth:2,strokeColor:"#333",shape:"circle",offsetX:0,offsetY:0,radius:2,cssClass:""},label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}},customSVG:{SVG:void 0,cssClass:void 0,offsetX:0,offsetY:0},image:{path:void 0,width:20,height:20,offsetX:0,offsetY:0}},this.yAxisAnnotation={id:void 0,y:0,y2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,width:"100%",yAxisIndex:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"end",position:"right",offsetX:0,offsetY:-3,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.xAxisAnnotation={id:void 0,x:0,x2:null,strokeDashArray:1,fillColor:"#c2c2c2",borderColor:"#c2c2c2",borderWidth:1,opacity:.3,offsetX:0,offsetY:0,label:{borderColor:"#c2c2c2",borderWidth:1,borderRadius:2,text:void 0,textAnchor:"middle",orientation:"vertical",position:"top",offsetX:0,offsetY:0,mouseEnter:void 0,mouseLeave:void 0,click:void 0,style:{background:"#fff",color:void 0,fontSize:"11px",fontFamily:void 0,fontWeight:400,cssClass:"",padding:{left:5,right:5,top:2,bottom:2}}}},this.text={x:0,y:0,text:"",textAnchor:"start",foreColor:void 0,fontSize:"13px",fontFamily:void 0,fontWeight:400,appendTo:".apexcharts-annotations",backgroundColor:"transparent",borderColor:"#c2c2c2",borderRadius:0,borderWidth:0,paddingLeft:4,paddingRight:4,paddingTop:2,paddingBottom:2}}return r(t,[{key:"init",value:function(){return{annotations:{yaxis:[this.yAxisAnnotation],xaxis:[this.xAxisAnnotation],points:[this.pointAnnotation],texts:[],images:[],shapes:[]},chart:{animations:{enabled:!0,easing:"easeinout",speed:800,animateGradually:{delay:150,enabled:!0},dynamicAnimation:{enabled:!0,speed:350}},background:"transparent",locales:[C],defaultLocale:"en",dropShadow:{enabled:!1,enabledOnSeries:void 0,top:2,left:2,blur:4,color:"#000",opacity:.35},events:{animationEnd:void 0,beforeMount:void 0,mounted:void 0,updated:void 0,click:void 0,mouseMove:void 0,mouseLeave:void 0,xAxisLabelClick:void 0,legendClick:void 0,markerClick:void 0,selection:void 0,dataPointSelection:void 0,dataPointMouseEnter:void 0,dataPointMouseLeave:void 0,beforeZoom:void 0,beforeResetZoom:void 0,zoomed:void 0,scrolled:void 0,brushScrolled:void 0},foreColor:"#373d3f",fontFamily:"Helvetica, Arial, sans-serif",height:"auto",parentHeightOffset:15,redrawOnParentResize:!0,redrawOnWindowResize:!0,id:void 0,group:void 0,offsetX:0,offsetY:0,selection:{enabled:!1,type:"x",fill:{color:"#24292e",opacity:.1},stroke:{width:1,color:"#24292e",opacity:.4,dashArray:3},xaxis:{min:void 0,max:void 0},yaxis:{min:void 0,max:void 0}},sparkline:{enabled:!1},brush:{enabled:!1,autoScaleYaxis:!0,target:void 0},stacked:!1,stackType:"normal",toolbar:{show:!0,offsetX:0,offsetY:0,tools:{download:!0,selection:!0,zoom:!0,zoomin:!0,zoomout:!0,pan:!0,reset:!0,customIcons:[]},export:{csv:{filename:void 0,columnDelimiter:",",headerCategory:"category",headerValue:"value",dateFormatter:function(t){return new Date(t).toDateString()}},png:{filename:void 0},svg:{filename:void 0}},autoSelected:"zoom"},type:"line",width:"100%",zoom:{enabled:!0,type:"x",autoScaleYaxis:!1,zoomedArea:{fill:{color:"#90CAF9",opacity:.4},stroke:{color:"#0D47A1",opacity:.4,width:1}}}},plotOptions:{area:{fillTo:"origin"},bar:{horizontal:!1,columnWidth:"70%",barHeight:"70%",distributed:!1,borderRadius:0,borderRadiusApplication:"around",borderRadiusWhenStacked:"last",rangeBarOverlap:!0,rangeBarGroupRows:!1,hideZeroBarsWhenGrouped:!0,colors:{ranges:[],backgroundBarColors:[],backgroundBarOpacity:1,backgroundBarRadius:0},dataLabels:{position:"top",maxItems:100,hideOverflowingLabels:!0,orientation:"horizontal",total:{enabled:!1,formatter:void 0,offsetX:0,offsetY:0,style:{color:"#373d3f",fontSize:"12px",fontFamily:void 0,fontWeight:600}}}},bubble:{zScaling:!0,minBubbleRadius:void 0,maxBubbleRadius:void 0},candlestick:{colors:{upward:"#00B746",downward:"#EF403C"},wick:{useFillColor:!0}},boxPlot:{colors:{upper:"#00E396",lower:"#008FFB"}},heatmap:{radius:2,enableShades:!0,shadeIntensity:.5,reverseNegativeShade:!1,distributed:!1,useFillColorAsStroke:!1,colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0}},treemap:{enableShades:!0,shadeIntensity:.5,distributed:!1,reverseNegativeShade:!1,useFillColorAsStroke:!1,colorScale:{inverse:!1,ranges:[],min:void 0,max:void 0}},radialBar:{inverseOrder:!1,startAngle:0,endAngle:360,offsetX:0,offsetY:0,hollow:{margin:5,size:"50%",background:"transparent",image:void 0,imageWidth:150,imageHeight:150,imageOffsetX:0,imageOffsetY:0,imageClipped:!0,position:"front",dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},track:{show:!0,startAngle:void 0,endAngle:void 0,background:"#f2f2f2",strokeWidth:"97%",opacity:1,margin:5,dropShadow:{enabled:!1,top:0,left:0,blur:3,color:"#000",opacity:.5}},dataLabels:{show:!0,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:0,formatter:function(t){return t}},value:{show:!0,fontSize:"14px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:16,formatter:function(t){return t+"%"}},total:{show:!1,label:"Total",fontSize:"16px",fontWeight:600,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)/t.globals.series.length+"%"}}}},pie:{customScale:1,offsetX:0,offsetY:0,startAngle:0,endAngle:360,expandOnClick:!0,dataLabels:{offset:0,minAngleToShowLabel:10},donut:{size:"65%",background:"transparent",labels:{show:!1,name:{show:!0,fontSize:"16px",fontFamily:void 0,fontWeight:600,color:void 0,offsetY:-10,formatter:function(t){return t}},value:{show:!0,fontSize:"20px",fontFamily:void 0,fontWeight:400,color:void 0,offsetY:10,formatter:function(t){return t}},total:{show:!1,showAlways:!1,label:"Total",fontSize:"16px",fontWeight:400,fontFamily:void 0,color:void 0,formatter:function(t){return t.globals.seriesTotals.reduce((function(t,e){return t+e}),0)}}}}},polarArea:{rings:{strokeWidth:1,strokeColor:"#e8e8e8"},spokes:{strokeWidth:1,connectorColors:"#e8e8e8"}},radar:{size:void 0,offsetX:0,offsetY:0,polygons:{strokeWidth:1,strokeColors:"#e8e8e8",connectorColors:"#e8e8e8",fill:{colors:void 0}}}},colors:void 0,dataLabels:{enabled:!0,enabledOnSeries:void 0,formatter:function(t){return null!==t?t:""},textAnchor:"middle",distributed:!1,offsetX:0,offsetY:0,style:{fontSize:"12px",fontFamily:void 0,fontWeight:600,colors:void 0},background:{enabled:!0,foreColor:"#fff",borderRadius:2,padding:4,opacity:.9,borderWidth:1,borderColor:"#fff",dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.45}},dropShadow:{enabled:!1,top:1,left:1,blur:1,color:"#000",opacity:.45}},fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]},image:{src:[],width:void 0,height:void 0},pattern:{style:"squares",width:6,height:6,strokeWidth:2}},forecastDataPoints:{count:0,fillOpacity:.5,strokeWidth:void 0,dashArray:4},grid:{show:!0,borderColor:"#e0e0e0",strokeDashArray:0,position:"back",xaxis:{lines:{show:!1}},yaxis:{lines:{show:!0}},row:{colors:void 0,opacity:.5},column:{colors:void 0,opacity:.5},padding:{top:0,right:10,bottom:0,left:12}},labels:[],legend:{show:!0,showForSingleSeries:!1,showForNullSeries:!0,showForZeroSeries:!0,floating:!1,position:"bottom",horizontalAlign:"center",inverseOrder:!1,fontSize:"12px",fontFamily:void 0,fontWeight:400,width:void 0,height:void 0,formatter:void 0,tooltipHoverFormatter:void 0,offsetX:-20,offsetY:4,customLegendItems:[],labels:{colors:void 0,useSeriesColors:!1},markers:{width:12,height:12,strokeWidth:0,fillColors:void 0,strokeColor:"#fff",radius:12,customHTML:void 0,offsetX:0,offsetY:0,onClick:void 0},itemMargin:{horizontal:5,vertical:2},onItemClick:{toggleDataSeries:!0},onItemHover:{highlightDataSeries:!0}},markers:{discrete:[],size:0,colors:void 0,strokeColors:"#fff",strokeWidth:2,strokeOpacity:.9,strokeDashArray:0,fillOpacity:1,shape:"circle",width:8,height:8,radius:2,offsetX:0,offsetY:0,onClick:void 0,onDblClick:void 0,showNullDataPoints:!0,hover:{size:void 0,sizeOffset:3}},noData:{text:void 0,align:"center",verticalAlign:"middle",offsetX:0,offsetY:0,style:{color:void 0,fontSize:"14px",fontFamily:void 0}},responsive:[],series:void 0,states:{normal:{filter:{type:"none",value:0}},hover:{filter:{type:"lighten",value:.1}},active:{allowMultipleDataPointsSelection:!1,filter:{type:"darken",value:.5}}},title:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:0,floating:!1,style:{fontSize:"14px",fontWeight:900,fontFamily:void 0,color:void 0}},subtitle:{text:void 0,align:"left",margin:5,offsetX:0,offsetY:30,floating:!1,style:{fontSize:"12px",fontWeight:400,fontFamily:void 0,color:void 0}},stroke:{show:!0,curve:"smooth",lineCap:"butt",width:2,colors:void 0,dashArray:0,fill:{type:"solid",colors:void 0,opacity:.85,gradient:{shade:"dark",type:"horizontal",shadeIntensity:.5,gradientToColors:void 0,inverseColors:!0,opacityFrom:1,opacityTo:1,stops:[0,50,100],colorStops:[]}}},tooltip:{enabled:!0,enabledOnSeries:void 0,shared:!0,followCursor:!1,intersect:!1,inverseOrder:!1,custom:void 0,fillSeriesColor:!1,theme:"light",cssClass:"",style:{fontSize:"12px",fontFamily:void 0},onDatasetHover:{highlightDataSeries:!1},x:{show:!0,format:"dd MMM",formatter:void 0},y:{formatter:void 0,title:{formatter:function(t){return t?t+": ":""}}},z:{formatter:void 0,title:"Size: "},marker:{show:!0,fillColors:void 0},items:{display:"flex"},fixed:{enabled:!1,position:"topRight",offsetX:0,offsetY:0}},xaxis:{type:"category",categories:[],convertedCatToNumeric:!1,offsetX:0,offsetY:0,overwriteCategories:void 0,labels:{show:!0,rotate:-45,rotateAlways:!1,hideOverlappingLabels:!0,trim:!1,minHeight:void 0,maxHeight:120,showDuplicates:!0,style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""},offsetX:0,offsetY:0,format:void 0,formatter:void 0,datetimeUTC:!0,datetimeFormatter:{year:"yyyy",month:"MMM 'yy",day:"dd MMM",hour:"HH:mm",minute:"HH:mm:ss",second:"HH:mm:ss"}},group:{groups:[],style:{colors:[],fontSize:"12px",fontWeight:400,fontFamily:void 0,cssClass:""}},axisBorder:{show:!0,color:"#e0e0e0",width:"100%",height:1,offsetX:0,offsetY:0},axisTicks:{show:!0,color:"#e0e0e0",height:6,offsetX:0,offsetY:0},tickAmount:void 0,tickPlacement:"on",min:void 0,max:void 0,range:void 0,floating:!1,decimalsInFloat:void 0,position:"bottom",title:{text:void 0,offsetX:0,offsetY:0,style:{color:void 0,fontSize:"12px",fontWeight:900,fontFamily:void 0,cssClass:""}},crosshairs:{show:!0,width:1,position:"back",opacity:.9,stroke:{color:"#b6b6b6",width:1,dashArray:3},fill:{type:"solid",color:"#B1B9C4",gradient:{colorFrom:"#D8E3F0",colorTo:"#BED1E6",stops:[0,100],opacityFrom:.4,opacityTo:.5}},dropShadow:{enabled:!1,left:0,top:0,blur:1,opacity:.4}},tooltip:{enabled:!0,offsetY:0,formatter:void 0,style:{fontSize:"12px",fontFamily:void 0}}},yaxis:this.yAxis,theme:{mode:"light",palette:"palette1",monochrome:{enabled:!1,color:"#008FFB",shadeTo:"light",shadeIntensity:.65}}}}}]),t}(),P=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.graphics=new m(this.ctx),this.w.globals.isBarHorizontal&&(this.invertAxis=!0),this.helpers=new w(this),this.xAxisAnnotations=new k(this),this.yAxisAnnotations=new A(this),this.pointsAnnotations=new S(this),this.w.globals.isBarHorizontal&&this.w.config.yaxis[0].reversed&&(this.inversedReversedAxis=!0),this.xDivision=this.w.globals.gridWidth/this.w.globals.dataPoints}return r(t,[{key:"drawAxesAnnotations",value:function(){var t=this.w;if(t.globals.axisCharts){for(var e=this.yAxisAnnotations.drawYAxisAnnotations(),i=this.xAxisAnnotations.drawXAxisAnnotations(),a=this.pointsAnnotations.drawPointAnnotations(),s=t.config.chart.animations.enabled,r=[e,i,a],o=[i.node,e.node,a.node],n=0;n<3;n++)t.globals.dom.elGraphical.add(r[n]),!s||t.globals.resized||t.globals.dataChanged||"scatter"!==t.config.chart.type&&"bubble"!==t.config.chart.type&&t.globals.dataPoints>1&&o[n].classList.add("apexcharts-element-hidden"),t.globals.delayedElements.push({el:o[n],index:0});this.helpers.annotationsBackground()}}},{key:"drawImageAnnos",value:function(){var t=this;this.w.config.annotations.images.map((function(e,i){t.addImage(e,i)}))}},{key:"drawTextAnnos",value:function(){var t=this;this.w.config.annotations.texts.map((function(e,i){t.addText(e,i)}))}},{key:"addXaxisAnnotation",value:function(t,e,i){this.xAxisAnnotations.addXaxisAnnotation(t,e,i)}},{key:"addYaxisAnnotation",value:function(t,e,i){this.yAxisAnnotations.addYaxisAnnotation(t,e,i)}},{key:"addPointAnnotation",value:function(t,e,i){this.pointsAnnotations.addPointAnnotation(t,e,i)}},{key:"addText",value:function(t,e){var i=t.x,a=t.y,s=t.text,r=t.textAnchor,o=t.foreColor,n=t.fontSize,l=t.fontFamily,h=t.fontWeight,c=t.cssClass,d=t.backgroundColor,g=t.borderWidth,u=t.strokeDashArray,f=t.borderRadius,p=t.borderColor,x=t.appendTo,b=void 0===x?".apexcharts-annotations":x,v=t.paddingLeft,m=void 0===v?4:v,y=t.paddingRight,w=void 0===y?4:y,k=t.paddingBottom,A=void 0===k?2:k,S=t.paddingTop,C=void 0===S?2:S,L=this.w,P=this.graphics.drawText({x:i,y:a,text:s,textAnchor:r||"start",fontSize:n||"12px",fontWeight:h||"regular",fontFamily:l||L.config.chart.fontFamily,foreColor:o||L.config.chart.foreColor,cssClass:c}),T=L.globals.dom.baseEl.querySelector(b);T&&T.appendChild(P.node);var M=P.bbox();if(s){var I=this.graphics.drawRect(M.x-m,M.y-C,M.width+m+w,M.height+A+C,f,d||"transparent",1,g,p,u);T.insertBefore(I.node,P.node)}}},{key:"addImage",value:function(t,e){var i=this.w,a=t.path,s=t.x,r=void 0===s?0:s,o=t.y,n=void 0===o?0:o,l=t.width,h=void 0===l?20:l,c=t.height,d=void 0===c?20:c,g=t.appendTo,u=void 0===g?".apexcharts-annotations":g,f=i.globals.dom.Paper.image(a);f.size(h,d).move(r,n);var p=i.globals.dom.baseEl.querySelector(u);return p&&p.appendChild(f.node),f}},{key:"addXaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"xaxis",contextMethod:i.addXaxisAnnotation}),i}},{key:"addYaxisAnnotationExternal",value:function(t,e,i){return this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"yaxis",contextMethod:i.addYaxisAnnotation}),i}},{key:"addPointAnnotationExternal",value:function(t,e,i){return void 0===this.invertAxis&&(this.invertAxis=i.w.globals.isBarHorizontal),this.addAnnotationExternal({params:t,pushToMemory:e,context:i,type:"point",contextMethod:i.addPointAnnotation}),i}},{key:"addAnnotationExternal",value:function(t){var e=t.params,i=t.pushToMemory,a=t.context,s=t.type,r=t.contextMethod,o=a,n=o.w,l=n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations")),h=l.childNodes.length+1,c=new L,d=Object.assign({},"xaxis"===s?c.xAxisAnnotation:"yaxis"===s?c.yAxisAnnotation:c.pointAnnotation),g=x.extend(d,e);switch(s){case"xaxis":this.addXaxisAnnotation(g,l,h);break;case"yaxis":this.addYaxisAnnotation(g,l,h);break;case"point":this.addPointAnnotation(g,l,h)}var u=n.globals.dom.baseEl.querySelector(".apexcharts-".concat(s,"-annotations .apexcharts-").concat(s,"-annotation-label[rel='").concat(h,"']")),f=this.helpers.addBackgroundToAnno(u,g);return f&&l.insertBefore(f.node,u),i&&n.globals.memory.methodsToExec.push({context:o,id:g.id?g.id:x.randomId(),method:r,label:"addAnnotation",params:e}),a}},{key:"clearAnnotations",value:function(t){var e=t.w,i=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations");e.globals.memory.methodsToExec.map((function(t,i){"addText"!==t.label&&"addAnnotation"!==t.label||e.globals.memory.methodsToExec.splice(i,1)})),i=x.listToArray(i),Array.prototype.forEach.call(i,(function(t){for(;t.firstChild;)t.removeChild(t.firstChild)}))}},{key:"removeAnnotation",value:function(t,e){var i=t.w,a=i.globals.dom.baseEl.querySelectorAll(".".concat(e));a&&(i.globals.memory.methodsToExec.map((function(t,a){t.id===e&&i.globals.memory.methodsToExec.splice(a,1)})),Array.prototype.forEach.call(a,(function(t){t.parentElement.removeChild(t)})))}}]),t}(),T=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.months31=[1,3,5,7,8,10,12],this.months30=[2,4,6,9,11],this.daysCntOfYear=[0,31,59,90,120,151,181,212,243,273,304,334]}return r(t,[{key:"isValidDate",value:function(t){return!isNaN(this.parseDate(t))}},{key:"getTimeStamp",value:function(t){return Date.parse(t)?this.w.config.xaxis.labels.datetimeUTC?new Date(new Date(t).toISOString().substr(0,25)).getTime():new Date(t).getTime():t}},{key:"getDate",value:function(t){return this.w.config.xaxis.labels.datetimeUTC?new Date(new Date(t).toUTCString()):new Date(t)}},{key:"parseDate",value:function(t){var e=Date.parse(t);if(!isNaN(e))return this.getTimeStamp(t);var i=Date.parse(t.replace(/-/g,"/").replace(/[a-z]+/gi," "));return i=this.getTimeStamp(i)}},{key:"parseDateWithTimezone",value:function(t){return Date.parse(t.replace(/-/g,"/").replace(/[a-z]+/gi," "))}},{key:"formatDate",value:function(t,e){var i=this.w.globals.locale,a=this.w.config.xaxis.labels.datetimeUTC,s=["\0"].concat(u(i.months)),r=["\x01"].concat(u(i.shortMonths)),o=["\x02"].concat(u(i.days)),n=["\x03"].concat(u(i.shortDays));function l(t,e){var i=t+"";for(e=e||2;i.length12?g-12:0===g?12:g;e=(e=(e=(e=e.replace(/(^|[^\\])HH+/g,"$1"+l(g))).replace(/(^|[^\\])H/g,"$1"+g)).replace(/(^|[^\\])hh+/g,"$1"+l(f))).replace(/(^|[^\\])h/g,"$1"+f);var p=a?t.getUTCMinutes():t.getMinutes();e=(e=e.replace(/(^|[^\\])mm+/g,"$1"+l(p))).replace(/(^|[^\\])m/g,"$1"+p);var x=a?t.getUTCSeconds():t.getSeconds();e=(e=e.replace(/(^|[^\\])ss+/g,"$1"+l(x))).replace(/(^|[^\\])s/g,"$1"+x);var b=a?t.getUTCMilliseconds():t.getMilliseconds();e=e.replace(/(^|[^\\])fff+/g,"$1"+l(b,3)),b=Math.round(b/10),e=e.replace(/(^|[^\\])ff/g,"$1"+l(b)),b=Math.round(b/10);var v=g<12?"AM":"PM";e=(e=(e=e.replace(/(^|[^\\])f/g,"$1"+b)).replace(/(^|[^\\])TT+/g,"$1"+v)).replace(/(^|[^\\])T/g,"$1"+v.charAt(0));var m=v.toLowerCase();e=(e=e.replace(/(^|[^\\])tt+/g,"$1"+m)).replace(/(^|[^\\])t/g,"$1"+m.charAt(0));var y=-t.getTimezoneOffset(),w=a||!y?"Z":y>0?"+":"-";if(!a){var k=(y=Math.abs(y))%60;w+=l(Math.floor(y/60))+":"+l(k)}e=e.replace(/(^|[^\\])K/g,"$1"+w);var A=(a?t.getUTCDay():t.getDay())+1;return e=(e=(e=(e=(e=e.replace(new RegExp(o[0],"g"),o[A])).replace(new RegExp(n[0],"g"),n[A])).replace(new RegExp(s[0],"g"),s[c])).replace(new RegExp(r[0],"g"),r[c])).replace(/\\(.)/g,"$1")}},{key:"getTimeUnitsfromTimestamp",value:function(t,e,i){var a=this.w;void 0!==a.config.xaxis.min&&(t=a.config.xaxis.min),void 0!==a.config.xaxis.max&&(e=a.config.xaxis.max);var s=this.getDate(t),r=this.getDate(e),o=this.formatDate(s,"yyyy MM dd HH mm ss fff").split(" "),n=this.formatDate(r,"yyyy MM dd HH mm ss fff").split(" ");return{minMillisecond:parseInt(o[6],10),maxMillisecond:parseInt(n[6],10),minSecond:parseInt(o[5],10),maxSecond:parseInt(n[5],10),minMinute:parseInt(o[4],10),maxMinute:parseInt(n[4],10),minHour:parseInt(o[3],10),maxHour:parseInt(n[3],10),minDate:parseInt(o[2],10),maxDate:parseInt(n[2],10),minMonth:parseInt(o[1],10)-1,maxMonth:parseInt(n[1],10)-1,minYear:parseInt(o[0],10),maxYear:parseInt(n[0],10)}}},{key:"isLeapYear",value:function(t){return t%4==0&&t%100!=0||t%400==0}},{key:"calculcateLastDaysOfMonth",value:function(t,e,i){return this.determineDaysOfMonths(t,e)-i}},{key:"determineDaysOfYear",value:function(t){var e=365;return this.isLeapYear(t)&&(e=366),e}},{key:"determineRemainingDaysOfYear",value:function(t,e,i){var a=this.daysCntOfYear[e]+i;return e>1&&this.isLeapYear()&&a++,a}},{key:"determineDaysOfMonths",value:function(t,e){var i=30;switch(t=x.monthMod(t),!0){case this.months30.indexOf(t)>-1:2===t&&(i=this.isLeapYear(e)?29:28);break;case this.months31.indexOf(t)>-1:default:i=31}return i}}]),t}(),M=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.tooltipKeyFormat="dd MMM"}return r(t,[{key:"xLabelFormat",value:function(t,e,i,a){var s=this.w;if("datetime"===s.config.xaxis.type&&void 0===s.config.xaxis.labels.formatter&&void 0===s.config.tooltip.x.formatter){var r=new T(this.ctx);return r.formatDate(r.getDate(e),s.config.tooltip.x.format)}return t(e,i,a)}},{key:"defaultGeneralFormatter",value:function(t){return Array.isArray(t)?t.map((function(t){return t})):t}},{key:"defaultYFormatter",value:function(t,e,i){var a=this.w;return x.isNumber(t)&&(t=0!==a.globals.yValueDecimal?t.toFixed(void 0!==e.decimalsInFloat?e.decimalsInFloat:a.globals.yValueDecimal):a.globals.maxYArr[i]-a.globals.minYArr[i]<5?t.toFixed(1):t.toFixed(0)),t}},{key:"setLabelFormatters",value:function(){var t=this,e=this.w;return e.globals.xaxisTooltipFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttKeyFormatter=function(e){return t.defaultGeneralFormatter(e)},e.globals.ttZFormatter=function(t){return t},e.globals.legendFormatter=function(e){return t.defaultGeneralFormatter(e)},void 0!==e.config.xaxis.labels.formatter?e.globals.xLabelFormatter=e.config.xaxis.labels.formatter:e.globals.xLabelFormatter=function(t){if(x.isNumber(t)){if(!e.config.xaxis.convertedCatToNumeric&&"numeric"===e.config.xaxis.type){if(x.isNumber(e.config.xaxis.decimalsInFloat))return t.toFixed(e.config.xaxis.decimalsInFloat);var i=e.globals.maxX-e.globals.minX;return i>0&&i<100?t.toFixed(1):t.toFixed(0)}if(e.globals.isBarHorizontal)if(e.globals.maxY-e.globals.minYArr<4)return t.toFixed(1);return t.toFixed(0)}return t},"function"==typeof e.config.tooltip.x.formatter?e.globals.ttKeyFormatter=e.config.tooltip.x.formatter:e.globals.ttKeyFormatter=e.globals.xLabelFormatter,"function"==typeof e.config.xaxis.tooltip.formatter&&(e.globals.xaxisTooltipFormatter=e.config.xaxis.tooltip.formatter),(Array.isArray(e.config.tooltip.y)||void 0!==e.config.tooltip.y.formatter)&&(e.globals.ttVal=e.config.tooltip.y),void 0!==e.config.tooltip.z.formatter&&(e.globals.ttZFormatter=e.config.tooltip.z.formatter),void 0!==e.config.legend.formatter&&(e.globals.legendFormatter=e.config.legend.formatter),e.config.yaxis.forEach((function(i,a){void 0!==i.labels.formatter?e.globals.yLabelFormatters[a]=i.labels.formatter:e.globals.yLabelFormatters[a]=function(s){return e.globals.xyCharts?Array.isArray(s)?s.map((function(e){return t.defaultYFormatter(e,i,a)})):t.defaultYFormatter(s,i,a):s}})),e.globals}},{key:"heatmapLabelFormatters",value:function(){var t=this.w;if("heatmap"===t.config.chart.type){t.globals.yAxisScale[0].result=t.globals.seriesNames.slice();var e=t.globals.seriesNames.reduce((function(t,e){return t.length>e.length?t:e}),0);t.globals.yAxisScale[0].niceMax=e,t.globals.yAxisScale[0].niceMin=e}}}]),t}(),I=function(t){var e,i=t.isTimeline,a=t.ctx,s=t.seriesIndex,r=t.dataPointIndex,o=t.y1,n=t.y2,l=t.w,h=l.globals.seriesRangeStart[s][r],c=l.globals.seriesRangeEnd[s][r],d=l.globals.labels[r],g=l.config.series[s].name?l.config.series[s].name:"",u=l.globals.ttKeyFormatter,f=l.config.tooltip.y.title.formatter,p={w:l,seriesIndex:s,dataPointIndex:r,start:h,end:c};("function"==typeof f&&(g=f(g,p)),null!==(e=l.config.series[s].data[r])&&void 0!==e&&e.x&&(d=l.config.series[s].data[r].x),i)||"datetime"===l.config.xaxis.type&&(d=new M(a).xLabelFormat(l.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new T(a).formatDate,w:l}));"function"==typeof u&&(d=u(d,p)),Number.isFinite(o)&&Number.isFinite(n)&&(h=o,c=n);var x="",b="",v=l.globals.colors[s];if(void 0===l.config.tooltip.x.formatter)if("datetime"===l.config.xaxis.type){var m=new T(a);x=m.formatDate(m.getDate(h),l.config.tooltip.x.format),b=m.formatDate(m.getDate(c),l.config.tooltip.x.format)}else x=h,b=c;else x=l.config.tooltip.x.formatter(h),b=l.config.tooltip.x.formatter(c);return{start:h,end:c,startVal:x,endVal:b,ylabel:d,color:v,seriesName:g}},z=function(t){var e=t.color,i=t.seriesName,a=t.ylabel,s=t.start,r=t.end,o=t.seriesIndex,n=t.dataPointIndex,l=t.ctx.tooltip.tooltipLabels.getFormatters(o);s=l.yLbFormatter(s),r=l.yLbFormatter(r);var h=l.yLbFormatter(t.w.globals.series[o][n]),c='\n '.concat(s,'\n - \n ').concat(r,"\n ");return'
    '+(i||"")+'
    '+a+": "+(t.w.globals.comboCharts?"rangeArea"===t.w.config.series[o].type||"rangeBar"===t.w.config.series[o].type?c:"".concat(h,""):c)+"
    "},X=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"line",value:function(){return{chart:{animations:{easing:"swing"}},dataLabels:{enabled:!1},stroke:{width:5,curve:"straight"},markers:{size:0,hover:{sizeOffset:6}},xaxis:{crosshairs:{width:1}}}}},{key:"sparkline",value:function(t){this.opts.yaxis[0].show=!1,this.opts.yaxis[0].title.text="",this.opts.yaxis[0].axisBorder.show=!1,this.opts.yaxis[0].axisTicks.show=!1,this.opts.yaxis[0].floating=!0;return x.extend(t,{grid:{show:!1,padding:{left:0,right:0,top:0,bottom:0}},legend:{show:!1},xaxis:{labels:{show:!1},tooltip:{enabled:!1},axisBorder:{show:!1},axisTicks:{show:!1}},chart:{toolbar:{show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1}})}},{key:"bar",value:function(){return{chart:{stacked:!1,animations:{easing:"swing"}},plotOptions:{bar:{dataLabels:{position:"center"}}},dataLabels:{style:{colors:["#fff"]},background:{enabled:!1}},stroke:{width:0,lineCap:"round"},fill:{opacity:.85},legend:{markers:{shape:"square",radius:2,size:8}},tooltip:{shared:!1,intersect:!0},xaxis:{tooltip:{enabled:!1},tickPlacement:"between",crosshairs:{width:"barWidth",position:"back",fill:{type:"gradient"},dropShadow:{enabled:!1},stroke:{width:0}}}}}},{key:"candlestick",value:function(){var t=this;return{stroke:{width:1,colors:["#333"]},fill:{opacity:1},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Open","High","","Low","Close"],"candlestick")}},states:{active:{filter:{type:"none"}}},xaxis:{crosshairs:{width:1}}}}},{key:"boxPlot",value:function(){var t=this;return{chart:{animations:{dynamicAnimation:{enabled:!1}}},stroke:{width:1,colors:["#24292e"]},dataLabels:{enabled:!1},tooltip:{shared:!0,custom:function(e){var i=e.seriesIndex,a=e.dataPointIndex,s=e.w;return t._getBoxTooltip(s,i,a,["Minimum","Q1","Median","Q3","Maximum"],"boxPlot")}},markers:{size:5,strokeWidth:1,strokeColors:"#111"},xaxis:{crosshairs:{width:1}}}}},{key:"rangeBar",value:function(){return{stroke:{width:0,lineCap:"square"},plotOptions:{bar:{borderRadius:0,dataLabels:{position:"center"}}},dataLabels:{enabled:!1,formatter:function(t,e){e.ctx;var i=e.seriesIndex,a=e.dataPointIndex,s=e.w,r=function(){var t=s.globals.seriesRangeStart[i][a];return s.globals.seriesRangeEnd[i][a]-t};return s.globals.comboCharts?"rangeBar"===s.config.series[i].type||"rangeArea"===s.config.series[i].type?r():t:r()},background:{enabled:!1},style:{colors:["#fff"]}},tooltip:{shared:!1,followCursor:!0,custom:function(t){return t.w.config.plotOptions&&t.w.config.plotOptions.bar&&t.w.config.plotOptions.bar.horizontal?function(t){var i=I(e(e({},t),{},{isTimeline:!0})),a=i.color,s=i.seriesName,r=i.ylabel,o=i.startVal,n=i.endVal;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t):function(t){var i=I(t),a=i.color,s=i.seriesName,r=i.ylabel,o=i.start,n=i.end;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t)}},xaxis:{tickPlacement:"between",tooltip:{enabled:!1},crosshairs:{stroke:{width:0}}}}}},{key:"area",value:function(){return{stroke:{width:4,fill:{type:"solid",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}}},fill:{type:"gradient",gradient:{inverseColors:!1,shade:"light",type:"vertical",opacityFrom:.65,opacityTo:.5,stops:[0,100,100]}},markers:{size:0,hover:{sizeOffset:6}},tooltip:{followCursor:!1}}}},{key:"rangeArea",value:function(){return{stroke:{curve:"straight",width:0},fill:{type:"solid",opacity:.6},markers:{size:0},states:{hover:{filter:{type:"none"}},active:{filter:{type:"none"}}},tooltip:{intersect:!1,shared:!0,followCursor:!0,custom:function(t){return function(t){var i=I(t),a=i.color,s=i.seriesName,r=i.ylabel,o=i.start,n=i.end;return z(e(e({},t),{},{color:a,seriesName:s,ylabel:r,start:o,end:n}))}(t)}}}}},{key:"brush",value:function(t){return x.extend(t,{chart:{toolbar:{autoSelected:"selection",show:!1},zoom:{enabled:!1}},dataLabels:{enabled:!1},stroke:{width:1},tooltip:{enabled:!1},xaxis:{tooltip:{enabled:!1}}})}},{key:"stacked100",value:function(t){t.dataLabels=t.dataLabels||{},t.dataLabels.formatter=t.dataLabels.formatter||void 0;var e=t.dataLabels.formatter;return t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})),"bar"===t.chart.type&&(t.dataLabels.formatter=e||function(t){return"number"==typeof t&&t?t.toFixed(0)+"%":t}),t}},{key:"stackedBars",value:function(){var t=this.bar();return e(e({},t),{},{plotOptions:e(e({},t.plotOptions),{},{bar:e(e({},t.plotOptions.bar),{},{borderRadiusApplication:"end",borderRadiusWhenStacked:"last"})})})}},{key:"convertCatToNumeric",value:function(t){return t.xaxis.convertedCatToNumeric=!0,t}},{key:"convertCatToNumericXaxis",value:function(t,e,i){t.xaxis.type="numeric",t.xaxis.labels=t.xaxis.labels||{},t.xaxis.labels.formatter=t.xaxis.labels.formatter||function(t){return x.isNumber(t)?Math.floor(t):t};var a=t.xaxis.labels.formatter,s=t.xaxis.categories&&t.xaxis.categories.length?t.xaxis.categories:t.labels;return i&&i.length&&(s=i.map((function(t){return Array.isArray(t)?t:String(t)}))),s&&s.length&&(t.xaxis.labels.formatter=function(t){return x.isNumber(t)?a(s[Math.floor(t)-1]):a(t)}),t.xaxis.categories=[],t.labels=[],t.xaxis.tickAmount=t.xaxis.tickAmount||"dataPoints",t}},{key:"bubble",value:function(){return{dataLabels:{style:{colors:["#fff"]}},tooltip:{shared:!1,intersect:!0},xaxis:{crosshairs:{width:0}},fill:{type:"solid",gradient:{shade:"light",inverse:!0,shadeIntensity:.55,opacityFrom:.4,opacityTo:.8}}}}},{key:"scatter",value:function(){return{dataLabels:{enabled:!1},tooltip:{shared:!1,intersect:!0},markers:{size:6,strokeWidth:1,hover:{sizeOffset:2}}}}},{key:"heatmap",value:function(){return{chart:{stacked:!1},fill:{opacity:1},dataLabels:{style:{colors:["#fff"]}},stroke:{colors:["#fff"]},tooltip:{followCursor:!0,marker:{show:!1},x:{show:!1}},legend:{position:"top",markers:{shape:"square",size:10,offsetY:2}},grid:{padding:{right:20}}}}},{key:"treemap",value:function(){return{chart:{zoom:{enabled:!1}},dataLabels:{style:{fontSize:14,fontWeight:600,colors:["#fff"]}},stroke:{show:!0,width:2,colors:["#fff"]},legend:{show:!1},fill:{gradient:{stops:[0,100]}},tooltip:{followCursor:!0,x:{show:!1}},grid:{padding:{left:0,right:0}},xaxis:{crosshairs:{show:!1},tooltip:{enabled:!1}}}}},{key:"pie",value:function(){return{chart:{toolbar:{show:!1}},plotOptions:{pie:{donut:{labels:{show:!1}}}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",stops:[0,100]}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"donut",value:function(){return{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},style:{colors:["#fff"]},background:{enabled:!1},dropShadow:{enabled:!0}},stroke:{colors:["#fff"]},fill:{opacity:1,gradient:{shade:"light",shadeIntensity:.35,stops:[80,100],opacityFrom:1,opacityTo:1}},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"polarArea",value:function(){return this.opts.yaxis[0].tickAmount=this.opts.yaxis[0].tickAmount?this.opts.yaxis[0].tickAmount:6,{chart:{toolbar:{show:!1}},dataLabels:{formatter:function(t){return t.toFixed(1)+"%"},enabled:!1},stroke:{show:!0,width:2},fill:{opacity:.7},tooltip:{theme:"dark",fillSeriesColor:!0},legend:{position:"right"}}}},{key:"radar",value:function(){return this.opts.yaxis[0].labels.offsetY=this.opts.yaxis[0].labels.offsetY?this.opts.yaxis[0].labels.offsetY:6,{dataLabels:{enabled:!1,style:{fontSize:"11px"}},stroke:{width:2},markers:{size:3,strokeWidth:1,strokeOpacity:1},fill:{opacity:.2},tooltip:{shared:!1,intersect:!0,followCursor:!0},grid:{show:!1},xaxis:{labels:{formatter:function(t){return t},style:{colors:["#a8a8a8"],fontSize:"11px"}},tooltip:{enabled:!1},crosshairs:{show:!1}}}}},{key:"radialBar",value:function(){return{chart:{animations:{dynamicAnimation:{enabled:!0,speed:800}},toolbar:{show:!1}},fill:{gradient:{shade:"dark",shadeIntensity:.4,inverseColors:!1,type:"diagonal2",opacityFrom:1,opacityTo:1,stops:[70,98,100]}},legend:{show:!1,position:"right"},tooltip:{enabled:!1,fillSeriesColor:!0}}}},{key:"_getBoxTooltip",value:function(t,e,i,a,s){var r=t.globals.seriesCandleO[e][i],o=t.globals.seriesCandleH[e][i],n=t.globals.seriesCandleM[e][i],l=t.globals.seriesCandleL[e][i],h=t.globals.seriesCandleC[e][i];return t.config.series[e].type&&t.config.series[e].type!==s?'
    \n '.concat(t.config.series[e].name?t.config.series[e].name:"series-"+(e+1),": ").concat(t.globals.series[e][i],"\n
    "):'
    ')+"
    ".concat(a[0],': ')+r+"
    "+"
    ".concat(a[1],': ')+o+"
    "+(n?"
    ".concat(a[2],': ')+n+"
    ":"")+"
    ".concat(a[3],': ')+l+"
    "+"
    ".concat(a[4],': ')+h+"
    "}}]),t}(),E=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"init",value:function(t){var e=t.responsiveOverride,a=this.opts,s=new L,r=new X(a);this.chartType=a.chart.type,a=this.extendYAxis(a),a=this.extendAnnotations(a);var o=s.init(),n={};if(a&&"object"===i(a)){var l={};l=-1!==["line","area","bar","candlestick","boxPlot","rangeBar","rangeArea","bubble","scatter","heatmap","treemap","pie","polarArea","donut","radar","radialBar"].indexOf(a.chart.type)?r[a.chart.type]():r.line(),a.chart.stacked&&"bar"===a.chart.type&&(l=r.stackedBars()),a.chart.brush&&a.chart.brush.enabled&&(l=r.brush(l)),a.chart.stacked&&"100%"===a.chart.stackType&&(a=r.stacked100(a)),this.checkForDarkTheme(window.Apex),this.checkForDarkTheme(a),a.xaxis=a.xaxis||window.Apex.xaxis||{},e||(a.xaxis.convertedCatToNumeric=!1),((a=this.checkForCatToNumericXAxis(this.chartType,l,a)).chart.sparkline&&a.chart.sparkline.enabled||window.Apex.chart&&window.Apex.chart.sparkline&&window.Apex.chart.sparkline.enabled)&&(l=r.sparkline(l)),n=x.extend(o,l)}var h=x.extend(n,window.Apex);return o=x.extend(h,a),o=this.handleUserInputErrors(o)}},{key:"checkForCatToNumericXAxis",value:function(t,e,i){var a=new X(i),s=("bar"===t||"boxPlot"===t)&&i.plotOptions&&i.plotOptions.bar&&i.plotOptions.bar.horizontal,r="pie"===t||"polarArea"===t||"donut"===t||"radar"===t||"radialBar"===t||"heatmap"===t,o="datetime"!==i.xaxis.type&&"numeric"!==i.xaxis.type,n=i.xaxis.tickPlacement?i.xaxis.tickPlacement:e.xaxis&&e.xaxis.tickPlacement;return s||r||!o||"between"===n||(i=a.convertCatToNumeric(i)),i}},{key:"extendYAxis",value:function(t,e){var i=new L;(void 0===t.yaxis||!t.yaxis||Array.isArray(t.yaxis)&&0===t.yaxis.length)&&(t.yaxis={}),t.yaxis.constructor!==Array&&window.Apex.yaxis&&window.Apex.yaxis.constructor!==Array&&(t.yaxis=x.extend(t.yaxis,window.Apex.yaxis)),t.yaxis.constructor!==Array?t.yaxis=[x.extend(i.yAxis,t.yaxis)]:t.yaxis=x.extendArray(t.yaxis,i.yAxis);var a=!1;t.yaxis.forEach((function(t){t.logarithmic&&(a=!0)}));var s=t.series;return e&&!s&&(s=e.config.series),a&&s.length!==t.yaxis.length&&s.length&&(t.yaxis=s.map((function(e,a){if(e.name||(s[a].name="series-".concat(a+1)),t.yaxis[a])return t.yaxis[a].seriesName=s[a].name,t.yaxis[a];var r=x.extend(i.yAxis,t.yaxis[0]);return r.show=!1,r}))),a&&s.length>1&&s.length!==t.yaxis.length&&console.warn("A multi-series logarithmic chart should have equal number of series and y-axes. Please make sure to equalize both."),t}},{key:"extendAnnotations",value:function(t){return void 0===t.annotations&&(t.annotations={},t.annotations.yaxis=[],t.annotations.xaxis=[],t.annotations.points=[]),t=this.extendYAxisAnnotations(t),t=this.extendXAxisAnnotations(t),t=this.extendPointAnnotations(t)}},{key:"extendYAxisAnnotations",value:function(t){var e=new L;return t.annotations.yaxis=x.extendArray(void 0!==t.annotations.yaxis?t.annotations.yaxis:[],e.yAxisAnnotation),t}},{key:"extendXAxisAnnotations",value:function(t){var e=new L;return t.annotations.xaxis=x.extendArray(void 0!==t.annotations.xaxis?t.annotations.xaxis:[],e.xAxisAnnotation),t}},{key:"extendPointAnnotations",value:function(t){var e=new L;return t.annotations.points=x.extendArray(void 0!==t.annotations.points?t.annotations.points:[],e.pointAnnotation),t}},{key:"checkForDarkTheme",value:function(t){t.theme&&"dark"===t.theme.mode&&(t.tooltip||(t.tooltip={}),"light"!==t.tooltip.theme&&(t.tooltip.theme="dark"),t.chart.foreColor||(t.chart.foreColor="#f6f7f8"),t.chart.background||(t.chart.background="#424242"),t.theme.palette||(t.theme.palette="palette4"))}},{key:"handleUserInputErrors",value:function(t){var e=t;if(e.tooltip.shared&&e.tooltip.intersect)throw new Error("tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false.");if("bar"===e.chart.type&&e.plotOptions.bar.horizontal){if(e.yaxis.length>1)throw new Error("Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false");e.yaxis[0].reversed&&(e.yaxis[0].opposite=!0),e.xaxis.tooltip.enabled=!1,e.yaxis[0].tooltip.enabled=!1,e.chart.zoom.enabled=!1}return"bar"!==e.chart.type&&"rangeBar"!==e.chart.type||e.tooltip.shared&&"barWidth"===e.xaxis.crosshairs.width&&e.series.length>1&&(e.xaxis.crosshairs.width="tickWidth"),"candlestick"!==e.chart.type&&"boxPlot"!==e.chart.type||e.yaxis[0].reversed&&(console.warn("Reversed y-axis in ".concat(e.chart.type," chart is not supported.")),e.yaxis[0].reversed=!1),e}}]),t}(),Y=function(){function t(){a(this,t)}return r(t,[{key:"initGlobalVars",value:function(t){t.series=[],t.seriesCandleO=[],t.seriesCandleH=[],t.seriesCandleM=[],t.seriesCandleL=[],t.seriesCandleC=[],t.seriesRangeStart=[],t.seriesRangeEnd=[],t.seriesRange=[],t.seriesPercent=[],t.seriesGoals=[],t.seriesX=[],t.seriesZ=[],t.seriesNames=[],t.seriesTotals=[],t.seriesLog=[],t.seriesColors=[],t.stackedSeriesTotals=[],t.seriesXvalues=[],t.seriesYvalues=[],t.labels=[],t.hasGroups=!1,t.groups=[],t.categoryLabels=[],t.timescaleLabels=[],t.noLabelsProvided=!1,t.resizeTimer=null,t.selectionResizeTimer=null,t.delayedElements=[],t.pointsArray=[],t.dataLabelsRects=[],t.isXNumeric=!1,t.skipLastTimelinelabel=!1,t.skipFirstTimelinelabel=!1,t.isDataXYZ=!1,t.isMultiLineX=!1,t.isMultipleYAxis=!1,t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE,t.minYArr=[],t.maxYArr=[],t.maxX=-Number.MAX_VALUE,t.minX=Number.MAX_VALUE,t.initialMaxX=-Number.MAX_VALUE,t.initialMinX=Number.MAX_VALUE,t.maxDate=0,t.minDate=Number.MAX_VALUE,t.minZ=Number.MAX_VALUE,t.maxZ=-Number.MAX_VALUE,t.minXDiff=Number.MAX_VALUE,t.yAxisScale=[],t.xAxisScale=null,t.xAxisTicksPositions=[],t.yLabelsCoords=[],t.yTitleCoords=[],t.barPadForNumericAxis=0,t.padHorizontal=0,t.xRange=0,t.yRange=[],t.zRange=0,t.dataPoints=0,t.xTickAmount=0}},{key:"globalVars",value:function(t){return{chartID:null,cuid:null,events:{beforeMount:[],mounted:[],updated:[],clicked:[],selection:[],dataPointSelection:[],zoomed:[],scrolled:[]},colors:[],clientX:null,clientY:null,fill:{colors:[]},stroke:{colors:[]},dataLabels:{style:{colors:[]}},radarPolygons:{fill:{colors:[]}},markers:{colors:[],size:t.markers.size,largestSize:0},animationEnded:!1,isTouchDevice:"ontouchstart"in window||navigator.msMaxTouchPoints,isDirty:!1,isExecCalled:!1,initialConfig:null,initialSeries:[],lastXAxis:[],lastYAxis:[],columnSeries:null,labels:[],timescaleLabels:[],noLabelsProvided:!1,allSeriesCollapsed:!1,collapsedSeries:[],collapsedSeriesIndices:[],ancillaryCollapsedSeries:[],ancillaryCollapsedSeriesIndices:[],risingSeries:[],dataFormatXNumeric:!1,capturedSeriesIndex:-1,capturedDataPointIndex:-1,selectedDataPoints:[],goldenPadding:35,invalidLogScale:!1,ignoreYAxisIndexes:[],yAxisSameScaleIndices:[],maxValsInArrayIndex:0,radialSize:0,selection:void 0,zoomEnabled:"zoom"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.zoom&&t.chart.zoom.enabled,panEnabled:"pan"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.pan,selectionEnabled:"selection"===t.chart.toolbar.autoSelected&&t.chart.toolbar.tools.selection,yaxis:null,mousedown:!1,lastClientPosition:{},visibleXRange:void 0,yValueDecimal:0,total:0,SVGNS:"http://www.w3.org/2000/svg",svgWidth:0,svgHeight:0,noData:!1,locale:{},dom:{},memory:{methodsToExec:[]},shouldAnimate:!0,skipLastTimelinelabel:!1,skipFirstTimelinelabel:!1,delayedElements:[],axisCharts:!0,isDataXYZ:!1,resized:!1,resizeTimer:null,comboCharts:!1,dataChanged:!1,previousPaths:[],allSeriesHasEqualX:!0,pointsArray:[],dataLabelsRects:[],lastDrawnDataLabelsIndexes:[],hasNullValues:!1,easing:null,zoomed:!1,gridWidth:0,gridHeight:0,rotateXLabels:!1,defaultLabels:!1,xLabelFormatter:void 0,yLabelFormatters:[],xaxisTooltipFormatter:void 0,ttKeyFormatter:void 0,ttVal:void 0,ttZFormatter:void 0,LINE_HEIGHT_RATIO:1.618,xAxisLabelsHeight:0,xAxisGroupLabelsHeight:0,xAxisLabelsWidth:0,yAxisLabelsWidth:0,scaleX:1,scaleY:1,translateX:0,translateY:0,translateYAxisX:[],yAxisWidths:[],translateXAxisY:0,translateXAxisX:0,tooltip:null}}},{key:"init",value:function(t){var e=this.globalVars(t);return this.initGlobalVars(e),e.initialConfig=x.extend({},t),e.initialSeries=x.clone(t.series),e.lastXAxis=x.clone(e.initialConfig.xaxis),e.lastYAxis=x.clone(e.initialConfig.yaxis),e}}]),t}(),F=function(){function t(e){a(this,t),this.opts=e}return r(t,[{key:"init",value:function(){var t=new E(this.opts).init({responsiveOverride:!1});return{config:t,globals:(new Y).init(t)}}}]),t}(),R=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.opts=null,this.seriesIndex=0}return r(t,[{key:"clippedImgArea",value:function(t){var e=this.w,i=e.config,a=parseInt(e.globals.gridWidth,10),s=parseInt(e.globals.gridHeight,10),r=a>s?a:s,o=t.image,n=0,l=0;void 0===t.width&&void 0===t.height?void 0!==i.fill.image.width&&void 0!==i.fill.image.height?(n=i.fill.image.width+1,l=i.fill.image.height):(n=r+1,l=r):(n=t.width,l=t.height);var h=document.createElementNS(e.globals.SVGNS,"pattern");m.setAttrs(h,{id:t.patternID,patternUnits:t.patternUnits?t.patternUnits:"userSpaceOnUse",width:n+"px",height:l+"px"});var c=document.createElementNS(e.globals.SVGNS,"image");h.appendChild(c),c.setAttributeNS(window.SVG.xlink,"href",o),m.setAttrs(c,{x:0,y:0,preserveAspectRatio:"none",width:n+"px",height:l+"px"}),c.style.opacity=t.opacity,e.globals.dom.elDefs.node.appendChild(h)}},{key:"getSeriesIndex",value:function(t){var e=this.w;return("bar"===e.config.chart.type||"rangeBar"===e.config.chart.type)&&e.config.plotOptions.bar.distributed||"heatmap"===e.config.chart.type||"treemap"===e.config.chart.type?this.seriesIndex=t.seriesNumber:this.seriesIndex=t.seriesNumber%e.globals.series.length,this.seriesIndex}},{key:"fillPath",value:function(t){var e=this.w;this.opts=t;var i,a,s,r=this.w.config;this.seriesIndex=this.getSeriesIndex(t);var o=this.getFillColors()[this.seriesIndex];void 0!==e.globals.seriesColors[this.seriesIndex]&&(o=e.globals.seriesColors[this.seriesIndex]),"function"==typeof o&&(o=o({seriesIndex:this.seriesIndex,dataPointIndex:t.dataPointIndex,value:t.value,w:e}));var n=t.fillType?t.fillType:this.getFillType(this.seriesIndex),l=Array.isArray(r.fill.opacity)?r.fill.opacity[this.seriesIndex]:r.fill.opacity;t.color&&(o=t.color);var h=o;if(-1===o.indexOf("rgb")?o.length<9&&(h=x.hexToRgba(o,l)):o.indexOf("rgba")>-1&&(l=x.getOpacityFromRGBA(o)),t.opacity&&(l=t.opacity),"pattern"===n&&(a=this.handlePatternFill({fillConfig:t.fillConfig,patternFill:a,fillColor:o,fillOpacity:l,defaultColor:h})),"gradient"===n&&(s=this.handleGradientFill({fillConfig:t.fillConfig,fillColor:o,fillOpacity:l,i:this.seriesIndex})),"image"===n){var c=r.fill.image.src,d=t.patternID?t.patternID:"";this.clippedImgArea({opacity:l,image:Array.isArray(c)?t.seriesNumber-1&&(u=x.getOpacityFromRGBA(g));var f=void 0===o.gradient.opacityTo?a:Array.isArray(o.gradient.opacityTo)?o.gradient.opacityTo[r]:o.gradient.opacityTo;if(void 0===o.gradient.gradientToColors||0===o.gradient.gradientToColors.length)n="dark"===o.gradient.shade?c.shadeColor(-1*parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?x.rgb2hex(i):i):c.shadeColor(parseFloat(o.gradient.shadeIntensity),i.indexOf("rgb")>-1?x.rgb2hex(i):i);else if(o.gradient.gradientToColors[l.seriesNumber]){var p=o.gradient.gradientToColors[l.seriesNumber];n=p,p.indexOf("rgba")>-1&&(f=x.getOpacityFromRGBA(p))}else n=i;if(o.gradient.gradientFrom&&(g=o.gradient.gradientFrom),o.gradient.gradientTo&&(n=o.gradient.gradientTo),o.gradient.inverseColors){var b=g;g=n,n=b}return g.indexOf("rgb")>-1&&(g=x.rgb2hex(g)),n.indexOf("rgb")>-1&&(n=x.rgb2hex(n)),h.drawGradient(d,g,n,u,f,l.size,o.gradient.stops,o.gradient.colorStops,r)}}]),t}(),D=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"setGlobalMarkerSize",value:function(){var t=this.w;if(t.globals.markers.size=Array.isArray(t.config.markers.size)?t.config.markers.size:[t.config.markers.size],t.globals.markers.size.length>0){if(t.globals.markers.size.length4&&void 0!==arguments[4]&&arguments[4],o=this.w,n=e,l=t,h=null,c=new m(this.ctx),d=o.config.markers.discrete&&o.config.markers.discrete.length;if((o.globals.markers.size[e]>0||r||d)&&(h=c.group({class:r||d?"":"apexcharts-series-markers"})).attr("clip-path","url(#gridRectMarkerMask".concat(o.globals.cuid,")")),Array.isArray(l.x))for(var g=0;g0:o.config.markers.size>0;if(p||r||d){x.isNumber(l.y[g])?f+=" w".concat(x.randomId()):f="apexcharts-nullpoint";var b=this.getMarkerConfig({cssClass:f,seriesIndex:e,dataPointIndex:u});o.config.series[n].data[u]&&(o.config.series[n].data[u].fillColor&&(b.pointFillColor=o.config.series[n].data[u].fillColor),o.config.series[n].data[u].strokeColor&&(b.pointStrokeColor=o.config.series[n].data[u].strokeColor)),a&&(b.pSize=a),(s=c.drawMarker(l.x[g],l.y[g],b)).attr("rel",u),s.attr("j",u),s.attr("index",e),s.node.setAttribute("default-marker-size",b.pSize);var y=new v(this.ctx);y.setSelectionFilter(s,e,u),this.addEvents(s),h&&h.add(s)}else void 0===o.globals.pointsArray[e]&&(o.globals.pointsArray[e]=[]),o.globals.pointsArray[e].push([l.x[g],l.y[g]])}return h}},{key:"getMarkerConfig",value:function(t){var e=t.cssClass,i=t.seriesIndex,a=t.dataPointIndex,s=void 0===a?null:a,r=t.finishRadius,o=void 0===r?null:r,n=this.w,l=this.getMarkerStyle(i),h=n.globals.markers.size[i],c=n.config.markers;return null!==s&&c.discrete.length&&c.discrete.map((function(t){t.seriesIndex===i&&t.dataPointIndex===s&&(l.pointStrokeColor=t.strokeColor,l.pointFillColor=t.fillColor,h=t.size,l.pointShape=t.shape)})),{pSize:null===o?h:o,pRadius:c.radius,width:Array.isArray(c.width)?c.width[i]:c.width,height:Array.isArray(c.height)?c.height[i]:c.height,pointStrokeWidth:Array.isArray(c.strokeWidth)?c.strokeWidth[i]:c.strokeWidth,pointStrokeColor:l.pointStrokeColor,pointFillColor:l.pointFillColor,shape:l.pointShape||(Array.isArray(c.shape)?c.shape[i]:c.shape),class:e,pointStrokeOpacity:Array.isArray(c.strokeOpacity)?c.strokeOpacity[i]:c.strokeOpacity,pointStrokeDashArray:Array.isArray(c.strokeDashArray)?c.strokeDashArray[i]:c.strokeDashArray,pointFillOpacity:Array.isArray(c.fillOpacity)?c.fillOpacity[i]:c.fillOpacity,seriesIndex:i}}},{key:"addEvents",value:function(t){var e=this.w,i=new m(this.ctx);t.node.addEventListener("mouseenter",i.pathMouseEnter.bind(this.ctx,t)),t.node.addEventListener("mouseleave",i.pathMouseLeave.bind(this.ctx,t)),t.node.addEventListener("mousedown",i.pathMouseDown.bind(this.ctx,t)),t.node.addEventListener("click",e.config.markers.onClick),t.node.addEventListener("dblclick",e.config.markers.onDblClick),t.node.addEventListener("touchstart",i.pathMouseDown.bind(this.ctx,t),{passive:!0})}},{key:"getMarkerStyle",value:function(t){var e=this.w,i=e.globals.markers.colors,a=e.config.markers.strokeColor||e.config.markers.strokeColors;return{pointStrokeColor:Array.isArray(a)?a[t]:a,pointFillColor:Array.isArray(i)?i[t]:i}}}]),t}(),H=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.initialAnim=this.w.config.chart.animations.enabled,this.dynamicAnim=this.initialAnim&&this.w.config.chart.animations.dynamicAnimation.enabled}return r(t,[{key:"draw",value:function(t,e,i){var a=this.w,s=new m(this.ctx),r=i.realIndex,o=i.pointsPos,n=i.zRatio,l=i.elParent,h=s.group({class:"apexcharts-series-markers apexcharts-series-".concat(a.config.chart.type)});if(h.attr("clip-path","url(#gridRectMarkerMask".concat(a.globals.cuid,")")),Array.isArray(o.x))for(var c=0;cp.maxBubbleRadius&&(f=p.maxBubbleRadius)}a.config.chart.animations.enabled||(u=f);var x=o.x[c],b=o.y[c];if(u=u||0,null!==b&&void 0!==a.globals.series[r][d]||(g=!1),g){var v=this.drawPoint(x,b,u,f,r,d,e);h.add(v)}l.add(h)}}},{key:"drawPoint",value:function(t,e,i,a,s,r,o){var n=this.w,l=s,h=new b(this.ctx),c=new v(this.ctx),d=new R(this.ctx),g=new D(this.ctx),u=new m(this.ctx),f=g.getMarkerConfig({cssClass:"apexcharts-marker",seriesIndex:l,dataPointIndex:r,finishRadius:"bubble"===n.config.chart.type||n.globals.comboCharts&&n.config.series[s]&&"bubble"===n.config.series[s].type?a:null});a=f.pSize;var p,x=d.fillPath({seriesNumber:s,dataPointIndex:r,color:f.pointFillColor,patternUnits:"objectBoundingBox",value:n.globals.series[s][o]});if("circle"===f.shape?p=u.drawCircle(i):"square"!==f.shape&&"rect"!==f.shape||(p=u.drawRect(0,0,f.width-f.pointStrokeWidth/2,f.height-f.pointStrokeWidth/2,f.pRadius)),n.config.series[l].data[r]&&n.config.series[l].data[r].fillColor&&(x=n.config.series[l].data[r].fillColor),p.attr({x:t-f.width/2-f.pointStrokeWidth/2,y:e-f.height/2-f.pointStrokeWidth/2,cx:t,cy:e,fill:x,"fill-opacity":f.pointFillOpacity,stroke:f.pointStrokeColor,r:a,"stroke-width":f.pointStrokeWidth,"stroke-dasharray":f.pointStrokeDashArray,"stroke-opacity":f.pointStrokeOpacity}),n.config.chart.dropShadow.enabled){var y=n.config.chart.dropShadow;c.dropShadow(p,y,s)}if(!this.initialAnim||n.globals.dataChanged||n.globals.resized)n.globals.animationEnded=!0;else{var w=n.config.chart.animations.speed;h.animateMarker(p,0,"circle"===f.shape?a:{width:f.width,height:f.height},w,n.globals.easing,(function(){window.setTimeout((function(){h.animationCompleted(p)}),100)}))}if(n.globals.dataChanged&&"circle"===f.shape)if(this.dynamicAnim){var k,A,S,C,L=n.config.chart.animations.dynamicAnimation.speed;null!=(C=n.globals.previousPaths[s]&&n.globals.previousPaths[s][o])&&(k=C.x,A=C.y,S=void 0!==C.r?C.r:a);for(var P=0;Pn.globals.gridHeight+d&&(e=n.globals.gridHeight+d/2),void 0===n.globals.dataLabelsRects[a]&&(n.globals.dataLabelsRects[a]=[]),n.globals.dataLabelsRects[a].push({x:t,y:e,width:c,height:d});var g=n.globals.dataLabelsRects[a].length-2,u=void 0!==n.globals.lastDrawnDataLabelsIndexes[a]?n.globals.lastDrawnDataLabelsIndexes[a][n.globals.lastDrawnDataLabelsIndexes[a].length-1]:0;if(void 0!==n.globals.dataLabelsRects[a][g]){var f=n.globals.dataLabelsRects[a][u];(t>f.x+f.width+2||e>f.y+f.height+2||t+ce.globals.gridWidth+p.textRects.width+10)&&(n="");var x=e.globals.dataLabels.style.colors[r];(("bar"===e.config.chart.type||"rangeBar"===e.config.chart.type)&&e.config.plotOptions.bar.distributed||e.config.dataLabels.distributed)&&(x=e.globals.dataLabels.style.colors[o]),"function"==typeof x&&(x=x({series:e.globals.series,seriesIndex:r,dataPointIndex:o,w:e})),g&&(x=g);var b=d.offsetX,y=d.offsetY;if("bar"!==e.config.chart.type&&"rangeBar"!==e.config.chart.type||(b=0,y=0),p.drawnextLabel){var w=i.drawText({width:100,height:parseInt(d.style.fontSize,10),x:a+b,y:s+y,foreColor:x,textAnchor:l||d.textAnchor,text:n,fontSize:h||d.style.fontSize,fontFamily:d.style.fontFamily,fontWeight:d.style.fontWeight||"normal"});if(w.attr({class:"apexcharts-datalabel",cx:a,cy:s}),d.dropShadow.enabled){var k=d.dropShadow;new v(this.ctx).dropShadow(w,k)}c.add(w),void 0===e.globals.lastDrawnDataLabelsIndexes[r]&&(e.globals.lastDrawnDataLabelsIndexes[r]=[]),e.globals.lastDrawnDataLabelsIndexes[r].push(o)}}}},{key:"addBackgroundToDataLabel",value:function(t,e){var i=this.w,a=i.config.dataLabels.background,s=a.padding,r=a.padding/2,o=e.width,n=e.height,l=new m(this.ctx).drawRect(e.x-s,e.y-r/2,o+2*s,n+r,a.borderRadius,"transparent"===i.config.chart.background?"#fff":i.config.chart.background,a.opacity,a.borderWidth,a.borderColor);a.dropShadow.enabled&&new v(this.ctx).dropShadow(l,a.dropShadow);return l}},{key:"dataLabelsBackground",value:function(){var t=this.w;if("bubble"!==t.config.chart.type)for(var e=t.globals.dom.baseEl.querySelectorAll(".apexcharts-datalabels text"),i=0;i0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w,s=x.clone(a.globals.initialSeries);a.globals.previousPaths=[],i?(a.globals.collapsedSeries=[],a.globals.ancillaryCollapsedSeries=[],a.globals.collapsedSeriesIndices=[],a.globals.ancillaryCollapsedSeriesIndices=[]):s=this.emptyCollapsedSeries(s),a.config.series=s,t&&(e&&(a.globals.zoomed=!1,this.ctx.updateHelpers.revertDefaultAxisMinMax()),this.ctx.updateHelpers._updateSeries(s,a.config.chart.animations.dynamicAnimation.enabled))}},{key:"emptyCollapsedSeries",value:function(t){for(var e=this.w,i=0;i-1&&(t[i].data=[]);return t}},{key:"toggleSeriesOnHover",value:function(t,e){var i=this.w;e||(e=t.target);var a=i.globals.dom.baseEl.querySelectorAll(".apexcharts-series, .apexcharts-datalabels");if("mousemove"===t.type){var s=parseInt(e.getAttribute("rel"),10)-1,r=null,o=null;i.globals.axisCharts||"radialBar"===i.config.chart.type?i.globals.axisCharts?(r=i.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(s,"']")),o=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels[data\\:realIndex='".concat(s,"']"))):r=i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s+1,"']")):r=i.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(s+1,"'] path"));for(var n=0;n=t.from&&a<=t.to&&s[e].classList.remove(i.legendInactiveClass)}}(a.config.plotOptions.heatmap.colorScale.ranges[o])}else"mouseout"===t.type&&r("remove")}},{key:"getActiveConfigSeriesIndex",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"asc",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],i=this.w,a=0;if(i.config.series.length>1)for(var s=i.config.series.map((function(t,a){return t.data&&t.data.length>0&&-1===i.globals.collapsedSeriesIndices.indexOf(a)&&(!i.globals.comboCharts||0===e.length||e.length&&e.indexOf(i.config.series[a].type)>-1)?a:-1})),r="asc"===t?0:s.length-1;"asc"===t?r=0;"asc"===t?r++:r--)if(-1!==s[r]){a=s[r];break}return a}},{key:"getBarSeriesIndices",value:function(){return this.w.globals.comboCharts?this.w.config.series.map((function(t,e){return"bar"===t.type||"column"===t.type?e:-1})).filter((function(t){return-1!==t})):this.w.config.series.map((function(t,e){return e}))}},{key:"getPreviousPaths",value:function(){var t=this.w;function e(e,i,a){for(var s=e[i].childNodes,r={type:a,paths:[],realIndex:e[i].getAttribute("data:realIndex")},o=0;o0)for(var a=function(e){for(var i=t.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(t.config.chart.type," .apexcharts-series[data\\:realIndex='").concat(e,"'] rect")),a=[],s=function(t){var e=function(e){return i[t].getAttribute(e)},s={x:parseFloat(e("x")),y:parseFloat(e("y")),width:parseFloat(e("width")),height:parseFloat(e("height"))};a.push({rect:s,color:i[t].getAttribute("color")})},r=0;r0)for(var a=0;a0?t:[]}));return t}}]),t}(),W=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.twoDSeries=[],this.threeDSeries=[],this.twoDSeriesX=[],this.seriesGoals=[],this.coreUtils=new y(this.ctx)}return r(t,[{key:"isMultiFormat",value:function(){return this.isFormatXY()||this.isFormat2DArray()}},{key:"isFormatXY",value:function(){var t=this.w.config.series.slice(),e=new N(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&null!==t[this.activeSeriesIndex].data[0]&&void 0!==t[this.activeSeriesIndex].data[0].x&&null!==t[this.activeSeriesIndex].data[0])return!0}},{key:"isFormat2DArray",value:function(){var t=this.w.config.series.slice(),e=new N(this.ctx);if(this.activeSeriesIndex=e.getActiveConfigSeriesIndex(),void 0!==t[this.activeSeriesIndex].data&&t[this.activeSeriesIndex].data.length>0&&void 0!==t[this.activeSeriesIndex].data[0]&&null!==t[this.activeSeriesIndex].data[0]&&t[this.activeSeriesIndex].data[0].constructor===Array)return!0}},{key:"handleFormat2DArray",value:function(t,e){for(var i=this.w.config,a=this.w.globals,s="boxPlot"===i.chart.type||"boxPlot"===i.series[e].type,r=0;r=5?this.twoDSeries.push(x.parseNumber(t[e].data[r][4])):this.twoDSeries.push(x.parseNumber(t[e].data[r][1])),a.dataFormatXNumeric=!0),"datetime"===i.xaxis.type){var o=new Date(t[e].data[r][0]);o=new Date(o).getTime(),this.twoDSeriesX.push(o)}else this.twoDSeriesX.push(t[e].data[r][0]);for(var n=0;n-1&&(r=this.activeSeriesIndex);for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:this.ctx,a=this.w.config,s=this.w.globals,r=new T(i),o=a.labels.length>0?a.labels.slice():a.xaxis.categories.slice();s.isRangeBar="rangeBar"===a.chart.type&&s.isBarHorizontal,s.hasGroups="category"===a.xaxis.type&&a.xaxis.group.groups.length>0,s.hasGroups&&(s.groups=a.xaxis.group.groups);for(var n=function(){for(var t=0;t0&&(this.twoDSeriesX=o,s.seriesX.push(this.twoDSeriesX))),s.labels.push(this.twoDSeriesX);var h=t[l].data.map((function(t){return x.parseNumber(t)}));s.series.push(h)}s.seriesZ.push(this.threeDSeries),void 0!==t[l].name?s.seriesNames.push(t[l].name):s.seriesNames.push("series-"+parseInt(l+1,10)),void 0!==t[l].color?s.seriesColors.push(t[l].color):s.seriesColors.push(void 0)}return this.w}},{key:"parseDataNonAxisCharts",value:function(t){var e=this.w.globals,i=this.w.config;e.series=t.slice(),e.seriesNames=i.labels.slice();for(var a=0;a0)i.labels=e.xaxis.categories;else if(e.labels.length>0)i.labels=e.labels.slice();else if(this.fallbackToCategory){if(i.labels=i.labels[0],i.seriesRange.length&&(i.seriesRange.map((function(t){t.forEach((function(t){i.labels.indexOf(t.x)<0&&t.x&&i.labels.push(t.x)}))})),i.labels=i.labels.filter((function(t,e,i){return i.indexOf(t)===e}))),e.xaxis.convertedCatToNumeric)new X(e).convertCatToNumericXaxis(e,this.ctx,i.seriesX[0]),this._generateExternalLabels(t)}else this._generateExternalLabels(t)}},{key:"_generateExternalLabels",value:function(t){var e=this.w.globals,i=this.w.config,a=[];if(e.axisCharts){if(e.series.length>0)if(this.isFormatXY())for(var s=i.series.map((function(t,e){return t.data.filter((function(t,e,i){return i.findIndex((function(e){return e.x===t.x}))===e}))})),r=s.reduce((function(t,e,i,a){return a[t].length>e.length?t:i}),0),o=0;o4&&void 0!==arguments[4]?arguments[4]:[],r=arguments.length>5&&void 0!==arguments[5]?arguments[5]:"12px",o=!(arguments.length>6&&void 0!==arguments[6])||arguments[6],n=this.w,l=void 0===t[a]?"":t[a],h=l,c=n.globals.xLabelFormatter,d=n.config.xaxis.labels.formatter,g=!1,u=new M(this.ctx),f=l;o&&(h=u.xLabelFormat(c,l,f,{i:a,dateFormatter:new T(this.ctx).formatDate,w:n}),void 0!==d&&(h=d(l,t[a],{i:a,dateFormatter:new T(this.ctx).formatDate,w:n})));var p=function(t){var i=null;return e.forEach((function(t){"month"===t.unit?i="year":"day"===t.unit?i="month":"hour"===t.unit?i="day":"minute"===t.unit&&(i="hour")})),i===t};e.length>0?(g=p(e[a].unit),i=e[a].position,h=e[a].value):"datetime"===n.config.xaxis.type&&void 0===d&&(h=""),void 0===h&&(h=""),h=Array.isArray(h)?h:h.toString();var x=new m(this.ctx),b={};b=n.globals.rotateXLabels&&o?x.getTextRects(h,parseInt(r,10),null,"rotate(".concat(n.config.xaxis.labels.rotate," 0 0)"),!1):x.getTextRects(h,parseInt(r,10));var v=!n.config.xaxis.labels.showDuplicates&&this.ctx.timeScale;return!Array.isArray(h)&&(0===h.indexOf("NaN")||0===h.toLowerCase().indexOf("invalid")||h.toLowerCase().indexOf("infinity")>=0||s.indexOf(h)>=0&&v)&&(h=""),{x:i,text:h,textRect:b,isBold:g}}},{key:"checkLabelBasedOnTickamount",value:function(t,e,i){var a=this.w,s=a.config.xaxis.tickAmount;return"dataPoints"===s&&(s=Math.round(a.globals.gridWidth/120)),s>i||t%Math.round(i/(s+1))==0||(e.text=""),e}},{key:"checkForOverflowingLabels",value:function(t,e,i,a,s){var r=this.w;if(0===t&&r.globals.skipFirstTimelinelabel&&(e.text=""),t===i-1&&r.globals.skipLastTimelinelabel&&(e.text=""),r.config.xaxis.labels.hideOverlappingLabels&&a.length>0){var o=s[s.length-1];e.x0){!0===n.config.yaxis[s].opposite&&(t+=a.width);for(var c=e;c>=0;c--){var d=h+e/10+n.config.yaxis[s].labels.offsetY-1;n.globals.isBarHorizontal&&(d=r*c),"heatmap"===n.config.chart.type&&(d+=r/2);var g=l.drawLine(t+i.offsetX-a.width+a.offsetX,d+a.offsetY,t+i.offsetX+a.offsetX,d+a.offsetY,a.color);o.add(g),h+=r}}}}]),t}(),G=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"scaleSvgNode",value:function(t,e){var i=parseFloat(t.getAttributeNS(null,"width")),a=parseFloat(t.getAttributeNS(null,"height"));t.setAttributeNS(null,"width",i*e),t.setAttributeNS(null,"height",a*e),t.setAttributeNS(null,"viewBox","0 0 "+i+" "+a)}},{key:"fixSvgStringForIe11",value:function(t){if(!x.isIE11())return t.replace(/ /g," ");var e=0,i=t.replace(/xmlns="http:\/\/www.w3.org\/2000\/svg"/g,(function(t){return 2===++e?'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev"':t}));return i=(i=i.replace(/xmlns:NS\d+=""/g,"")).replace(/NS\d+:(\w+:\w+=")/g,"$1")}},{key:"getSvgString",value:function(t){null==t&&(t=1);var e=this.w.globals.dom.Paper.svg();if(1!==t){var i=this.w.globals.dom.Paper.node.cloneNode(!0);this.scaleSvgNode(i,t),e=(new XMLSerializer).serializeToString(i)}return this.fixSvgStringForIe11(e)}},{key:"cleanup",value:function(){var t=this.w,e=t.globals.dom.baseEl.getElementsByClassName("apexcharts-xcrosshairs"),i=t.globals.dom.baseEl.getElementsByClassName("apexcharts-ycrosshairs"),a=t.globals.dom.baseEl.querySelectorAll(".apexcharts-zoom-rect, .apexcharts-selection-rect");Array.prototype.forEach.call(a,(function(t){t.setAttribute("width",0)})),e&&e[0]&&(e[0].setAttribute("x",-500),e[0].setAttribute("x1",-500),e[0].setAttribute("x2",-500)),i&&i[0]&&(i[0].setAttribute("y",-100),i[0].setAttribute("y1",-100),i[0].setAttribute("y2",-100))}},{key:"svgUrl",value:function(){this.cleanup();var t=this.getSvgString(),e=new Blob([t],{type:"image/svg+xml;charset=utf-8"});return URL.createObjectURL(e)}},{key:"dataURI",value:function(t){var e=this;return new Promise((function(i){var a=e.w,s=t?t.scale||t.width/a.globals.svgWidth:1;e.cleanup();var r=document.createElement("canvas");r.width=a.globals.svgWidth*s,r.height=parseInt(a.globals.dom.elWrap.style.height,10)*s;var o="transparent"===a.config.chart.background?"#fff":a.config.chart.background,n=r.getContext("2d");n.fillStyle=o,n.fillRect(0,0,r.width*s,r.height*s);var l=e.getSvgString(s);if(window.canvg&&x.isIE11()){var h=window.canvg.Canvg.fromString(n,l,{ignoreClear:!0,ignoreDimensions:!0});h.start();var c=r.msToBlob();h.stop(),i({blob:c})}else{var d="data:image/svg+xml,"+encodeURIComponent(l),g=new Image;g.crossOrigin="anonymous",g.onload=function(){if(n.drawImage(g,0,0),r.msToBlob){var t=r.msToBlob();i({blob:t})}else{var e=r.toDataURL("image/png");i({imgURI:e})}},g.src=d}}))}},{key:"exportToSVG",value:function(){this.triggerDownload(this.svgUrl(),this.w.config.chart.toolbar.export.svg.filename,".svg")}},{key:"exportToPng",value:function(){var t=this;this.dataURI().then((function(e){var i=e.imgURI,a=e.blob;a?navigator.msSaveOrOpenBlob(a,t.w.globals.chartID+".png"):t.triggerDownload(i,t.w.config.chart.toolbar.export.png.filename,".png")}))}},{key:"exportToCSV",value:function(t){var e=this,i=t.series,a=t.fileName,s=t.columnDelimiter,r=void 0===s?",":s,o=t.lineDelimiter,n=void 0===o?"\n":o,l=this.w;i||(i=l.config.series);var h=[],c=[],d="",g=l.globals.series.map((function(t,e){return-1===l.globals.collapsedSeriesIndices.indexOf(e)?t:[]})),f=Math.max.apply(Math,u(i.map((function(t){return t.data?t.data.length:0})))),p=new W(this.ctx),b=new B(this.ctx),v=function(t){var i="";if(l.globals.axisCharts){if("category"===l.config.xaxis.type||l.config.xaxis.convertedCatToNumeric)if(l.globals.isBarHorizontal){var a=l.globals.yLabelFormatters[0],s=new N(e.ctx).getActiveConfigSeriesIndex();i=a(l.globals.labels[t],{seriesIndex:s,dataPointIndex:t,w:l})}else i=b.getLabel(l.globals.labels,l.globals.timescaleLabels,0,t).text;"datetime"===l.config.xaxis.type&&(l.config.xaxis.categories.length?i=l.config.xaxis.categories[t]:l.config.labels.length&&(i=l.config.labels[t]))}else i=l.config.labels[t];return Array.isArray(i)&&(i=i.join(" ")),x.isNumber(i)?i:i.split(r).join("")},m=function(t,e){if(h.length&&0===e&&c.push(h.join(r)),t.data){t.data=t.data.length&&t.data||u(Array(f)).map((function(){return""}));for(var a=0;a=10?l.config.chart.toolbar.export.csv.dateFormatter(s):x.isNumber(s)?s:s.split(r).join("")));for(var o=0;o0&&!s.globals.isBarHorizontal&&(this.xaxisLabels=s.globals.timescaleLabels.slice()),s.config.xaxis.overwriteCategories&&(this.xaxisLabels=s.config.xaxis.overwriteCategories),this.drawnLabels=[],this.drawnLabelsRects=[],"top"===s.config.xaxis.position?this.offY=0:this.offY=s.globals.gridHeight+1,this.offY=this.offY+s.config.xaxis.axisBorder.offsetY,this.isCategoryBarHorizontal="bar"===s.config.chart.type&&s.config.plotOptions.bar.horizontal,this.xaxisFontSize=s.config.xaxis.labels.style.fontSize,this.xaxisFontFamily=s.config.xaxis.labels.style.fontFamily,this.xaxisForeColors=s.config.xaxis.labels.style.colors,this.xaxisBorderWidth=s.config.xaxis.axisBorder.width,this.isCategoryBarHorizontal&&(this.xaxisBorderWidth=s.config.yaxis[0].axisBorder.width.toString()),this.xaxisBorderWidth.indexOf("%")>-1?this.xaxisBorderWidth=s.globals.gridWidth*parseInt(this.xaxisBorderWidth,10)/100:this.xaxisBorderWidth=parseInt(this.xaxisBorderWidth,10),this.xaxisBorderHeight=s.config.xaxis.axisBorder.height,this.yaxis=s.config.yaxis[0]}return r(t,[{key:"drawXaxis",value:function(){var t=this.w,e=new m(this.ctx),i=e.group({class:"apexcharts-xaxis",transform:"translate(".concat(t.config.xaxis.offsetX,", ").concat(t.config.xaxis.offsetY,")")}),a=e.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(t.globals.translateXAxisX,", ").concat(t.globals.translateXAxisY,")")});i.add(a);for(var s=[],r=0;r6&&void 0!==arguments[6]?arguments[6]:{},h=[],c=[],d=this.w,g=l.xaxisFontSize||this.xaxisFontSize,u=l.xaxisFontFamily||this.xaxisFontFamily,f=l.xaxisForeColors||this.xaxisForeColors,p=l.fontWeight||d.config.xaxis.labels.style.fontWeight,x=l.cssClass||d.config.xaxis.labels.style.cssClass,b=d.globals.padHorizontal,v=a.length,m="category"===d.config.xaxis.type?d.globals.dataPoints:v;if(0===m&&v>m&&(m=v),s){var y=m>1?m-1:m;o=d.globals.gridWidth/y,b=b+r(0,o)/2+d.config.xaxis.labels.offsetX}else o=d.globals.gridWidth/m,b=b+r(0,o)+d.config.xaxis.labels.offsetX;for(var w=function(s){var l=b-r(s,o)/2+d.config.xaxis.labels.offsetX;0===s&&1===v&&o/2===b&&1===m&&(l=d.globals.gridWidth/2);var y=n.axesUtils.getLabel(a,d.globals.timescaleLabels,l,s,h,g,t),w=28;d.globals.rotateXLabels&&t&&(w=22),d.config.xaxis.title.text&&"top"===d.config.xaxis.position&&(w+=parseFloat(d.config.xaxis.title.style.fontSize)+2),t||(w=w+parseFloat(g)+(d.globals.xAxisLabelsHeight-d.globals.xAxisGroupLabelsHeight)+(d.globals.rotateXLabels?10:0)),y=void 0!==d.config.xaxis.tickAmount&&"dataPoints"!==d.config.xaxis.tickAmount&&"datetime"!==d.config.xaxis.type?n.axesUtils.checkLabelBasedOnTickamount(s,y,v):n.axesUtils.checkForOverflowingLabels(s,y,v,h,c);if(d.config.xaxis.labels.show){var k=e.drawText({x:y.x,y:n.offY+d.config.xaxis.labels.offsetY+w-("top"===d.config.xaxis.position?d.globals.xAxisHeight+d.config.xaxis.axisTicks.height-2:0),text:y.text,textAnchor:"middle",fontWeight:y.isBold?600:p,fontSize:g,fontFamily:u,foreColor:Array.isArray(f)?t&&d.config.xaxis.convertedCatToNumeric?f[d.globals.minX+s-1]:f[s]:f,isPlainText:!1,cssClass:(t?"apexcharts-xaxis-label ":"apexcharts-xaxis-group-label ")+x});if(i.add(k),k.on("click",(function(t){if("function"==typeof d.config.chart.events.xAxisLabelClick){var e=Object.assign({},d,{labelIndex:s});d.config.chart.events.xAxisLabelClick(t,n.ctx,e)}})),t){var A=document.createElementNS(d.globals.SVGNS,"title");A.textContent=Array.isArray(y.text)?y.text.join(" "):y.text,k.node.appendChild(A),""!==y.text&&(h.push(y.text),c.push(y))}}sa.globals.gridWidth)){var r=this.offY+a.config.xaxis.axisTicks.offsetY;if(e=e+r+a.config.xaxis.axisTicks.height,"top"===a.config.xaxis.position&&(e=r-a.config.xaxis.axisTicks.height),a.config.xaxis.axisTicks.show){var o=new m(this.ctx).drawLine(t+a.config.xaxis.axisTicks.offsetX,r+a.config.xaxis.offsetY,s+a.config.xaxis.axisTicks.offsetX,e+a.config.xaxis.offsetY,a.config.xaxis.axisTicks.color);i.add(o),o.node.classList.add("apexcharts-xaxis-tick")}}}},{key:"getXAxisTicksPositions",value:function(){var t=this.w,e=[],i=this.xaxisLabels.length,a=t.globals.padHorizontal;if(t.globals.timescaleLabels.length>0)for(var s=0;s0){var h=s[s.length-1].getBBox(),c=s[0].getBBox();h.x<-20&&s[s.length-1].parentNode.removeChild(s[s.length-1]),c.x+c.width>t.globals.gridWidth&&!t.globals.isBarHorizontal&&s[0].parentNode.removeChild(s[0]);for(var d=0;d0&&(this.xaxisLabels=i.globals.timescaleLabels.slice())}return r(t,[{key:"drawGridArea",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,e=this.w,i=new m(this.ctx);null===t&&(t=i.group({class:"apexcharts-grid"}));var a=i.drawLine(e.globals.padHorizontal,1,e.globals.padHorizontal,e.globals.gridHeight,"transparent"),s=i.drawLine(e.globals.padHorizontal,e.globals.gridHeight,e.globals.gridWidth,e.globals.gridHeight,"transparent");return t.add(s),t.add(a),t}},{key:"drawGrid",value:function(){var t=null;return this.w.globals.axisCharts&&(t=this.renderGrid(),this.drawGridArea(t.el)),t}},{key:"createGridMask",value:function(){var t=this.w,e=t.globals,i=new m(this.ctx),a=Array.isArray(t.config.stroke.width)?0:t.config.stroke.width;if(Array.isArray(t.config.stroke.width)){var s=0;t.config.stroke.width.forEach((function(t){s=Math.max(s,t)})),a=s}e.dom.elGridRectMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elGridRectMask.setAttribute("id","gridRectMask".concat(e.cuid)),e.dom.elGridRectMarkerMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elGridRectMarkerMask.setAttribute("id","gridRectMarkerMask".concat(e.cuid)),e.dom.elForecastMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elForecastMask.setAttribute("id","forecastMask".concat(e.cuid)),e.dom.elNonForecastMask=document.createElementNS(e.SVGNS,"clipPath"),e.dom.elNonForecastMask.setAttribute("id","nonForecastMask".concat(e.cuid));var r=t.config.chart.type,o=0,n=0;("bar"===r||"rangeBar"===r||"candlestick"===r||"boxPlot"===r||t.globals.comboBarCount>0)&&t.globals.isXNumeric&&!t.globals.isBarHorizontal&&(o=t.config.grid.padding.left,n=t.config.grid.padding.right,e.barPadForNumericAxis>o&&(o=e.barPadForNumericAxis,n=e.barPadForNumericAxis)),e.dom.elGridRect=i.drawRect(-a/2-o-2,-a/2,e.gridWidth+a+n+o+4,e.gridHeight+a,0,"#fff");var l=t.globals.markers.largestSize+1;e.dom.elGridRectMarker=i.drawRect(2*-l,2*-l,e.gridWidth+4*l,e.gridHeight+4*l,0,"#fff"),e.dom.elGridRectMask.appendChild(e.dom.elGridRect.node),e.dom.elGridRectMarkerMask.appendChild(e.dom.elGridRectMarker.node);var h=e.dom.baseEl.querySelector("defs");h.appendChild(e.dom.elGridRectMask),h.appendChild(e.dom.elForecastMask),h.appendChild(e.dom.elNonForecastMask),h.appendChild(e.dom.elGridRectMarkerMask)}},{key:"_drawGridLines",value:function(t){var e=t.i,i=t.x1,a=t.y1,s=t.x2,r=t.y2,o=t.xCount,n=t.parent,l=this.w;if(!(0===e&&l.globals.skipFirstTimelinelabel||e===o-1&&l.globals.skipLastTimelinelabel&&!l.config.xaxis.labels.formatter||"radar"===l.config.chart.type)){l.config.grid.xaxis.lines.show&&this._drawGridLine({i:e,x1:i,y1:a,x2:s,y2:r,xCount:o,parent:n});var h=0;if(l.globals.hasGroups&&"between"===l.config.xaxis.tickPlacement){var c=l.globals.groups;if(c){for(var d=0,g=0;d2));s++);return!t.globals.isBarHorizontal||this.isRangeBar?(i=this.xaxisLabels.length,this.isRangeBar&&(a=t.globals.labels.length,t.config.xaxis.tickAmount&&t.config.xaxis.labels.formatter&&(i=t.config.xaxis.tickAmount)),this._drawXYLines({xCount:i,tickAmount:a})):(i=a,a=t.globals.xTickAmount,this._drawInvertedXYLines({xCount:i,tickAmount:a})),this.drawGridBands(i,a),{el:this.elg,elGridBorders:this.elGridBorders,xAxisTickWidth:t.globals.gridWidth/i}}},{key:"drawGridBands",value:function(t,e){var i=this.w;if(void 0!==i.config.grid.row.colors&&i.config.grid.row.colors.length>0)for(var a=0,s=i.globals.gridHeight/e,r=i.globals.gridWidth,o=0,n=0;o=i.config.grid.row.colors.length&&(n=0),this._drawGridBandRect({c:n,x1:0,y1:a,x2:r,y2:s,type:"row"}),a+=i.globals.gridHeight/e;if(void 0!==i.config.grid.column.colors&&i.config.grid.column.colors.length>0)for(var l=i.globals.isBarHorizontal||"category"!==i.config.xaxis.type&&!i.config.xaxis.convertedCatToNumeric?t:t-1,h=i.globals.padHorizontal,c=i.globals.padHorizontal+i.globals.gridWidth/l,d=i.globals.gridHeight,g=0,u=0;g=i.config.grid.column.colors.length&&(u=0),this._drawGridBandRect({c:u,x1:h,y1:0,x2:c,y2:d,type:"column"}),h+=i.globals.gridWidth/l}}]),t}(),_=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"niceScale",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,s=arguments.length>4?arguments[4]:void 0,r=this.w,o=Math.abs(e-t);if("dataPoints"===(i=this._adjustTicksForSmallRange(i,a,o))&&(i=r.globals.dataPoints-1),t===Number.MIN_VALUE&&0===e||!x.isNumber(t)&&!x.isNumber(e)||t===Number.MIN_VALUE&&e===-Number.MAX_VALUE){t=0,e=i;var n=this.linearScale(t,e,i);return n}t>e?(console.warn("axis.min cannot be greater than axis.max"),e=t+.1):t===e&&(t=0===t?0:t-.5,e=0===e?2:e+.5);var l=[];o<1&&s&&("candlestick"===r.config.chart.type||"candlestick"===r.config.series[a].type||"boxPlot"===r.config.chart.type||"boxPlot"===r.config.series[a].type||r.globals.isRangeData)&&(e*=1.01);var h=i+1;h<2?h=2:h>2&&(h-=2);var c=o/h,d=Math.floor(x.log10(c)),g=Math.pow(10,d),u=Math.round(c/g);u<1&&(u=1);var f=u*g,p=f*Math.floor(t/f),b=f*Math.ceil(e/f),v=p;if(s&&o>2){for(;l.push(v),!((v+=f)>b););return{result:l,niceMin:l[0],niceMax:l[l.length-1]}}var m=t;(l=[]).push(m);for(var y=Math.abs(e-t)/i,w=0;w<=i;w++)m+=y,l.push(m);return l[l.length-2]>=e&&l.pop(),{result:l,niceMin:l[0],niceMax:l[l.length-1]}}},{key:"linearScale",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:10,a=arguments.length>3?arguments[3]:void 0,s=Math.abs(e-t);"dataPoints"===(i=this._adjustTicksForSmallRange(i,a,s))&&(i=this.w.globals.dataPoints-1);var r=s/i;i===Number.MAX_VALUE&&(i=10,r=1);for(var o=[],n=t;i>=0;)o.push(n),n+=r,i-=1;return{result:o,niceMin:o[0],niceMax:o[o.length-1]}}},{key:"logarithmicScaleNice",value:function(t,e,i){e<=0&&(e=Math.max(t,i)),t<=0&&(t=Math.min(e,i));for(var a=[],s=Math.ceil(Math.log(e)/Math.log(i)+1),r=Math.floor(Math.log(t)/Math.log(i));r5)a.allSeriesCollapsed=!1,a.yAxisScale[t]=this.logarithmicScale(e,i,r.logBase),a.yAxisScale[t]=r.forceNiceScale?this.logarithmicScaleNice(e,i,r.logBase):this.logarithmicScale(e,i,r.logBase);else if(i!==-Number.MAX_VALUE&&x.isNumber(i))if(a.allSeriesCollapsed=!1,void 0===r.min&&void 0===r.max||r.forceNiceScale){var n=void 0===s.yaxis[t].max&&void 0===s.yaxis[t].min||s.yaxis[t].forceNiceScale;a.yAxisScale[t]=this.niceScale(e,i,r.tickAmount?r.tickAmount:o<5&&o>1?o+1:5,t,n)}else a.yAxisScale[t]=this.linearScale(e,i,r.tickAmount,t);else a.yAxisScale[t]=this.linearScale(0,5,5)}},{key:"setXScale",value:function(t,e){var i=this.w,a=i.globals,s=i.config.xaxis,r=Math.abs(e-t);return e!==-Number.MAX_VALUE&&x.isNumber(e)?a.xAxisScale=this.linearScale(t,e,s.tickAmount?s.tickAmount:r<5&&r>1?r+1:5,0):a.xAxisScale=this.linearScale(0,5,5),a.xAxisScale}},{key:"setMultipleYScales",value:function(){var t=this,e=this.w.globals,i=this.w.config,a=e.minYArr.concat([]),s=e.maxYArr.concat([]),r=[];i.yaxis.forEach((function(e,o){var n=o;i.series.forEach((function(t,i){t.name===e.seriesName&&(n=i,o!==i?r.push({index:i,similarIndex:o,alreadyExists:!0}):r.push({index:i}))}));var l=a[n],h=s[n];t.setYScaleForIndex(o,l,h)})),this.sameScaleInMultipleAxes(a,s,r)}},{key:"sameScaleInMultipleAxes",value:function(t,e,i){var a=this,s=this.w.config,r=this.w.globals,o=[];i.forEach((function(t){t.alreadyExists&&(void 0===o[t.index]&&(o[t.index]=[]),o[t.index].push(t.index),o[t.index].push(t.similarIndex))})),r.yAxisSameScaleIndices=o,o.forEach((function(t,e){o.forEach((function(i,a){var s,r;e!==a&&(s=t,r=i,s.filter((function(t){return-1!==r.indexOf(t)}))).length>0&&(o[e]=o[e].concat(o[a]))}))}));var n=o.map((function(t){return t.filter((function(e,i){return t.indexOf(e)===i}))})).map((function(t){return t.sort()}));o=o.filter((function(t){return!!t}));var l=n.slice(),h=l.map((function(t){return JSON.stringify(t)}));l=l.filter((function(t,e){return h.indexOf(JSON.stringify(t))===e}));var c=[],d=[];t.forEach((function(t,i){l.forEach((function(a,s){a.indexOf(i)>-1&&(void 0===c[s]&&(c[s]=[],d[s]=[]),c[s].push({key:i,value:t}),d[s].push({key:i,value:e[i]}))}))}));var g=Array.apply(null,Array(l.length)).map(Number.prototype.valueOf,Number.MIN_VALUE),u=Array.apply(null,Array(l.length)).map(Number.prototype.valueOf,-Number.MAX_VALUE);c.forEach((function(t,e){t.forEach((function(t,i){g[e]=Math.min(t.value,g[e])}))})),d.forEach((function(t,e){t.forEach((function(t,i){u[e]=Math.max(t.value,u[e])}))})),t.forEach((function(t,e){d.forEach((function(t,i){var o=g[i],n=u[i];s.chart.stacked&&(n=0,t.forEach((function(t,e){t.value!==-Number.MAX_VALUE&&(n+=t.value),o!==Number.MIN_VALUE&&(o+=c[i][e].value)}))),t.forEach((function(i,l){t[l].key===e&&(void 0!==s.yaxis[e].min&&(o="function"==typeof s.yaxis[e].min?s.yaxis[e].min(r.minY):s.yaxis[e].min),void 0!==s.yaxis[e].max&&(n="function"==typeof s.yaxis[e].max?s.yaxis[e].max(r.maxY):s.yaxis[e].max),a.setYScaleForIndex(e,o,n))}))}))}))}},{key:"autoScaleY",value:function(t,e,i){t||(t=this);var a=t.w;if(a.globals.isMultipleYAxis||a.globals.collapsedSeries.length)return console.warn("autoScaleYaxis is not supported in a multi-yaxis chart."),e;var s=a.globals.seriesX[0],r=a.config.chart.stacked;return e.forEach((function(t,o){for(var n=0,l=0;l=i.xaxis.min){n=l;break}var h,c,d=a.globals.minYArr[o],g=a.globals.maxYArr[o],u=a.globals.stackedSeriesTotals;a.globals.series.forEach((function(o,l){var f=o[n];r?(f=u[n],h=c=f,u.forEach((function(t,e){s[e]<=i.xaxis.max&&s[e]>=i.xaxis.min&&(t>c&&null!==t&&(c=t),o[e]=i.xaxis.min){var r=t,o=t;a.globals.series.forEach((function(i,a){null!==t&&(r=Math.min(i[e],r),o=Math.max(i[e],o))})),o>c&&null!==o&&(c=o),rd&&(h=d),e.length>1?(e[l].min=void 0===t.min?h:t.min,e[l].max=void 0===t.max?c:t.max):(e[0].min=void 0===t.min?h:t.min,e[0].max=void 0===t.max?c:t.max)}))})),e}}]),t}(),U=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.scales=new _(e)}return r(t,[{key:"init",value:function(){this.setYRange(),this.setXRange(),this.setZRange()}},{key:"getMinYMaxY",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Number.MAX_VALUE,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:-Number.MAX_VALUE,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w.config,r=this.w.globals,o=-Number.MAX_VALUE,n=Number.MIN_VALUE;null===a&&(a=t+1);var l=r.series,h=l,c=l;"candlestick"===s.chart.type?(h=r.seriesCandleL,c=r.seriesCandleH):"boxPlot"===s.chart.type?(h=r.seriesCandleO,c=r.seriesCandleC):r.isRangeData&&(h=r.seriesRangeStart,c=r.seriesRangeEnd);for(var d=t;dh[d][g]&&h[d][g]<0&&(n=h[d][g])):r.hasNullValues=!0}}return"rangeBar"===s.chart.type&&r.seriesRangeStart.length&&r.isBarHorizontal&&(n=e),"bar"===s.chart.type&&(n<0&&o<0&&(o=0),n===Number.MIN_VALUE&&(n=0)),{minY:n,maxY:o,lowestY:e,highestY:i}}},{key:"setYRange",value:function(){var t=this.w.globals,e=this.w.config;t.maxY=-Number.MAX_VALUE,t.minY=Number.MIN_VALUE;var i=Number.MAX_VALUE;if(t.isMultipleYAxis)for(var a=0;a=0&&i<=10||void 0!==e.yaxis[0].min||void 0!==e.yaxis[0].max)&&(o=0),t.minY=i-5*o/100,i>0&&t.minY<0&&(t.minY=0),t.maxY=t.maxY+5*o/100}if(e.yaxis.forEach((function(e,i){void 0!==e.max&&("number"==typeof e.max?t.maxYArr[i]=e.max:"function"==typeof e.max&&(t.maxYArr[i]=e.max(t.isMultipleYAxis?t.maxYArr[i]:t.maxY)),t.maxY=t.maxYArr[i]),void 0!==e.min&&("number"==typeof e.min?t.minYArr[i]=e.min:"function"==typeof e.min&&(t.minYArr[i]=e.min(t.isMultipleYAxis?t.minYArr[i]===Number.MIN_VALUE?0:t.minYArr[i]:t.minY)),t.minY=t.minYArr[i])})),t.isBarHorizontal){["min","max"].forEach((function(i){void 0!==e.xaxis[i]&&"number"==typeof e.xaxis[i]&&("min"===i?t.minY=e.xaxis[i]:t.maxY=e.xaxis[i])}))}return t.isMultipleYAxis?(this.scales.setMultipleYScales(),t.minY=i,t.yAxisScale.forEach((function(e,i){t.minYArr[i]=e.niceMin,t.maxYArr[i]=e.niceMax}))):(this.scales.setYScaleForIndex(0,t.minY,t.maxY),t.minY=t.yAxisScale[0].niceMin,t.maxY=t.yAxisScale[0].niceMax,t.minYArr[0]=t.yAxisScale[0].niceMin,t.maxYArr[0]=t.yAxisScale[0].niceMax),{minY:t.minY,maxY:t.maxY,minYArr:t.minYArr,maxYArr:t.maxYArr,yAxisScale:t.yAxisScale}}},{key:"setXRange",value:function(){var t=this.w.globals,e=this.w.config,i="numeric"===e.xaxis.type||"datetime"===e.xaxis.type||"category"===e.xaxis.type&&!t.noLabelsProvided||t.noLabelsProvided||t.isXNumeric;if(t.isXNumeric&&function(){for(var e=0;et.dataPoints&&0!==t.dataPoints&&(a=t.dataPoints-1)):"dataPoints"===e.xaxis.tickAmount?(t.series.length>1&&(a=t.series[t.maxValsInArrayIndex].length-1),t.isXNumeric&&(a=t.maxX-t.minX-1)):a=e.xaxis.tickAmount,t.xTickAmount=a,void 0!==e.xaxis.max&&"number"==typeof e.xaxis.max&&(t.maxX=e.xaxis.max),void 0!==e.xaxis.min&&"number"==typeof e.xaxis.min&&(t.minX=e.xaxis.min),void 0!==e.xaxis.range&&(t.minX=t.maxX-e.xaxis.range),t.minX!==Number.MAX_VALUE&&t.maxX!==-Number.MAX_VALUE)if(e.xaxis.convertedCatToNumeric&&!t.dataFormatXNumeric){for(var s=[],r=t.minX-1;r0&&(t.xAxisScale=this.scales.linearScale(1,t.labels.length,a-1),t.seriesX=t.labels.slice());i&&(t.labels=t.xAxisScale.result.slice())}return t.isBarHorizontal&&t.labels.length&&(t.xTickAmount=t.labels.length),this._handleSingleDataPoint(),this._getMinXDiff(),{minX:t.minX,maxX:t.maxX}}},{key:"setZRange",value:function(){var t=this.w.globals;if(t.isDataXYZ)for(var e=0;e0){var s=e-a[i-1];s>0&&(t.minXDiff=Math.min(s,t.minXDiff))}})),1!==t.dataPoints&&t.minXDiff!==Number.MAX_VALUE||(t.minXDiff=.5)}))}},{key:"_setStackedMinMax",value:function(){var t=this.w.globals,e=[],i=[];if(t.series.length)for(var a=0;a0?s=s+parseFloat(t.series[o][a])+1e-4:r+=parseFloat(t.series[o][a])),o===t.series.length-1&&(e.push(s),i.push(r));for(var n=0;n=0;b--)x(b);if(void 0!==i.config.yaxis[t].title.text){var v=a.group({class:"apexcharts-yaxis-title"}),y=0;i.config.yaxis[t].opposite&&(y=i.globals.translateYAxisX[t]);var w=a.drawText({x:y,y:i.globals.gridHeight/2+i.globals.translateY+i.config.yaxis[t].title.offsetY,text:i.config.yaxis[t].title.text,textAnchor:"end",foreColor:i.config.yaxis[t].title.style.color,fontSize:i.config.yaxis[t].title.style.fontSize,fontWeight:i.config.yaxis[t].title.style.fontWeight,fontFamily:i.config.yaxis[t].title.style.fontFamily,cssClass:"apexcharts-yaxis-title-text "+i.config.yaxis[t].title.style.cssClass});v.add(w),l.add(v)}var k=i.config.yaxis[t].axisBorder,A=31+k.offsetX;if(i.config.yaxis[t].opposite&&(A=-31-k.offsetX),k.show){var S=a.drawLine(A,i.globals.translateY+k.offsetY-2,A,i.globals.gridHeight+i.globals.translateY+k.offsetY+2,k.color,0,k.width);l.add(S)}return i.config.yaxis[t].axisTicks.show&&this.axesUtils.drawYAxisTicks(A,c,k,i.config.yaxis[t].axisTicks,t,d,l),l}},{key:"drawYaxisInversed",value:function(t){var e=this.w,i=new m(this.ctx),a=i.group({class:"apexcharts-xaxis apexcharts-yaxis-inversed"}),s=i.group({class:"apexcharts-xaxis-texts-g",transform:"translate(".concat(e.globals.translateXAxisX,", ").concat(e.globals.translateXAxisY,")")});a.add(s);var r=e.globals.yAxisScale[t].result.length-1,o=e.globals.gridWidth/r+.1,n=o+e.config.xaxis.labels.offsetX,l=e.globals.xLabelFormatter,h=e.globals.yAxisScale[t].result.slice(),c=e.globals.timescaleLabels;c.length>0&&(this.xaxisLabels=c.slice(),r=(h=c.slice()).length),h=this.axesUtils.checkForReversedLabels(t,h);var d=c.length;if(e.config.xaxis.labels.show)for(var g=d?0:r;d?g=0;d?g++:g--){var u=h[g];u=l(u,g,e);var f=e.globals.gridWidth+e.globals.padHorizontal-(n-o+e.config.xaxis.labels.offsetX);if(c.length){var p=this.axesUtils.getLabel(h,c,f,g,this.drawnLabels,this.xaxisFontSize);f=p.x,u=p.text,this.drawnLabels.push(p.text),0===g&&e.globals.skipFirstTimelinelabel&&(u=""),g===h.length-1&&e.globals.skipLastTimelinelabel&&(u="")}var x=i.drawText({x:f,y:this.xAxisoffX+e.config.xaxis.labels.offsetY+30-("top"===e.config.xaxis.position?e.globals.xAxisHeight+e.config.xaxis.axisTicks.height-2:0),text:u,textAnchor:"middle",foreColor:Array.isArray(this.xaxisForeColors)?this.xaxisForeColors[t]:this.xaxisForeColors,fontSize:this.xaxisFontSize,fontFamily:this.xaxisFontFamily,fontWeight:e.config.xaxis.labels.style.fontWeight,isPlainText:!1,cssClass:"apexcharts-xaxis-label "+e.config.xaxis.labels.style.cssClass});s.add(x),x.tspan(u);var b=document.createElementNS(e.globals.SVGNS,"title");b.textContent=u,x.node.appendChild(b),n+=o}return this.inversedYAxisTitleText(a),this.inversedYAxisBorder(a),a}},{key:"inversedYAxisBorder",value:function(t){var e=this.w,i=new m(this.ctx),a=e.config.xaxis.axisBorder;if(a.show){var s=0;"bar"===e.config.chart.type&&e.globals.isXNumeric&&(s-=15);var r=i.drawLine(e.globals.padHorizontal+s+a.offsetX,this.xAxisoffX,e.globals.gridWidth,this.xAxisoffX,a.color,0,a.height);this.elgrid&&this.elgrid.elGridBorders?this.elgrid.elGridBorders.add(r):t.add(r)}}},{key:"inversedYAxisTitleText",value:function(t){var e=this.w,i=new m(this.ctx);if(void 0!==e.config.xaxis.title.text){var a=i.group({class:"apexcharts-xaxis-title apexcharts-yaxis-title-inversed"}),s=i.drawText({x:e.globals.gridWidth/2+e.config.xaxis.title.offsetX,y:this.xAxisoffX+parseFloat(this.xaxisFontSize)+parseFloat(e.config.xaxis.title.style.fontSize)+e.config.xaxis.title.offsetY+20,text:e.config.xaxis.title.text,textAnchor:"middle",fontSize:e.config.xaxis.title.style.fontSize,fontFamily:e.config.xaxis.title.style.fontFamily,fontWeight:e.config.xaxis.title.style.fontWeight,foreColor:e.config.xaxis.title.style.color,cssClass:"apexcharts-xaxis-title-text "+e.config.xaxis.title.style.cssClass});a.add(s),t.add(a)}}},{key:"yAxisTitleRotate",value:function(t,e){var i=this.w,a=new m(this.ctx),s={width:0,height:0},r={width:0,height:0},o=i.globals.dom.baseEl.querySelector(" .apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-texts-g"));null!==o&&(s=o.getBoundingClientRect());var n=i.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(t,"'] .apexcharts-yaxis-title text"));if(null!==n&&(r=n.getBoundingClientRect()),null!==n){var l=this.xPaddingForYAxisTitle(t,s,r,e);n.setAttribute("x",l.xPos-(e?10:0))}if(null!==n){var h=a.rotateAroundCenter(n);n.setAttribute("transform","rotate(".concat(e?-1*i.config.yaxis[t].title.rotate:i.config.yaxis[t].title.rotate," ").concat(h.x," ").concat(h.y,")"))}}},{key:"xPaddingForYAxisTitle",value:function(t,e,i,a){var s=this.w,r=0,o=0,n=10;return void 0===s.config.yaxis[t].title.text||t<0?{xPos:o,padd:0}:(a?(o=e.width+s.config.yaxis[t].title.offsetX+i.width/2+n/2,0===(r+=1)&&(o-=n/2)):(o=-1*e.width+s.config.yaxis[t].title.offsetX+n/2+i.width/2,s.globals.isBarHorizontal&&(n=25,o=-1*e.width-s.config.yaxis[t].title.offsetX-n)),{xPos:o,padd:n})}},{key:"setYAxisXPosition",value:function(t,e){var i=this.w,a=0,s=0,r=18,o=1;i.config.yaxis.length>1&&(this.multipleYs=!0),i.config.yaxis.map((function(n,l){var h=i.globals.ignoreYAxisIndexes.indexOf(l)>-1||!n.show||n.floating||0===t[l].width,c=t[l].width+e[l].width;n.opposite?i.globals.isBarHorizontal?(s=i.globals.gridWidth+i.globals.translateX-1,i.globals.translateYAxisX[l]=s-n.labels.offsetX):(s=i.globals.gridWidth+i.globals.translateX+o,h||(o=o+c+20),i.globals.translateYAxisX[l]=s-n.labels.offsetX+20):(a=i.globals.translateX-r,h||(r=r+c+20),i.globals.translateYAxisX[l]=a+n.labels.offsetX)}))}},{key:"setYAxisTextAlignments",value:function(){var t=this.w,e=t.globals.dom.baseEl.getElementsByClassName("apexcharts-yaxis");(e=x.listToArray(e)).forEach((function(e,i){var a=t.config.yaxis[i];if(a&&!a.floating&&void 0!==a.labels.align){var s=t.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-texts-g")),r=t.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(i,"'] .apexcharts-yaxis-label"));r=x.listToArray(r);var o=s.getBoundingClientRect();"left"===a.labels.align?(r.forEach((function(t,e){t.setAttribute("text-anchor","start")})),a.opposite||s.setAttribute("transform","translate(-".concat(o.width,", 0)"))):"center"===a.labels.align?(r.forEach((function(t,e){t.setAttribute("text-anchor","middle")})),s.setAttribute("transform","translate(".concat(o.width/2*(a.opposite?1:-1),", 0)"))):"right"===a.labels.align&&(r.forEach((function(t,e){t.setAttribute("text-anchor","end")})),a.opposite&&s.setAttribute("transform","translate(".concat(o.width,", 0)")))}}))}}]),t}(),Z=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.documentEvent=x.bind(this.documentEvent,this)}return r(t,[{key:"addEventListener",value:function(t,e){var i=this.w;i.globals.events.hasOwnProperty(t)?i.globals.events[t].push(e):i.globals.events[t]=[e]}},{key:"removeEventListener",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){var a=i.globals.events[t].indexOf(e);-1!==a&&i.globals.events[t].splice(a,1)}}},{key:"fireEvent",value:function(t,e){var i=this.w;if(i.globals.events.hasOwnProperty(t)){e&&e.length||(e=[]);for(var a=i.globals.events[t],s=a.length,r=0;r0&&(e=this.w.config.chart.locales.concat(window.Apex.chart.locales));var i=e.filter((function(e){return e.name===t}))[0];if(!i)throw new Error("Wrong locale name provided. Please make sure you set the correct locale name in options");var a=x.extend(C,i);this.w.globals.locale=a.options}}]),t}(),J=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"drawAxis",value:function(t,e){var i,a,s=this,r=this.w.globals,o=this.w.config,n=new V(this.ctx,e),l=new q(this.ctx,e);r.axisCharts&&"radar"!==t&&(r.isBarHorizontal?(a=l.drawYaxisInversed(0),i=n.drawXaxisInversed(0),r.dom.elGraphical.add(i),r.dom.elGraphical.add(a)):(i=n.drawXaxis(),r.dom.elGraphical.add(i),o.yaxis.map((function(t,e){if(-1===r.ignoreYAxisIndexes.indexOf(e)&&(a=l.drawYaxis(e),r.dom.Paper.add(a),"back"===s.w.config.grid.position)){var i=r.dom.Paper.children()[1];i.remove(),r.dom.Paper.add(i)}}))))}}]),t}(),Q=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"drawXCrosshairs",value:function(){var t=this.w,e=new m(this.ctx),i=new v(this.ctx),a=t.config.xaxis.crosshairs.fill.gradient,s=t.config.xaxis.crosshairs.dropShadow,r=t.config.xaxis.crosshairs.fill.type,o=a.colorFrom,n=a.colorTo,l=a.opacityFrom,h=a.opacityTo,c=a.stops,d=s.enabled,g=s.left,u=s.top,f=s.blur,p=s.color,b=s.opacity,y=t.config.xaxis.crosshairs.fill.color;if(t.config.xaxis.crosshairs.show){"gradient"===r&&(y=e.drawGradient("vertical",o,n,l,h,null,c,null));var w=e.drawRect();1===t.config.xaxis.crosshairs.width&&(w=e.drawLine());var k=t.globals.gridHeight;(!x.isNumber(k)||k<0)&&(k=0);var A=t.config.xaxis.crosshairs.width;(!x.isNumber(A)||A<0)&&(A=0),w.attr({class:"apexcharts-xcrosshairs",x:0,y:0,y2:k,width:A,height:k,fill:y,filter:"none","fill-opacity":t.config.xaxis.crosshairs.opacity,stroke:t.config.xaxis.crosshairs.stroke.color,"stroke-width":t.config.xaxis.crosshairs.stroke.width,"stroke-dasharray":t.config.xaxis.crosshairs.stroke.dashArray}),d&&(w=i.dropShadow(w,{left:g,top:u,blur:f,color:p,opacity:b})),t.globals.dom.elGraphical.add(w)}}},{key:"drawYCrosshairs",value:function(){var t=this.w,e=new m(this.ctx),i=t.config.yaxis[0].crosshairs,a=t.globals.barPadForNumericAxis;if(t.config.yaxis[0].crosshairs.show){var s=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,i.stroke.dashArray,i.stroke.width);s.attr({class:"apexcharts-ycrosshairs"}),t.globals.dom.elGraphical.add(s)}var r=e.drawLine(-a,0,t.globals.gridWidth+a,0,i.stroke.color,0,0);r.attr({class:"apexcharts-ycrosshairs-hidden"}),t.globals.dom.elGraphical.add(r)}}]),t}(),K=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"checkResponsiveConfig",value:function(t){var e=this,i=this.w,a=i.config;if(0!==a.responsive.length){var s=a.responsive.slice();s.sort((function(t,e){return t.breakpoint>e.breakpoint?1:e.breakpoint>t.breakpoint?-1:0})).reverse();var r=new E({}),o=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},a=s[0].breakpoint,o=window.innerWidth>0?window.innerWidth:screen.width;if(o>a){var n=y.extendArrayProps(r,i.globals.initialConfig,i);t=x.extend(n,t),t=x.extend(i.config,t),e.overrideResponsiveOptions(t)}else for(var l=0;l0&&"function"==typeof e.config.colors[0]&&(e.globals.colors=e.config.series.map((function(i,a){var s=e.config.colors[a];return s||(s=e.config.colors[0]),"function"==typeof s?(t.isColorFn=!0,s({value:e.globals.axisCharts?e.globals.series[a][0]?e.globals.series[a][0]:0:e.globals.series[a],seriesIndex:a,dataPointIndex:a,w:e})):s})))),e.globals.seriesColors.map((function(t,i){t&&(e.globals.colors[i]=t)})),e.config.theme.monochrome.enabled){var a=[],s=e.globals.series.length;(this.isBarDistributed||this.isHeatmapDistributed)&&(s=e.globals.series[0].length*e.globals.series.length);for(var r=e.config.theme.monochrome.color,o=1/(s/e.config.theme.monochrome.shadeIntensity),n=e.config.theme.monochrome.shadeTo,l=0,h=0;h2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=e||a.globals.series.length;if(null===i&&(i=this.isBarDistributed||this.isHeatmapDistributed||"heatmap"===a.config.chart.type&&a.config.plotOptions.heatmap.colorScale.inverse),i&&a.globals.series.length&&(s=a.globals.series[a.globals.maxValsInArrayIndex].length*a.globals.series.length),t.lengtht.globals.svgWidth&&(this.dCtx.lgRect.width=t.globals.svgWidth/1.5),this.dCtx.lgRect}},{key:"getLargestStringFromMultiArr",value:function(t,e){var i=t;if(this.w.globals.isMultiLineX){var a=e.map((function(t,e){return Array.isArray(t)?t.length:1})),s=Math.max.apply(Math,u(a));i=e[a.indexOf(s)]}return i}}]),t}(),at=function(){function t(e){a(this,t),this.w=e.w,this.dCtx=e}return r(t,[{key:"getxAxisLabelsCoords",value:function(){var t,e=this.w,i=e.globals.labels.slice();if(e.config.xaxis.convertedCatToNumeric&&0===i.length&&(i=e.globals.categoryLabels),e.globals.timescaleLabels.length>0){var a=this.getxAxisTimeScaleLabelsCoords();t={width:a.width,height:a.height},e.globals.rotateXLabels=!1}else{this.dCtx.lgWidthForSideLegends="left"!==e.config.legend.position&&"right"!==e.config.legend.position||e.config.legend.floating?0:this.dCtx.lgRect.width;var s=e.globals.xLabelFormatter,r=x.getLargestStringFromArr(i),o=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,i);e.globals.isBarHorizontal&&(o=r=e.globals.yAxisScale[0].result.reduce((function(t,e){return t.length>e.length?t:e}),0));var n=new M(this.dCtx.ctx),l=r;r=n.xLabelFormat(s,r,l,{i:void 0,dateFormatter:new T(this.dCtx.ctx).formatDate,w:e}),o=n.xLabelFormat(s,o,l,{i:void 0,dateFormatter:new T(this.dCtx.ctx).formatDate,w:e}),(e.config.xaxis.convertedCatToNumeric&&void 0===r||""===String(r).trim())&&(o=r="1");var h=new m(this.dCtx.ctx),c=h.getTextRects(r,e.config.xaxis.labels.style.fontSize),d=c;if(r!==o&&(d=h.getTextRects(o,e.config.xaxis.labels.style.fontSize)),(t={width:c.width>=d.width?c.width:d.width,height:c.height>=d.height?c.height:d.height}).width*i.length>e.globals.svgWidth-this.dCtx.lgWidthForSideLegends-this.dCtx.yAxisWidth-this.dCtx.gridPad.left-this.dCtx.gridPad.right&&0!==e.config.xaxis.labels.rotate||e.config.xaxis.labels.rotateAlways){if(!e.globals.isBarHorizontal){e.globals.rotateXLabels=!0;var g=function(t){return h.getTextRects(t,e.config.xaxis.labels.style.fontSize,e.config.xaxis.labels.style.fontFamily,"rotate(".concat(e.config.xaxis.labels.rotate," 0 0)"),!1)};c=g(r),r!==o&&(d=g(o)),t.height=(c.height>d.height?c.height:d.height)/1.5,t.width=c.width>d.width?c.width:d.width}}else e.globals.rotateXLabels=!1}return e.config.xaxis.labels.show||(t={width:0,height:0}),{width:t.width,height:t.height}}},{key:"getxAxisGroupLabelsCoords",value:function(){var t,e=this.w;if(!e.globals.hasGroups)return{width:0,height:0};var i,a=(null===(t=e.config.xaxis.group.style)||void 0===t?void 0:t.fontSize)||e.config.xaxis.labels.style.fontSize,s=e.globals.groups.map((function(t){return t.title})),r=x.getLargestStringFromArr(s),o=this.dCtx.dimHelpers.getLargestStringFromMultiArr(r,s),n=new m(this.dCtx.ctx),l=n.getTextRects(r,a),h=l;return r!==o&&(h=n.getTextRects(o,a)),i={width:l.width>=h.width?l.width:h.width,height:l.height>=h.height?l.height:h.height},e.config.xaxis.labels.show||(i={width:0,height:0}),{width:i.width,height:i.height}}},{key:"getxAxisTitleCoords",value:function(){var t=this.w,e=0,i=0;if(void 0!==t.config.xaxis.title.text){var a=new m(this.dCtx.ctx).getTextRects(t.config.xaxis.title.text,t.config.xaxis.title.style.fontSize);e=a.width,i=a.height}return{width:e,height:i}}},{key:"getxAxisTimeScaleLabelsCoords",value:function(){var t,e=this.w;this.dCtx.timescaleLabels=e.globals.timescaleLabels.slice();var i=this.dCtx.timescaleLabels.map((function(t){return t.value})),a=i.reduce((function(t,e){return void 0===t?(console.error("You have possibly supplied invalid Date format. Please supply a valid JavaScript Date"),0):t.length>e.length?t:e}),0);return 1.05*(t=new m(this.dCtx.ctx).getTextRects(a,e.config.xaxis.labels.style.fontSize)).width*i.length>e.globals.gridWidth&&0!==e.config.xaxis.labels.rotate&&(e.globals.overlappingXLabels=!0),t}},{key:"additionalPaddingXLabels",value:function(t){var e=this,i=this.w,a=i.globals,s=i.config,r=s.xaxis.type,o=t.width;a.skipLastTimelinelabel=!1,a.skipFirstTimelinelabel=!1;var n=i.config.yaxis[0].opposite&&i.globals.isBarHorizontal,l=function(t,n){(function(t){return-1!==a.collapsedSeriesIndices.indexOf(t)})(n)||function(t){if(e.dCtx.timescaleLabels&&e.dCtx.timescaleLabels.length){var n=e.dCtx.timescaleLabels[0],l=e.dCtx.timescaleLabels[e.dCtx.timescaleLabels.length-1].position+o/1.75-e.dCtx.yAxisWidthRight,h=n.position-o/1.75+e.dCtx.yAxisWidthLeft,c="right"===i.config.legend.position&&e.dCtx.lgRect.width>0?e.dCtx.lgRect.width:0;l>a.svgWidth-a.translateX-c&&(a.skipLastTimelinelabel=!0),h<-(t.show&&!t.floating||"bar"!==s.chart.type&&"candlestick"!==s.chart.type&&"rangeBar"!==s.chart.type&&"boxPlot"!==s.chart.type?10:o/1.75)&&(a.skipFirstTimelinelabel=!0)}else"datetime"===r?e.dCtx.gridPad.rightString(n.niceMax).length?c:n.niceMax,g=h(d,{seriesIndex:o,dataPointIndex:-1,w:e}),u=g;if(void 0!==g&&0!==g.length||(g=d),e.globals.isBarHorizontal){a=0;var f=e.globals.labels.slice();g=h(g=x.getLargestStringFromArr(f),{seriesIndex:o,dataPointIndex:-1,w:e}),u=t.dCtx.dimHelpers.getLargestStringFromMultiArr(g,f)}var p=new m(t.dCtx.ctx),b="rotate(".concat(r.labels.rotate," 0 0)"),v=p.getTextRects(g,r.labels.style.fontSize,r.labels.style.fontFamily,b,!1),y=v;g!==u&&(y=p.getTextRects(u,r.labels.style.fontSize,r.labels.style.fontFamily,b,!1)),i.push({width:(l>y.width||l>v.width?l:y.width>v.width?y.width:v.width)+a,height:y.height>v.height?y.height:v.height})}else i.push({width:0,height:0})})),i}},{key:"getyAxisTitleCoords",value:function(){var t=this,e=this.w,i=[];return e.config.yaxis.map((function(e,a){if(e.show&&void 0!==e.title.text){var s=new m(t.dCtx.ctx),r="rotate(".concat(e.title.rotate," 0 0)"),o=s.getTextRects(e.title.text,e.title.style.fontSize,e.title.style.fontFamily,r,!1);i.push({width:o.width,height:o.height})}else i.push({width:0,height:0})})),i}},{key:"getTotalYAxisWidth",value:function(){var t=this.w,e=0,i=0,a=0,s=t.globals.yAxisScale.length>1?10:0,r=new B(this.dCtx.ctx),o=function(o,n){var l=t.config.yaxis[n].floating,h=0;o.width>0&&!l?(h=o.width+s,function(e){return t.globals.ignoreYAxisIndexes.indexOf(e)>-1}(n)&&(h=h-o.width-s)):h=l||r.isYAxisHidden(n)?0:5,t.config.yaxis[n].opposite?a+=h:i+=h,e+=h};return t.globals.yLabelsCoords.map((function(t,e){o(t,e)})),t.globals.yTitleCoords.map((function(t,e){o(t,e)})),t.globals.isBarHorizontal&&!t.config.yaxis[0].floating&&(e=t.globals.yLabelsCoords[0].width+t.globals.yTitleCoords[0].width+15),this.dCtx.yAxisWidthLeft=i,this.dCtx.yAxisWidthRight=a,e}}]),t}(),rt=function(){function t(e){a(this,t),this.w=e.w,this.dCtx=e}return r(t,[{key:"gridPadForColumnsInNumericAxis",value:function(t){var e=this.w;if(e.globals.noData||e.globals.allSeriesCollapsed)return 0;var i=function(t){return"bar"===t||"rangeBar"===t||"candlestick"===t||"boxPlot"===t},a=e.config.chart.type,s=0,r=i(a)?e.config.series.length:1;if(e.globals.comboBarCount>0&&(r=e.globals.comboBarCount),e.globals.collapsedSeries.forEach((function(t){i(t.type)&&(r-=1)})),e.config.chart.stacked&&(r=1),(i(a)||e.globals.comboBarCount>0)&&e.globals.isXNumeric&&!e.globals.isBarHorizontal&&r>0){var o,n,l=Math.abs(e.globals.initialMaxX-e.globals.initialMinX);l<=3&&(l=e.globals.dataPoints),o=l/t,e.globals.minXDiff&&e.globals.minXDiff/o>0&&(n=e.globals.minXDiff/o),n>t/2&&(n/=2),(s=n/r*parseInt(e.config.plotOptions.bar.columnWidth,10)/100)<1&&(s=1),s=s/(r>1?1:1.5)+5,e.globals.barPadForNumericAxis=s}return s}},{key:"gridPadFortitleSubtitle",value:function(){var t=this,e=this.w,i=e.globals,a=this.dCtx.isSparkline||!e.globals.axisCharts?0:10;["title","subtitle"].forEach((function(i){void 0!==e.config[i].text?a+=e.config[i].margin:a+=t.dCtx.isSparkline||!e.globals.axisCharts?0:5})),!e.config.legend.show||"bottom"!==e.config.legend.position||e.config.legend.floating||e.globals.axisCharts||(a+=10);var s=this.dCtx.dimHelpers.getTitleSubtitleCoords("title"),r=this.dCtx.dimHelpers.getTitleSubtitleCoords("subtitle");i.gridHeight=i.gridHeight-s.height-r.height-a,i.translateY=i.translateY+s.height+r.height+a}},{key:"setGridXPosForDualYAxis",value:function(t,e){var i=this.w,a=new B(this.dCtx.ctx);i.config.yaxis.map((function(s,r){-1!==i.globals.ignoreYAxisIndexes.indexOf(r)||s.floating||a.isYAxisHidden(r)||(s.opposite&&(i.globals.translateX=i.globals.translateX-(e[r].width+t[r].width)-parseInt(i.config.yaxis[r].labels.style.fontSize,10)/1.2-12),i.globals.translateX<2&&(i.globals.translateX=2))}))}}]),t}(),ot=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.lgRect={},this.yAxisWidth=0,this.yAxisWidthLeft=0,this.yAxisWidthRight=0,this.xAxisHeight=0,this.isSparkline=this.w.config.chart.sparkline.enabled,this.dimHelpers=new it(this),this.dimYAxis=new st(this),this.dimXAxis=new at(this),this.dimGrid=new rt(this),this.lgWidthForSideLegends=0,this.gridPad=this.w.config.grid.padding,this.xPadRight=0,this.xPadLeft=0}return r(t,[{key:"plotCoords",value:function(){var t=this,e=this.w,i=e.globals;this.lgRect=this.dimHelpers.getLegendsRect(),this.isSparkline&&(e.config.markers.discrete.length>0||e.config.markers.size>0)&&Object.entries(this.gridPad).forEach((function(e){var i=g(e,2),a=i[0],s=i[1];t.gridPad[a]=Math.max(s,t.w.globals.markers.largestSize/1.5)})),i.axisCharts?this.setDimensionsForAxisCharts():this.setDimensionsForNonAxisCharts(),this.dimGrid.gridPadFortitleSubtitle(),i.gridHeight=i.gridHeight-this.gridPad.top-this.gridPad.bottom,i.gridWidth=i.gridWidth-this.gridPad.left-this.gridPad.right-this.xPadRight-this.xPadLeft;var a=this.dimGrid.gridPadForColumnsInNumericAxis(i.gridWidth);i.gridWidth=i.gridWidth-2*a,i.translateX=i.translateX+this.gridPad.left+this.xPadLeft+(a>0?a+4:0),i.translateY=i.translateY+this.gridPad.top}},{key:"setDimensionsForAxisCharts",value:function(){var t=this,e=this.w,i=e.globals,a=this.dimYAxis.getyAxisLabelsCoords(),s=this.dimYAxis.getyAxisTitleCoords();e.globals.yLabelsCoords=[],e.globals.yTitleCoords=[],e.config.yaxis.map((function(t,i){e.globals.yLabelsCoords.push({width:a[i].width,index:i}),e.globals.yTitleCoords.push({width:s[i].width,index:i})})),this.yAxisWidth=this.dimYAxis.getTotalYAxisWidth();var r=this.dimXAxis.getxAxisLabelsCoords(),o=this.dimXAxis.getxAxisGroupLabelsCoords(),n=this.dimXAxis.getxAxisTitleCoords();this.conditionalChecksForAxisCoords(r,n,o),i.translateXAxisY=e.globals.rotateXLabels?this.xAxisHeight/8:-4,i.translateXAxisX=e.globals.rotateXLabels&&e.globals.isXNumeric&&e.config.xaxis.labels.rotate<=-45?-this.xAxisWidth/4:0,e.globals.isBarHorizontal&&(i.rotateXLabels=!1,i.translateXAxisY=parseInt(e.config.xaxis.labels.style.fontSize,10)/1.5*-1),i.translateXAxisY=i.translateXAxisY+e.config.xaxis.labels.offsetY,i.translateXAxisX=i.translateXAxisX+e.config.xaxis.labels.offsetX;var l=this.yAxisWidth,h=this.xAxisHeight;i.xAxisLabelsHeight=this.xAxisHeight-n.height,i.xAxisGroupLabelsHeight=i.xAxisLabelsHeight-r.height,i.xAxisLabelsWidth=this.xAxisWidth,i.xAxisHeight=this.xAxisHeight;var c=10;("radar"===e.config.chart.type||this.isSparkline)&&(l=0,h=i.goldenPadding),this.isSparkline&&(this.lgRect={height:0,width:0}),(this.isSparkline||"treemap"===e.config.chart.type)&&(l=0,h=0,c=0),this.isSparkline||this.dimXAxis.additionalPaddingXLabels(r);var d=function(){i.translateX=l,i.gridHeight=i.svgHeight-t.lgRect.height-h-(t.isSparkline||"treemap"===e.config.chart.type?0:e.globals.rotateXLabels?10:15),i.gridWidth=i.svgWidth-l};switch("top"===e.config.xaxis.position&&(c=i.xAxisHeight-e.config.xaxis.axisTicks.height-5),e.config.legend.position){case"bottom":i.translateY=c,d();break;case"top":i.translateY=this.lgRect.height+c,d();break;case"left":i.translateY=c,i.translateX=this.lgRect.width+l,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l;break;case"right":i.translateY=c,i.translateX=l,i.gridHeight=i.svgHeight-h-12,i.gridWidth=i.svgWidth-this.lgRect.width-l-5;break;default:throw new Error("Legend position not supported")}this.dimGrid.setGridXPosForDualYAxis(s,a),new q(this.ctx).setYAxisXPosition(a,s)}},{key:"setDimensionsForNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=t.config,a=0;t.config.legend.show&&!t.config.legend.floating&&(a=20);var s="pie"===i.chart.type||"polarArea"===i.chart.type||"donut"===i.chart.type?"pie":"radialBar",r=i.plotOptions[s].offsetY,o=i.plotOptions[s].offsetX;if(!i.legend.show||i.legend.floating)return e.gridHeight=e.svgHeight-i.grid.padding.left+i.grid.padding.right,e.gridWidth=e.gridHeight,e.translateY=r,void(e.translateX=o+(e.svgWidth-e.gridWidth)/2);switch(i.legend.position){case"bottom":e.gridHeight=e.svgHeight-this.lgRect.height-e.goldenPadding,e.gridWidth=e.svgWidth,e.translateY=r-10,e.translateX=o+(e.svgWidth-e.gridWidth)/2;break;case"top":e.gridHeight=e.svgHeight-this.lgRect.height-e.goldenPadding,e.gridWidth=e.svgWidth,e.translateY=this.lgRect.height+r+10,e.translateX=o+(e.svgWidth-e.gridWidth)/2;break;case"left":e.gridWidth=e.svgWidth-this.lgRect.width-a,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=o+this.lgRect.width+a;break;case"right":e.gridWidth=e.svgWidth-this.lgRect.width-a-5,e.gridHeight="auto"!==i.chart.height?e.svgHeight:e.gridWidth,e.translateY=r,e.translateX=o+10;break;default:throw new Error("Legend position not supported")}}},{key:"conditionalChecksForAxisCoords",value:function(t,e,i){var a=this.w,s=a.globals.hasGroups?2:1,r=i.height+t.height+e.height,o=a.globals.isMultiLineX?1.2:a.globals.LINE_HEIGHT_RATIO,n=a.globals.rotateXLabels?22:10,l=a.globals.rotateXLabels&&"bottom"===a.config.legend.position?10:0;this.xAxisHeight=r*o+s*n+l,this.xAxisWidth=t.width,this.xAxisHeight-e.height>a.config.xaxis.labels.maxHeight&&(this.xAxisHeight=a.config.xaxis.labels.maxHeight),a.config.xaxis.labels.minHeight&&this.xAxisHeightc&&(this.yAxisWidth=c)}}]),t}(),nt=function(){function t(e){a(this,t),this.w=e.w,this.lgCtx=e}return r(t,[{key:"getLegendBBox",value:function(){var t=this.w.globals.dom.baseEl.querySelector(".apexcharts-legend").getBoundingClientRect(),e=t.width;return{clwh:t.height,clww:e}}},{key:"toggleDataSeries",value:function(t,e){var i=this,a=this.w;if(a.globals.axisCharts||"radialBar"===a.config.chart.type){a.globals.resized=!0;var s=null,r=null;if(a.globals.risingSeries=[],a.globals.axisCharts?(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(t,"']")),r=parseInt(s.getAttribute("data:realIndex"),10)):(s=a.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(t+1,"']")),r=parseInt(s.getAttribute("rel"),10)-1),e)[{cs:a.globals.collapsedSeries,csi:a.globals.collapsedSeriesIndices},{cs:a.globals.ancillaryCollapsedSeries,csi:a.globals.ancillaryCollapsedSeriesIndices}].forEach((function(t){i.riseCollapsedSeries(t.cs,t.csi,r)}));else this.hideSeries({seriesEl:s,realIndex:r})}else{var o=a.globals.dom.Paper.select(" .apexcharts-series[rel='".concat(t+1,"'] path")),n=a.config.chart.type;if("pie"===n||"polarArea"===n||"donut"===n){var l=a.config.plotOptions.pie.donut.labels;new m(this.lgCtx.ctx).pathMouseDown(o.members[0],null),this.lgCtx.ctx.pie.printDataLabelsInner(o.members[0].node,l)}o.fire("click")}}},{key:"hideSeries",value:function(t){var e=t.seriesEl,i=t.realIndex,a=this.w,s=x.clone(a.config.series);if(a.globals.axisCharts){var r=!1;if(a.config.yaxis[i]&&a.config.yaxis[i].show&&a.config.yaxis[i].showAlways&&(r=!0,a.globals.ancillaryCollapsedSeriesIndices.indexOf(i)<0&&(a.globals.ancillaryCollapsedSeries.push({index:i,data:s[i].data.slice(),type:e.parentNode.className.baseVal.split("-")[1]}),a.globals.ancillaryCollapsedSeriesIndices.push(i))),!r){a.globals.collapsedSeries.push({index:i,data:s[i].data.slice(),type:e.parentNode.className.baseVal.split("-")[1]}),a.globals.collapsedSeriesIndices.push(i);var o=a.globals.risingSeries.indexOf(i);a.globals.risingSeries.splice(o,1)}}else a.globals.collapsedSeries.push({index:i,data:s[i]}),a.globals.collapsedSeriesIndices.push(i);for(var n=e.childNodes,l=0;l0){for(var r=0;r-1&&(t[a].data=[])})):t.forEach((function(i,a){e.globals.collapsedSeriesIndices.indexOf(a)>-1&&(t[a]=0)})),t}}]),t}(),lt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.onLegendClick=this.onLegendClick.bind(this),this.onLegendHovered=this.onLegendHovered.bind(this),this.isBarsDistributed="bar"===this.w.config.chart.type&&this.w.config.plotOptions.bar.distributed&&1===this.w.config.series.length,this.legendHelpers=new nt(this)}return r(t,[{key:"init",value:function(){var t=this.w,e=t.globals,i=t.config;if((i.legend.showForSingleSeries&&1===e.series.length||this.isBarsDistributed||e.series.length>1||!e.axisCharts)&&i.legend.show){for(;e.dom.elLegendWrap.firstChild;)e.dom.elLegendWrap.removeChild(e.dom.elLegendWrap.firstChild);this.drawLegends(),"bottom"===i.legend.position||"top"===i.legend.position?this.legendAlignHorizontal():"right"!==i.legend.position&&"left"!==i.legend.position||this.legendAlignVertical()}}},{key:"drawLegends",value:function(){var t=this,e=this.w,i=e.config.legend.fontFamily,a=e.globals.seriesNames,s=e.globals.colors.slice();if("heatmap"===e.config.chart.type){var r=e.config.plotOptions.heatmap.colorScale.ranges;a=r.map((function(t){return t.name?t.name:t.from+" - "+t.to})),s=r.map((function(t){return t.color}))}else this.isBarsDistributed&&(a=e.globals.labels.slice());e.config.legend.customLegendItems.length&&(a=e.config.legend.customLegendItems);for(var o=e.globals.legendFormatter,n=e.config.legend.inverseOrder,l=n?a.length-1:0;n?l>=0:l<=a.length-1;n?l--:l++){var h=o(a[l],{seriesIndex:l,w:e}),c=!1,d=!1;if(e.globals.collapsedSeries.length>0)for(var g=0;g0)for(var u=0;u0?l-10:0)+(h>0?h-10:0)}a.style.position="absolute",r=r+t+i.config.legend.offsetX,o=o+e+i.config.legend.offsetY,a.style.left=r+"px",a.style.top=o+"px","bottom"===i.config.legend.position?(a.style.top="auto",a.style.bottom=5-i.config.legend.offsetY+"px"):"right"===i.config.legend.position&&(a.style.left="auto",a.style.right=25+i.config.legend.offsetX+"px");["width","height"].forEach((function(t){a.style[t]&&(a.style[t]=parseInt(i.config.legend[t],10)+"px")}))}},{key:"legendAlignHorizontal",value:function(){var t=this.w;t.globals.dom.elLegendWrap.style.right=0;var e=this.legendHelpers.getLegendBBox(),i=new ot(this.ctx),a=i.dimHelpers.getTitleSubtitleCoords("title"),s=i.dimHelpers.getTitleSubtitleCoords("subtitle"),r=0;"bottom"===t.config.legend.position?r=-e.clwh/1.8:"top"===t.config.legend.position&&(r=a.height+s.height+t.config.title.margin+t.config.subtitle.margin-10),this.setLegendWrapXY(20,r)}},{key:"legendAlignVertical",value:function(){var t=this.w,e=this.legendHelpers.getLegendBBox(),i=0;"left"===t.config.legend.position&&(i=20),"right"===t.config.legend.position&&(i=t.globals.svgWidth-e.clww-10),this.setLegendWrapXY(i,20)}},{key:"onLegendHovered",value:function(t){var e=this.w,i=t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker");if("heatmap"===e.config.chart.type||this.isBarsDistributed){if(i){var a=parseInt(t.target.getAttribute("rel"),10)-1;this.ctx.events.fireEvent("legendHover",[this.ctx,a,this.w]),new N(this.ctx).highlightRangeInSeries(t,t.target)}}else!t.target.classList.contains("apexcharts-inactive-legend")&&i&&new N(this.ctx).toggleSeriesOnHover(t,t.target)}},{key:"onLegendClick",value:function(t){var e=this.w;if(!e.config.legend.customLegendItems.length&&(t.target.classList.contains("apexcharts-legend-text")||t.target.classList.contains("apexcharts-legend-marker"))){var i=parseInt(t.target.getAttribute("rel"),10)-1,a="true"===t.target.getAttribute("data:collapsed"),s=this.w.config.chart.events.legendClick;"function"==typeof s&&s(this.ctx,i,this.w),this.ctx.events.fireEvent("legendClick",[this.ctx,i,this.w]);var r=this.w.config.legend.markers.onClick;"function"==typeof r&&t.target.classList.contains("apexcharts-legend-marker")&&(r(this.ctx,i,this.w),this.ctx.events.fireEvent("legendMarkerClick",[this.ctx,i,this.w])),"treemap"!==e.config.chart.type&&"heatmap"!==e.config.chart.type&&!this.isBarsDistributed&&e.config.legend.onItemClick.toggleDataSeries&&this.legendHelpers.toggleDataSeries(i,a)}}}]),t}(),ht=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w;var i=this.w;this.ev=this.w.config.chart.events,this.selectedClass="apexcharts-selected",this.localeValues=this.w.globals.locale.toolbar,this.minX=i.globals.minX,this.maxX=i.globals.maxX}return r(t,[{key:"createToolbar",value:function(){var t=this,e=this.w,i=function(){return document.createElement("div")},a=i();if(a.setAttribute("class","apexcharts-toolbar"),a.style.top=e.config.chart.toolbar.offsetY+"px",a.style.right=3-e.config.chart.toolbar.offsetX+"px",e.globals.dom.elWrap.appendChild(a),this.elZoom=i(),this.elZoomIn=i(),this.elZoomOut=i(),this.elPan=i(),this.elSelection=i(),this.elZoomReset=i(),this.elMenuIcon=i(),this.elMenu=i(),this.elCustomIcons=[],this.t=e.config.chart.toolbar.tools,Array.isArray(this.t.customIcons))for(var s=0;s\n \n \n\n'),o("zoomOut",this.elZoomOut,'\n \n \n\n');var n=function(i){t.t[i]&&e.config.chart[i].enabled&&r.push({el:"zoom"===i?t.elZoom:t.elSelection,icon:"string"==typeof t.t[i]?t.t[i]:"zoom"===i?'\n \n \n \n':'\n \n \n',title:t.localeValues["zoom"===i?"selectionZoom":"selection"],class:e.globals.isTouchDevice?"apexcharts-element-hidden":"apexcharts-".concat(i,"-icon")})};n("zoom"),n("selection"),this.t.pan&&e.config.chart.zoom.enabled&&r.push({el:this.elPan,icon:"string"==typeof this.t.pan?this.t.pan:'\n \n \n \n \n \n \n \n',title:this.localeValues.pan,class:e.globals.isTouchDevice?"apexcharts-element-hidden":"apexcharts-pan-icon"}),o("reset",this.elZoomReset,'\n \n \n'),this.t.download&&r.push({el:this.elMenuIcon,icon:"string"==typeof this.t.download?this.t.download:'',title:this.localeValues.menu,class:"apexcharts-menu-icon"});for(var l=0;l0&&e.height>0&&this.slDraggableRect.selectize({points:"l, r",pointSize:8,pointType:"rect"}).resize({constraint:{minX:0,minY:0,maxX:t.globals.gridWidth,maxY:t.globals.gridHeight}}).on("resizing",this.selectionDragging.bind(this,"resizing"))}}},{key:"preselectedSelection",value:function(){var t=this.w,e=this.xyRatios;if(!t.globals.zoomEnabled)if(void 0!==t.globals.selection&&null!==t.globals.selection)this.drawSelectionRect(t.globals.selection);else if(void 0!==t.config.chart.selection.xaxis.min&&void 0!==t.config.chart.selection.xaxis.max){var i=(t.config.chart.selection.xaxis.min-t.globals.minX)/e.xRatio,a={x:i,y:0,width:t.globals.gridWidth-(t.globals.maxX-t.config.chart.selection.xaxis.max)/e.xRatio-i,height:t.globals.gridHeight,translateX:0,translateY:0,selectionEnabled:!0};this.drawSelectionRect(a),this.makeSelectionRectDraggable(),"function"==typeof t.config.chart.events.selection&&t.config.chart.events.selection(this.ctx,{xaxis:{min:t.config.chart.selection.xaxis.min,max:t.config.chart.selection.xaxis.max},yaxis:{}})}}},{key:"drawSelectionRect",value:function(t){var e=t.x,i=t.y,a=t.width,s=t.height,r=t.translateX,o=void 0===r?0:r,n=t.translateY,l=void 0===n?0:n,h=this.w,c=this.zoomRect,d=this.selectionRect;if(this.dragged||null!==h.globals.selection){var g={transform:"translate("+o+", "+l+")"};h.globals.zoomEnabled&&this.dragged&&(a<0&&(a=1),c.attr({x:e,y:i,width:a,height:s,fill:h.config.chart.zoom.zoomedArea.fill.color,"fill-opacity":h.config.chart.zoom.zoomedArea.fill.opacity,stroke:h.config.chart.zoom.zoomedArea.stroke.color,"stroke-width":h.config.chart.zoom.zoomedArea.stroke.width,"stroke-opacity":h.config.chart.zoom.zoomedArea.stroke.opacity}),m.setAttrs(c.node,g)),h.globals.selectionEnabled&&(d.attr({x:e,y:i,width:a>0?a:0,height:s>0?s:0,fill:h.config.chart.selection.fill.color,"fill-opacity":h.config.chart.selection.fill.opacity,stroke:h.config.chart.selection.stroke.color,"stroke-width":h.config.chart.selection.stroke.width,"stroke-dasharray":h.config.chart.selection.stroke.dashArray,"stroke-opacity":h.config.chart.selection.stroke.opacity}),m.setAttrs(d.node,g))}}},{key:"hideSelectionRect",value:function(t){t&&t.attr({x:0,y:0,width:0,height:0})}},{key:"selectionDrawing",value:function(t){var e=t.context,i=t.zoomtype,a=this.w,s=e,r=this.gridRect.getBoundingClientRect(),o=s.startX-1,n=s.startY,l=!1,h=!1,c=s.clientX-r.left-o,d=s.clientY-r.top-n,g={};return Math.abs(c+o)>a.globals.gridWidth?c=a.globals.gridWidth-o:s.clientX-r.left<0&&(c=o),o>s.clientX-r.left&&(l=!0,c=Math.abs(c)),n>s.clientY-r.top&&(h=!0,d=Math.abs(d)),g="x"===i?{x:l?o-c:o,y:0,width:c,height:a.globals.gridHeight}:"y"===i?{x:0,y:h?n-d:n,width:a.globals.gridWidth,height:d}:{x:l?o-c:o,y:h?n-d:n,width:c,height:d},s.drawSelectionRect(g),s.selectionDragging("resizing"),g}},{key:"selectionDragging",value:function(t,e){var i=this,a=this.w,s=this.xyRatios,r=this.selectionRect,o=0;"resizing"===t&&(o=30);var n=function(t){return parseFloat(r.node.getAttribute(t))},l={x:n("x"),y:n("y"),width:n("width"),height:n("height")};a.globals.selection=l,"function"==typeof a.config.chart.events.selection&&a.globals.selectionEnabled&&(clearTimeout(this.w.globals.selectionResizeTimer),this.w.globals.selectionResizeTimer=window.setTimeout((function(){var t=i.gridRect.getBoundingClientRect(),e=r.node.getBoundingClientRect(),o={xaxis:{min:a.globals.xAxisScale.niceMin+(e.left-t.left)*s.xRatio,max:a.globals.xAxisScale.niceMin+(e.right-t.left)*s.xRatio},yaxis:{min:a.globals.yAxisScale[0].niceMin+(t.bottom-e.bottom)*s.yRatio[0],max:a.globals.yAxisScale[0].niceMax-(e.top-t.top)*s.yRatio[0]}};a.config.chart.events.selection(i.ctx,o),a.config.chart.brush.enabled&&void 0!==a.config.chart.events.brushScrolled&&a.config.chart.events.brushScrolled(i.ctx,o)}),o))}},{key:"selectionDrawn",value:function(t){var e=t.context,i=t.zoomtype,a=this.w,s=e,r=this.xyRatios,o=this.ctx.toolbar;if(s.startX>s.endX){var n=s.startX;s.startX=s.endX,s.endX=n}if(s.startY>s.endY){var l=s.startY;s.startY=s.endY,s.endY=l}var h=void 0,c=void 0;a.globals.isRangeBar?(h=a.globals.yAxisScale[0].niceMin+s.startX*r.invertedYRatio,c=a.globals.yAxisScale[0].niceMin+s.endX*r.invertedYRatio):(h=a.globals.xAxisScale.niceMin+s.startX*r.xRatio,c=a.globals.xAxisScale.niceMin+s.endX*r.xRatio);var d=[],g=[];if(a.config.yaxis.forEach((function(t,e){d.push(a.globals.yAxisScale[e].niceMax-r.yRatio[e]*s.startY),g.push(a.globals.yAxisScale[e].niceMax-r.yRatio[e]*s.endY)})),s.dragged&&(s.dragX>10||s.dragY>10)&&h!==c)if(a.globals.zoomEnabled){var u=x.clone(a.globals.initialConfig.yaxis),f=x.clone(a.globals.initialConfig.xaxis);if(a.globals.zoomed=!0,a.config.xaxis.convertedCatToNumeric&&(h=Math.floor(h),c=Math.floor(c),h<1&&(h=1,c=a.globals.dataPoints),c-h<2&&(c=h+1)),"xy"!==i&&"x"!==i||(f={min:h,max:c}),"xy"!==i&&"y"!==i||u.forEach((function(t,e){u[e].min=g[e],u[e].max=d[e]})),a.config.chart.zoom.autoScaleYaxis){var p=new _(s.ctx);u=p.autoScaleY(s.ctx,u,{xaxis:f})}if(o){var b=o.getBeforeZoomRange(f,u);b&&(f=b.xaxis?b.xaxis:f,u=b.yaxis?b.yaxis:u)}var v={xaxis:f};a.config.chart.group||(v.yaxis=u),s.ctx.updateHelpers._updateOptions(v,!1,s.w.config.chart.animations.dynamicAnimation.enabled),"function"==typeof a.config.chart.events.zoomed&&o.zoomCallback(f,u)}else if(a.globals.selectionEnabled){var m,y=null;m={min:h,max:c},"xy"!==i&&"y"!==i||(y=x.clone(a.config.yaxis)).forEach((function(t,e){y[e].min=g[e],y[e].max=d[e]})),a.globals.selection=s.selection,"function"==typeof a.config.chart.events.selection&&a.config.chart.events.selection(s.ctx,{xaxis:m,yaxis:y})}}},{key:"panDragging",value:function(t){var e=t.context,i=this.w,a=e;if(void 0!==i.globals.lastClientPosition.x){var s=i.globals.lastClientPosition.x-a.clientX,r=i.globals.lastClientPosition.y-a.clientY;Math.abs(s)>Math.abs(r)&&s>0?this.moveDirection="left":Math.abs(s)>Math.abs(r)&&s<0?this.moveDirection="right":Math.abs(r)>Math.abs(s)&&r>0?this.moveDirection="up":Math.abs(r)>Math.abs(s)&&r<0&&(this.moveDirection="down")}i.globals.lastClientPosition={x:a.clientX,y:a.clientY};var o=i.globals.isRangeBar?i.globals.minY:i.globals.minX,n=i.globals.isRangeBar?i.globals.maxY:i.globals.maxX;i.config.xaxis.convertedCatToNumeric||a.panScrolled(o,n)}},{key:"delayedPanScrolled",value:function(){var t=this.w,e=t.globals.minX,i=t.globals.maxX,a=(t.globals.maxX-t.globals.minX)/2;"left"===this.moveDirection?(e=t.globals.minX+a,i=t.globals.maxX+a):"right"===this.moveDirection&&(e=t.globals.minX-a,i=t.globals.maxX-a),e=Math.floor(e),i=Math.floor(i),this.updateScrolledChart({xaxis:{min:e,max:i}},e,i)}},{key:"panScrolled",value:function(t,e){var i=this.w,a=this.xyRatios,s=x.clone(i.globals.initialConfig.yaxis),r=a.xRatio,o=i.globals.minX,n=i.globals.maxX;i.globals.isRangeBar&&(r=a.invertedYRatio,o=i.globals.minY,n=i.globals.maxY),"left"===this.moveDirection?(t=o+i.globals.gridWidth/15*r,e=n+i.globals.gridWidth/15*r):"right"===this.moveDirection&&(t=o-i.globals.gridWidth/15*r,e=n-i.globals.gridWidth/15*r),i.globals.isRangeBar||(ti.globals.initialMaxX)&&(t=o,e=n);var l={min:t,max:e};i.config.chart.zoom.autoScaleYaxis&&(s=new _(this.ctx).autoScaleY(this.ctx,s,{xaxis:l}));var h={xaxis:{min:t,max:e}};i.config.chart.group||(h.yaxis=s),this.updateScrolledChart(h,t,e)}},{key:"updateScrolledChart",value:function(t,e,i){var a=this.w;this.ctx.updateHelpers._updateOptions(t,!1,!1),"function"==typeof a.config.chart.events.scrolled&&a.config.chart.events.scrolled(this.ctx,{xaxis:{min:e,max:i}})}}]),i}(),dt=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx}return r(t,[{key:"getNearestValues",value:function(t){var e=t.hoverArea,i=t.elGrid,a=t.clientX,s=t.clientY,r=this.w,o=i.getBoundingClientRect(),n=o.width,l=o.height,h=n/(r.globals.dataPoints-1),c=l/r.globals.dataPoints,d=this.hasBars();!r.globals.comboCharts&&!d||r.config.xaxis.convertedCatToNumeric||(h=n/r.globals.dataPoints);var g=a-o.left-r.globals.barPadForNumericAxis,u=s-o.top;g<0||u<0||g>n||u>l?(e.classList.remove("hovering-zoom"),e.classList.remove("hovering-pan")):r.globals.zoomEnabled?(e.classList.remove("hovering-pan"),e.classList.add("hovering-zoom")):r.globals.panEnabled&&(e.classList.remove("hovering-zoom"),e.classList.add("hovering-pan"));var f=Math.round(g/h),p=Math.floor(u/c);d&&!r.config.xaxis.convertedCatToNumeric&&(f=Math.ceil(g/h),f-=1);var b=null,v=null,m=[],y=[];if(r.globals.seriesXvalues.forEach((function(t){m.push([t[0]+1e-6].concat(t))})),r.globals.seriesYvalues.forEach((function(t){y.push([t[0]+1e-6].concat(t))})),m=m.map((function(t){return t.filter((function(t){return x.isNumber(t)}))})),y=y.map((function(t){return t.filter((function(t){return x.isNumber(t)}))})),r.globals.isXNumeric){var w=this.ttCtx.getElGrid().getBoundingClientRect(),k=g*(w.width/n),A=u*(w.height/l);b=(v=this.closestInMultiArray(k,A,m,y)).index,f=v.j,null!==b&&(m=r.globals.seriesXvalues[b],f=(v=this.closestInArray(k,m)).index)}return r.globals.capturedSeriesIndex=null===b?-1:b,(!f||f<1)&&(f=0),r.globals.isBarHorizontal?r.globals.capturedDataPointIndex=p:r.globals.capturedDataPointIndex=f,{capturedSeries:b,j:r.globals.isBarHorizontal?p:f,hoverX:g,hoverY:u}}},{key:"closestInMultiArray",value:function(t,e,i,a){var s=this.w,r=0,o=null,n=-1;s.globals.series.length>1?r=this.getFirstActiveXArray(i):o=0;var l=i[r][0],h=Math.abs(t-l);if(i.forEach((function(e){e.forEach((function(e,i){var a=Math.abs(t-e);a0?e:-1})),s=0;s0)for(var a=0;ai?-1:0}));var e=[];return t.forEach((function(t){e.push(t.querySelector(".apexcharts-marker"))})),e}},{key:"hasMarkers",value:function(){return this.getElMarkers().length>0}},{key:"getElBars",value:function(){return this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-bar-series, .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series")}},{key:"hasBars",value:function(){return this.getElBars().length>0}},{key:"getHoverMarkerSize",value:function(t){var e=this.w,i=e.config.markers.hover.size;return void 0===i&&(i=e.globals.markers.size[t]+e.config.markers.hover.sizeOffset),i}},{key:"toggleAllTooltipSeriesGroups",value:function(t){var e=this.w,i=this.ttCtx;0===i.allTooltipSeriesGroups.length&&(i.allTooltipSeriesGroups=e.globals.dom.baseEl.querySelectorAll(".apexcharts-tooltip-series-group"));for(var a=i.allTooltipSeriesGroups,s=0;s ').concat(i.attrs.name,"
    "),e+="
    ".concat(i.val,"
    ")})),v.innerHTML=t+"
    ",m.innerHTML=e+""};o?l.globals.seriesGoals[e][i]&&Array.isArray(l.globals.seriesGoals[e][i])?y():(v.innerHTML="",m.innerHTML=""):y()}else v.innerHTML="",m.innerHTML="";null!==f&&(a[e].querySelector(".apexcharts-tooltip-text-z-label").innerHTML=l.config.tooltip.z.title,a[e].querySelector(".apexcharts-tooltip-text-z-value").innerHTML=void 0!==f?f:"");o&&p[0]&&(null==c||l.globals.ancillaryCollapsedSeriesIndices.indexOf(e)>-1||l.globals.collapsedSeriesIndices.indexOf(e)>-1?p[0].parentNode.style.display="none":p[0].parentNode.style.display=l.config.tooltip.items.display)}},{key:"toggleActiveInactiveSeries",value:function(t){var e=this.w;if(t)this.tooltipUtil.toggleAllTooltipSeriesGroups("enable");else{this.tooltipUtil.toggleAllTooltipSeriesGroups("disable");var i=e.globals.dom.baseEl.querySelector(".apexcharts-tooltip-series-group");i&&(i.classList.add("apexcharts-active"),i.style.display=e.config.tooltip.items.display)}}},{key:"getValuesToPrint",value:function(t){var e=t.i,i=t.j,a=this.w,s=this.ctx.series.filteredSeriesX(),r="",o="",n=null,l=null,h={series:a.globals.series,seriesIndex:e,dataPointIndex:i,w:a},c=a.globals.ttZFormatter;null===i?l=a.globals.series[e]:a.globals.isXNumeric&&"treemap"!==a.config.chart.type?(r=s[e][i],0===s[e].length&&(r=s[this.tooltipUtil.getFirstActiveXArray(s)][i])):r=void 0!==a.globals.labels[i]?a.globals.labels[i]:"";var d=r;a.globals.isXNumeric&&"datetime"===a.config.xaxis.type?r=new M(this.ctx).xLabelFormat(a.globals.ttKeyFormatter,d,d,{i:void 0,dateFormatter:new T(this.ctx).formatDate,w:this.w}):r=a.globals.isBarHorizontal?a.globals.yLabelFormatters[0](d,h):a.globals.xLabelFormatter(d,h);return void 0!==a.config.tooltip.x.formatter&&(r=a.globals.ttKeyFormatter(d,h)),a.globals.seriesZ.length>0&&a.globals.seriesZ[e].length>0&&(n=c(a.globals.seriesZ[e][i],a)),o="function"==typeof a.config.xaxis.tooltip.formatter?a.globals.xaxisTooltipFormatter(d,h):r,{val:Array.isArray(l)?l.join(" "):l,xVal:Array.isArray(r)?r.join(" "):r,xAxisTTVal:Array.isArray(o)?o.join(" "):o,zVal:n}}},{key:"handleCustomTooltip",value:function(t){var e=t.i,i=t.j,a=t.y1,s=t.y2,r=t.w,o=this.ttCtx.getElTooltip(),n=r.config.tooltip.custom;Array.isArray(n)&&n[e]&&(n=n[e]),o.innerHTML=n({ctx:this.ctx,series:r.globals.series,seriesIndex:e,dataPointIndex:i,y1:a,y2:s,w:r})}}]),t}(),ut=function(){function t(e){a(this,t),this.ttCtx=e,this.ctx=e.ctx,this.w=e.w}return r(t,[{key:"moveXCrosshairs",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.ttCtx,a=this.w,s=i.getElXCrosshairs(),r=t-i.xcrosshairsWidth/2,o=a.globals.labels.slice().length;if(null!==e&&(r=a.globals.gridWidth/o*e),null===s||a.globals.isBarHorizontal||(s.setAttribute("x",r),s.setAttribute("x1",r),s.setAttribute("x2",r),s.setAttribute("y2",a.globals.gridHeight),s.classList.add("apexcharts-active")),r<0&&(r=0),r>a.globals.gridWidth&&(r=a.globals.gridWidth),i.isXAxisTooltipEnabled){var n=r;"tickWidth"!==a.config.xaxis.crosshairs.width&&"barWidth"!==a.config.xaxis.crosshairs.width||(n=r+i.xcrosshairsWidth/2),this.moveXAxisTooltip(n)}}},{key:"moveYCrosshairs",value:function(t){var e=this.ttCtx;null!==e.ycrosshairs&&m.setAttrs(e.ycrosshairs,{y1:t,y2:t}),null!==e.ycrosshairsHidden&&m.setAttrs(e.ycrosshairsHidden,{y1:t,y2:t})}},{key:"moveXAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;if(null!==i.xaxisTooltip&&0!==i.xcrosshairsWidth){i.xaxisTooltip.classList.add("apexcharts-active");var a=i.xaxisOffY+e.config.xaxis.tooltip.offsetY+e.globals.translateY+1+e.config.xaxis.offsetY;if(t-=i.xaxisTooltip.getBoundingClientRect().width/2,!isNaN(t)){t+=e.globals.translateX;var s;s=new m(this.ctx).getTextRects(i.xaxisTooltipText.innerHTML),i.xaxisTooltipText.style.minWidth=s.width+"px",i.xaxisTooltip.style.left=t+"px",i.xaxisTooltip.style.top=a+"px"}}}},{key:"moveYAxisTooltip",value:function(t){var e=this.w,i=this.ttCtx;null===i.yaxisTTEls&&(i.yaxisTTEls=e.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip"));var a=parseInt(i.ycrosshairsHidden.getAttribute("y1"),10),s=e.globals.translateY+a,r=i.yaxisTTEls[t].getBoundingClientRect().height,o=e.globals.translateYAxisX[t]-2;e.config.yaxis[t].opposite&&(o-=26),s-=r/2,-1===e.globals.ignoreYAxisIndexes.indexOf(t)?(i.yaxisTTEls[t].classList.add("apexcharts-active"),i.yaxisTTEls[t].style.top=s+"px",i.yaxisTTEls[t].style.left=o+e.config.yaxis[t].tooltip.offsetX+"px"):i.yaxisTTEls[t].classList.remove("apexcharts-active")}},{key:"moveTooltip",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,a=this.w,s=this.ttCtx,r=s.getElTooltip(),o=s.tooltipRect,n=null!==i?parseFloat(i):1,l=parseFloat(t)+n+5,h=parseFloat(e)+n/2;if(l>a.globals.gridWidth/2&&(l=l-o.ttWidth-n-10),l>a.globals.gridWidth-o.ttWidth-10&&(l=a.globals.gridWidth-o.ttWidth),l<-20&&(l=-20),a.config.tooltip.followCursor){var c=s.getElGrid(),d=c.getBoundingClientRect();h=s.e.clientY+a.globals.translateY-d.top-o.ttHeight/2}else a.globals.isBarHorizontal||o.ttHeight/2+h>a.globals.gridHeight&&(h=a.globals.gridHeight-o.ttHeight+a.globals.translateY);isNaN(l)||(l+=a.globals.translateX,r.style.left=l+"px",r.style.top=h+"px")}},{key:"moveMarkers",value:function(t,e){var i=this.w,a=this.ttCtx;if(i.globals.markers.size[t]>0)for(var s=i.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(t,"'] .apexcharts-marker")),r=0;r0&&(h.setAttribute("r",n),h.setAttribute("cx",i),h.setAttribute("cy",a)),this.moveXCrosshairs(i),r.fixedTooltip||this.moveTooltip(i,a,n)}}},{key:"moveDynamicPointsOnHover",value:function(t){var e,i=this.ttCtx,a=i.w,s=0,r=0,o=a.globals.pointsArray;e=new N(this.ctx).getActiveConfigSeriesIndex("asc",["line","area","scatter","bubble"]);var n=i.tooltipUtil.getHoverMarkerSize(e);o[e]&&(s=o[e][t][0],r=o[e][t][1]);var l=i.tooltipUtil.getAllMarkers();if(null!==l)for(var h=0;h0?(l[h]&&l[h].setAttribute("r",n),l[h]&&l[h].setAttribute("cy",d)):l[h]&&l[h].setAttribute("r",0)}}if(this.moveXCrosshairs(s),!i.fixedTooltip){var f=r||a.globals.gridHeight;this.moveTooltip(s,f,n)}}},{key:"moveStickyTooltipOverBars",value:function(t){var e=this.w,i=this.ttCtx,a=e.globals.columnSeries?e.globals.columnSeries.length:e.globals.series.length,s=a>=2&&a%2==0?Math.floor(a/2):Math.floor(a/2)+1;e.globals.isBarHorizontal&&(s=new N(this.ctx).getActiveConfigSeriesIndex("desc")+1);var r=e.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(s,"'] path[j='").concat(t,"'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(s,"'] path[j='").concat(t,"']")),o=r?parseFloat(r.getAttribute("cx")):0,n=r?parseFloat(r.getAttribute("cy")):0,l=r?parseFloat(r.getAttribute("barWidth")):0,h=i.getElGrid().getBoundingClientRect(),c=r.classList.contains("apexcharts-candlestick-area")||r.classList.contains("apexcharts-boxPlot-area");if(e.globals.isXNumeric?(r&&!c&&(o-=a%2!=0?l/2:0),r&&c&&e.globals.comboCharts&&(o-=l/2)):e.globals.isBarHorizontal||(o=i.xAxisTicksPositions[t-1]+i.dataPointsDividedWidth/2,isNaN(o)&&(o=i.xAxisTicksPositions[t]-i.dataPointsDividedWidth/2)),e.globals.isBarHorizontal?n-=i.tooltipRect.ttHeight:e.config.tooltip.followCursor?n=i.e.clientY-h.top-i.tooltipRect.ttHeight/2:n+i.tooltipRect.ttHeight+15>e.globals.gridHeight&&(n=e.globals.gridHeight),e.globals.isBarHorizontal||this.moveXCrosshairs(o),!i.fixedTooltip){var d=n||e.globals.gridHeight;this.moveTooltip(o,d)}}}]),t}(),ft=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e,this.ctx=e.ctx,this.tooltipPosition=new ut(e)}return r(t,[{key:"drawDynamicPoints",value:function(){var t=this.w,e=new m(this.ctx),i=new D(this.ctx),a=t.globals.dom.baseEl.querySelectorAll(".apexcharts-series");a=u(a),t.config.chart.stacked&&a.sort((function(t,e){return parseFloat(t.getAttribute("data:realIndex"))-parseFloat(e.getAttribute("data:realIndex"))}));for(var s=0;s2&&void 0!==arguments[2]?arguments[2]:null,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null,s=this.w;"bubble"!==s.config.chart.type&&this.newPointSize(t,e);var r=e.getAttribute("cx"),o=e.getAttribute("cy");if(null!==i&&null!==a&&(r=i,o=a),this.tooltipPosition.moveXCrosshairs(r),!this.fixedTooltip){if("radar"===s.config.chart.type){var n=this.ttCtx.getElGrid(),l=n.getBoundingClientRect();r=this.ttCtx.e.clientX-l.left}this.tooltipPosition.moveTooltip(r,o,s.config.markers.hover.size)}}},{key:"enlargePoints",value:function(t){for(var e=this.w,i=this,a=this.ttCtx,s=t,r=e.globals.dom.baseEl.querySelectorAll(".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"),o=e.config.markers.hover.size,n=0;n=0?t[e].setAttribute("r",i):t[e].setAttribute("r",0)}}}]),t}(),pt=function(){function t(e){a(this,t),this.w=e.w,this.ttCtx=e}return r(t,[{key:"getAttr",value:function(t,e){return parseFloat(t.target.getAttribute(e))}},{key:"handleHeatTreeTooltip",value:function(t){var e=t.e,i=t.opt,a=t.x,s=t.y,r=t.type,o=this.ttCtx,n=this.w;if(e.target.classList.contains("apexcharts-".concat(r,"-rect"))){var l=this.getAttr(e,"i"),h=this.getAttr(e,"j"),c=this.getAttr(e,"cx"),d=this.getAttr(e,"cy"),g=this.getAttr(e,"width"),u=this.getAttr(e,"height");if(o.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:l,j:h,shared:!1,e:e}),n.globals.capturedSeriesIndex=l,n.globals.capturedDataPointIndex=h,a=c+o.tooltipRect.ttWidth/2+g,s=d+o.tooltipRect.ttHeight/2-u/2,o.tooltipPosition.moveXCrosshairs(c+g/2),a>n.globals.gridWidth/2&&(a=c-o.tooltipRect.ttWidth/2+g),o.w.config.tooltip.followCursor){var f=n.globals.dom.elWrap.getBoundingClientRect();a=n.globals.clientX-f.left-(a>n.globals.gridWidth/2?o.tooltipRect.ttWidth:0),s=n.globals.clientY-f.top-(s>n.globals.gridHeight/2?o.tooltipRect.ttHeight:0)}}return{x:a,y:s}}},{key:"handleMarkerTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=t.x,o=t.y,n=this.w,l=this.ttCtx;if(a.target.classList.contains("apexcharts-marker")){var h=parseInt(s.paths.getAttribute("cx"),10),c=parseInt(s.paths.getAttribute("cy"),10),d=parseFloat(s.paths.getAttribute("val"));if(i=parseInt(s.paths.getAttribute("rel"),10),e=parseInt(s.paths.parentNode.parentNode.parentNode.getAttribute("rel"),10)-1,l.intersect){var g=x.findAncestor(s.paths,"apexcharts-series");g&&(e=parseInt(g.getAttribute("data:realIndex"),10))}if(l.tooltipLabels.drawSeriesTexts({ttItems:s.ttItems,i:e,j:i,shared:!l.showOnIntersect&&n.config.tooltip.shared,e:a}),"mouseup"===a.type&&l.markerClick(a,e,i),n.globals.capturedSeriesIndex=e,n.globals.capturedDataPointIndex=i,r=h,o=c+n.globals.translateY-1.4*l.tooltipRect.ttHeight,l.w.config.tooltip.followCursor){var u=l.getElGrid().getBoundingClientRect();o=l.e.clientY+n.globals.translateY-u.top}d<0&&(o=c),l.marker.enlargeCurrentPoint(i,s.paths,r,o)}return{x:r,y:o}}},{key:"handleBarTooltip",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,o=this.ttCtx,n=o.getElTooltip(),l=0,h=0,c=0,d=this.getBarTooltipXY({e:a,opt:s});e=d.i;var g=d.barHeight,u=d.j;r.globals.capturedSeriesIndex=e,r.globals.capturedDataPointIndex=u,r.globals.isBarHorizontal&&o.tooltipUtil.hasBars()||!r.config.tooltip.shared?(h=d.x,c=d.y,i=Array.isArray(r.config.stroke.width)?r.config.stroke.width[e]:r.config.stroke.width,l=h):r.globals.comboCharts||r.config.tooltip.shared||(l/=2),isNaN(c)&&(c=r.globals.svgHeight-o.tooltipRect.ttHeight);var f=parseInt(s.paths.parentNode.getAttribute("data:realIndex"),10),p=r.globals.isMultipleYAxis?r.config.yaxis[f]&&r.config.yaxis[f].reversed:r.config.yaxis[0].reversed;if(h+o.tooltipRect.ttWidth>r.globals.gridWidth&&!p?h-=o.tooltipRect.ttWidth:h<0&&(h=0),o.w.config.tooltip.followCursor){var x=o.getElGrid().getBoundingClientRect();c=o.e.clientY-x.top}null===o.tooltip&&(o.tooltip=r.globals.dom.baseEl.querySelector(".apexcharts-tooltip")),r.config.tooltip.shared||(r.globals.comboBarCount>0?o.tooltipPosition.moveXCrosshairs(l+i/2):o.tooltipPosition.moveXCrosshairs(l)),!o.fixedTooltip&&(!r.config.tooltip.shared||r.globals.isBarHorizontal&&o.tooltipUtil.hasBars())&&(p&&(h-=o.tooltipRect.ttWidth)<0&&(h=0),!p||r.globals.isBarHorizontal&&o.tooltipUtil.hasBars()||(c=c+g-2*(r.globals.series[e][u]<0?g:0)),c=c+r.globals.translateY-o.tooltipRect.ttHeight/2,n.style.left=h+r.globals.translateX+"px",n.style.top=c+"px")}},{key:"getBarTooltipXY",value:function(t){var e=t.e,i=t.opt,a=this.w,s=null,r=this.ttCtx,o=0,n=0,l=0,h=0,c=0,d=e.target.classList;if(d.contains("apexcharts-bar-area")||d.contains("apexcharts-candlestick-area")||d.contains("apexcharts-boxPlot-area")||d.contains("apexcharts-rangebar-area")){var g=e.target,u=g.getBoundingClientRect(),f=i.elGrid.getBoundingClientRect(),p=u.height;c=u.height;var x=u.width,b=parseInt(g.getAttribute("cx"),10),v=parseInt(g.getAttribute("cy"),10);h=parseFloat(g.getAttribute("barWidth"));var m="touchmove"===e.type?e.touches[0].clientX:e.clientX;s=parseInt(g.getAttribute("j"),10),o=parseInt(g.parentNode.getAttribute("rel"),10)-1;var y=g.getAttribute("data-range-y1"),w=g.getAttribute("data-range-y2");a.globals.comboCharts&&(o=parseInt(g.parentNode.getAttribute("data:realIndex"),10)),r.tooltipLabels.drawSeriesTexts({ttItems:i.ttItems,i:o,j:s,y1:y?parseInt(y,10):null,y2:w?parseInt(w,10):null,shared:!r.showOnIntersect&&a.config.tooltip.shared,e:e}),a.config.tooltip.followCursor?a.globals.isBarHorizontal?(n=m-f.left+15,l=v-r.dataPointsDividedHeight+p/2-r.tooltipRect.ttHeight/2):(n=a.globals.isXNumeric?b-x/2:b-r.dataPointsDividedWidth+x/2,l=e.clientY-f.top-r.tooltipRect.ttHeight/2-15):a.globals.isBarHorizontal?((n=b)0&&i.setAttribute("width",e.xcrosshairsWidth)}},{key:"handleYCrosshair",value:function(){var t=this.w,e=this.ttCtx;e.ycrosshairs=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs"),e.ycrosshairsHidden=t.globals.dom.baseEl.querySelector(".apexcharts-ycrosshairs-hidden")}},{key:"drawYaxisTooltipText",value:function(t,e,i){var a=this.ttCtx,s=this.w,r=s.globals.yLabelFormatters[t];if(a.yaxisTooltips[t]){var o=a.getElGrid().getBoundingClientRect(),n=(e-o.top)*i.yRatio[t],l=s.globals.maxYArr[t]-s.globals.minYArr[t],h=s.globals.minYArr[t]+(l-n);a.tooltipPosition.moveYCrosshairs(e-o.top),a.yaxisTooltipText[t].innerHTML=r(h),a.tooltipPosition.moveYAxisTooltip(t)}}}]),t}(),bt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w;var i=this.w;this.tConfig=i.config.tooltip,this.tooltipUtil=new dt(this),this.tooltipLabels=new gt(this),this.tooltipPosition=new ut(this),this.marker=new ft(this),this.intersect=new pt(this),this.axesTooltip=new xt(this),this.showOnIntersect=this.tConfig.intersect,this.showTooltipTitle=this.tConfig.x.show,this.fixedTooltip=this.tConfig.fixed.enabled,this.xaxisTooltip=null,this.yaxisTTEls=null,this.isBarShared=!i.globals.isBarHorizontal&&this.tConfig.shared,this.lastHoverTime=Date.now()}return r(t,[{key:"getElTooltip",value:function(t){return t||(t=this),t.w.globals.dom.baseEl?t.w.globals.dom.baseEl.querySelector(".apexcharts-tooltip"):null}},{key:"getElXCrosshairs",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-xcrosshairs")}},{key:"getElGrid",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-grid")}},{key:"drawTooltip",value:function(t){var e=this.w;this.xyRatios=t,this.isXAxisTooltipEnabled=e.config.xaxis.tooltip.enabled&&e.globals.axisCharts,this.yaxisTooltips=e.config.yaxis.map((function(t,i){return!!(t.show&&t.tooltip.enabled&&e.globals.axisCharts)})),this.allTooltipSeriesGroups=[],e.globals.axisCharts||(this.showTooltipTitle=!1);var i=document.createElement("div");if(i.classList.add("apexcharts-tooltip"),e.config.tooltip.cssClass&&i.classList.add(e.config.tooltip.cssClass),i.classList.add("apexcharts-theme-".concat(this.tConfig.theme)),e.globals.dom.elWrap.appendChild(i),e.globals.axisCharts){this.axesTooltip.drawXaxisTooltip(),this.axesTooltip.drawYaxisTooltip(),this.axesTooltip.setXCrosshairWidth(),this.axesTooltip.handleYCrosshair();var a=new V(this.ctx);this.xAxisTicksPositions=a.getXAxisTicksPositions()}if(!e.globals.comboCharts&&!this.tConfig.intersect&&"rangeBar"!==e.config.chart.type||this.tConfig.shared||(this.showOnIntersect=!0),0!==e.config.markers.size&&0!==e.globals.markers.largestSize||this.marker.drawDynamicPoints(this),e.globals.collapsedSeries.length!==e.globals.series.length){this.dataPointsDividedHeight=e.globals.gridHeight/e.globals.dataPoints,this.dataPointsDividedWidth=e.globals.gridWidth/e.globals.dataPoints,this.showTooltipTitle&&(this.tooltipTitle=document.createElement("div"),this.tooltipTitle.classList.add("apexcharts-tooltip-title"),this.tooltipTitle.style.fontFamily=this.tConfig.style.fontFamily||e.config.chart.fontFamily,this.tooltipTitle.style.fontSize=this.tConfig.style.fontSize,i.appendChild(this.tooltipTitle));var s=e.globals.series.length;(e.globals.xyCharts||e.globals.comboCharts)&&this.tConfig.shared&&(s=this.showOnIntersect?1:e.globals.series.length),this.legendLabels=e.globals.dom.baseEl.querySelectorAll(".apexcharts-legend-text"),this.ttItems=this.createTTElements(s),this.addSVGEvents()}}},{key:"createTTElements",value:function(t){for(var e=this,i=this.w,a=[],s=this.getElTooltip(),r=function(r){var o=document.createElement("div");o.classList.add("apexcharts-tooltip-series-group"),o.style.order=i.config.tooltip.inverseOrder?t-r:r+1,e.tConfig.shared&&e.tConfig.enabledOnSeries&&Array.isArray(e.tConfig.enabledOnSeries)&&e.tConfig.enabledOnSeries.indexOf(r)<0&&o.classList.add("apexcharts-tooltip-series-group-hidden");var n=document.createElement("span");n.classList.add("apexcharts-tooltip-marker"),n.style.backgroundColor=i.globals.colors[r],o.appendChild(n);var l=document.createElement("div");l.classList.add("apexcharts-tooltip-text"),l.style.fontFamily=e.tConfig.style.fontFamily||i.config.chart.fontFamily,l.style.fontSize=e.tConfig.style.fontSize,["y","goals","z"].forEach((function(t){var e=document.createElement("div");e.classList.add("apexcharts-tooltip-".concat(t,"-group"));var i=document.createElement("span");i.classList.add("apexcharts-tooltip-text-".concat(t,"-label")),e.appendChild(i);var a=document.createElement("span");a.classList.add("apexcharts-tooltip-text-".concat(t,"-value")),e.appendChild(a),l.appendChild(e)})),o.appendChild(l),s.appendChild(o),a.push(o)},o=0;o0&&this.addPathsEventListeners(u,c),this.tooltipUtil.hasBars()&&!this.tConfig.shared&&this.addDatapointEventsListeners(c)}}},{key:"drawFixedTooltipRect",value:function(){var t=this.w,e=this.getElTooltip(),i=e.getBoundingClientRect(),a=i.width+10,s=i.height+10,r=this.tConfig.fixed.offsetX,o=this.tConfig.fixed.offsetY,n=this.tConfig.fixed.position.toLowerCase();return n.indexOf("right")>-1&&(r=r+t.globals.svgWidth-a+10),n.indexOf("bottom")>-1&&(o=o+t.globals.svgHeight-s-10),e.style.left=r+"px",e.style.top=o+"px",{x:r,y:o,ttWidth:a,ttHeight:s}}},{key:"addDatapointEventsListeners",value:function(t){var e=this.w.globals.dom.baseEl.querySelectorAll(".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area");this.addPathsEventListeners(e,t)}},{key:"addPathsEventListeners",value:function(t,e){for(var i=this,a=function(a){var s={paths:t[a],tooltipEl:e.tooltipEl,tooltipY:e.tooltipY,tooltipX:e.tooltipX,elGrid:e.elGrid,hoverArea:e.hoverArea,ttItems:e.ttItems};["mousemove","mouseup","touchmove","mouseout","touchend"].map((function(e){return t[a].addEventListener(e,i.onSeriesHover.bind(i,s),{capture:!1,passive:!0})}))},s=0;s=100?this.seriesHover(t,e):(clearTimeout(this.seriesHoverTimeout),this.seriesHoverTimeout=setTimeout((function(){i.seriesHover(t,e)}),100-a))}},{key:"seriesHover",value:function(t,e){var i=this;this.lastHoverTime=Date.now();var a=[],s=this.w;s.config.chart.group&&(a=this.ctx.getGroupedCharts()),s.globals.axisCharts&&(s.globals.minX===-1/0&&s.globals.maxX===1/0||0===s.globals.dataPoints)||(a.length?a.forEach((function(a){var s=i.getElTooltip(a),r={paths:t.paths,tooltipEl:s,tooltipY:t.tooltipY,tooltipX:t.tooltipX,elGrid:t.elGrid,hoverArea:t.hoverArea,ttItems:a.w.globals.tooltip.ttItems};a.w.globals.minX===i.w.globals.minX&&a.w.globals.maxX===i.w.globals.maxX&&a.w.globals.tooltip.seriesHoverByContext({chartCtx:a,ttCtx:a.w.globals.tooltip,opt:r,e:e})})):this.seriesHoverByContext({chartCtx:this.ctx,ttCtx:this.w.globals.tooltip,opt:t,e:e}))}},{key:"seriesHoverByContext",value:function(t){var e=t.chartCtx,i=t.ttCtx,a=t.opt,s=t.e,r=e.w,o=this.getElTooltip();if(o){if(i.tooltipRect={x:0,y:0,ttWidth:o.getBoundingClientRect().width,ttHeight:o.getBoundingClientRect().height},i.e=s,i.tooltipUtil.hasBars()&&!r.globals.comboCharts&&!i.isBarShared)if(this.tConfig.onDatasetHover.highlightDataSeries)new N(e).toggleSeriesOnHover(s,s.target.parentNode);i.fixedTooltip&&i.drawFixedTooltipRect(),r.globals.axisCharts?i.axisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect}):i.nonAxisChartsTooltips({e:s,opt:a,tooltipRect:i.tooltipRect})}}},{key:"axisChartsTooltips",value:function(t){var e,i,a=t.e,s=t.opt,r=this.w,o=s.elGrid.getBoundingClientRect(),n="touchmove"===a.type?a.touches[0].clientX:a.clientX,l="touchmove"===a.type?a.touches[0].clientY:a.clientY;if(this.clientY=l,this.clientX=n,r.globals.capturedSeriesIndex=-1,r.globals.capturedDataPointIndex=-1,lo.top+o.height)this.handleMouseOut(s);else{if(Array.isArray(this.tConfig.enabledOnSeries)&&!r.config.tooltip.shared){var h=parseInt(s.paths.getAttribute("index"),10);if(this.tConfig.enabledOnSeries.indexOf(h)<0)return void this.handleMouseOut(s)}var c=this.getElTooltip(),d=this.getElXCrosshairs(),g=r.globals.xyCharts||"bar"===r.config.chart.type&&!r.globals.isBarHorizontal&&this.tooltipUtil.hasBars()&&this.tConfig.shared||r.globals.comboCharts&&this.tooltipUtil.hasBars();if("mousemove"===a.type||"touchmove"===a.type||"mouseup"===a.type){if(r.globals.collapsedSeries.length+r.globals.ancillaryCollapsedSeries.length===r.globals.series.length)return;null!==d&&d.classList.add("apexcharts-active");var u=this.yaxisTooltips.filter((function(t){return!0===t}));if(null!==this.ycrosshairs&&u.length&&this.ycrosshairs.classList.add("apexcharts-active"),g&&!this.showOnIntersect)this.handleStickyTooltip(a,n,l,s);else if("heatmap"===r.config.chart.type||"treemap"===r.config.chart.type){var f=this.intersect.handleHeatTreeTooltip({e:a,opt:s,x:e,y:i,type:r.config.chart.type});e=f.x,i=f.y,c.style.left=e+"px",c.style.top=i+"px"}else this.tooltipUtil.hasBars()&&this.intersect.handleBarTooltip({e:a,opt:s}),this.tooltipUtil.hasMarkers()&&this.intersect.handleMarkerTooltip({e:a,opt:s,x:e,y:i});if(this.yaxisTooltips.length)for(var p=0;pl.width?this.handleMouseOut(a):null!==n?this.handleStickyCapturedSeries(t,n,a,o):(this.tooltipUtil.isXoverlap(o)||s.globals.isBarHorizontal)&&this.create(t,this,0,o,a.ttItems)}},{key:"handleStickyCapturedSeries",value:function(t,e,i,a){var s=this.w;if(!this.tConfig.shared&&null===s.globals.series[e][a])return void this.handleMouseOut(i);void 0!==s.globals.series[e][a]?this.tConfig.shared&&this.tooltipUtil.isXoverlap(a)&&this.tooltipUtil.isInitialSeriesSameLen()?this.create(t,this,e,a,i.ttItems):this.create(t,this,e,a,i.ttItems,!1):this.tooltipUtil.isXoverlap(a)&&this.create(t,this,0,a,i.ttItems)}},{key:"deactivateHoverFilter",value:function(){for(var t=this.w,e=new m(this.ctx),i=t.globals.dom.Paper.select(".apexcharts-bar-area"),a=0;a5&&void 0!==arguments[5]?arguments[5]:null,S=this.w,C=i;"mouseup"===t.type&&this.markerClick(t,a,s),null===A&&(A=this.tConfig.shared);var L=this.tooltipUtil.hasMarkers(),P=this.tooltipUtil.getElBars();if(S.config.legend.tooltipHoverFormatter){var T=S.config.legend.tooltipHoverFormatter,M=Array.from(this.legendLabels);M.forEach((function(t){var e=t.getAttribute("data:default-text");t.innerHTML=decodeURIComponent(e)}));for(var I=0;I0?C.marker.enlargePoints(s):C.tooltipPosition.moveDynamicPointsOnHover(s)),this.tooltipUtil.hasBars()&&(this.barSeriesHeight=this.tooltipUtil.getBarsHeight(P),this.barSeriesHeight>0)){var R=new m(this.ctx),D=S.globals.dom.Paper.select(".apexcharts-bar-area[j='".concat(s,"']"));this.deactivateHoverFilter(),this.tooltipPosition.moveStickyTooltipOverBars(s);for(var H=0;Hs.globals.gridHeight&&(u=s.globals.gridHeight-b)),{bcx:h,bcy:l,dataLabelsX:e,dataLabelsY:u,totalDataLabelsX:a,totalDataLabelsY:i,totalDataLabelsAnchor:"middle"}}},{key:"calculateBarsDataLabelsPosition",value:function(t){var e=this.w,i=t.x,a=t.i,s=t.j,r=t.realIndex,o=t.bcy,n=t.barHeight,l=t.barWidth,h=t.textRects,c=t.dataLabelsX,d=t.strokeWidth,g=t.dataLabelsConfig,u=t.barDataLabelsConfig,f=t.barTotalDataLabelsConfig,p=t.offX,x=t.offY,b=e.globals.gridHeight/e.globals.dataPoints;l=Math.abs(l);var v,y,w=o-(this.barCtx.isRangeBar?0:b)+n/2+h.height/2+x-3,k="start",A=this.barCtx.series[a][s]<0,S=i;switch(this.barCtx.isReversed&&(S=i+l-(A?2*l:0),i=e.globals.gridWidth-l),u.position){case"center":c=A?S+l/2-p:Math.max(h.width/2,S-l/2)+p;break;case"bottom":c=A?S+l-d-Math.round(h.width/2)-p:S-l+d+Math.round(h.width/2)+p;break;case"top":c=A?S-d+Math.round(h.width/2)-p:S-d-Math.round(h.width/2)+p}if(this.barCtx.lastActiveBarSerieIndex===r&&f.enabled){var C=new m(this.barCtx.ctx).getTextRects(this.getStackedTotalDataLabel({realIndex:r,j:s}),g.fontSize);A?(v=S-d+Math.round(C.width/2)-p-f.offsetX-15,k="end"):v=S-d-Math.round(C.width/2)+p+f.offsetX+15,y=w+f.offsetY}return e.config.chart.stacked||(c<0?c=c+h.width+d:c+h.width/2>e.globals.gridWidth&&(c=e.globals.gridWidth-h.width-d)),{bcx:i,bcy:o,dataLabelsX:c,dataLabelsY:w,totalDataLabelsX:v,totalDataLabelsY:y,totalDataLabelsAnchor:k}}},{key:"drawCalculatedDataLabels",value:function(t){var i=t.x,a=t.y,s=t.val,r=t.i,o=t.j,n=t.textRects,l=t.barHeight,h=t.barWidth,c=t.dataLabelsConfig,d=this.w,g="rotate(0)";"vertical"===d.config.plotOptions.bar.dataLabels.orientation&&(g="rotate(-90, ".concat(i,", ").concat(a,")"));var u=new O(this.barCtx.ctx),f=new m(this.barCtx.ctx),p=c.formatter,x=null,b=d.globals.collapsedSeriesIndices.indexOf(r)>-1;if(c.enabled&&!b){x=f.group({class:"apexcharts-data-labels",transform:g});var v="";void 0!==s&&(v=p(s,e(e({},d),{},{seriesIndex:r,dataPointIndex:o,w:d})));var y=d.globals.series[r][o]<0,w=d.config.plotOptions.bar.dataLabels.position;if("vertical"===d.config.plotOptions.bar.dataLabels.orientation&&("top"===w&&(c.textAnchor=y?"end":"start"),"center"===w&&(c.textAnchor="middle"),"bottom"===w&&(c.textAnchor=y?"end":"start")),this.barCtx.isRangeBar&&this.barCtx.barOptions.dataLabels.hideOverflowingLabels)hMath.abs(h)&&(v=""):n.height/1.6>Math.abs(l)&&(v=""));var k=e({},c);this.barCtx.isHorizontal&&s<0&&("start"===c.textAnchor?k.textAnchor="end":"end"===c.textAnchor&&(k.textAnchor="start")),u.plotDataLabelsText({x:i,y:a,text:v,i:r,j:o,parent:x,dataLabelsConfig:k,alwaysDrawDataLabel:!0,offsetCorrection:!0})}return x}},{key:"drawTotalDataLabels",value:function(t){var e,i=t.x,a=t.y,s=t.val,r=t.realIndex,o=t.textAnchor,n=t.barTotalDataLabelsConfig,l=new m(this.barCtx.ctx);return n.enabled&&void 0!==i&&void 0!==a&&this.barCtx.lastActiveBarSerieIndex===r&&(e=l.drawText({x:i,y:a,foreColor:n.style.color,text:s,textAnchor:o,fontFamily:n.style.fontFamily,fontSize:n.style.fontSize,fontWeight:n.style.fontWeight})),e}}]),t}(),mt=function(){function t(e){a(this,t),this.w=e.w,this.barCtx=e}return r(t,[{key:"initVariables",value:function(t){var e=this.w;this.barCtx.series=t,this.barCtx.totalItems=0,this.barCtx.seriesLen=0,this.barCtx.visibleI=-1,this.barCtx.visibleItems=1;for(var i=0;i0&&(this.barCtx.seriesLen=this.barCtx.seriesLen+1,this.barCtx.totalItems+=t[i].length),e.globals.isXNumeric)for(var a=0;ae.globals.minX&&e.globals.seriesX[i][a]0&&(a=l.globals.minXDiff/d),(r=a/this.barCtx.seriesLen*parseInt(this.barCtx.barOptions.columnWidth,10)/100)<1&&(r=1)}o=l.globals.gridHeight-this.barCtx.baseLineY[this.barCtx.yaxisIndex]-(this.barCtx.isReversed?l.globals.gridHeight:0)+(this.barCtx.isReversed?2*this.barCtx.baseLineY[this.barCtx.yaxisIndex]:0),t=l.globals.padHorizontal+(a-r*this.barCtx.seriesLen)/2}return{x:t,y:e,yDivision:i,xDivision:a,barHeight:s,barWidth:r,zeroH:o,zeroW:n}}},{key:"getPathFillColor",value:function(t,e,i,a){var s,r,o,n,l=this.w,h=new R(this.barCtx.ctx),c=null,d=this.barCtx.barOptions.distributed?i:e;this.barCtx.barOptions.colors.ranges.length>0&&this.barCtx.barOptions.colors.ranges.map((function(a){t[e][i]>=a.from&&t[e][i]<=a.to&&(c=a.color)}));return l.config.series[e].data[i]&&l.config.series[e].data[i].fillColor&&(c=l.config.series[e].data[i].fillColor),h.fillPath({seriesNumber:this.barCtx.barOptions.distributed?d:a,dataPointIndex:i,color:c,value:t[e][i],fillConfig:null===(s=l.config.series[e].data[i])||void 0===s?void 0:s.fill,fillType:null!==(r=l.config.series[e].data[i])&&void 0!==r&&null!==(o=r.fill)&&void 0!==o&&o.type?null===(n=l.config.series[e].data[i])||void 0===n?void 0:n.fill.type:l.config.fill.type})}},{key:"getStrokeWidth",value:function(t,e,i){var a=0,s=this.w;return this.barCtx.series[t][e]?this.barCtx.isNullValue=!1:this.barCtx.isNullValue=!0,s.config.stroke.show&&(this.barCtx.isNullValue||(a=Array.isArray(this.barCtx.strokeWidth)?this.barCtx.strokeWidth[i]:this.barCtx.strokeWidth)),a}},{key:"shouldApplyRadius",value:function(t){var e=this.w,i=!1;return e.config.plotOptions.bar.borderRadius>0&&(e.config.chart.stacked&&"last"===e.config.plotOptions.bar.borderRadiusWhenStacked?this.barCtx.lastActiveBarSerieIndex===t&&(i=!0):i=!0),i}},{key:"barBackground",value:function(t){var e=t.j,i=t.i,a=t.x1,s=t.x2,r=t.y1,o=t.y2,n=t.elSeries,l=this.w,h=new m(this.barCtx.ctx),c=new N(this.barCtx.ctx).getActiveConfigSeriesIndex();if(this.barCtx.barOptions.colors.backgroundBarColors.length>0&&c===i){e>=this.barCtx.barOptions.colors.backgroundBarColors.length&&(e%=this.barCtx.barOptions.colors.backgroundBarColors.length);var d=this.barCtx.barOptions.colors.backgroundBarColors[e],g=h.drawRect(void 0!==a?a:0,void 0!==r?r:0,void 0!==s?s:l.globals.gridWidth,void 0!==o?o:l.globals.gridHeight,this.barCtx.barOptions.colors.backgroundBarRadius,d,this.barCtx.barOptions.colors.backgroundBarOpacity);n.add(g),g.node.classList.add("apexcharts-backgroundBar")}}},{key:"getColumnPaths",value:function(t){var e,i=t.barWidth,a=t.barXPosition,s=t.y1,r=t.y2,o=t.strokeWidth,n=t.realIndex,l=t.i,h=t.j,c=t.w,d=new m(this.barCtx.ctx);(o=Array.isArray(o)?o[n]:o)||(o=0);var g=i,u=a;null!==(e=c.config.series[n].data[h])&&void 0!==e&&e.columnWidthOffset&&(u=a-c.config.series[n].data[h].columnWidthOffset/2,g=i+c.config.series[n].data[h].columnWidthOffset);var f=u,p=u+g;s+=.001,r+=.001;var x=d.move(f,s),b=d.move(f,s),v=d.line(p-o,s);return c.globals.previousPaths.length>0&&(b=this.barCtx.getPreviousPath(n,h,!1)),x=x+d.line(f,r)+d.line(p-o,r)+d.line(p-o,s)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),b=b+d.line(f,s)+v+v+v+v+v+d.line(f,s)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(n)&&(x=d.roundPathCorners(x,c.config.plotOptions.bar.borderRadius)),c.config.chart.stacked&&(this.barCtx.yArrj.push(r),this.barCtx.yArrjF.push(Math.abs(s-r)),this.barCtx.yArrjVal.push(this.barCtx.series[l][h])),{pathTo:x,pathFrom:b}}},{key:"getBarpaths",value:function(t){var e,i=t.barYPosition,a=t.barHeight,s=t.x1,r=t.x2,o=t.strokeWidth,n=t.realIndex,l=t.i,h=t.j,c=t.w,d=new m(this.barCtx.ctx);(o=Array.isArray(o)?o[n]:o)||(o=0);var g=i,u=a;null!==(e=c.config.series[n].data[h])&&void 0!==e&&e.barHeightOffset&&(g=i-c.config.series[n].data[h].barHeightOffset/2,u=a+c.config.series[n].data[h].barHeightOffset);var f=g,p=g+u;s+=.001,r+=.001;var x=d.move(s,f),b=d.move(s,f);c.globals.previousPaths.length>0&&(b=this.barCtx.getPreviousPath(n,h,!1));var v=d.line(s,p-o);return x=x+d.line(r,f)+d.line(r,p-o)+v+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),b=b+d.line(s,f)+v+v+v+v+v+d.line(s,f)+("around"===c.config.plotOptions.bar.borderRadiusApplication?" Z":" z"),this.shouldApplyRadius(n)&&(x=d.roundPathCorners(x,c.config.plotOptions.bar.borderRadius)),c.config.chart.stacked&&(this.barCtx.xArrj.push(r),this.barCtx.xArrjF.push(Math.abs(s-r)),this.barCtx.xArrjVal.push(this.barCtx.series[l][h])),{pathTo:x,pathFrom:b}}},{key:"checkZeroSeries",value:function(t){for(var e=t.series,i=this.w,a=0;a=0;o--)this.barCtx.zeroSerieses.indexOf(o)>-1&&o===this.radiusOnSeriesNumber&&(this.barCtx.radiusOnSeriesNumber-=1);for(var n=e.length-1;n>=0;n--)i.globals.collapsedSeriesIndices.indexOf(this.barCtx.radiusOnSeriesNumber)>-1&&(this.barCtx.radiusOnSeriesNumber-=1)}},{key:"getXForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e+t/this.barCtx.invertedYRatio-2*(this.barCtx.isReversed?t/this.barCtx.invertedYRatio:0)),a}},{key:"getYForValue",value:function(t,e){var i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=i?e:null;return null!=t&&(a=e-t/this.barCtx.yRatio[this.barCtx.yaxisIndex]+2*(this.barCtx.isReversed?t/this.barCtx.yRatio[this.barCtx.yaxisIndex]:0)),a}},{key:"getGoalValues",value:function(t,e,i,a,s){var r=this,n=this.w,l=[];return n.globals.seriesGoals[a]&&n.globals.seriesGoals[a][s]&&Array.isArray(n.globals.seriesGoals[a][s])&&n.globals.seriesGoals[a][s].forEach((function(a){var s;l.push((o(s={},t,"x"===t?r.getXForValue(a.value,e,!1):r.getYForValue(a.value,i,!1)),o(s,"attrs",a),s))})),l}},{key:"drawGoalLine",value:function(t){var e=t.barXPosition,i=t.barYPosition,a=t.goalX,s=t.goalY,r=t.barWidth,o=t.barHeight,n=new m(this.barCtx.ctx),l=n.group({className:"apexcharts-bar-goals-groups"}),h=null;return this.barCtx.isHorizontal?Array.isArray(a)&&a.forEach((function(t){var e=void 0!==t.attrs.strokeHeight?t.attrs.strokeHeight:o/2,a=i+e+o/2;h=n.drawLine(t.x,a-2*e,t.x,a,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeWidth?t.attrs.strokeWidth:2,t.attrs.strokeLineCap),l.add(h)})):Array.isArray(s)&&s.forEach((function(t){var i=void 0!==t.attrs.strokeWidth?t.attrs.strokeWidth:r/2,a=e+i+r/2;h=n.drawLine(a-2*i,t.y,a,t.y,t.attrs.strokeColor?t.attrs.strokeColor:void 0,t.attrs.strokeDashArray,t.attrs.strokeHeight?t.attrs.strokeHeight:2,t.attrs.strokeLineCap),l.add(h)})),l}}]),t}(),yt=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w;var s=this.w;this.barOptions=s.config.plotOptions.bar,this.isHorizontal=this.barOptions.horizontal,this.strokeWidth=s.config.stroke.width,this.isNullValue=!1,this.isRangeBar=s.globals.seriesRange.length&&this.isHorizontal,this.xyRatios=i,null!==this.xyRatios&&(this.xRatio=i.xRatio,this.initialXRatio=i.initialXRatio,this.yRatio=i.yRatio,this.invertedXRatio=i.invertedXRatio,this.invertedYRatio=i.invertedYRatio,this.baseLineY=i.baseLineY,this.baseLineInvertedY=i.baseLineInvertedY),this.yaxisIndex=0,this.seriesLen=0;var r=new N(this.ctx);this.lastActiveBarSerieIndex=r.getActiveConfigSeriesIndex("desc",["bar","column"]);var o=r.getBarSeriesIndices(),n=new y(this.ctx);this.stackedSeriesTotals=n.getStackedSeriesTotals(this.w.config.series.map((function(t,e){return-1===o.indexOf(e)?e:-1})).filter((function(t){return-1!==t}))),this.barHelpers=new mt(this)}return r(t,[{key:"draw",value:function(t,i){var a=this.w,s=new m(this.ctx),r=new y(this.ctx,a);t=r.getLogSeries(t),this.series=t,this.yRatio=r.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);var o=s.group({class:"apexcharts-bar-series apexcharts-plot-series"});a.config.dataLabels.enabled&&this.totalItems>this.barOptions.dataLabels.maxItems&&console.warn("WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering.");for(var n=0,l=0;n0&&(this.visibleI=this.visibleI+1);var k=0,A=0;this.yRatio.length>1&&(this.yaxisIndex=v),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed;var S=this.barHelpers.initialPositions();f=S.y,k=S.barHeight,c=S.yDivision,g=S.zeroW,u=S.x,A=S.barWidth,h=S.xDivision,d=S.zeroH,this.horizontal||b.push(u+A/2);for(var C=s.group({class:"apexcharts-datalabels","data:realIndex":v}),L=s.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),P=0;P0&&b.push(u+A/2),p.push(f);var X=this.barHelpers.getPathFillColor(t,n,P,v);this.renderSeries({realIndex:v,pathFill:X,j:P,i:n,pathFrom:M.pathFrom,pathTo:M.pathTo,strokeWidth:T,elSeries:w,x:u,y:f,series:t,barHeight:k,barWidth:A,elDataLabelsWrap:C,elGoalsMarkers:L,visibleSeries:this.visibleI,type:"bar"})}a.globals.seriesXvalues[v]=b,a.globals.seriesYvalues[v]=p,o.add(w)}return o}},{key:"renderSeries",value:function(t){var e=t.realIndex,i=t.pathFill,a=t.lineFill,s=t.j,r=t.i,o=t.pathFrom,n=t.pathTo,l=t.strokeWidth,h=t.elSeries,c=t.x,d=t.y,g=t.y1,u=t.y2,f=t.series,p=t.barHeight,x=t.barWidth,b=t.barYPosition,y=t.elDataLabelsWrap,w=t.elGoalsMarkers,k=t.visibleSeries,A=t.type,S=this.w,C=new m(this.ctx);a||(a=this.barOptions.distributed?S.globals.stroke.colors[s]:S.globals.stroke.colors[e]),S.config.series[r].data[s]&&S.config.series[r].data[s].strokeColor&&(a=S.config.series[r].data[s].strokeColor),this.isNullValue&&(i="none");var L=s/S.config.chart.animations.animateGradually.delay*(S.config.chart.animations.speed/S.globals.dataPoints)/2.4,P=C.renderPaths({i:r,j:s,realIndex:e,pathFrom:o,pathTo:n,stroke:a,strokeWidth:l,strokeLineCap:S.config.stroke.lineCap,fill:i,animationDelay:L,initialSpeed:S.config.chart.animations.speed,dataChangeSpeed:S.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(A,"-area")});P.attr("clip-path","url(#gridRectMask".concat(S.globals.cuid,")"));var T=S.config.forecastDataPoints;T.count>0&&s>=S.globals.dataPoints-T.count&&(P.node.setAttribute("stroke-dasharray",T.dashArray),P.node.setAttribute("stroke-width",T.strokeWidth),P.node.setAttribute("fill-opacity",T.fillOpacity)),void 0!==g&&void 0!==u&&(P.attr("data-range-y1",g),P.attr("data-range-y2",u)),new v(this.ctx).setSelectionFilter(P,e,s),h.add(P);var M=new vt(this).handleBarDataLabels({x:c,y:d,y1:g,y2:u,i:r,j:s,series:f,realIndex:e,barHeight:p,barWidth:x,barYPosition:b,renderedPath:P,visibleSeries:k});return null!==M.dataLabels&&y.add(M.dataLabels),M.totalDataLabels&&y.add(M.totalDataLabels),h.add(y),w&&h.add(w),h}},{key:"drawBarPaths",value:function(t){var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,o=t.x,n=t.y,l=t.yDivision,h=t.elSeries,c=this.w,d=i.i,g=i.j;if(c.globals.isXNumeric)e=(n=(c.globals.seriesX[d][g]-c.globals.minX)/this.invertedXRatio-a)+a*this.visibleI;else if(c.config.plotOptions.bar.hideZeroBarsWhenGrouped){var u=0,f=0;c.globals.seriesPercent.forEach((function(t,e){t[g]&&u++,e0&&parseInt(r.realIndex,10)===parseInt(t,10)&&void 0!==a.globals.previousPaths[s].paths[e]&&(i=a.globals.previousPaths[s].paths[e].d)}return i}}]),t}(),wt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this,s=this.w;this.graphics=new m(this.ctx),this.bar=new yt(this.ctx,this.xyRatios);var r=new y(this.ctx,s);t=r.getLogSeries(t),this.yRatio=r.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t),"100%"===s.config.chart.stackType&&(t=s.globals.seriesPercent.slice()),this.series=t,this.totalItems=0,this.prevY=[],this.prevX=[],this.prevYF=[],this.prevXF=[],this.prevYVal=[],this.prevXVal=[],this.xArrj=[],this.xArrjF=[],this.xArrjVal=[],this.yArrj=[],this.yArrjF=[],this.yArrjVal=[];for(var o=0;o0&&(this.totalItems+=t[o].length);for(var n=this.graphics.group({class:"apexcharts-bar-series apexcharts-plot-series"}),l=0,h=0,c=function(r,o){var c=void 0,d=void 0,g=void 0,u=void 0,f=[],p=[],b=s.globals.comboCharts?i[r]:r;a.yRatio.length>1&&(a.yaxisIndex=b),a.isReversed=s.config.yaxis[a.yaxisIndex]&&s.config.yaxis[a.yaxisIndex].reversed;var v=a.graphics.group({class:"apexcharts-series",seriesName:x.escapeString(s.globals.seriesNames[b]),rel:r+1,"data:realIndex":b});a.ctx.series.addCollapsedClassToSeries(v,b);var m=a.graphics.group({class:"apexcharts-datalabels","data:realIndex":b}),y=a.graphics.group({class:"apexcharts-bar-goals-markers",style:"pointer-events: none"}),w=0,k=0,A=a.initialPositions(l,h,c,d,g,u);h=A.y,w=A.barHeight,d=A.yDivision,u=A.zeroW,l=A.x,k=A.barWidth,c=A.xDivision,g=A.zeroH,a.yArrj=[],a.yArrjF=[],a.yArrjVal=[],a.xArrj=[],a.xArrjF=[],a.xArrjVal=[],1===a.prevY.length&&a.prevY[0].every((function(t){return isNaN(t)}))&&(a.prevY[0]=a.prevY[0].map((function(t){return g})),a.prevYF[0]=a.prevYF[0].map((function(t){return 0})));for(var S=0;S1?(i=l.globals.minXDiff/this.xRatio)*parseInt(this.barOptions.columnWidth,10)/100:n*parseInt(l.config.plotOptions.bar.columnWidth,10)/100,s=l.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?l.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),t=l.globals.padHorizontal+(i-n)/2),{x:t,y:e,yDivision:a,xDivision:i,barHeight:o,barWidth:n,zeroH:s,zeroW:r}}},{key:"drawStackedBarPaths",value:function(t){for(var e,i=t.indexes,a=t.barHeight,s=t.strokeWidth,r=t.zeroW,o=t.x,n=t.y,l=t.yDivision,h=t.elSeries,c=this.w,d=n,g=i.i,u=i.j,f=0,p=0;p0){var x=r;this.prevXVal[g-1][u]<0?x=this.series[g][u]>=0?this.prevX[g-1][u]+f-2*(this.isReversed?f:0):this.prevX[g-1][u]:this.prevXVal[g-1][u]>=0&&(x=this.series[g][u]>=0?this.prevX[g-1][u]:this.prevX[g-1][u]-f+2*(this.isReversed?f:0)),e=x}else e=r;o=null===this.series[g][u]?e:e+this.series[g][u]/this.invertedYRatio-2*(this.isReversed?this.series[g][u]/this.invertedYRatio:0);var b=this.barHelpers.getBarpaths({barYPosition:d,barHeight:a,x1:e,x2:o,strokeWidth:s,series:this.series,realIndex:i.realIndex,i:g,j:u,w:c});return this.barHelpers.barBackground({j:u,i:g,y1:d,y2:a,elSeries:h}),n+=l,{pathTo:b.pathTo,pathFrom:b.pathFrom,goalX:this.barHelpers.getGoalValues("x",r,null,g,u),barYPosition:d,x:o,y:n}}},{key:"drawStackedColumnPaths",value:function(t){var e=t.indexes,i=t.x,a=t.y,s=t.xDivision,r=t.barWidth,o=t.zeroH;t.strokeWidth;var n=t.elSeries,l=this.w,h=e.i,c=e.j,d=e.bc;if(l.globals.isXNumeric){var g=l.globals.seriesX[h][c];g||(g=0),i=(g-l.globals.minX)/this.xRatio-r/2}for(var u,f=i,p=0,x=0;x0&&!l.globals.isXNumeric||h>0&&l.globals.isXNumeric&&l.globals.seriesX[h-1][c]===l.globals.seriesX[h][c]){var b,v,m=Math.min(this.yRatio.length+1,h+1);if(void 0!==this.prevY[h-1])for(var y=1;y=0?v-p+2*(this.isReversed?p:0):v;break}if(this.prevYVal[h-w][c]>=0){b=this.series[h][c]>=0?v:v+p-2*(this.isReversed?p:0);break}}void 0===b&&(b=l.globals.gridHeight),u=this.prevYF[0].every((function(t){return 0===t}))&&this.prevYF.slice(1,h).every((function(t){return t.every((function(t){return isNaN(t)}))}))?o:b}else u=o;a=this.series[h][c]?u-this.series[h][c]/this.yRatio[this.yaxisIndex]+2*(this.isReversed?this.series[h][c]/this.yRatio[this.yaxisIndex]:0):u;var k=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:r,y1:u,y2:a,yRatio:this.yRatio[this.yaxisIndex],strokeWidth:this.strokeWidth,series:this.series,realIndex:e.realIndex,i:h,j:c,w:l});return this.barHelpers.barBackground({bc:d,j:c,i:h,x1:f,x2:r,elSeries:n}),i+=s,{pathTo:k.pathTo,pathFrom:k.pathFrom,goalY:this.barHelpers.getGoalValues("y",null,o,h,c),barXPosition:f,x:l.globals.isXNumeric?i-s:i,y:a}}}]),s}(),kt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this,s=this.w,r=new m(this.ctx),o=new R(this.ctx);this.candlestickOptions=this.w.config.plotOptions.candlestick,this.boxOptions=this.w.config.plotOptions.boxPlot,this.isHorizontal=s.config.plotOptions.bar.horizontal;var n=new y(this.ctx,s);t=n.getLogSeries(t),this.series=t,this.yRatio=n.getLogYRatios(this.yRatio),this.barHelpers.initVariables(t);for(var l=r.group({class:"apexcharts-".concat(s.config.chart.type,"-series apexcharts-plot-series")}),h=function(n){a.isBoxPlot="boxPlot"===s.config.chart.type||"boxPlot"===s.config.series[n].type;var h,c,d,g,u=void 0,f=void 0,p=[],b=[],v=s.globals.comboCharts?i[n]:n,m=r.group({class:"apexcharts-series",seriesName:x.escapeString(s.globals.seriesNames[v]),rel:n+1,"data:realIndex":v});a.ctx.series.addCollapsedClassToSeries(m,v),t[n].length>0&&(a.visibleI=a.visibleI+1);var y,w;a.yRatio.length>1&&(a.yaxisIndex=v);var k=a.barHelpers.initialPositions();f=k.y,y=k.barHeight,c=k.yDivision,g=k.zeroW,u=k.x,w=k.barWidth,h=k.xDivision,d=k.zeroH,b.push(u+w/2);for(var A=r.group({class:"apexcharts-datalabels","data:realIndex":v}),S=function(i){var r=a.barHelpers.getStrokeWidth(n,i,v),l=null,x={indexes:{i:n,j:i,realIndex:v},x:u,y:f,strokeWidth:r,elSeries:m};l=a.isHorizontal?a.drawHorizontalBoxPaths(e(e({},x),{},{yDivision:c,barHeight:y,zeroW:g})):a.drawVerticalBoxPaths(e(e({},x),{},{xDivision:h,barWidth:w,zeroH:d})),f=l.y,u=l.x,i>0&&b.push(u+w/2),p.push(f),l.pathTo.forEach((function(e,h){var c=!a.isBoxPlot&&a.candlestickOptions.wick.useFillColor?l.color[h]:s.globals.stroke.colors[n],d=o.fillPath({seriesNumber:v,dataPointIndex:i,color:l.color[h],value:t[n][i]});a.renderSeries({realIndex:v,pathFill:d,lineFill:c,j:i,i:n,pathFrom:l.pathFrom,pathTo:e,strokeWidth:r,elSeries:m,x:u,y:f,series:t,barHeight:y,barWidth:w,elDataLabelsWrap:A,visibleSeries:a.visibleI,type:s.config.chart.type})}))},C=0;Cb.c&&(d=!1);var w=Math.min(b.o,b.c),k=Math.max(b.o,b.c),A=b.m;n.globals.isXNumeric&&(i=(n.globals.seriesX[x][c]-n.globals.minX)/this.xRatio-s/2);var S=i+s*this.visibleI;void 0===this.series[h][c]||null===this.series[h][c]?(w=r,k=r):(w=r-w/p,k=r-k/p,v=r-b.h/p,y=r-b.l/p,A=r-b.m/p);var C=l.move(S,r),L=l.move(S+s/2,w);return n.globals.previousPaths.length>0&&(L=this.getPreviousPath(x,c,!0)),C=this.isBoxPlot?[l.move(S,w)+l.line(S+s/2,w)+l.line(S+s/2,v)+l.line(S+s/4,v)+l.line(S+s-s/4,v)+l.line(S+s/2,v)+l.line(S+s/2,w)+l.line(S+s,w)+l.line(S+s,A)+l.line(S,A)+l.line(S,w+o/2),l.move(S,A)+l.line(S+s,A)+l.line(S+s,k)+l.line(S+s/2,k)+l.line(S+s/2,y)+l.line(S+s-s/4,y)+l.line(S+s/4,y)+l.line(S+s/2,y)+l.line(S+s/2,k)+l.line(S,k)+l.line(S,A)+"z"]:[l.move(S,k)+l.line(S+s/2,k)+l.line(S+s/2,v)+l.line(S+s/2,k)+l.line(S+s,k)+l.line(S+s,w)+l.line(S+s/2,w)+l.line(S+s/2,y)+l.line(S+s/2,w)+l.line(S,w)+l.line(S,k-o/2)],L+=l.move(S,w),n.globals.isXNumeric||(i+=a),{pathTo:C,pathFrom:L,x:i,y:k,barXPosition:S,color:this.isBoxPlot?f:d?[g]:[u]}}},{key:"drawHorizontalBoxPaths",value:function(t){var e=t.indexes;t.x;var i=t.y,a=t.yDivision,s=t.barHeight,r=t.zeroW,o=t.strokeWidth,n=this.w,l=new m(this.ctx),h=e.i,c=e.j,d=this.boxOptions.colors.lower;this.isBoxPlot&&(d=[this.boxOptions.colors.lower,this.boxOptions.colors.upper]);var g=this.invertedYRatio,u=e.realIndex,f=this.getOHLCValue(u,c),p=r,x=r,b=Math.min(f.o,f.c),v=Math.max(f.o,f.c),y=f.m;n.globals.isXNumeric&&(i=(n.globals.seriesX[u][c]-n.globals.minX)/this.invertedXRatio-s/2);var w=i+s*this.visibleI;void 0===this.series[h][c]||null===this.series[h][c]?(b=r,v=r):(b=r+b/g,v=r+v/g,p=r+f.h/g,x=r+f.l/g,y=r+f.m/g);var k=l.move(r,w),A=l.move(b,w+s/2);return n.globals.previousPaths.length>0&&(A=this.getPreviousPath(u,c,!0)),k=[l.move(b,w)+l.line(b,w+s/2)+l.line(p,w+s/2)+l.line(p,w+s/2-s/4)+l.line(p,w+s/2+s/4)+l.line(p,w+s/2)+l.line(b,w+s/2)+l.line(b,w+s)+l.line(y,w+s)+l.line(y,w)+l.line(b+o/2,w),l.move(y,w)+l.line(y,w+s)+l.line(v,w+s)+l.line(v,w+s/2)+l.line(x,w+s/2)+l.line(x,w+s-s/4)+l.line(x,w+s/4)+l.line(x,w+s/2)+l.line(v,w+s/2)+l.line(v,w)+l.line(y,w)+"z"],A+=l.move(b,w),n.globals.isXNumeric||(i+=a),{pathTo:k,pathFrom:A,x:v,y:i,barYPosition:w,color:d}}},{key:"getOHLCValue",value:function(t,e){var i=this.w;return{o:this.isBoxPlot?i.globals.seriesCandleH[t][e]:i.globals.seriesCandleO[t][e],h:this.isBoxPlot?i.globals.seriesCandleO[t][e]:i.globals.seriesCandleH[t][e],m:i.globals.seriesCandleM[t][e],l:this.isBoxPlot?i.globals.seriesCandleC[t][e]:i.globals.seriesCandleL[t][e],c:this.isBoxPlot?i.globals.seriesCandleL[t][e]:i.globals.seriesCandleC[t][e]}}}]),s}(),At=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"checkColorRange",value:function(){var t=this.w,e=!1,i=t.config.plotOptions[t.config.chart.type];return i.colorScale.ranges.length>0&&i.colorScale.ranges.map((function(t,i){t.from<=0&&(e=!0)})),e}},{key:"getShadeColor",value:function(t,e,i,a){var s=this.w,r=1,o=s.config.plotOptions[t].shadeIntensity,n=this.determineColor(t,e,i);s.globals.hasNegs||a?r=s.config.plotOptions[t].reverseNegativeShade?n.percent<0?n.percent/100*(1.25*o):(1-n.percent/100)*(1.25*o):n.percent<=0?1-(1+n.percent/100)*o:(1-n.percent/100)*o:(r=1-n.percent/100,"treemap"===t&&(r=(1-n.percent/100)*(1.25*o)));var l=n.color,h=new x;return s.config.plotOptions[t].enableShades&&(l="dark"===this.w.config.theme.mode?x.hexToRgba(h.shadeColor(-1*r,n.color),s.config.fill.opacity):x.hexToRgba(h.shadeColor(r,n.color),s.config.fill.opacity)),{color:l,colorProps:n}}},{key:"determineColor",value:function(t,e,i){var a=this.w,s=a.globals.series[e][i],r=a.config.plotOptions[t],o=r.colorScale.inverse?i:e;r.distributed&&"treemap"===a.config.chart.type&&(o=i);var n=a.globals.colors[o],l=null,h=Math.min.apply(Math,u(a.globals.series[e])),c=Math.max.apply(Math,u(a.globals.series[e]));r.distributed||"heatmap"!==t||(h=a.globals.minY,c=a.globals.maxY),void 0!==r.colorScale.min&&(h=r.colorScale.mina.globals.maxY?r.colorScale.max:a.globals.maxY);var d=Math.abs(c)+Math.abs(h),g=100*s/(0===d?d-1e-6:d);r.colorScale.ranges.length>0&&r.colorScale.ranges.map((function(t,e){if(s>=t.from&&s<=t.to){n=t.color,l=t.foreColor?t.foreColor:null,h=t.from,c=t.to;var i=Math.abs(c)+Math.abs(h);g=100*s/(0===i?i-1e-6:i)}}));return{color:n,foreColor:l,percent:g}}},{key:"calculateDataLabels",value:function(t){var e=t.text,i=t.x,a=t.y,s=t.i,r=t.j,o=t.colorProps,n=t.fontSize,l=this.w.config.dataLabels,h=new m(this.ctx),c=new O(this.ctx),d=null;if(l.enabled){d=h.group({class:"apexcharts-data-labels"});var g=l.offsetX,u=l.offsetY,f=i+g,p=a+parseFloat(l.style.fontSize)/3+u;c.plotDataLabelsText({x:f,y:p,text:e,i:s,j:r,color:o.foreColor,parent:d,fontSize:n,dataLabelsConfig:l})}return d}},{key:"addListeners",value:function(t){var e=new m(this.ctx);t.node.addEventListener("mouseenter",e.pathMouseEnter.bind(this,t)),t.node.addEventListener("mouseleave",e.pathMouseLeave.bind(this,t)),t.node.addEventListener("mousedown",e.pathMouseDown.bind(this,t))}}]),t}(),St=function(){function t(e,i){a(this,t),this.ctx=e,this.w=e.w,this.xRatio=i.xRatio,this.yRatio=i.yRatio,this.dynamicAnim=this.w.config.chart.animations.dynamicAnimation,this.helpers=new At(e),this.rectRadius=this.w.config.plotOptions.heatmap.radius,this.strokeWidth=this.w.config.stroke.show?this.w.config.stroke.width:0}return r(t,[{key:"draw",value:function(t){var e=this.w,i=new m(this.ctx),a=i.group({class:"apexcharts-heatmap"});a.attr("clip-path","url(#gridRectMask".concat(e.globals.cuid,")"));var s=e.globals.gridWidth/e.globals.dataPoints,r=e.globals.gridHeight/e.globals.series.length,o=0,n=!1;this.negRange=this.helpers.checkColorRange();var l=t.slice();e.config.yaxis[0].reversed&&(n=!0,l.reverse());for(var h=n?0:l.length-1;n?h=0;n?h++:h--){var c=i.group({class:"apexcharts-series apexcharts-heatmap-series",seriesName:x.escapeString(e.globals.seriesNames[h]),rel:h+1,"data:realIndex":h});if(this.ctx.series.addCollapsedClassToSeries(c,h),e.config.chart.dropShadow.enabled){var d=e.config.chart.dropShadow;new v(this.ctx).dropShadow(c,d,h)}for(var g=0,u=e.config.plotOptions.heatmap.shadeIntensity,f=0;f-1&&this.pieClicked(d),i.config.dataLabels.enabled){var A=w.x,S=w.y,C=100*u/this.fullAngle+"%";if(0!==u&&i.config.plotOptions.pie.dataLabels.minAngleToShowLabelthis.fullAngle?e.endAngle=e.endAngle-(a+o):a+o=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle&&(n=this.fullAngle+this.w.config.plotOptions.pie.startAngle%this.fullAngle-.01),Math.ceil(n)>this.fullAngle&&(n-=this.fullAngle);var l=Math.PI*(n-90)/180,h=e.centerX+s*Math.cos(o),c=e.centerY+s*Math.sin(o),d=e.centerX+s*Math.cos(l),g=e.centerY+s*Math.sin(l),u=x.polarToCartesian(e.centerX,e.centerY,e.donutSize,n),f=x.polarToCartesian(e.centerX,e.centerY,e.donutSize,r),p=a>180?1:0,b=["M",h,c,"A",s,s,0,p,1,d,g];return"donut"===e.chartType?[].concat(b,["L",u.x,u.y,"A",e.donutSize,e.donutSize,0,p,0,f.x,f.y,"L",h,c,"z"]).join(" "):"pie"===e.chartType||"polarArea"===e.chartType?[].concat(b,["L",e.centerX,e.centerY,"L",h,c]).join(" "):[].concat(b).join(" ")}},{key:"drawPolarElements",value:function(t){var e=this.w,i=new _(this.ctx),a=new m(this.ctx),s=new Ct(this.ctx),r=a.group(),o=a.group(),n=i.niceScale(0,Math.ceil(this.maxY),e.config.yaxis[0].tickAmount,0,!0),l=n.result.reverse(),h=n.result.length;this.maxY=n.niceMax;for(var c=e.globals.radialSize,d=c/(h-1),g=0;g1&&t.total.show&&(s=t.total.color);var o=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-label"),n=r.globals.dom.baseEl.querySelector(".apexcharts-datalabel-value");i=(0,t.value.formatter)(i,r),a||"function"!=typeof t.total.formatter||(i=t.total.formatter(r));var l=e===t.total.label;e=t.name.formatter(e,l,r),null!==o&&(o.textContent=e),null!==n&&(n.textContent=i),null!==o&&(o.style.fill=s)}},{key:"printDataLabelsInner",value:function(t,e){var i=this.w,a=t.getAttribute("data:value"),s=i.globals.seriesNames[parseInt(t.parentNode.getAttribute("rel"),10)-1];i.globals.series.length>1&&this.printInnerLabels(e,s,a,t);var r=i.globals.dom.baseEl.querySelector(".apexcharts-datalabels-group");null!==r&&(r.style.opacity=1)}},{key:"drawSpokes",value:function(t){var e=this,i=this.w,a=new m(this.ctx),s=i.config.plotOptions.polarArea.spokes;if(0!==s.strokeWidth){for(var r=[],o=360/i.globals.series.length,n=0;n1)o&&!e.total.showAlways?l({makeSliceOut:!1,printLabel:!0}):this.printInnerLabels(e,e.total.label,e.total.formatter(s));else if(l({makeSliceOut:!1,printLabel:!0}),!o)if(s.globals.selectedDataPoints.length&&s.globals.series.length>1)if(s.globals.selectedDataPoints[0].length>0){var h=s.globals.selectedDataPoints[0],c=s.globals.dom.baseEl.querySelector(".apexcharts-".concat(this.chartType.toLowerCase(),"-slice-").concat(h));this.printDataLabelsInner(c,e)}else r&&s.globals.selectedDataPoints.length&&0===s.globals.selectedDataPoints[0].length&&(r.style.opacity=0);else r&&s.globals.series.length>1&&(r.style.opacity=0)}}]),t}(),Pt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.chartType=this.w.config.chart.type,this.initialAnim=this.w.config.chart.animations.enabled,this.dynamicAnim=this.initialAnim&&this.w.config.chart.animations.dynamicAnimation.enabled,this.animDur=0;var i=this.w;this.graphics=new m(this.ctx),this.lineColorArr=void 0!==i.globals.stroke.colors?i.globals.stroke.colors:i.globals.colors,this.defaultSize=i.globals.svgHeight0&&(p=i.getPreviousPath(n));for(var b=0;b=10?t.x>0?(i="start",a+=10):t.x<0&&(i="end",a-=10):i="middle",Math.abs(t.y)>=e-10&&(t.y<0?s-=10:t.y>0&&(s+=10)),{textAnchor:i,newX:a,newY:s}}},{key:"getPreviousPath",value:function(t){for(var e=this.w,i=null,a=0;a0&&parseInt(s.realIndex,10)===parseInt(t,10)&&void 0!==e.globals.previousPaths[a].paths[0]&&(i=e.globals.previousPaths[a].paths[0].d)}return i}},{key:"getDataPointsPos",value:function(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.dataPointsLen;t=t||[],e=e||[];for(var a=[],s=0;s=360&&(g=360-Math.abs(this.startAngle)-.1);var u=i.drawPath({d:"",stroke:c,strokeWidth:o*parseInt(h.strokeWidth,10)/100,fill:"none",strokeOpacity:h.opacity,classes:"apexcharts-radialbar-area"});if(h.dropShadow.enabled){var f=h.dropShadow;s.dropShadow(u,f)}l.add(u),u.attr("id","apexcharts-radialbarTrack-"+n),this.animatePaths(u,{centerX:t.centerX,centerY:t.centerY,endAngle:g,startAngle:d,size:t.size,i:n,totalItems:2,animBeginArr:0,dur:0,isTrack:!0,easing:e.globals.easing})}return a}},{key:"drawArcs",value:function(t){var e=this.w,i=new m(this.ctx),a=new R(this.ctx),s=new v(this.ctx),r=i.group(),o=this.getStrokeWidth(t);t.size=t.size-o/2;var n=e.config.plotOptions.radialBar.hollow.background,l=t.size-o*t.series.length-this.margin*t.series.length-o*parseInt(e.config.plotOptions.radialBar.track.strokeWidth,10)/100/2,h=l-e.config.plotOptions.radialBar.hollow.margin;void 0!==e.config.plotOptions.radialBar.hollow.image&&(n=this.drawHollowImage(t,r,l,n));var c=this.drawHollow({size:h,centerX:t.centerX,centerY:t.centerY,fill:n||"transparent"});if(e.config.plotOptions.radialBar.hollow.dropShadow.enabled){var d=e.config.plotOptions.radialBar.hollow.dropShadow;s.dropShadow(c,d)}var g=1;!this.radialDataLabels.total.show&&e.globals.series.length>1&&(g=0);var u=null;this.radialDataLabels.show&&(u=this.renderInnerDataLabels(this.radialDataLabels,{hollowSize:l,centerX:t.centerX,centerY:t.centerY,opacity:g})),"back"===e.config.plotOptions.radialBar.hollow.position&&(r.add(c),u&&r.add(u));var f=!1;e.config.plotOptions.radialBar.inverseOrder&&(f=!0);for(var p=f?t.series.length-1:0;f?p>=0:p100?100:t.series[p])/100,S=Math.round(this.totalAngle*A)+this.startAngle,C=void 0;e.globals.dataChanged&&(k=this.startAngle,C=Math.round(this.totalAngle*x.negToZero(e.globals.previousPaths[p])/100)+k),Math.abs(S)+Math.abs(w)>=360&&(S-=.01),Math.abs(C)+Math.abs(k)>=360&&(C-=.01);var L=S-w,P=Array.isArray(e.config.stroke.dashArray)?e.config.stroke.dashArray[p]:e.config.stroke.dashArray,T=i.drawPath({d:"",stroke:y,strokeWidth:o,fill:"none",fillOpacity:e.config.fill.opacity,classes:"apexcharts-radialbar-area apexcharts-radialbar-slice-"+p,strokeDashArray:P});if(m.setAttrs(T.node,{"data:angle":L,"data:value":t.series[p]}),e.config.chart.dropShadow.enabled){var M=e.config.chart.dropShadow;s.dropShadow(T,M,p)}s.setSelectionFilter(T,0,p),this.addListeners(T,this.radialDataLabels),b.add(T),T.attr({index:0,j:p});var I=0;!this.initialAnim||e.globals.resized||e.globals.dataChanged||(I=e.config.chart.animations.speed),e.globals.dataChanged&&(I=e.config.chart.animations.dynamicAnimation.speed),this.animDur=I/(1.2*t.series.length)+this.animDur,this.animBeginArr.push(this.animDur),this.animatePaths(T,{centerX:t.centerX,centerY:t.centerY,endAngle:S,startAngle:w,prevEndAngle:C,prevStartAngle:k,size:t.size,i:p,totalItems:2,animBeginArr:this.animBeginArr,dur:I,shouldSetPrevPaths:!0,easing:e.globals.easing})}return{g:r,elHollow:c,dataLabels:u}}},{key:"drawHollow",value:function(t){var e=new m(this.ctx).drawCircle(2*t.size);return e.attr({class:"apexcharts-radialbar-hollow",cx:t.centerX,cy:t.centerY,r:t.size,fill:t.fill}),e}},{key:"drawHollowImage",value:function(t,e,i,a){var s=this.w,r=new R(this.ctx),o=x.randomId(),n=s.config.plotOptions.radialBar.hollow.image;if(s.config.plotOptions.radialBar.hollow.imageClipped)r.clippedImgArea({width:i,height:i,image:n,patternID:"pattern".concat(s.globals.cuid).concat(o)}),a="url(#pattern".concat(s.globals.cuid).concat(o,")");else{var l=s.config.plotOptions.radialBar.hollow.imageWidth,h=s.config.plotOptions.radialBar.hollow.imageHeight;if(void 0===l&&void 0===h){var c=s.globals.dom.Paper.image(n).loaded((function(e){this.move(t.centerX-e.width/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-e.height/2+s.config.plotOptions.radialBar.hollow.imageOffsetY)}));e.add(c)}else{var d=s.globals.dom.Paper.image(n).loaded((function(e){this.move(t.centerX-l/2+s.config.plotOptions.radialBar.hollow.imageOffsetX,t.centerY-h/2+s.config.plotOptions.radialBar.hollow.imageOffsetY),this.size(l,h)}));e.add(d)}}return a}},{key:"getStrokeWidth",value:function(t){var e=this.w;return t.size*(100-parseInt(e.config.plotOptions.radialBar.hollow.size,10))/100/(t.series.length+1)-this.margin}}]),i}(),Mt=function(t){n(s,yt);var i=d(s);function s(){return a(this,s),i.apply(this,arguments)}return r(s,[{key:"draw",value:function(t,i){var a=this.w,s=new m(this.ctx);this.rangeBarOptions=this.w.config.plotOptions.rangeBar,this.series=t,this.seriesRangeStart=a.globals.seriesRangeStart,this.seriesRangeEnd=a.globals.seriesRangeEnd,this.barHelpers.initVariables(t);for(var r=s.group({class:"apexcharts-rangebar-series apexcharts-plot-series"}),o=0;o0&&(this.visibleI=this.visibleI+1);var p=0,b=0;this.yRatio.length>1&&(this.yaxisIndex=u);var v=this.barHelpers.initialPositions();d=v.y,h=v.zeroW,c=v.x,b=v.barWidth,n=v.xDivision,l=v.zeroH;for(var y=s.group({class:"apexcharts-datalabels","data:realIndex":u}),w=s.group({class:"apexcharts-rangebar-goals-markers",style:"pointer-events: none"}),k=0;k0}));return a=l.config.plotOptions.bar.rangeBarGroupRows?s+o*g:s+r*this.visibleI+o*g,u>-1&&!l.config.plotOptions.bar.rangeBarOverlap&&(h=l.globals.seriesRange[e][u].overlaps).indexOf(c)>-1&&(a=(r=n.barHeight/h.length)*this.visibleI+o*(100-parseInt(this.barOptions.barHeight,10))/100/2+r*(this.visibleI+h.indexOf(c))+o*g),{barYPosition:a,barHeight:r}}},{key:"drawRangeColumnPaths",value:function(t){var e=t.indexes,i=t.x;t.strokeWidth;var a=t.xDivision,s=t.barWidth,r=t.zeroH,o=this.w,n=e.i,l=e.j,h=this.yRatio[this.yaxisIndex],c=e.realIndex,d=this.getRangeValue(c,l),g=Math.min(d.start,d.end),u=Math.max(d.start,d.end);o.globals.isXNumeric&&(i=(o.globals.seriesX[n][l]-o.globals.minX)/this.xRatio-s/2);var f=i+s*this.visibleI;void 0===this.series[n][l]||null===this.series[n][l]?g=r:(g=r-g/h,u=r-u/h);var p=Math.abs(u-g),x=this.barHelpers.getColumnPaths({barXPosition:f,barWidth:s,y1:g,y2:u,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,realIndex:e.realIndex,i:c,j:l,w:o});return o.globals.isXNumeric||(i+=a),{pathTo:x.pathTo,pathFrom:x.pathFrom,barHeight:p,x:i,y:u,goalY:this.barHelpers.getGoalValues("y",null,r,n,l),barXPosition:f}}},{key:"drawRangeBarPaths",value:function(t){var e=t.indexes,i=t.y,a=t.y1,s=t.y2,r=t.yDivision,o=t.barHeight,n=t.barYPosition,l=t.zeroW,h=this.w,c=l+a/this.invertedYRatio,d=l+s/this.invertedYRatio,g=Math.abs(d-c),u=this.barHelpers.getBarpaths({barYPosition:n,barHeight:o,x1:c,x2:d,strokeWidth:this.strokeWidth,series:this.seriesRangeEnd,i:e.realIndex,realIndex:e.realIndex,j:e.j,w:h});return h.globals.isXNumeric||(i+=r),{pathTo:u.pathTo,pathFrom:u.pathFrom,barWidth:g,x:d,goalX:this.barHelpers.getGoalValues("x",l,null,e.realIndex,e.j),y:i}}},{key:"getRangeValue",value:function(t,e){var i=this.w;return{start:i.globals.seriesRangeStart[t][e],end:i.globals.seriesRangeEnd[t][e]}}}]),s}(),It=function(){function t(e){a(this,t),this.w=e.w,this.lineCtx=e}return r(t,[{key:"sameValueSeriesFix",value:function(t,e){var i=this.w;if(("gradient"===i.config.fill.type||"gradient"===i.config.fill.type[t])&&new y(this.lineCtx.ctx,i).seriesHaveSameValues(t)){var a=e[t].slice();a[a.length-1]=a[a.length-1]+1e-6,e[t]=a}return e}},{key:"calculatePoints",value:function(t){var e=t.series,i=t.realIndex,a=t.x,s=t.y,r=t.i,o=t.j,n=t.prevY,l=this.w,h=[],c=[];if(0===o){var d=this.lineCtx.categoryAxisCorrection+l.config.markers.offsetX;l.globals.isXNumeric&&(d=(l.globals.seriesX[i][0]-l.globals.minX)/this.lineCtx.xRatio+l.config.markers.offsetX),h.push(d),c.push(x.isNumber(e[r][0])?n+l.config.markers.offsetY:null),h.push(a+l.config.markers.offsetX),c.push(x.isNumber(e[r][o+1])?s+l.config.markers.offsetY:null)}else h.push(a+l.config.markers.offsetX),c.push(x.isNumber(e[r][o+1])?s+l.config.markers.offsetY:null);return{x:h,y:c}}},{key:"checkPreviousPaths",value:function(t){for(var e=t.pathFromLine,i=t.pathFromArea,a=t.realIndex,s=this.w,r=0;r0&&parseInt(o.realIndex,10)===parseInt(a,10)&&("line"===o.type?(this.lineCtx.appendPathFrom=!1,e=s.globals.previousPaths[r].paths[0].d):"area"===o.type&&(this.lineCtx.appendPathFrom=!1,i=s.globals.previousPaths[r].paths[0].d,s.config.stroke.show&&s.globals.previousPaths[r].paths[1]&&(e=s.globals.previousPaths[r].paths[1].d)))}return{pathFromLine:e,pathFromArea:i}}},{key:"determineFirstPrevY",value:function(t){var e,i=t.i,a=t.series,s=t.prevY,r=t.lineYPosition,o=this.w;if(void 0!==(null===(e=a[i])||void 0===e?void 0:e[0]))s=(r=o.config.chart.stacked&&i>0?this.lineCtx.prevSeriesY[i-1][0]:this.lineCtx.zeroY)-a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]+2*(this.lineCtx.isReversed?a[i][0]/this.lineCtx.yRatio[this.lineCtx.yaxisIndex]:0);else if(o.config.chart.stacked&&i>0&&void 0===a[i][0])for(var n=i-1;n>=0;n--)if(null!==a[n][0]&&void 0!==a[n][0]){s=r=this.lineCtx.prevSeriesY[n][0];break}return{prevY:s,lineYPosition:r}}}]),t}(),zt=function(){function t(e,i,s){a(this,t),this.ctx=e,this.w=e.w,this.xyRatios=i,this.pointsChart=!("bubble"!==this.w.config.chart.type&&"scatter"!==this.w.config.chart.type)||s,this.scatter=new H(this.ctx),this.noNegatives=this.w.globals.minX===Number.MAX_VALUE,this.lineHelpers=new It(this),this.markers=new D(this.ctx),this.prevSeriesY=[],this.categoryAxisCorrection=0,this.yaxisIndex=0}return r(t,[{key:"draw",value:function(t,i,a,s){var r=this.w,o=new m(this.ctx),n=r.globals.comboCharts?i:r.config.chart.type,l=o.group({class:"apexcharts-".concat(n,"-series apexcharts-plot-series")}),h=new y(this.ctx,r);this.yRatio=this.xyRatios.yRatio,this.zRatio=this.xyRatios.zRatio,this.xRatio=this.xyRatios.xRatio,this.baseLineY=this.xyRatios.baseLineY,t=h.getLogSeries(t),this.yRatio=h.getLogYRatios(this.yRatio);for(var c=[],d=0;d0&&(p=(r.globals.seriesX[g][0]-r.globals.minX)/this.xRatio),f.push(p);var x,b=p,v=void 0,w=b,k=this.zeroY,A=this.zeroY;k=this.lineHelpers.determineFirstPrevY({i:d,series:t,prevY:k,lineYPosition:0}).prevY,u.push(k),x=k;"rangeArea"===n&&(v=A=this.lineHelpers.determineFirstPrevY({i:d,series:s,prevY:A,lineYPosition:0}).prevY);var S={type:n,series:t,realIndex:g,i:d,x:p,y:1,pX:b,pY:x,pathsFrom:this._calculatePathsFrom({type:n,series:t,i:d,realIndex:g,prevX:w,prevY:k,prevY2:A}),linePaths:[],areaPaths:[],seriesIndex:a,lineYPosition:0,xArrj:f,yArrj:u,seriesRangeEnd:s},C=this._iterateOverDataPoints(e(e({},S),{},{iterations:"rangeArea"===n?t[d].length-1:void 0,isRangeStart:!0}));if("rangeArea"===n){var L=this._calculatePathsFrom({series:s,i:d,realIndex:g,prevX:w,prevY:A}),P=this._iterateOverDataPoints(e(e({},S),{},{series:s,pY:v,pathsFrom:L,iterations:s[d].length-1,isRangeStart:!1}));C.linePaths[0]=P.linePath+C.linePath,C.pathFromLine=P.pathFromLine+C.pathFromLine}this._handlePaths({type:n,realIndex:g,i:d,paths:C}),this.elSeries.add(this.elPointsMain),this.elSeries.add(this.elDataLabelsWrap),c.push(this.elSeries)}if(r.config.chart.stacked)for(var T=c.length;T>0;T--)l.add(c[T-1]);else for(var M=0;M1&&(this.yaxisIndex=i),this.isReversed=a.config.yaxis[this.yaxisIndex]&&a.config.yaxis[this.yaxisIndex].reversed,this.zeroY=a.globals.gridHeight-this.baseLineY[this.yaxisIndex]-(this.isReversed?a.globals.gridHeight:0)+(this.isReversed?2*this.baseLineY[this.yaxisIndex]:0),this.areaBottomY=this.zeroY,(this.zeroY>a.globals.gridHeight||"end"===a.config.plotOptions.area.fillTo)&&(this.areaBottomY=a.globals.gridHeight),this.categoryAxisCorrection=this.xDivision/2,this.elSeries=s.group({class:"apexcharts-series",seriesName:x.escapeString(a.globals.seriesNames[i])}),this.elPointsMain=s.group({class:"apexcharts-series-markers-wrap","data:realIndex":i}),this.elDataLabelsWrap=s.group({class:"apexcharts-datalabels","data:realIndex":i});var r=t[e].length===a.globals.dataPoints;this.elSeries.attr({"data:longestSeries":r,rel:e+1,"data:realIndex":i}),this.appendPathFrom=!0}},{key:"_calculatePathsFrom",value:function(t){var e,i,a,s,r=t.type,o=t.series,n=t.i,l=t.realIndex,h=t.prevX,c=t.prevY,d=t.prevY2,g=this.w,u=new m(this.ctx);if(null===o[n][0]){for(var f=0;f0){var p=this.lineHelpers.checkPreviousPaths({pathFromLine:a,pathFromArea:s,realIndex:l});a=p.pathFromLine,s=p.pathFromArea}return{prevX:h,prevY:c,linePath:e,areaPath:i,pathFromLine:a,pathFromArea:s}}},{key:"_handlePaths",value:function(t){var i=t.type,a=t.realIndex,s=t.i,r=t.paths,o=this.w,n=new m(this.ctx),l=new R(this.ctx);this.prevSeriesY.push(r.yArrj),o.globals.seriesXvalues[a]=r.xArrj,o.globals.seriesYvalues[a]=r.yArrj;var h=o.config.forecastDataPoints;if(h.count>0&&"rangeArea"!==i){var c=o.globals.seriesXvalues[a][o.globals.seriesXvalues[a].length-h.count-1],d=n.drawRect(c,0,o.globals.gridWidth,o.globals.gridHeight,0);o.globals.dom.elForecastMask.appendChild(d.node);var g=n.drawRect(0,0,c,o.globals.gridHeight,0);o.globals.dom.elNonForecastMask.appendChild(g.node)}this.pointsChart||o.globals.delayedElements.push({el:this.elPointsMain.node,index:a});var u={i:s,realIndex:a,animationDelay:s,initialSpeed:o.config.chart.animations.speed,dataChangeSpeed:o.config.chart.animations.dynamicAnimation.speed,className:"apexcharts-".concat(i)};if("area"===i)for(var f=l.fillPath({seriesNumber:a}),p=0;p0&&"rangeArea"!==i){var S=n.renderPaths(k);S.node.setAttribute("stroke-dasharray",h.dashArray),h.strokeWidth&&S.node.setAttribute("stroke-width",h.strokeWidth),this.elSeries.add(S),S.attr("clip-path","url(#forecastMask".concat(o.globals.cuid,")")),A.attr("clip-path","url(#nonForecastMask".concat(o.globals.cuid,")"))}}}}},{key:"_iterateOverDataPoints",value:function(t){var e=t.type,i=t.series,a=t.iterations,s=t.realIndex,r=t.i,o=t.x,n=t.y,l=t.pX,h=t.pY,c=t.pathsFrom,d=t.linePaths,g=t.areaPaths,u=t.seriesIndex,f=t.lineYPosition,p=t.xArrj,b=t.yArrj,v=t.isRangeStart,y=t.seriesRangeEnd,w=this.w,k=new m(this.ctx),A=this.yRatio,S=c.prevY,C=c.linePath,L=c.areaPath,P=c.pathFromLine,T=c.pathFromArea,M=x.isNumber(w.globals.minYArr[s])?w.globals.minYArr[s]:w.globals.minY;a||(a=w.globals.dataPoints>1?w.globals.dataPoints-1:w.globals.dataPoints);for(var I=n,z=0;z0&&w.globals.collapsedSeries.length-1){e--;break}return e>=0?e:0}(r-1)][z+1]}else f=this.zeroY;else f=this.zeroY;X?n=f-M/A[this.yaxisIndex]+2*(this.isReversed?M/A[this.yaxisIndex]:0):(n=f-i[r][z+1]/A[this.yaxisIndex]+2*(this.isReversed?i[r][z+1]/A[this.yaxisIndex]:0),"rangeArea"===e&&(I=f-y[r][z+1]/A[this.yaxisIndex]+2*(this.isReversed?y[r][z+1]/A[this.yaxisIndex]:0))),p.push(o),b.push(n);var Y=this.lineHelpers.calculatePoints({series:i,x:o,y:n,realIndex:s,i:r,j:z,prevY:S}),F=this._createPaths({type:e,series:i,i:r,realIndex:s,j:z,x:o,y:n,y2:I,pX:l,pY:h,linePath:C,areaPath:L,linePaths:d,areaPaths:g,seriesIndex:u,isRangeStart:v});g=F.areaPaths,d=F.linePaths,l=F.pX,h=F.pY,L=F.areaPath,C=F.linePath,this.appendPathFrom&&(P+=k.line(o,this.zeroY),T+=k.line(o,this.zeroY)),this.handleNullDataPoints(i,Y,r,z,s),this._handleMarkersAndLabels({type:e,pointsPos:Y,i:r,j:z,realIndex:s,isRangeStart:v})}return{yArrj:b,xArrj:p,pathFromArea:T,areaPaths:g,pathFromLine:P,linePaths:d,linePath:C,areaPath:L}}},{key:"_handleMarkersAndLabels",value:function(t){var e=t.type,i=t.pointsPos,a=t.isRangeStart,s=t.i,r=t.j,o=t.realIndex,n=this.w,l=new O(this.ctx);if(this.pointsChart)this.scatter.draw(this.elSeries,r,{realIndex:o,pointsPos:i,zRatio:this.zRatio,elParent:this.elPointsMain});else{n.globals.series[s].length>1&&this.elPointsMain.node.classList.add("apexcharts-element-hidden");var h=this.markers.plotChartMarkers(i,o,r+1);null!==h&&this.elPointsMain.add(h)}var c=l.drawDataLabel({type:e,isRangeStart:a,pos:i,i:o,j:r+1});null!==c&&this.elDataLabelsWrap.add(c)}},{key:"_createPaths",value:function(t){var e=t.type,i=t.series,a=t.i,s=t.realIndex,r=t.j,o=t.x,n=t.y,l=t.y2,h=t.pX,c=t.pY,d=t.linePath,g=t.areaPath,u=t.linePaths,f=t.areaPaths,p=t.seriesIndex,x=t.isRangeStart,b=this.w,v=new m(this.ctx),y=b.config.stroke.curve,w=this.areaBottomY;if(Array.isArray(b.config.stroke.curve)&&(y=Array.isArray(p)?b.config.stroke.curve[p[a]]:b.config.stroke.curve[a]),"smooth"===y){var k=.35*(o-h);b.globals.hasNullValues?(null!==i[a][r]&&(null!==i[a][r+1]?(d=v.move(h,c)+v.curve(h+k,c,o-k,n,o+1,n),g=v.move(h+1,c)+v.curve(h+k,c,o-k,n,o+1,n)+v.line(o,w)+v.line(h,w)+"z"):(d=v.move(h,c),g=v.move(h,c)+"z")),u.push(d),f.push(g)):(d+=v.curve(h+k,c,o-k,n,o,n),g+=v.curve(h+k,c,o-k,n,o,n)),h=o,c=n,r===i[a].length-2&&(g=g+v.curve(h,c,o,n,o,w)+v.move(o,n)+"z","rangeArea"===e&&x?d=d+v.curve(h,c,o,n,o,l)+v.move(o,l)+"z":b.globals.hasNullValues||(u.push(d),f.push(g)))}else{if(null===i[a][r+1]){d+=v.move(o,n);var A=b.globals.isXNumeric?(b.globals.seriesX[s][r]-b.globals.minX)/this.xRatio:o-this.xDivision;g=g+v.line(A,w)+v.move(o,n)+"z"}null===i[a][r]&&(d+=v.move(o,n),g+=v.move(o,w)),"stepline"===y?(d=d+v.line(o,null,"H")+v.line(null,n,"V"),g=g+v.line(o,null,"H")+v.line(null,n,"V")):"straight"===y&&(d+=v.line(o,n),g+=v.line(o,n)),r===i[a].length-2&&(g=g+v.line(o,w)+v.move(o,n)+"z","rangeArea"===e&&x?d=d+v.line(o,l)+v.move(o,l)+"z":(u.push(d),f.push(g)))}return{linePaths:u,areaPaths:f,pX:h,pY:c,linePath:d,areaPath:g}}},{key:"handleNullDataPoints",value:function(t,e,i,a,s){var r=this.w;if(null===t[i][a]&&r.config.markers.showNullDataPoints||1===t[i].length){var o=this.markers.plotChartMarkers(e,s,a+1,this.strokeWidth-r.config.markers.strokeWidth/2,!0);null!==o&&this.elPointsMain.add(o)}}}]),t}();window.TreemapSquared={},window.TreemapSquared.generate=function(){function t(e,i,a,s){this.xoffset=e,this.yoffset=i,this.height=s,this.width=a,this.shortestEdge=function(){return Math.min(this.height,this.width)},this.getCoordinates=function(t){var e,i=[],a=this.xoffset,s=this.yoffset,o=r(t)/this.height,n=r(t)/this.width;if(this.width>=this.height)for(e=0;e=this.height){var a=e/this.height,s=this.width-a;i=new t(this.xoffset+a,this.yoffset,s,this.height)}else{var r=e/this.width,o=this.height-r;i=new t(this.xoffset,this.yoffset+r,this.width,o)}return i}}function e(e,a,s,o,n){o=void 0===o?0:o,n=void 0===n?0:n;var l=i(function(t,e){var i,a=[],s=e/r(t);for(i=0;i=o}(e,l=t[0],n)?(e.push(l),i(t.slice(1),e,s,o)):(h=s.cutArea(r(e),o),o.push(s.getCoordinates(e)),i(t,[],h,o)),o;o.push(s.getCoordinates(e))}function a(t,e){var i=Math.min.apply(Math,t),a=Math.max.apply(Math,t),s=r(t);return Math.max(Math.pow(e,2)*a/Math.pow(s,2),Math.pow(s,2)/(Math.pow(e,2)*i))}function s(t){return t&&t.constructor===Array}function r(t){var e,i=0;for(e=0;er-a&&l.width<=o-s){var h=n.rotateAroundCenter(t.node);t.node.setAttribute("transform","rotate(-90 ".concat(h.x," ").concat(h.y,")"))}}},{key:"animateTreemap",value:function(t,e,i,a){var s=new b(this.ctx);s.animateRect(t,{x:e.x,y:e.y,width:e.width,height:e.height},{x:i.x,y:i.y,width:i.width,height:i.height},a,(function(){s.animationCompleted(t)}))}}]),t}(),Ft=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w,this.timeScaleArray=[],this.utc=this.w.config.xaxis.labels.datetimeUTC}return r(t,[{key:"calculateTimeScaleTicks",value:function(t,i){var a=this,s=this.w;if(s.globals.allSeriesCollapsed)return s.globals.labels=[],s.globals.timescaleLabels=[],[];var r=new T(this.ctx),o=(i-t)/864e5;this.determineInterval(o),s.globals.disableZoomIn=!1,s.globals.disableZoomOut=!1,o<.00011574074074074075?s.globals.disableZoomIn=!0:o>5e4&&(s.globals.disableZoomOut=!0);var n=r.getTimeUnitsfromTimestamp(t,i,this.utc),l=s.globals.gridWidth/o,h=l/24,c=h/60,d=c/60,g=Math.floor(24*o),u=Math.floor(1440*o),f=Math.floor(86400*o),p=Math.floor(o),x=Math.floor(o/30),b=Math.floor(o/365),v={minMillisecond:n.minMillisecond,minSecond:n.minSecond,minMinute:n.minMinute,minHour:n.minHour,minDate:n.minDate,minMonth:n.minMonth,minYear:n.minYear},m={firstVal:v,currentMillisecond:v.minMillisecond,currentSecond:v.minSecond,currentMinute:v.minMinute,currentHour:v.minHour,currentMonthDate:v.minDate,currentDate:v.minDate,currentMonth:v.minMonth,currentYear:v.minYear,daysWidthOnXAxis:l,hoursWidthOnXAxis:h,minutesWidthOnXAxis:c,secondsWidthOnXAxis:d,numberOfSeconds:f,numberOfMinutes:u,numberOfHours:g,numberOfDays:p,numberOfMonths:x,numberOfYears:b};switch(this.tickInterval){case"years":this.generateYearScale(m);break;case"months":case"half_year":this.generateMonthScale(m);break;case"months_days":case"months_fortnight":case"days":case"week_days":this.generateDayScale(m);break;case"hours":this.generateHourScale(m);break;case"minutes_fives":case"minutes":this.generateMinuteScale(m);break;case"seconds_tens":case"seconds_fives":case"seconds":this.generateSecondScale(m)}var y=this.timeScaleArray.map((function(t){var i={position:t.position,unit:t.unit,year:t.year,day:t.day?t.day:1,hour:t.hour?t.hour:0,month:t.month+1};return"month"===t.unit?e(e({},i),{},{day:1,value:t.value+1}):"day"===t.unit||"hour"===t.unit?e(e({},i),{},{value:t.value}):"minute"===t.unit?e(e({},i),{},{value:t.value,minute:t.value}):"second"===t.unit?e(e({},i),{},{value:t.value,minute:t.minute,second:t.second}):t}));return y.filter((function(t){var e=1,i=Math.ceil(s.globals.gridWidth/120),r=t.value;void 0!==s.config.xaxis.tickAmount&&(i=s.config.xaxis.tickAmount),y.length>i&&(e=Math.floor(y.length/i));var o=!1,n=!1;switch(a.tickInterval){case"years":"year"===t.unit&&(o=!0);break;case"half_year":e=7,"year"===t.unit&&(o=!0);break;case"months":e=1,"year"===t.unit&&(o=!0);break;case"months_fortnight":e=15,"year"!==t.unit&&"month"!==t.unit||(o=!0),30===r&&(n=!0);break;case"months_days":e=10,"month"===t.unit&&(o=!0),30===r&&(n=!0);break;case"week_days":e=8,"month"===t.unit&&(o=!0);break;case"days":e=1,"month"===t.unit&&(o=!0);break;case"hours":"day"===t.unit&&(o=!0);break;case"minutes_fives":case"seconds_fives":r%5!=0&&(n=!0);break;case"seconds_tens":r%10!=0&&(n=!0)}if("hours"===a.tickInterval||"minutes_fives"===a.tickInterval||"seconds_tens"===a.tickInterval||"seconds_fives"===a.tickInterval){if(!n)return!0}else if((r%e==0||o)&&!n)return!0}))}},{key:"recalcDimensionsBasedOnFormat",value:function(t,e){var i=this.w,a=this.formatDates(t),s=this.removeOverlappingTS(a);i.globals.timescaleLabels=s.slice(),new ot(this.ctx).plotCoords()}},{key:"determineInterval",value:function(t){var e=24*t,i=60*e;switch(!0){case t/365>5:this.tickInterval="years";break;case t>800:this.tickInterval="half_year";break;case t>180:this.tickInterval="months";break;case t>90:this.tickInterval="months_fortnight";break;case t>60:this.tickInterval="months_days";break;case t>30:this.tickInterval="week_days";break;case t>2:this.tickInterval="days";break;case e>2.4:this.tickInterval="hours";break;case i>15:this.tickInterval="minutes_fives";break;case i>5:this.tickInterval="minutes";break;case i>1:this.tickInterval="seconds_tens";break;case 60*i>20:this.tickInterval="seconds_fives";break;default:this.tickInterval="seconds"}}},{key:"generateYearScale",value:function(t){var e=t.firstVal,i=t.currentMonth,a=t.currentYear,s=t.daysWidthOnXAxis,r=t.numberOfYears,o=e.minYear,n=0,l=new T(this.ctx),h="year";if(e.minDate>1||e.minMonth>0){var c=l.determineRemainingDaysOfYear(e.minYear,e.minMonth,e.minDate);n=(l.determineDaysOfYear(e.minYear)-c+1)*s,o=e.minYear+1,this.timeScaleArray.push({position:n,value:o,unit:h,year:o,month:x.monthMod(i+1)})}else 1===e.minDate&&0===e.minMonth&&this.timeScaleArray.push({position:n,value:o,unit:h,year:a,month:x.monthMod(i+1)});for(var d=o,g=n,u=0;u1){l=(h.determineDaysOfMonths(a+1,e.minYear)-i+1)*r,n=x.monthMod(a+1);var g=s+d,u=x.monthMod(n),f=n;0===n&&(c="year",f=g,u=1,g+=d+=1),this.timeScaleArray.push({position:l,value:f,unit:c,year:g,month:u})}else this.timeScaleArray.push({position:l,value:n,unit:c,year:s,month:x.monthMod(a)});for(var p=n+1,b=l,v=0,m=1;vo.determineDaysOfMonths(e+1,i)?(h=1,n="month",g=e+=1,e):e},d=(24-e.minHour)*s,g=l,u=c(h,i,a);0===e.minHour&&1===e.minDate?(d=0,g=x.monthMod(e.minMonth),n="month",h=e.minDate,r++):1!==e.minDate&&0===e.minHour&&0===e.minMinute&&(d=0,l=e.minDate,g=l,u=c(h=l,i,a)),this.timeScaleArray.push({position:d,value:g,unit:n,year:this._getYear(a,u,0),month:x.monthMod(u),day:h});for(var f=d,p=0;pn.determineDaysOfMonths(e+1,s)&&(p=1,e+=1),{month:e,date:p}},c=function(t,e){return t>n.determineDaysOfMonths(e+1,s)?e+=1:e},d=60-(e.minMinute+e.minSecond/60),g=d*r,u=e.minHour+1,f=u+1;60===d&&(g=0,f=(u=e.minHour)+1);var p=i,b=c(p,a);this.timeScaleArray.push({position:g,value:u,unit:l,day:p,hour:f,year:s,month:x.monthMod(b)});for(var v=g,m=0;m=24)f=0,l="day",b=h(p+=1,b).month,b=c(p,b);var y=this._getYear(s,b,0);v=60*r+v;var w=0===f?p:f;this.timeScaleArray.push({position:v,value:w,unit:l,hour:f,day:p,year:y,month:x.monthMod(b)}),f++}}},{key:"generateMinuteScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,n=t.currentYear,l=t.minutesWidthOnXAxis,h=t.secondsWidthOnXAxis,c=t.numberOfMinutes,d=a+1,g=r,u=o,f=n,p=s,b=(60-i-e/1e3)*h,v=0;v=60&&(d=0,24===(p+=1)&&(p=0)),this.timeScaleArray.push({position:b,value:d,unit:"minute",hour:p,minute:d,day:g,year:this._getYear(f,u,0),month:x.monthMod(u)}),b+=l,d++}},{key:"generateSecondScale",value:function(t){for(var e=t.currentMillisecond,i=t.currentSecond,a=t.currentMinute,s=t.currentHour,r=t.currentDate,o=t.currentMonth,n=t.currentYear,l=t.secondsWidthOnXAxis,h=t.numberOfSeconds,c=i+1,d=a,g=r,u=o,f=n,p=s,b=(1e3-e)/1e3*l,v=0;v=60&&(c=0,++d>=60&&(d=0,24===++p&&(p=0))),this.timeScaleArray.push({position:b,value:c,unit:"second",hour:p,minute:d,second:c,day:g,year:this._getYear(f,u,0),month:x.monthMod(u)}),b+=l,c++}},{key:"createRawDateString",value:function(t,e){var i=t.year;return 0===t.month&&(t.month=1),i+="-"+("0"+t.month.toString()).slice(-2),"day"===t.unit?i+="day"===t.unit?"-"+("0"+e).slice(-2):"-01":i+="-"+("0"+(t.day?t.day:"1")).slice(-2),"hour"===t.unit?i+="hour"===t.unit?"T"+("0"+e).slice(-2):"T00":i+="T"+("0"+(t.hour?t.hour:"0")).slice(-2),"minute"===t.unit?i+=":"+("0"+e).slice(-2):i+=":"+(t.minute?("0"+t.minute).slice(-2):"00"),"second"===t.unit?i+=":"+("0"+e).slice(-2):i+=":00",this.utc&&(i+=".000Z"),i}},{key:"formatDates",value:function(t){var e=this,i=this.w;return t.map((function(t){var a=t.value.toString(),s=new T(e.ctx),r=e.createRawDateString(t,a),o=s.getDate(s.parseDate(r));if(e.utc||(o=s.getDate(s.parseDateWithTimezone(r))),void 0===i.config.xaxis.labels.format){var n="dd MMM",l=i.config.xaxis.labels.datetimeFormatter;"year"===t.unit&&(n=l.year),"month"===t.unit&&(n=l.month),"day"===t.unit&&(n=l.day),"hour"===t.unit&&(n=l.hour),"minute"===t.unit&&(n=l.minute),"second"===t.unit&&(n=l.second),a=s.formatDate(o,n)}else a=s.formatDate(o,i.config.xaxis.labels.format);return{dateString:r,position:t.position,value:a,unit:t.unit,year:t.year,month:t.month}}))}},{key:"removeOverlappingTS",value:function(t){var e,i=this,a=new m(this.ctx),s=!1;t.length>0&&t[0].value&&t.every((function(e){return e.value.length===t[0].value.length}))&&(s=!0,e=a.getTextRects(t[0].value).width);var r=0,o=t.map((function(o,n){if(n>0&&i.w.config.xaxis.labels.hideOverlappingLabels){var l=s?e:a.getTextRects(t[r].value).width,h=t[r].position;return o.position>h+l+10?(r=n,o):null}return o}));return o=o.filter((function(t){return null!==t}))}},{key:"_getYear",value:function(t,e,i){return t+Math.floor(e/12)+i}}]),t}(),Rt=function(){function t(e,i){a(this,t),this.ctx=i,this.w=i.w,this.el=e}return r(t,[{key:"setupElements",value:function(){var t=this.w.globals,e=this.w.config,i=e.chart.type;t.axisCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble","radar","heatmap","treemap"].indexOf(i)>-1,t.xyCharts=["line","area","bar","rangeBar","rangeArea","candlestick","boxPlot","scatter","bubble"].indexOf(i)>-1,t.isBarHorizontal=("bar"===e.chart.type||"rangeBar"===e.chart.type||"boxPlot"===e.chart.type)&&e.plotOptions.bar.horizontal,t.chartClass=".apexcharts"+t.chartID,t.dom.baseEl=this.el,t.dom.elWrap=document.createElement("div"),m.setAttrs(t.dom.elWrap,{id:t.chartClass.substring(1),class:"apexcharts-canvas "+t.chartClass.substring(1)}),this.el.appendChild(t.dom.elWrap),t.dom.Paper=new window.SVG.Doc(t.dom.elWrap),t.dom.Paper.attr({class:"apexcharts-svg","xmlns:data":"ApexChartsNS",transform:"translate(".concat(e.chart.offsetX,", ").concat(e.chart.offsetY,")")}),t.dom.Paper.node.style.background=e.chart.background,this.setSVGDimensions(),t.dom.elGraphical=t.dom.Paper.group().attr({class:"apexcharts-inner apexcharts-graphical"}),t.dom.elAnnotations=t.dom.Paper.group().attr({class:"apexcharts-annotations"}),t.dom.elDefs=t.dom.Paper.defs(),t.dom.elLegendWrap=document.createElement("div"),t.dom.elLegendWrap.classList.add("apexcharts-legend"),t.dom.elWrap.appendChild(t.dom.elLegendWrap),t.dom.Paper.add(t.dom.elGraphical),t.dom.elGraphical.add(t.dom.elDefs)}},{key:"plotChartType",value:function(t,e){var i=this.w,a=i.config,s=i.globals,r={series:[],i:[]},o={series:[],i:[]},n={series:[],i:[]},l={series:[],i:[]},h={series:[],i:[]},c={series:[],i:[]},d={series:[],i:[]},g={series:[],i:[]},u={series:[],seriesRangeEnd:[],i:[]};s.series.map((function(e,f){var p=0;void 0!==t[f].type?("column"===t[f].type||"bar"===t[f].type?(s.series.length>1&&a.plotOptions.bar.horizontal&&console.warn("Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"),h.series.push(e),h.i.push(f),p++,i.globals.columnSeries=h.series):"area"===t[f].type?(o.series.push(e),o.i.push(f),p++):"line"===t[f].type?(r.series.push(e),r.i.push(f),p++):"scatter"===t[f].type?(n.series.push(e),n.i.push(f)):"bubble"===t[f].type?(l.series.push(e),l.i.push(f),p++):"candlestick"===t[f].type?(c.series.push(e),c.i.push(f),p++):"boxPlot"===t[f].type?(d.series.push(e),d.i.push(f),p++):"rangeBar"===t[f].type?(g.series.push(e),g.i.push(f),p++):"rangeArea"===t[f].type?(u.series.push(s.seriesRangeStart[f]),u.seriesRangeEnd.push(s.seriesRangeEnd[f]),u.i.push(f),p++):console.warn("You have specified an unrecognized chart type. Available types for this property are line/area/column/bar/scatter/bubble"),p>1&&(s.comboCharts=!0)):(r.series.push(e),r.i.push(f))}));var f=new zt(this.ctx,e),p=new kt(this.ctx,e);this.ctx.pie=new Lt(this.ctx);var x=new Tt(this.ctx);this.ctx.rangeBar=new Mt(this.ctx,e);var b=new Pt(this.ctx),v=[];if(s.comboCharts){if(o.series.length>0&&v.push(f.draw(o.series,"area",o.i)),h.series.length>0)if(i.config.chart.stacked){var m=new wt(this.ctx,e);v.push(m.draw(h.series,h.i))}else this.ctx.bar=new yt(this.ctx,e),v.push(this.ctx.bar.draw(h.series,h.i));if(u.series.length>0&&v.push(f.draw(u.series,"rangeArea",u.i,u.seriesRangeEnd)),r.series.length>0&&v.push(f.draw(r.series,"line",r.i)),c.series.length>0&&v.push(p.draw(c.series,c.i)),d.series.length>0&&v.push(p.draw(d.series,d.i)),g.series.length>0&&v.push(this.ctx.rangeBar.draw(g.series,g.i)),n.series.length>0){var y=new zt(this.ctx,e,!0);v.push(y.draw(n.series,"scatter",n.i))}if(l.series.length>0){var w=new zt(this.ctx,e,!0);v.push(w.draw(l.series,"bubble",l.i))}}else switch(a.chart.type){case"line":v=f.draw(s.series,"line");break;case"area":v=f.draw(s.series,"area");break;case"bar":if(a.chart.stacked)v=new wt(this.ctx,e).draw(s.series);else this.ctx.bar=new yt(this.ctx,e),v=this.ctx.bar.draw(s.series);break;case"candlestick":v=new kt(this.ctx,e).draw(s.series);break;case"boxPlot":v=new kt(this.ctx,e).draw(s.series);break;case"rangeBar":v=this.ctx.rangeBar.draw(s.series);break;case"rangeArea":v=f.draw(s.seriesRangeStart,"rangeArea",void 0,s.seriesRangeEnd);break;case"heatmap":v=new St(this.ctx,e).draw(s.series);break;case"treemap":v=new Yt(this.ctx,e).draw(s.series);break;case"pie":case"donut":case"polarArea":v=this.ctx.pie.draw(s.series);break;case"radialBar":v=x.draw(s.series);break;case"radar":v=b.draw(s.series);break;default:v=f.draw(s.series)}return v}},{key:"setSVGDimensions",value:function(){var t=this.w.globals,e=this.w.config;t.svgWidth=e.chart.width,t.svgHeight=e.chart.height;var i=x.getDimensions(this.el),a=e.chart.width.toString().split(/[0-9]+/g).pop();"%"===a?x.isNumber(i[0])&&(0===i[0].width&&(i=x.getDimensions(this.el.parentNode)),t.svgWidth=i[0]*parseInt(e.chart.width,10)/100):"px"!==a&&""!==a||(t.svgWidth=parseInt(e.chart.width,10));var s=e.chart.height.toString().split(/[0-9]+/g).pop();if("auto"!==t.svgHeight&&""!==t.svgHeight)if("%"===s){var r=x.getDimensions(this.el.parentNode);t.svgHeight=r[1]*parseInt(e.chart.height,10)/100}else t.svgHeight=parseInt(e.chart.height,10);else t.axisCharts?t.svgHeight=t.svgWidth/1.61:t.svgHeight=t.svgWidth/1.2;if(t.svgWidth<0&&(t.svgWidth=0),t.svgHeight<0&&(t.svgHeight=0),m.setAttrs(t.dom.Paper.node,{width:t.svgWidth,height:t.svgHeight}),"%"!==s){var o=e.chart.sparkline.enabled?0:t.axisCharts?e.chart.parentHeightOffset:0;t.dom.Paper.node.parentNode.parentNode.style.minHeight=t.svgHeight+o+"px"}t.dom.elWrap.style.width=t.svgWidth+"px",t.dom.elWrap.style.height=t.svgHeight+"px"}},{key:"shiftGraphPosition",value:function(){var t=this.w.globals,e=t.translateY,i={transform:"translate("+t.translateX+", "+e+")"};m.setAttrs(t.dom.elGraphical.node,i)}},{key:"resizeNonAxisCharts",value:function(){var t=this.w,e=t.globals,i=0,a=t.config.chart.sparkline.enabled?1:15;a+=t.config.grid.padding.bottom,"top"!==t.config.legend.position&&"bottom"!==t.config.legend.position||!t.config.legend.show||t.config.legend.floating||(i=new lt(this.ctx).legendHelpers.getLegendBBox().clwh+10);var s=t.globals.dom.baseEl.querySelector(".apexcharts-radialbar, .apexcharts-pie"),r=2.05*t.globals.radialSize;if(s&&!t.config.chart.sparkline.enabled&&0!==t.config.plotOptions.radialBar.startAngle){var o=x.getBoundingClientRect(s);r=o.bottom;var n=o.bottom-o.top;r=Math.max(2.05*t.globals.radialSize,n)}var l=r+e.translateY+i+a;e.dom.elLegendForeign&&e.dom.elLegendForeign.setAttribute("height",l),t.config.chart.height&&String(t.config.chart.height).indexOf("%")>0||(e.dom.elWrap.style.height=l+"px",m.setAttrs(e.dom.Paper.node,{height:l}),e.dom.Paper.node.parentNode.parentNode.style.minHeight=l+"px")}},{key:"coreCalculations",value:function(){new U(this.ctx).init()}},{key:"resetGlobals",value:function(){var t=this,e=function(){return t.w.config.series.map((function(t){return[]}))},i=new Y,a=this.w.globals;i.initGlobalVars(a),a.seriesXvalues=e(),a.seriesYvalues=e()}},{key:"isMultipleY",value:function(){if(this.w.config.yaxis.constructor===Array&&this.w.config.yaxis.length>1)return this.w.globals.isMultipleYAxis=!0,!0}},{key:"xySettings",value:function(){var t=null,e=this.w;if(e.globals.axisCharts){if("back"===e.config.xaxis.crosshairs.position)new Q(this.ctx).drawXCrosshairs();if("back"===e.config.yaxis[0].crosshairs.position)new Q(this.ctx).drawYCrosshairs();if("datetime"===e.config.xaxis.type&&void 0===e.config.xaxis.labels.formatter){this.ctx.timeScale=new Ft(this.ctx);var i=[];isFinite(e.globals.minX)&&isFinite(e.globals.maxX)&&!e.globals.isBarHorizontal?i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minX,e.globals.maxX):e.globals.isBarHorizontal&&(i=this.ctx.timeScale.calculateTimeScaleTicks(e.globals.minY,e.globals.maxY)),this.ctx.timeScale.recalcDimensionsBasedOnFormat(i)}t=new y(this.ctx).getCalculatedRatios()}return t}},{key:"updateSourceChart",value:function(t){this.ctx.w.globals.selection=void 0,this.ctx.updateHelpers._updateOptions({chart:{selection:{xaxis:{min:t.w.globals.minX,max:t.w.globals.maxX}}}},!1,!1)}},{key:"setupBrushHandler",value:function(){var t=this,i=this.w;if(i.config.chart.brush.enabled&&"function"!=typeof i.config.chart.events.selection){var a=i.config.chart.brush.targets||[i.config.chart.brush.target];a.forEach((function(e){var i=ApexCharts.getChartByID(e);i.w.globals.brushSource=t.ctx,"function"!=typeof i.w.config.chart.events.zoomed&&(i.w.config.chart.events.zoomed=function(){t.updateSourceChart(i)}),"function"!=typeof i.w.config.chart.events.scrolled&&(i.w.config.chart.events.scrolled=function(){t.updateSourceChart(i)})})),i.config.chart.events.selection=function(t,s){a.forEach((function(t){var a=ApexCharts.getChartByID(t),r=x.clone(i.config.yaxis);if(i.config.chart.brush.autoScaleYaxis&&1===a.w.globals.series.length){var o=new _(a);r=o.autoScaleY(a,r,s)}var n=a.w.config.yaxis.reduce((function(t,i,s){return[].concat(u(t),[e(e({},a.w.config.yaxis[s]),{},{min:r[0].min,max:r[0].max})])}),[]);a.ctx.updateHelpers._updateOptions({xaxis:{min:s.xaxis.min,max:s.xaxis.max},yaxis:n},!1,!1,!1,!1)}))}}}}]),t}(),Dt=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"_updateOptions",value:function(t){var e=this,a=arguments.length>1&&void 0!==arguments[1]&&arguments[1],s=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return new Promise((function(n){var l=[e.ctx];r&&(l=e.ctx.getSyncedCharts()),e.ctx.w.globals.isExecCalled&&(l=[e.ctx],e.ctx.w.globals.isExecCalled=!1),l.forEach((function(r,h){var c=r.w;if(c.globals.shouldAnimate=s,a||(c.globals.resized=!0,c.globals.dataChanged=!0,s&&r.series.getPreviousPaths()),t&&"object"===i(t)&&(r.config=new E(t),t=y.extendArrayProps(r.config,t,c),r.w.globals.chartID!==e.ctx.w.globals.chartID&&delete t.series,c.config=x.extend(c.config,t),o&&(c.globals.lastXAxis=t.xaxis?x.clone(t.xaxis):[],c.globals.lastYAxis=t.yaxis?x.clone(t.yaxis):[],c.globals.initialConfig=x.extend({},c.config),c.globals.initialSeries=x.clone(c.config.series),t.series))){for(var d=0;d2&&void 0!==arguments[2]&&arguments[2];return new Promise((function(s){var r,o=i.w;return o.globals.shouldAnimate=e,o.globals.dataChanged=!0,e&&i.ctx.series.getPreviousPaths(),o.globals.axisCharts?(0===(r=t.map((function(t,e){return i._extendSeries(t,e)}))).length&&(r=[{data:[]}]),o.config.series=r):o.config.series=t.slice(),a&&(o.globals.initialConfig.series=x.clone(o.config.series),o.globals.initialSeries=x.clone(o.config.series)),i.ctx.update().then((function(){s(i.ctx)}))}))}},{key:"_extendSeries",value:function(t,i){var a=this.w,s=a.config.series[i];return e(e({},a.config.series[i]),{},{name:t.name?t.name:s&&s.name,color:t.color?t.color:s&&s.color,type:t.type?t.type:s&&s.type,data:t.data?t.data:s&&s.data})}},{key:"toggleDataPointSelection",value:function(t,e){var i=this.w,a=null,s=".apexcharts-series[data\\:realIndex='".concat(t,"']");return i.globals.axisCharts?a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(e,"'], ").concat(s," circle[j='").concat(e,"'], ").concat(s," rect[j='").concat(e,"']")).members[0]:void 0===e&&(a=i.globals.dom.Paper.select("".concat(s," path[j='").concat(t,"']")).members[0],"pie"!==i.config.chart.type&&"polarArea"!==i.config.chart.type&&"donut"!==i.config.chart.type||this.ctx.pie.pieClicked(t)),a?(new m(this.ctx).pathMouseDown(a,null),a.node?a.node:null):(console.warn("toggleDataPointSelection: Element not found"),null)}},{key:"forceXAxisUpdate",value:function(t){var e=this.w;if(["min","max"].forEach((function(i){void 0!==t.xaxis[i]&&(e.config.xaxis[i]=t.xaxis[i],e.globals.lastXAxis[i]=t.xaxis[i])})),t.xaxis.categories&&t.xaxis.categories.length&&(e.config.xaxis.categories=t.xaxis.categories),e.config.xaxis.convertedCatToNumeric){var i=new X(t);t=i.convertCatToNumericXaxis(t,this.ctx)}return t}},{key:"forceYAxisUpdate",value:function(t){return t.chart&&t.chart.stacked&&"100%"===t.chart.stackType&&(Array.isArray(t.yaxis)?t.yaxis.forEach((function(e,i){t.yaxis[i].min=0,t.yaxis[i].max=100})):(t.yaxis.min=0,t.yaxis.max=100)),t}},{key:"revertDefaultAxisMinMax",value:function(t){var e=this,i=this.w,a=i.globals.lastXAxis,s=i.globals.lastYAxis;t&&t.xaxis&&(a=t.xaxis),t&&t.yaxis&&(s=t.yaxis),i.config.xaxis.min=a.min,i.config.xaxis.max=a.max;var r=function(t){void 0!==s[t]&&(i.config.yaxis[t].min=s[t].min,i.config.yaxis[t].max=s[t].max)};i.config.yaxis.map((function(t,a){i.globals.zoomed||void 0!==s[a]?r(a):void 0!==e.ctx.opts.yaxis[a]&&(t.min=e.ctx.opts.yaxis[a].min,t.max=e.ctx.opts.yaxis[a].max)}))}}]),t}();Xt="undefined"!=typeof window?window:void 0,Et=function(t,e){var a=(void 0!==this?this:t).SVG=function(t){if(a.supported)return t=new a.Doc(t),a.parser.draw||a.prepare(),t};if(a.ns="http://www.w3.org/2000/svg",a.xmlns="http://www.w3.org/2000/xmlns/",a.xlink="http://www.w3.org/1999/xlink",a.svgjs="http://svgjs.dev",a.supported=!0,!a.supported)return!1;a.did=1e3,a.eid=function(t){return"Svgjs"+d(t)+a.did++},a.create=function(t){var i=e.createElementNS(this.ns,t);return i.setAttribute("id",this.eid(t)),i},a.extend=function(){var t,e;e=(t=[].slice.call(arguments)).pop();for(var i=t.length-1;i>=0;i--)if(t[i])for(var s in e)t[i].prototype[s]=e[s];a.Set&&a.Set.inherit&&a.Set.inherit()},a.invent=function(t){var e="function"==typeof t.create?t.create:function(){this.constructor.call(this,a.create(t.create))};return t.inherit&&(e.prototype=new t.inherit),t.extend&&a.extend(e,t.extend),t.construct&&a.extend(t.parent||a.Container,t.construct),e},a.adopt=function(e){return e?e.instance?e.instance:((i="svg"==e.nodeName?e.parentNode instanceof t.SVGElement?new a.Nested:new a.Doc:"linearGradient"==e.nodeName?new a.Gradient("linear"):"radialGradient"==e.nodeName?new a.Gradient("radial"):a[d(e.nodeName)]?new(a[d(e.nodeName)]):new a.Element(e)).type=e.nodeName,i.node=e,e.instance=i,i instanceof a.Doc&&i.namespace().defs(),i.setData(JSON.parse(e.getAttribute("svgjs:data"))||{}),i):null;var i},a.prepare=function(){var t=e.getElementsByTagName("body")[0],i=(t?new a.Doc(t):a.adopt(e.documentElement).nested()).size(2,0);a.parser={body:t||e.documentElement,draw:i.style("opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden").node,poly:i.polyline().node,path:i.path().node,native:a.create("svg")}},a.parser={native:a.create("svg")},e.addEventListener("DOMContentLoaded",(function(){a.parser.draw||a.prepare()}),!1),a.regex={numberAndUnit:/^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i,hex:/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,rgb:/rgb\((\d+),(\d+),(\d+)\)/,reference:/#([a-z0-9\-_]+)/i,transforms:/\)\s*,?\s*/,whitespace:/\s/g,isHex:/^#[a-f0-9]{3,6}$/i,isRgb:/^rgb\(/,isCss:/[^:]+:[^;]+;?/,isBlank:/^(\s+)?$/,isNumber:/^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,isPercent:/^-?[\d\.]+%$/,isImage:/\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i,delimiter:/[\s,]+/,hyphen:/([^e])\-/gi,pathLetters:/[MLHVCSQTAZ]/gi,isPathLetter:/[MLHVCSQTAZ]/i,numbersWithDots:/((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi,dots:/\./g},a.utils={map:function(t,e){for(var i=t.length,a=[],s=0;s1?1:t,new a.Color({r:~~(this.r+(this.destination.r-this.r)*t),g:~~(this.g+(this.destination.g-this.g)*t),b:~~(this.b+(this.destination.b-this.b)*t)})):this}}),a.Color.test=function(t){return t+="",a.regex.isHex.test(t)||a.regex.isRgb.test(t)},a.Color.isRgb=function(t){return t&&"number"==typeof t.r&&"number"==typeof t.g&&"number"==typeof t.b},a.Color.isColor=function(t){return a.Color.isRgb(t)||a.Color.test(t)},a.Array=function(t,e){0==(t=(t||[]).valueOf()).length&&e&&(t=e.valueOf()),this.value=this.parse(t)},a.extend(a.Array,{toString:function(){return this.value.join(" ")},valueOf:function(){return this.value},parse:function(t){return t=t.valueOf(),Array.isArray(t)?t:this.split(t)}}),a.PointArray=function(t,e){a.Array.call(this,t,e||[[0,0]])},a.PointArray.prototype=new a.Array,a.PointArray.prototype.constructor=a.PointArray;for(var s={M:function(t,e,i){return e.x=i.x=t[0],e.y=i.y=t[1],["M",e.x,e.y]},L:function(t,e){return e.x=t[0],e.y=t[1],["L",t[0],t[1]]},H:function(t,e){return e.x=t[0],["H",t[0]]},V:function(t,e){return e.y=t[0],["V",t[0]]},C:function(t,e){return e.x=t[4],e.y=t[5],["C",t[0],t[1],t[2],t[3],t[4],t[5]]},Q:function(t,e){return e.x=t[2],e.y=t[3],["Q",t[0],t[1],t[2],t[3]]},Z:function(t,e,i){return e.x=i.x,e.y=i.y,["Z"]}},r="mlhvqtcsaz".split(""),o=0,n=r.length;ol);return r},bbox:function(){return a.parser.draw||a.prepare(),a.parser.path.setAttribute("d",this.toString()),a.parser.path.getBBox()}}),a.Number=a.invent({create:function(t,e){this.value=0,this.unit=e||"","number"==typeof t?this.value=isNaN(t)?0:isFinite(t)?t:t<0?-34e37:34e37:"string"==typeof t?(e=t.match(a.regex.numberAndUnit))&&(this.value=parseFloat(e[1]),"%"==e[5]?this.value/=100:"s"==e[5]&&(this.value*=1e3),this.unit=e[5]):t instanceof a.Number&&(this.value=t.valueOf(),this.unit=t.unit)},extend:{toString:function(){return("%"==this.unit?~~(1e8*this.value)/1e6:"s"==this.unit?this.value/1e3:this.value)+this.unit},toJSON:function(){return this.toString()},valueOf:function(){return this.value},plus:function(t){return t=new a.Number(t),new a.Number(this+t,this.unit||t.unit)},minus:function(t){return t=new a.Number(t),new a.Number(this-t,this.unit||t.unit)},times:function(t){return t=new a.Number(t),new a.Number(this*t,this.unit||t.unit)},divide:function(t){return t=new a.Number(t),new a.Number(this/t,this.unit||t.unit)},to:function(t){var e=new a.Number(this);return"string"==typeof t&&(e.unit=t),e},morph:function(t){return this.destination=new a.Number(t),t.relative&&(this.destination.value+=this.value),this},at:function(t){return this.destination?new a.Number(this.destination).minus(this).times(t).plus(this):this}}}),a.Element=a.invent({create:function(t){this._stroke=a.defaults.attrs.stroke,this._event=null,this.dom={},(this.node=t)&&(this.type=t.nodeName,this.node.instance=this,this._stroke=t.getAttribute("stroke")||this._stroke)},extend:{x:function(t){return this.attr("x",t)},y:function(t){return this.attr("y",t)},cx:function(t){return null==t?this.x()+this.width()/2:this.x(t-this.width()/2)},cy:function(t){return null==t?this.y()+this.height()/2:this.y(t-this.height()/2)},move:function(t,e){return this.x(t).y(e)},center:function(t,e){return this.cx(t).cy(e)},width:function(t){return this.attr("width",t)},height:function(t){return this.attr("height",t)},size:function(t,e){var i=u(this,t,e);return this.width(new a.Number(i.width)).height(new a.Number(i.height))},clone:function(t){this.writeDataToDom();var e=x(this.node.cloneNode(!0));return t?t.add(e):this.after(e),e},remove:function(){return this.parent()&&this.parent().removeElement(this),this},replace:function(t){return this.after(t).remove(),t},addTo:function(t){return t.put(this)},putIn:function(t){return t.add(this)},id:function(t){return this.attr("id",t)},show:function(){return this.style("display","")},hide:function(){return this.style("display","none")},visible:function(){return"none"!=this.style("display")},toString:function(){return this.attr("id")},classes:function(){var t=this.attr("class");return null==t?[]:t.trim().split(a.regex.delimiter)},hasClass:function(t){return-1!=this.classes().indexOf(t)},addClass:function(t){if(!this.hasClass(t)){var e=this.classes();e.push(t),this.attr("class",e.join(" "))}return this},removeClass:function(t){return this.hasClass(t)&&this.attr("class",this.classes().filter((function(e){return e!=t})).join(" ")),this},toggleClass:function(t){return this.hasClass(t)?this.removeClass(t):this.addClass(t)},reference:function(t){return a.get(this.attr(t))},parent:function(e){var i=this;if(!i.node.parentNode)return null;if(i=a.adopt(i.node.parentNode),!e)return i;for(;i&&i.node instanceof t.SVGElement;){if("string"==typeof e?i.matches(e):i instanceof e)return i;if(!i.node.parentNode||"#document"==i.node.parentNode.nodeName)return null;i=a.adopt(i.node.parentNode)}},doc:function(){return this instanceof a.Doc?this:this.parent(a.Doc)},parents:function(t){var e=[],i=this;do{if(!(i=i.parent(t))||!i.node)break;e.push(i)}while(i.parent);return e},matches:function(t){return function(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)}(this.node,t)},native:function(){return this.node},svg:function(t){var i=e.createElement("svg");if(!(t&&this instanceof a.Parent))return i.appendChild(t=e.createElement("svg")),this.writeDataToDom(),t.appendChild(this.node.cloneNode(!0)),i.innerHTML.replace(/^/,"").replace(/<\/svg>$/,"");i.innerHTML=""+t.replace(/\n/,"").replace(/<([\w:-]+)([^<]+?)\/>/g,"<$1$2>")+"";for(var s=0,r=i.firstChild.childNodes.length;s":function(t){return-Math.cos(t*Math.PI)/2+.5},">":function(t){return Math.sin(t*Math.PI/2)},"<":function(t){return 1-Math.cos(t*Math.PI/2)}},a.morph=function(t){return function(e,i){return new a.MorphObj(e,i).at(t)}},a.Situation=a.invent({create:function(t){this.init=!1,this.reversed=!1,this.reversing=!1,this.duration=new a.Number(t.duration).valueOf(),this.delay=new a.Number(t.delay).valueOf(),this.start=+new Date+this.delay,this.finish=this.start+this.duration,this.ease=t.ease,this.loop=0,this.loops=!1,this.animations={},this.attrs={},this.styles={},this.transforms=[],this.once={}}}),a.FX=a.invent({create:function(t){this._target=t,this.situations=[],this.active=!1,this.situation=null,this.paused=!1,this.lastPos=0,this.pos=0,this.absPos=0,this._speed=1},extend:{animate:function(t,e,s){"object"===i(t)&&(e=t.ease,s=t.delay,t=t.duration);var r=new a.Situation({duration:t||1e3,delay:s||0,ease:a.easing[e||"-"]||e});return this.queue(r),this},target:function(t){return t&&t instanceof a.Element?(this._target=t,this):this._target},timeToAbsPos:function(t){return(t-this.situation.start)/(this.situation.duration/this._speed)},absPosToTime:function(t){return this.situation.duration/this._speed*t+this.situation.start},startAnimFrame:function(){this.stopAnimFrame(),this.animationFrame=t.requestAnimationFrame(function(){this.step()}.bind(this))},stopAnimFrame:function(){t.cancelAnimationFrame(this.animationFrame)},start:function(){return!this.active&&this.situation&&(this.active=!0,this.startCurrent()),this},startCurrent:function(){return this.situation.start=+new Date+this.situation.delay/this._speed,this.situation.finish=this.situation.start+this.situation.duration/this._speed,this.initAnimations().step()},queue:function(t){return("function"==typeof t||t instanceof a.Situation)&&this.situations.push(t),this.situation||(this.situation=this.situations.shift()),this},dequeue:function(){return this.stop(),this.situation=this.situations.shift(),this.situation&&(this.situation instanceof a.Situation?this.start():this.situation.call(this)),this},initAnimations:function(){var t,e=this.situation;if(e.init)return this;for(var i in e.animations){t=this.target()[i](),Array.isArray(t)||(t=[t]),Array.isArray(e.animations[i])||(e.animations[i]=[e.animations[i]]);for(var s=t.length;s--;)e.animations[i][s]instanceof a.Number&&(t[s]=new a.Number(t[s])),e.animations[i][s]=t[s].morph(e.animations[i][s])}for(var i in e.attrs)e.attrs[i]=new a.MorphObj(this.target().attr(i),e.attrs[i]);for(var i in e.styles)e.styles[i]=new a.MorphObj(this.target().style(i),e.styles[i]);return e.initialTransformation=this.target().matrixify(),e.init=!0,this},clearQueue:function(){return this.situations=[],this},clearCurrent:function(){return this.situation=null,this},stop:function(t,e){var i=this.active;return this.active=!1,e&&this.clearQueue(),t&&this.situation&&(!i&&this.startCurrent(),this.atEnd()),this.stopAnimFrame(),this.clearCurrent()},after:function(t){var e=this.last();return this.target().on("finished.fx",(function i(a){a.detail.situation==e&&(t.call(this,e),this.off("finished.fx",i))})),this._callStart()},during:function(t){var e=this.last(),i=function(i){i.detail.situation==e&&t.call(this,i.detail.pos,a.morph(i.detail.pos),i.detail.eased,e)};return this.target().off("during.fx",i).on("during.fx",i),this.after((function(){this.off("during.fx",i)})),this._callStart()},afterAll:function(t){var e=function e(i){t.call(this),this.off("allfinished.fx",e)};return this.target().off("allfinished.fx",e).on("allfinished.fx",e),this._callStart()},last:function(){return this.situations.length?this.situations[this.situations.length-1]:this.situation},add:function(t,e,i){return this.last()[i||"animations"][t]=e,this._callStart()},step:function(t){var e,i,a;t||(this.absPos=this.timeToAbsPos(+new Date)),!1!==this.situation.loops?(e=Math.max(this.absPos,0),i=Math.floor(e),!0===this.situation.loops||ithis.lastPos&&r<=s&&(this.situation.once[r].call(this.target(),this.pos,s),delete this.situation.once[r]);return this.active&&this.target().fire("during",{pos:this.pos,eased:s,fx:this,situation:this.situation}),this.situation?(this.eachAt(),1==this.pos&&!this.situation.reversed||this.situation.reversed&&0==this.pos?(this.stopAnimFrame(),this.target().fire("finished",{fx:this,situation:this.situation}),this.situations.length||(this.target().fire("allfinished"),this.situations.length||(this.target().off(".fx"),this.active=!1)),this.active?this.dequeue():this.clearCurrent()):!this.paused&&this.active&&this.startAnimFrame(),this.lastPos=s,this):this},eachAt:function(){var t,e=this,i=this.target(),s=this.situation;for(var r in s.animations)t=[].concat(s.animations[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i[r].apply(i,t);for(var r in s.attrs)t=[r].concat(s.attrs[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i.attr.apply(i,t);for(var r in s.styles)t=[r].concat(s.styles[r]).map((function(t){return"string"!=typeof t&&t.at?t.at(s.ease(e.pos),e.pos):t})),i.style.apply(i,t);if(s.transforms.length){t=s.initialTransformation,r=0;for(var o=s.transforms.length;r=0;--s)this[m[s]]=null!=t[m[s]]?t[m[s]]:e[m[s]]},extend:{extract:function(){var t=f(this,0,1);f(this,1,0);var e=180/Math.PI*Math.atan2(t.y,t.x)-90;return{x:this.e,y:this.f,transformedX:(this.e*Math.cos(e*Math.PI/180)+this.f*Math.sin(e*Math.PI/180))/Math.sqrt(this.a*this.a+this.b*this.b),transformedY:(this.f*Math.cos(e*Math.PI/180)+this.e*Math.sin(-e*Math.PI/180))/Math.sqrt(this.c*this.c+this.d*this.d),rotation:e,a:this.a,b:this.b,c:this.c,d:this.d,e:this.e,f:this.f,matrix:new a.Matrix(this)}},clone:function(){return new a.Matrix(this)},morph:function(t){return this.destination=new a.Matrix(t),this},multiply:function(t){return new a.Matrix(this.native().multiply(function(t){return t instanceof a.Matrix||(t=new a.Matrix(t)),t}(t).native()))},inverse:function(){return new a.Matrix(this.native().inverse())},translate:function(t,e){return new a.Matrix(this.native().translate(t||0,e||0))},native:function(){for(var t=a.parser.native.createSVGMatrix(),e=m.length-1;e>=0;e--)t[m[e]]=this[m[e]];return t},toString:function(){return"matrix("+v(this.a)+","+v(this.b)+","+v(this.c)+","+v(this.d)+","+v(this.e)+","+v(this.f)+")"}},parent:a.Element,construct:{ctm:function(){return new a.Matrix(this.node.getCTM())},screenCTM:function(){if(this instanceof a.Nested){var t=this.rect(1,1),e=t.node.getScreenCTM();return t.remove(),new a.Matrix(e)}return new a.Matrix(this.node.getScreenCTM())}}}),a.Point=a.invent({create:function(t,e){var a;a=Array.isArray(t)?{x:t[0],y:t[1]}:"object"===i(t)?{x:t.x,y:t.y}:null!=t?{x:t,y:null!=e?e:t}:{x:0,y:0},this.x=a.x,this.y=a.y},extend:{clone:function(){return new a.Point(this)},morph:function(t,e){return this.destination=new a.Point(t,e),this}}}),a.extend(a.Element,{point:function(t,e){return new a.Point(t,e).transform(this.screenCTM().inverse())}}),a.extend(a.Element,{attr:function(t,e,s){if(null==t){for(t={},s=(e=this.node.attributes).length-1;s>=0;s--)t[e[s].nodeName]=a.regex.isNumber.test(e[s].nodeValue)?parseFloat(e[s].nodeValue):e[s].nodeValue;return t}if("object"===i(t))for(var r in t)this.attr(r,t[r]);else if(null===e)this.node.removeAttribute(t);else{if(null==e)return null==(e=this.node.getAttribute(t))?a.defaults.attrs[t]:a.regex.isNumber.test(e)?parseFloat(e):e;"stroke-width"==t?this.attr("stroke",parseFloat(e)>0?this._stroke:null):"stroke"==t&&(this._stroke=e),"fill"!=t&&"stroke"!=t||(a.regex.isImage.test(e)&&(e=this.doc().defs().image(e,0,0)),e instanceof a.Image&&(e=this.doc().defs().pattern(0,0,(function(){this.add(e)})))),"number"==typeof e?e=new a.Number(e):a.Color.isColor(e)?e=new a.Color(e):Array.isArray(e)&&(e=new a.Array(e)),"leading"==t?this.leading&&this.leading(e):"string"==typeof s?this.node.setAttributeNS(s,t,e.toString()):this.node.setAttribute(t,e.toString()),!this.rebuild||"font-size"!=t&&"x"!=t||this.rebuild(t,e)}return this}}),a.extend(a.Element,{transform:function(t,e){var s;return"object"!==i(t)?(s=new a.Matrix(this).extract(),"string"==typeof t?s[t]:s):(s=new a.Matrix(this),e=!!e||!!t.relative,null!=t.a&&(s=e?s.multiply(new a.Matrix(t)):new a.Matrix(t)),this.attr("transform",s))}}),a.extend(a.Element,{untransform:function(){return this.attr("transform",null)},matrixify:function(){return(this.attr("transform")||"").split(a.regex.transforms).slice(0,-1).map((function(t){var e=t.trim().split("(");return[e[0],e[1].split(a.regex.delimiter).map((function(t){return parseFloat(t)}))]})).reduce((function(t,e){return"matrix"==e[0]?t.multiply(p(e[1])):t[e[0]].apply(t,e[1])}),new a.Matrix)},toParent:function(t){if(this==t)return this;var e=this.screenCTM(),i=t.screenCTM().inverse();return this.addTo(t).untransform().transform(i.multiply(e)),this},toDoc:function(){return this.toParent(this.doc())}}),a.Transformation=a.invent({create:function(t,e){if(arguments.length>1&&"boolean"!=typeof e)return this.constructor.call(this,[].slice.call(arguments));if(Array.isArray(t))for(var a=0,s=this.arguments.length;a=0},index:function(t){return[].slice.call(this.node.childNodes).indexOf(t.node)},get:function(t){return a.adopt(this.node.childNodes[t])},first:function(){return this.get(0)},last:function(){return this.get(this.node.childNodes.length-1)},each:function(t,e){for(var i=this.children(),s=0,r=i.length;s=0;i--)e.childNodes[i]instanceof t.SVGElement&&x(e.childNodes[i]);return a.adopt(e).id(a.eid(e.nodeName))}function b(t){return null==t.x&&(t.x=0,t.y=0,t.width=0,t.height=0),t.w=t.width,t.h=t.height,t.x2=t.x+t.width,t.y2=t.y+t.height,t.cx=t.x+t.width/2,t.cy=t.y+t.height/2,t}function v(t){return Math.abs(t)>1e-37?t:0}["fill","stroke"].forEach((function(t){var e={};e[t]=function(e){if(void 0===e)return this;if("string"==typeof e||a.Color.isRgb(e)||e&&"function"==typeof e.fill)this.attr(t,e);else for(var i=l[t].length-1;i>=0;i--)null!=e[l[t][i]]&&this.attr(l.prefix(t,l[t][i]),e[l[t][i]]);return this},a.extend(a.Element,a.FX,e)})),a.extend(a.Element,a.FX,{translate:function(t,e){return this.transform({x:t,y:e})},matrix:function(t){return this.attr("transform",new a.Matrix(6==arguments.length?[].slice.call(arguments):t))},opacity:function(t){return this.attr("opacity",t)},dx:function(t){return this.x(new a.Number(t).plus(this instanceof a.FX?0:this.x()),!0)},dy:function(t){return this.y(new a.Number(t).plus(this instanceof a.FX?0:this.y()),!0)}}),a.extend(a.Path,{length:function(){return this.node.getTotalLength()},pointAt:function(t){return this.node.getPointAtLength(t)}}),a.Set=a.invent({create:function(t){Array.isArray(t)?this.members=t:this.clear()},extend:{add:function(){for(var t=[].slice.call(arguments),e=0,i=t.length;e-1&&this.members.splice(e,1),this},each:function(t){for(var e=0,i=this.members.length;e=0},index:function(t){return this.members.indexOf(t)},get:function(t){return this.members[t]},first:function(){return this.get(0)},last:function(){return this.get(this.members.length-1)},valueOf:function(){return this.members}},construct:{set:function(t){return new a.Set(t)}}}),a.FX.Set=a.invent({create:function(t){this.set=t}}),a.Set.inherit=function(){var t=[];for(var e in a.Shape.prototype)"function"==typeof a.Shape.prototype[e]&&"function"!=typeof a.Set.prototype[e]&&t.push(e);for(var e in t.forEach((function(t){a.Set.prototype[t]=function(){for(var e=0,i=this.members.length;e=0;t--)delete this.memory()[arguments[t]];return this},memory:function(){return this._memory||(this._memory={})}}),a.get=function(t){var i=e.getElementById(function(t){var e=(t||"").toString().match(a.regex.reference);if(e)return e[1]}(t)||t);return a.adopt(i)},a.select=function(t,i){return new a.Set(a.utils.map((i||e).querySelectorAll(t),(function(t){return a.adopt(t)})))},a.extend(a.Parent,{select:function(t){return a.select(t,this.node)}});var m="abcdef".split("");if("function"!=typeof t.CustomEvent){var y=function(t,i){i=i||{bubbles:!1,cancelable:!1,detail:void 0};var a=e.createEvent("CustomEvent");return a.initCustomEvent(t,i.bubbles,i.cancelable,i.detail),a};y.prototype=t.Event.prototype,a.CustomEvent=y}else a.CustomEvent=t.CustomEvent;return a},"function"==typeof define&&define.amd?define((function(){return Et(Xt,Xt.document)})):"object"===("undefined"==typeof exports?"undefined":i(exports))&&"undefined"!=typeof module?module.exports=Xt.document?Et(Xt,Xt.document):function(t){return Et(t,t.document)}:Xt.SVG=Et(Xt,Xt.document), /*! svg.filter.js - v2.0.2 - 2016-02-24 * https://github.com/wout/svg.filter.js * Copyright (c) 2016 Wout Fierens; Licensed MIT */ function(){SVG.Filter=SVG.invent({create:"filter",inherit:SVG.Parent,extend:{source:"SourceGraphic",sourceAlpha:"SourceAlpha",background:"BackgroundImage",backgroundAlpha:"BackgroundAlpha",fill:"FillPaint",stroke:"StrokePaint",autoSetIn:!0,put:function(t,e){return this.add(t,e),!t.attr("in")&&this.autoSetIn&&t.attr("in",this.source),t.attr("result")||t.attr("result",t),t},blend:function(t,e,i){return this.put(new SVG.BlendEffect(t,e,i))},colorMatrix:function(t,e){return this.put(new SVG.ColorMatrixEffect(t,e))},convolveMatrix:function(t){return this.put(new SVG.ConvolveMatrixEffect(t))},componentTransfer:function(t){return this.put(new SVG.ComponentTransferEffect(t))},composite:function(t,e,i){return this.put(new SVG.CompositeEffect(t,e,i))},flood:function(t,e){return this.put(new SVG.FloodEffect(t,e))},offset:function(t,e){return this.put(new SVG.OffsetEffect(t,e))},image:function(t){return this.put(new SVG.ImageEffect(t))},merge:function(){var t=[void 0];for(var e in arguments)t.push(arguments[e]);return this.put(new(SVG.MergeEffect.bind.apply(SVG.MergeEffect,t)))},gaussianBlur:function(t,e){return this.put(new SVG.GaussianBlurEffect(t,e))},morphology:function(t,e){return this.put(new SVG.MorphologyEffect(t,e))},diffuseLighting:function(t,e,i){return this.put(new SVG.DiffuseLightingEffect(t,e,i))},displacementMap:function(t,e,i,a,s){return this.put(new SVG.DisplacementMapEffect(t,e,i,a,s))},specularLighting:function(t,e,i,a){return this.put(new SVG.SpecularLightingEffect(t,e,i,a))},tile:function(){return this.put(new SVG.TileEffect)},turbulence:function(t,e,i,a,s){return this.put(new SVG.TurbulenceEffect(t,e,i,a,s))},toString:function(){return"url(#"+this.attr("id")+")"}}}),SVG.extend(SVG.Defs,{filter:function(t){var e=this.put(new SVG.Filter);return"function"==typeof t&&t.call(e,e),e}}),SVG.extend(SVG.Container,{filter:function(t){return this.defs().filter(t)}}),SVG.extend(SVG.Element,SVG.G,SVG.Nested,{filter:function(t){return this.filterer=t instanceof SVG.Element?t:this.doc().filter(t),this.doc()&&this.filterer.doc()!==this.doc()&&this.doc().defs().add(this.filterer),this.attr("filter",this.filterer),this.filterer},unfilter:function(t){return this.filterer&&!0===t&&this.filterer.remove(),delete this.filterer,this.attr("filter",null)}}),SVG.Effect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Element,extend:{in:function(t){return null==t?this.parent()&&this.parent().select('[result="'+this.attr("in")+'"]').get(0)||this.attr("in"):this.attr("in",t)},result:function(t){return null==t?this.attr("result"):this.attr("result",t)},toString:function(){return this.result()}}}),SVG.ParentEffect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Parent,extend:{in:function(t){return null==t?this.parent()&&this.parent().select('[result="'+this.attr("in")+'"]').get(0)||this.attr("in"):this.attr("in",t)},result:function(t){return null==t?this.attr("result"):this.attr("result",t)},toString:function(){return this.result()}}});var t={blend:function(t,e){return this.parent()&&this.parent().blend(this,t,e)},colorMatrix:function(t,e){return this.parent()&&this.parent().colorMatrix(t,e).in(this)},convolveMatrix:function(t){return this.parent()&&this.parent().convolveMatrix(t).in(this)},componentTransfer:function(t){return this.parent()&&this.parent().componentTransfer(t).in(this)},composite:function(t,e){return this.parent()&&this.parent().composite(this,t,e)},flood:function(t,e){return this.parent()&&this.parent().flood(t,e)},offset:function(t,e){return this.parent()&&this.parent().offset(t,e).in(this)},image:function(t){return this.parent()&&this.parent().image(t)},merge:function(){return this.parent()&&this.parent().merge.apply(this.parent(),[this].concat(arguments))},gaussianBlur:function(t,e){return this.parent()&&this.parent().gaussianBlur(t,e).in(this)},morphology:function(t,e){return this.parent()&&this.parent().morphology(t,e).in(this)},diffuseLighting:function(t,e,i){return this.parent()&&this.parent().diffuseLighting(t,e,i).in(this)},displacementMap:function(t,e,i,a){return this.parent()&&this.parent().displacementMap(this,t,e,i,a)},specularLighting:function(t,e,i,a){return this.parent()&&this.parent().specularLighting(t,e,i,a).in(this)},tile:function(){return this.parent()&&this.parent().tile().in(this)},turbulence:function(t,e,i,a,s){return this.parent()&&this.parent().turbulence(t,e,i,a,s).in(this)}};SVG.extend(SVG.Effect,t),SVG.extend(SVG.ParentEffect,t),SVG.ChildEffect=SVG.invent({create:function(){this.constructor.call(this)},inherit:SVG.Element,extend:{in:function(t){this.attr("in",t)}}});var e={blend:function(t,e,i){this.attr({in:t,in2:e,mode:i||"normal"})},colorMatrix:function(t,e){"matrix"==t&&(e=s(e)),this.attr({type:t,values:void 0===e?null:e})},convolveMatrix:function(t){t=s(t),this.attr({order:Math.sqrt(t.split(" ").length),kernelMatrix:t})},composite:function(t,e,i){this.attr({in:t,in2:e,operator:i})},flood:function(t,e){this.attr("flood-color",t),null!=e&&this.attr("flood-opacity",e)},offset:function(t,e){this.attr({dx:t,dy:e})},image:function(t){this.attr("href",t,SVG.xlink)},displacementMap:function(t,e,i,a,s){this.attr({in:t,in2:e,scale:i,xChannelSelector:a,yChannelSelector:s})},gaussianBlur:function(t,e){null!=t||null!=e?this.attr("stdDeviation",r(Array.prototype.slice.call(arguments))):this.attr("stdDeviation","0 0")},morphology:function(t,e){this.attr({operator:t,radius:e})},tile:function(){},turbulence:function(t,e,i,a,s){this.attr({numOctaves:e,seed:i,stitchTiles:a,baseFrequency:t,type:s})}},i={merge:function(){var t;if(arguments[0]instanceof SVG.Set){var e=this;arguments[0].each((function(t){this instanceof SVG.MergeNode?e.put(this):(this instanceof SVG.Effect||this instanceof SVG.ParentEffect)&&e.put(new SVG.MergeNode(this))}))}else{t=Array.isArray(arguments[0])?arguments[0]:arguments;for(var i=0;i1&&(T*=a=Math.sqrt(a),M*=a);s=(new SVG.Matrix).rotate(I).scale(1/T,1/M).rotate(-I),F=F.transform(s),R=R.transform(s),r=[R.x-F.x,R.y-F.y],n=r[0]*r[0]+r[1]*r[1],o=Math.sqrt(n),r[0]/=o,r[1]/=o,l=n<4?Math.sqrt(1-n/4):0,z===X&&(l*=-1);h=new SVG.Point((R.x+F.x)/2+l*-r[1],(R.y+F.y)/2+l*r[0]),c=new SVG.Point(F.x-h.x,F.y-h.y),d=new SVG.Point(R.x-h.x,R.y-h.y),g=Math.acos(c.x/Math.sqrt(c.x*c.x+c.y*c.y)),c.y<0&&(g*=-1);u=Math.acos(d.x/Math.sqrt(d.x*d.x+d.y*d.y)),d.y<0&&(u*=-1);X&&g>u&&(u+=2*Math.PI);!X&&gr.maxX-e.width&&(o=(a=r.maxX-e.width)-this.startPoints.box.x),null!=r.minY&&sr.maxY-e.height&&(n=(s=r.maxY-e.height)-this.startPoints.box.y),null!=r.snapToGrid&&(a-=a%r.snapToGrid,s-=s%r.snapToGrid,o-=o%r.snapToGrid,n-=n%r.snapToGrid),this.el instanceof SVG.G?this.el.matrix(this.startPoints.transform).transform({x:o,y:n},!0):this.el.move(a,s));return i},t.prototype.end=function(t){var e=this.drag(t);this.el.fire("dragend",{event:t,p:e,m:this.m,handler:this}),SVG.off(window,"mousemove.drag"),SVG.off(window,"touchmove.drag"),SVG.off(window,"mouseup.drag"),SVG.off(window,"touchend.drag")},SVG.extend(SVG.Element,{draggable:function(e,i){"function"!=typeof e&&"object"!=typeof e||(i=e,e=!0);var a=this.remember("_draggable")||new t(this);return(e=void 0===e||e)?a.init(i||{},e):(this.off("mousedown.drag"),this.off("touchstart.drag")),this}})}.call(void 0),function(){function t(t){this.el=t,t.remember("_selectHandler",this),this.pointSelection={isSelected:!1},this.rectSelection={isSelected:!1},this.pointsList={lt:[0,0],rt:["width",0],rb:["width","height"],lb:[0,"height"],t:["width",0],r:["width","height"],b:["width","height"],l:[0,"height"]},this.pointCoord=function(t,e,i){var a="string"!=typeof t?t:e[t];return i?a/2:a},this.pointCoords=function(t,e){var i=this.pointsList[t];return{x:this.pointCoord(i[0],e,"t"===t||"b"===t),y:this.pointCoord(i[1],e,"r"===t||"l"===t)}}}t.prototype.init=function(t,e){var i=this.el.bbox();this.options={};var a=this.el.selectize.defaults.points;for(var s in this.el.selectize.defaults)this.options[s]=this.el.selectize.defaults[s],void 0!==e[s]&&(this.options[s]=e[s]);var r=["points","pointsExclude"];for(var s in r){var o=this.options[r[s]];"string"==typeof o?o=o.length>0?o.split(/\s*,\s*/i):[]:"boolean"==typeof o&&"points"===r[s]&&(o=o?a:[]),this.options[r[s]]=o}this.options.points=[a,this.options.points].reduce((function(t,e){return t.filter((function(t){return e.indexOf(t)>-1}))})),this.options.points=[this.options.points,this.options.pointsExclude].reduce((function(t,e){return t.filter((function(t){return e.indexOf(t)<0}))})),this.parent=this.el.parent(),this.nested=this.nested||this.parent.group(),this.nested.matrix(new SVG.Matrix(this.el).translate(i.x,i.y)),this.options.deepSelect&&-1!==["line","polyline","polygon"].indexOf(this.el.type)?this.selectPoints(t):this.selectRect(t),this.observe(),this.cleanup()},t.prototype.selectPoints=function(t){return this.pointSelection.isSelected=t,this.pointSelection.set||(this.pointSelection.set=this.parent.set(),this.drawPoints()),this},t.prototype.getPointArray=function(){var t=this.el.bbox();return this.el.array().valueOf().map((function(e){return[e[0]-t.x,e[1]-t.y]}))},t.prototype.drawPoints=function(){for(var t=this,e=this.getPointArray(),i=0,a=e.length;i0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y+i[1]).size(this.parameters.box.width-i[0],this.parameters.box.height-i[1])}};break;case"rt":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).size(this.parameters.box.width+i[0],this.parameters.box.height-i[1])}};break;case"rb":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x-i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize+i[0]);i=this.checkAspectRatio(i),this.el.move(this.parameters.box.x,this.parameters.box.y).size(this.parameters.box.width+i[0],this.parameters.box.height+i[1])}};break;case"lb":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0&&this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return this.el.move(this.parameters.box.x+i[0],this.parameters.box.y),void this.el.attr("font-size",this.parameters.fontSize-i[0]);i=this.checkAspectRatio(i,!0),this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).size(this.parameters.box.width-i[0],this.parameters.box.height+i[1])}};break;case"t":this.calc=function(t,e){var i=this.snapToGrid(t,e,2);if(this.parameters.box.height-i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y+i[1]).height(this.parameters.box.height-i[1])}};break;case"r":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.width+i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).width(this.parameters.box.width+i[0])}};break;case"b":this.calc=function(t,e){var i=this.snapToGrid(t,e,0);if(this.parameters.box.height+i[1]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x,this.parameters.box.y).height(this.parameters.box.height+i[1])}};break;case"l":this.calc=function(t,e){var i=this.snapToGrid(t,e,1);if(this.parameters.box.width-i[0]>0){if("text"===this.parameters.type)return;this.el.move(this.parameters.box.x+i[0],this.parameters.box.y).width(this.parameters.box.width-i[0])}};break;case"rot":this.calc=function(t,e){var i=t+this.parameters.p.x,a=e+this.parameters.p.y,s=Math.atan2(this.parameters.p.y-this.parameters.box.y-this.parameters.box.height/2,this.parameters.p.x-this.parameters.box.x-this.parameters.box.width/2),r=Math.atan2(a-this.parameters.box.y-this.parameters.box.height/2,i-this.parameters.box.x-this.parameters.box.width/2),o=this.parameters.rotation+180*(r-s)/Math.PI+this.options.snapToAngle/2;this.el.center(this.parameters.box.cx,this.parameters.box.cy).rotate(o-o%this.options.snapToAngle,this.parameters.box.cx,this.parameters.box.cy)};break;case"point":this.calc=function(t,e){var i=this.snapToGrid(t,e,this.parameters.pointCoords[0],this.parameters.pointCoords[1]),a=this.el.array().valueOf();a[this.parameters.i][0]=this.parameters.pointCoords[0]+i[0],a[this.parameters.i][1]=this.parameters.pointCoords[1]+i[1],this.el.plot(a)}}this.el.fire("resizestart",{dx:this.parameters.x,dy:this.parameters.y,event:t}),SVG.on(window,"touchmove.resize",(function(t){e.update(t||window.event)})),SVG.on(window,"touchend.resize",(function(){e.done()})),SVG.on(window,"mousemove.resize",(function(t){e.update(t||window.event)})),SVG.on(window,"mouseup.resize",(function(){e.done()}))},t.prototype.update=function(t){if(t){var e=this._extractPosition(t),i=this.transformPoint(e.x,e.y),a=i.x-this.parameters.p.x,s=i.y-this.parameters.p.y;this.lastUpdateCall=[a,s],this.calc(a,s),this.el.fire("resizing",{dx:a,dy:s,event:t})}else this.lastUpdateCall&&this.calc(this.lastUpdateCall[0],this.lastUpdateCall[1])},t.prototype.done=function(){this.lastUpdateCall=null,SVG.off(window,"mousemove.resize"),SVG.off(window,"mouseup.resize"),SVG.off(window,"touchmove.resize"),SVG.off(window,"touchend.resize"),this.el.fire("resizedone")},t.prototype.snapToGrid=function(t,e,i,a){var s;return void 0!==a?s=[(i+t)%this.options.snapToGrid,(a+e)%this.options.snapToGrid]:(i=null==i?3:i,s=[(this.parameters.box.x+t+(1&i?0:this.parameters.box.width))%this.options.snapToGrid,(this.parameters.box.y+e+(2&i?0:this.parameters.box.height))%this.options.snapToGrid]),t<0&&(s[0]-=this.options.snapToGrid),e<0&&(s[1]-=this.options.snapToGrid),t-=Math.abs(s[0])o.maxX&&(t=o.maxX-s),void 0!==o.minY&&r+eo.maxY&&(e=o.maxY-r),[t,e]},t.prototype.checkAspectRatio=function(t,e){if(!this.options.saveAspectRatio)return t;var i=t.slice(),a=this.parameters.box.width/this.parameters.box.height,s=this.parameters.box.width+t[0],r=this.parameters.box.height-t[1],o=s/r;return oa&&(i[0]=this.parameters.box.width-r*a,e&&(i[0]=-i[0])),i},SVG.extend(SVG.Element,{resize:function(e){return(this.remember("_resizeHandler")||new t(this)).init(e||{}),this}}),SVG.Element.prototype.resize.defaults={snapToAngle:.1,snapToGrid:1,constraint:{},saveAspectRatio:!1}}).call(this)}(),void 0===window.Apex&&(window.Apex={});var Ht=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"initModules",value:function(){this.ctx.publicMethods=["updateOptions","updateSeries","appendData","appendSeries","toggleSeries","showSeries","hideSeries","setLocale","resetSeries","zoomX","toggleDataPointSelection","dataURI","exportToCSV","addXaxisAnnotation","addYaxisAnnotation","addPointAnnotation","clearAnnotations","removeAnnotation","paper","destroy"],this.ctx.eventList=["click","mousedown","mousemove","mouseleave","touchstart","touchmove","touchleave","mouseup","touchend"],this.ctx.animations=new b(this.ctx),this.ctx.axes=new J(this.ctx),this.ctx.core=new Rt(this.ctx.el,this.ctx),this.ctx.config=new E({}),this.ctx.data=new W(this.ctx),this.ctx.grid=new j(this.ctx),this.ctx.graphics=new m(this.ctx),this.ctx.coreUtils=new y(this.ctx),this.ctx.crosshairs=new Q(this.ctx),this.ctx.events=new Z(this.ctx),this.ctx.exports=new G(this.ctx),this.ctx.localization=new $(this.ctx),this.ctx.options=new L,this.ctx.responsive=new K(this.ctx),this.ctx.series=new N(this.ctx),this.ctx.theme=new tt(this.ctx),this.ctx.formatters=new M(this.ctx),this.ctx.titleSubtitle=new et(this.ctx),this.ctx.legend=new lt(this.ctx),this.ctx.toolbar=new ht(this.ctx),this.ctx.tooltip=new bt(this.ctx),this.ctx.dimensions=new ot(this.ctx),this.ctx.updateHelpers=new Dt(this.ctx),this.ctx.zoomPanSelection=new ct(this.ctx),this.ctx.w.globals.tooltip=new bt(this.ctx)}}]),t}(),Ot=function(){function t(e){a(this,t),this.ctx=e,this.w=e.w}return r(t,[{key:"clear",value:function(t){var e=t.isUpdating;this.ctx.zoomPanSelection&&this.ctx.zoomPanSelection.destroy(),this.ctx.toolbar&&this.ctx.toolbar.destroy(),this.ctx.animations=null,this.ctx.axes=null,this.ctx.annotations=null,this.ctx.core=null,this.ctx.data=null,this.ctx.grid=null,this.ctx.series=null,this.ctx.responsive=null,this.ctx.theme=null,this.ctx.formatters=null,this.ctx.titleSubtitle=null,this.ctx.legend=null,this.ctx.dimensions=null,this.ctx.options=null,this.ctx.crosshairs=null,this.ctx.zoomPanSelection=null,this.ctx.updateHelpers=null,this.ctx.toolbar=null,this.ctx.localization=null,this.ctx.w.globals.tooltip=null,this.clearDomElements({isUpdating:e})}},{key:"killSVG",value:function(t){t.each((function(t,e){this.removeClass("*"),this.off(),this.stop()}),!0),t.ungroup(),t.clear()}},{key:"clearDomElements",value:function(t){var e=this,i=t.isUpdating,a=this.w.globals.dom.Paper.node;a.parentNode&&a.parentNode.parentNode&&!i&&(a.parentNode.parentNode.style.minHeight="unset");var s=this.w.globals.dom.baseEl;s&&this.ctx.eventList.forEach((function(t){s.removeEventListener(t,e.ctx.events.documentEvent)}));var r=this.w.globals.dom;if(null!==this.ctx.el)for(;this.ctx.el.firstChild;)this.ctx.el.removeChild(this.ctx.el.firstChild);this.killSVG(r.Paper),r.Paper.remove(),r.elWrap=null,r.elGraphical=null,r.elAnnotations=null,r.elLegendWrap=null,r.baseEl=null,r.elGridRect=null,r.elGridRectMask=null,r.elGridRectMarkerMask=null,r.elForecastMask=null,r.elNonForecastMask=null,r.elDefs=null}}]),t}(),Nt=new WeakMap;var Wt=function(){function t(e,i){a(this,t),this.opts=i,this.ctx=this,this.w=new F(i).init(),this.el=e,this.w.globals.cuid=x.randomId(),this.w.globals.chartID=this.w.config.chart.id?x.escapeString(this.w.config.chart.id):this.w.globals.cuid,new Ht(this).initModules(),this.create=x.bind(this.create,this),this.windowResizeHandler=this._windowResizeHandler.bind(this),this.parentResizeHandler=this._parentResizeCallback.bind(this)}return r(t,[{key:"render",value:function(){var t=this;return new Promise((function(e,i){if(null!==t.el){void 0===Apex._chartInstances&&(Apex._chartInstances=[]),t.w.config.chart.id&&Apex._chartInstances.push({id:t.w.globals.chartID,group:t.w.config.chart.group,chart:t}),t.setLocale(t.w.config.chart.defaultLocale);var a=t.w.config.chart.events.beforeMount;if("function"==typeof a&&a(t,t.w),t.events.fireEvent("beforeMount",[t,t.w]),window.addEventListener("resize",t.windowResizeHandler),function(t,e){var i=!1;if(t.nodeType!==Node.DOCUMENT_FRAGMENT_NODE){var a=t.getBoundingClientRect();"none"!==t.style.display&&0!==a.width||(i=!0)}var s=new ResizeObserver((function(a){i&&e.call(t,a),i=!0}));t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?Array.from(t.children).forEach((function(t){return s.observe(t)})):s.observe(t),Nt.set(e,s)}(t.el.parentNode,t.parentResizeHandler),!t.css){var s=t.el.getRootNode&&t.el.getRootNode(),r=x.is("ShadowRoot",s),o=t.el.ownerDocument,n=o.getElementById("apexcharts-css");!r&&n||(t.css=document.createElement("style"),t.css.id="apexcharts-css",t.css.textContent='@keyframes opaque {\n 0% {\n opacity: 0\n }\n\n to {\n opacity: 1\n }\n}\n\n@keyframes resizeanim {\n 0%,to {\n opacity: 0\n }\n}\n\n.apexcharts-canvas {\n position: relative;\n user-select: none\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n -webkit-appearance: none;\n width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n border-radius: 4px;\n background-color: rgba(0,0,0,.5);\n box-shadow: 0 0 1px rgba(255,255,255,.5);\n -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)\n}\n\n.apexcharts-inner {\n position: relative\n}\n\n.apexcharts-text tspan {\n font-family: inherit\n}\n\n.legend-mouseover-inactive {\n transition: .15s ease all;\n opacity: .2\n}\n\n.apexcharts-legend-text {\n padding-left: 15px;\n margin-left: -15px;\n}\n\n.apexcharts-series-collapsed {\n opacity: 0\n}\n\n.apexcharts-tooltip {\n border-radius: 5px;\n box-shadow: 2px 2px 6px -4px #999;\n cursor: default;\n font-size: 14px;\n left: 62px;\n opacity: 0;\n pointer-events: none;\n position: absolute;\n top: 20px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n white-space: nowrap;\n z-index: 12;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n border: 1px solid #e3e3e3;\n background: rgba(255,255,255,.96)\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n color: #fff;\n background: rgba(30,30,30,.8)\n}\n\n.apexcharts-tooltip * {\n font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n padding: 6px;\n font-size: 15px;\n margin-bottom: 4px\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {\n background: #eceff1;\n border-bottom: 1px solid #ddd\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n background: rgba(0,0,0,.7);\n border-bottom: 1px solid #333\n}\n\n.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {\n display: inline-block;\n margin-left: 5px;\n font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {\n display: none\n}\n\n.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {\n margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n width: 12px;\n height: 12px;\n position: relative;\n top: 0;\n margin-right: 10px;\n border-radius: 50%\n}\n\n.apexcharts-tooltip-series-group {\n padding: 0 10px;\n display: none;\n text-align: left;\n justify-content: left;\n align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {\n padding-bottom: 4px\n}\n\n.apexcharts-tooltip-series-group-hidden {\n opacity: 0;\n height: 0;\n line-height: 0;\n padding: 0!important\n}\n\n.apexcharts-tooltip-y-group {\n padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,.apexcharts-tooltip-box {\n padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n display: flex;\n flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: " ";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_boundingRect,.svg_select_points_rot {\n pointer-events: none;\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {\n cursor: ew-resize;\n opacity: 1;\n visibility: visible\n}\n\n.svg_select_points {\n fill: #efefef;\n stroke: #333;\n rx: 2\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0,0,0,.7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {\n opacity: 0\n}\n\n.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-legend {\t\n display: flex;\t\n overflow: auto;\t\n padding: 0 10px;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\t\n flex-wrap: wrap\t\n}\t\n.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n flex-direction: column;\t\n bottom: 0;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n justify-content: flex-start;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\t\n justify-content: center; \t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\t\n justify-content: flex-end;\t\n}\t\n.apexcharts-legend-series {\t\n cursor: pointer;\t\n line-height: normal;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{\t\n display: flex;\t\n align-items: center;\t\n}\t\n.apexcharts-legend-text {\t\n position: relative;\t\n font-size: 14px;\t\n}\t\n.apexcharts-legend-text *, .apexcharts-legend-marker * {\t\n pointer-events: none;\t\n}\t\n.apexcharts-legend-marker {\t\n position: relative;\t\n display: inline-block;\t\n cursor: pointer;\t\n margin-right: 3px;\t\n border-style: solid;\n}\t\n \n.apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{\t\n display: inline-block;\t\n}\t\n.apexcharts-legend-series.apexcharts-no-click {\t\n cursor: auto;\t\n}\t\n.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\t\n display: none !important;\t\n}\t\n.apexcharts-inactive-legend {\t\n opacity: 0.45;\t\n}\n\n.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {\n pointer-events: none\n}\n\n.apexcharts-marker {\n transition: .15s ease all\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,.resize-triggers,.resize-triggers>div {\n content: " ";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n',r?s.prepend(t.css):o.head.appendChild(t.css))}var l=t.create(t.w.config.series,{});if(!l)return e(t);t.mount(l).then((function(){"function"==typeof t.w.config.chart.events.mounted&&t.w.config.chart.events.mounted(t,t.w),t.events.fireEvent("mounted",[t,t.w]),e(l)})).catch((function(t){i(t)}))}else i(new Error("Element not found"))}))}},{key:"create",value:function(t,e){var i=this.w;new Ht(this).initModules();var a=this.w.globals;(a.noData=!1,a.animationEnded=!1,this.responsive.checkResponsiveConfig(e),i.config.xaxis.convertedCatToNumeric)&&new X(i.config).convertCatToNumericXaxis(i.config,this.ctx);if(null===this.el)return a.animationEnded=!0,null;if(this.core.setupElements(),"treemap"===i.config.chart.type&&(i.config.grid.show=!1,i.config.yaxis[0].show=!1),0===a.svgWidth)return a.animationEnded=!0,null;var s=y.checkComboSeries(t);a.comboCharts=s.comboCharts,a.comboBarCount=s.comboBarCount;var r=t.every((function(t){return t.data&&0===t.data.length}));(0===t.length||r)&&this.series.handleNoData(),this.events.setupEventHandlers(),this.data.parseData(t),this.theme.init(),new D(this).setGlobalMarkerSize(),this.formatters.setLabelFormatters(),this.titleSubtitle.draw(),a.noData&&a.collapsedSeries.length!==a.series.length&&!i.config.legend.showForSingleSeries||this.legend.init(),this.series.hasAllSeriesEqualX(),a.axisCharts&&(this.core.coreCalculations(),"category"!==i.config.xaxis.type&&this.formatters.setLabelFormatters(),this.ctx.toolbar.minX=i.globals.minX,this.ctx.toolbar.maxX=i.globals.maxX),this.formatters.heatmapLabelFormatters(),new y(this).getLargestMarkerSize(),this.dimensions.plotCoords();var o=this.core.xySettings();this.grid.createGridMask();var n=this.core.plotChartType(t,o),l=new O(this);l.bringForward(),i.config.dataLabels.background.enabled&&l.dataLabelsBackground(),this.core.shiftGraphPosition();var h={plot:{left:i.globals.translateX,top:i.globals.translateY,width:i.globals.gridWidth,height:i.globals.gridHeight}};return{elGraph:n,xyRatios:o,elInner:i.globals.dom.elGraphical,dimensions:h}}},{key:"mount",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,i=this,a=i.w;return new Promise((function(s,r){if(null===i.el)return r(new Error("Not enough data to display or target element not found"));(null===e||a.globals.allSeriesCollapsed)&&i.series.handleNoData(),i.grid=new j(i);var o=i.grid.drawGrid();if(i.annotations=new P(i),i.annotations.drawImageAnnos(),i.annotations.drawTextAnnos(),"back"===a.config.grid.position&&o&&(a.globals.dom.elGraphical.add(o.el),o&&o.elGridBorders&&o.elGridBorders.node&&a.globals.dom.elGraphical.add(o.elGridBorders)),Array.isArray(e.elGraph))for(var n=0;n0&&a.globals.memory.methodsToExec.forEach((function(t){t.method(t.params,!1,t.context)})),a.globals.axisCharts||a.globals.noData||i.core.resizeNonAxisCharts(),s(i)}))}},{key:"destroy",value:function(){var t,e;window.removeEventListener("resize",this.windowResizeHandler),this.el.parentNode,t=this.parentResizeHandler,(e=Nt.get(t))&&(e.disconnect(),Nt.delete(t));var i=this.w.config.chart.id;i&&Apex._chartInstances.forEach((function(t,e){t.id===x.escapeString(i)&&Apex._chartInstances.splice(e,1)})),new Ot(this.ctx).clear({isUpdating:!1})}},{key:"updateOptions",value:function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],s=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],o=this.w;return o.globals.selection=void 0,t.series&&(this.series.resetSeries(!1,!0,!1),t.series.length&&t.series[0].data&&(t.series=t.series.map((function(t,i){return e.updateHelpers._extendSeries(t,i)}))),this.updateHelpers.revertDefaultAxisMinMax()),t.xaxis&&(t=this.updateHelpers.forceXAxisUpdate(t)),t.yaxis&&(t=this.updateHelpers.forceYAxisUpdate(t)),o.globals.collapsedSeriesIndices.length>0&&this.series.clearPreviousPaths(),t.theme&&(t=this.theme.updateThemeOptions(t)),this.updateHelpers._updateOptions(t,i,a,s,r)}},{key:"updateSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];return this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(t,e,i)}},{key:"appendSeries",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=this.w.config.series.slice();return a.push(t),this.series.resetSeries(!1),this.updateHelpers.revertDefaultAxisMinMax(),this.updateHelpers._updateSeries(a,e,i)}},{key:"appendData",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=this;i.w.globals.dataChanged=!0,i.series.getPreviousPaths();for(var a=i.w.config.series.slice(),s=0;s0&&void 0!==arguments[0])||arguments[0],e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];this.series.resetSeries(t,e)}},{key:"addEventListener",value:function(t,e){this.events.addEventListener(t,e)}},{key:"removeEventListener",value:function(t,e){this.events.removeEventListener(t,e)}},{key:"addXaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addXaxisAnnotationExternal(t,e,a)}},{key:"addYaxisAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addYaxisAnnotationExternal(t,e,a)}},{key:"addPointAnnotation",value:function(t){var e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:void 0,a=this;i&&(a=i),a.annotations.addPointAnnotationExternal(t,e,a)}},{key:"clearAnnotations",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:void 0,e=this;t&&(e=t),e.annotations.clearAnnotations(e)}},{key:"removeAnnotation",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0,i=this;e&&(i=e),i.annotations.removeAnnotation(i,t)}},{key:"getChartArea",value:function(){return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner")}},{key:"getSeriesTotalXRange",value:function(t,e){return this.coreUtils.getSeriesTotalsXRange(t,e)}},{key:"getHighestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new U(this.ctx);return e.getMinYMaxY(t).highestY}},{key:"getLowestValueInSeries",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=new U(this.ctx);return e.getMinYMaxY(t).lowestY}},{key:"getSeriesTotal",value:function(){return this.w.globals.seriesTotals}},{key:"toggleDataPointSelection",value:function(t,e){return this.updateHelpers.toggleDataPointSelection(t,e)}},{key:"zoomX",value:function(t,e){this.ctx.toolbar.zoomUpdateOptions(t,e)}},{key:"setLocale",value:function(t){this.localization.setCurrentLocaleValues(t)}},{key:"dataURI",value:function(t){return new G(this.ctx).dataURI(t)}},{key:"exportToCSV",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=new G(this.ctx);return e.exportToCSV(t)}},{key:"paper",value:function(){return this.w.globals.dom.Paper}},{key:"_parentResizeCallback",value:function(){this.w.globals.animationEnded&&this.w.config.chart.redrawOnParentResize&&this._windowResize()}},{key:"_windowResize",value:function(){var t=this;clearTimeout(this.w.globals.resizeTimer),this.w.globals.resizeTimer=window.setTimeout((function(){t.w.globals.resized=!0,t.w.globals.dataChanged=!1,t.ctx.update()}),150)}},{key:"_windowResizeHandler",value:function(){var t=this.w.config.chart.redrawOnWindowResize;"function"==typeof t&&(t=t()),t&&this._windowResize()}}],[{key:"getChartByID",value:function(t){var e=x.escapeString(t),i=Apex._chartInstances.filter((function(t){return t.id===e}))[0];return i&&i.chart}},{key:"initOnLoad",value:function(){for(var e=document.querySelectorAll("[data-apexcharts]"),i=0;i2?s-2:0),o=2;o arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } /* ** Generic functions which are not dependent on ApexCharts */ var Utils$1 = /*#__PURE__*/function () { function Utils() { _classCallCheck(this, Utils); } _createClass(Utils, [{ key: "shadeRGBColor", value: function shadeRGBColor(percent, color) { var f = color.split(','), t = percent < 0 ? 0 : 255, p = percent < 0 ? percent * -1 : percent, R = parseInt(f[0].slice(4), 10), G = parseInt(f[1], 10), B = parseInt(f[2], 10); return 'rgb(' + (Math.round((t - R) * p) + R) + ',' + (Math.round((t - G) * p) + G) + ',' + (Math.round((t - B) * p) + B) + ')'; } }, { key: "shadeHexColor", value: function shadeHexColor(percent, color) { var f = parseInt(color.slice(1), 16), t = percent < 0 ? 0 : 255, p = percent < 0 ? percent * -1 : percent, R = f >> 16, G = f >> 8 & 0x00ff, B = f & 0x0000ff; return '#' + (0x1000000 + (Math.round((t - R) * p) + R) * 0x10000 + (Math.round((t - G) * p) + G) * 0x100 + (Math.round((t - B) * p) + B)).toString(16).slice(1); } // beautiful color shading blending code // http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors }, { key: "shadeColor", value: function shadeColor(p, color) { if (Utils.isColorHex(color)) { return this.shadeHexColor(p, color); } else { return this.shadeRGBColor(p, color); } } }], [{ key: "bind", value: function bind(fn, me) { return function () { return fn.apply(me, arguments); }; } }, { key: "isObject", value: function isObject(item) { return item && _typeof(item) === 'object' && !Array.isArray(item) && item != null; } // Type checking that works across different window objects }, { key: "is", value: function is(type, val) { return Object.prototype.toString.call(val) === '[object ' + type + ']'; } }, { key: "listToArray", value: function listToArray(list) { var i, array = []; for (i = 0; i < list.length; i++) { array[i] = list[i]; } return array; } // to extend defaults with user options // credit: http://stackoverflow.com/questions/27936772/deep-object-merging-in-es6-es7#answer-34749873 }, { key: "extend", value: function extend(target, source) { var _this = this; if (typeof Object.assign !== 'function') { (function () { Object.assign = function (target) { if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } var output = Object(target); for (var index = 1; index < arguments.length; index++) { var _source = arguments[index]; if (_source !== undefined && _source !== null) { for (var nextKey in _source) { if (_source.hasOwnProperty(nextKey)) { output[nextKey] = _source[nextKey]; } } } } return output; }; })(); } var output = Object.assign({}, target); if (this.isObject(target) && this.isObject(source)) { Object.keys(source).forEach(function (key) { if (_this.isObject(source[key])) { if (!(key in target)) { Object.assign(output, _defineProperty({}, key, source[key])); } else { output[key] = _this.extend(target[key], source[key]); } } else { Object.assign(output, _defineProperty({}, key, source[key])); } }); } return output; } }, { key: "extendArray", value: function extendArray(arrToExtend, resultArr) { var extendedArr = []; arrToExtend.map(function (item) { extendedArr.push(Utils.extend(resultArr, item)); }); arrToExtend = extendedArr; return arrToExtend; } // If month counter exceeds 12, it starts again from 1 }, { key: "monthMod", value: function monthMod(month) { return month % 12; } }, { key: "clone", value: function clone(source) { if (Utils.is('Array', source)) { var cloneResult = []; for (var i = 0; i < source.length; i++) { cloneResult[i] = this.clone(source[i]); } return cloneResult; } else if (Utils.is('Null', source)) { // fixes an issue where null values were converted to {} return null; } else if (Utils.is('Date', source)) { return source; } else if (_typeof(source) === 'object') { var _cloneResult = {}; for (var prop in source) { if (source.hasOwnProperty(prop)) { _cloneResult[prop] = this.clone(source[prop]); } } return _cloneResult; } else { return source; } } }, { key: "log10", value: function log10(x) { return Math.log(x) / Math.LN10; } }, { key: "roundToBase10", value: function roundToBase10(x) { return Math.pow(10, Math.floor(Math.log10(x))); } }, { key: "roundToBase", value: function roundToBase(x, base) { return Math.pow(base, Math.floor(Math.log(x) / Math.log(base))); } }, { key: "parseNumber", value: function parseNumber(val) { if (val === null) return val; return parseFloat(val); } }, { key: "randomId", value: function randomId() { return (Math.random() + 1).toString(36).substring(4); } }, { key: "noExponents", value: function noExponents(val) { var data = String(val).split(/[eE]/); if (data.length === 1) return data[0]; var z = '', sign = val < 0 ? '-' : '', str = data[0].replace('.', ''), mag = Number(data[1]) + 1; if (mag < 0) { z = sign + '0.'; while (mag++) { z += '0'; } return z + str.replace(/^-/, ''); } mag -= str.length; while (mag--) { z += '0'; } return str + z; } }, { key: "getDimensions", value: function getDimensions(el) { var computedStyle = getComputedStyle(el, null); var elementHeight = el.clientHeight; var elementWidth = el.clientWidth; elementHeight -= parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom); elementWidth -= parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight); return [elementWidth, elementHeight]; } }, { key: "getBoundingClientRect", value: function getBoundingClientRect(element) { var rect = element.getBoundingClientRect(); return { top: rect.top, right: rect.right, bottom: rect.bottom, left: rect.left, width: element.clientWidth, height: element.clientHeight, x: rect.left, y: rect.top }; } }, { key: "getLargestStringFromArr", value: function getLargestStringFromArr(arr) { return arr.reduce(function (a, b) { if (Array.isArray(b)) { b = b.reduce(function (aa, bb) { return aa.length > bb.length ? aa : bb; }); } return a.length > b.length ? a : b; }, 0); } // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-12342275 }, { key: "hexToRgba", value: function hexToRgba() { var hex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '#999999'; var opacity = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.6; if (hex.substring(0, 1) !== '#') { hex = '#999999'; } var h = hex.replace('#', ''); h = h.match(new RegExp('(.{' + h.length / 3 + '})', 'g')); for (var i = 0; i < h.length; i++) { h[i] = parseInt(h[i].length === 1 ? h[i] + h[i] : h[i], 16); } if (typeof opacity !== 'undefined') h.push(opacity); return 'rgba(' + h.join(',') + ')'; } }, { key: "getOpacityFromRGBA", value: function getOpacityFromRGBA(rgba) { return parseFloat(rgba.replace(/^.*,(.+)\)/, '$1')); } }, { key: "rgb2hex", value: function rgb2hex(rgb) { rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); return rgb && rgb.length === 4 ? '#' + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[3], 10).toString(16)).slice(-2) : ''; } }, { key: "isColorHex", value: function isColorHex(color) { return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i.test(color); } }, { key: "getPolygonPos", value: function getPolygonPos(size, dataPointsLen) { var dotsArray = []; var angle = Math.PI * 2 / dataPointsLen; for (var i = 0; i < dataPointsLen; i++) { var curPos = {}; curPos.x = size * Math.sin(i * angle); curPos.y = -size * Math.cos(i * angle); dotsArray.push(curPos); } return dotsArray; } }, { key: "polarToCartesian", value: function polarToCartesian(centerX, centerY, radius, angleInDegrees) { var angleInRadians = (angleInDegrees - 90) * Math.PI / 180.0; return { x: centerX + radius * Math.cos(angleInRadians), y: centerY + radius * Math.sin(angleInRadians) }; } }, { key: "escapeString", value: function escapeString(str) { var escapeWith = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'x'; var newStr = str.toString().slice(); newStr = newStr.replace(/[` ~!@#$%^&*()|+\=?;:'",.<>{}[\]\\/]/gi, escapeWith); return newStr; } }, { key: "negToZero", value: function negToZero(val) { return val < 0 ? 0 : val; } }, { key: "moveIndexInArray", value: function moveIndexInArray(arr, old_index, new_index) { if (new_index >= arr.length) { var k = new_index - arr.length + 1; while (k--) { arr.push(undefined); } } arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); return arr; } }, { key: "extractNumber", value: function extractNumber(s) { return parseFloat(s.replace(/[^\d.]*/g, '')); } }, { key: "findAncestor", value: function findAncestor(el, cls) { while ((el = el.parentElement) && !el.classList.contains(cls)) { } return el; } }, { key: "setELstyles", value: function setELstyles(el, styles) { for (var key in styles) { if (styles.hasOwnProperty(key)) { el.style.key = styles[key]; } } } }, { key: "isNumber", value: function isNumber(value) { return !isNaN(value) && parseFloat(Number(value)) === value && !isNaN(parseInt(value, 10)); } }, { key: "isFloat", value: function isFloat(n) { return Number(n) === n && n % 1 !== 0; } }, { key: "isSafari", value: function isSafari() { return /^((?!chrome|android).)*safari/i.test(navigator.userAgent); } }, { key: "isFirefox", value: function isFirefox() { return navigator.userAgent.toLowerCase().indexOf('firefox') > -1; } }, { key: "isIE11", value: function isIE11() { if (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.appVersion.indexOf('Trident/') > -1) { return true; } } }, { key: "isIE", value: function isIE() { var ua = window.navigator.userAgent; var msie = ua.indexOf('MSIE '); if (msie > 0) { // IE 10 or older => return version number return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); } var trident = ua.indexOf('Trident/'); if (trident > 0) { // IE 11 => return version number var rv = ua.indexOf('rv:'); return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); } var edge = ua.indexOf('Edge/'); if (edge > 0) { // Edge (IE 12+) => return version number return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); } // other browser return false; } }]); return Utils; }(); /** * ApexCharts Animation Class. * * @module Animations **/ var Animations = /*#__PURE__*/function () { function Animations(ctx) { _classCallCheck(this, Animations); this.ctx = ctx; this.w = ctx.w; this.setEasingFunctions(); } _createClass(Animations, [{ key: "setEasingFunctions", value: function setEasingFunctions() { var easing; if (this.w.globals.easing) return; var userDefinedEasing = this.w.config.chart.animations.easing; switch (userDefinedEasing) { case 'linear': { easing = '-'; break; } case 'easein': { easing = '<'; break; } case 'easeout': { easing = '>'; break; } case 'easeinout': { easing = '<>'; break; } case 'swing': { easing = function easing(pos) { var s = 1.70158; var ret = (pos -= 1) * pos * ((s + 1) * pos + s) + 1; return ret; }; break; } case 'bounce': { easing = function easing(pos) { var ret = ''; if (pos < 1 / 2.75) { ret = 7.5625 * pos * pos; } else if (pos < 2 / 2.75) { ret = 7.5625 * (pos -= 1.5 / 2.75) * pos + 0.75; } else if (pos < 2.5 / 2.75) { ret = 7.5625 * (pos -= 2.25 / 2.75) * pos + 0.9375; } else { ret = 7.5625 * (pos -= 2.625 / 2.75) * pos + 0.984375; } return ret; }; break; } case 'elastic': { easing = function easing(pos) { if (pos === !!pos) return pos; return Math.pow(2, -10 * pos) * Math.sin((pos - 0.075) * (2 * Math.PI) / 0.3) + 1; }; break; } default: { easing = '<>'; } } this.w.globals.easing = easing; } }, { key: "animateLine", value: function animateLine(el, from, to, speed) { el.attr(from).animate(speed).attr(to); } /* ** Animate radius of a circle element */ }, { key: "animateMarker", value: function animateMarker(el, from, to, speed, easing, cb) { if (!from) from = 0; el.attr({ r: from, width: from, height: from }).animate(speed, easing).attr({ r: to, width: to.width, height: to.height }).afterAll(function () { cb(); }); } /* ** Animate radius and position of a circle element */ }, { key: "animateCircle", value: function animateCircle(el, from, to, speed, easing) { el.attr({ r: from.r, cx: from.cx, cy: from.cy }).animate(speed, easing).attr({ r: to.r, cx: to.cx, cy: to.cy }); } /* ** Animate rect properties */ }, { key: "animateRect", value: function animateRect(el, from, to, speed, fn) { el.attr(from).animate(speed).attr(to).afterAll(function () { return fn(); }); } }, { key: "animatePathsGradually", value: function animatePathsGradually(params) { var el = params.el, realIndex = params.realIndex, j = params.j, fill = params.fill, pathFrom = params.pathFrom, pathTo = params.pathTo, speed = params.speed, delay = params.delay; var me = this; var w = this.w; var delayFactor = 0; if (w.config.chart.animations.animateGradually.enabled) { delayFactor = w.config.chart.animations.animateGradually.delay; } if (w.config.chart.animations.dynamicAnimation.enabled && w.globals.dataChanged && w.config.chart.type !== 'bar') { // disabled due to this bug - https://github.com/apexcharts/vue-apexcharts/issues/75 delayFactor = 0; } me.morphSVG(el, realIndex, j, w.config.chart.type === 'line' && !w.globals.comboCharts ? 'stroke' : fill, pathFrom, pathTo, speed, delay * delayFactor); } }, { key: "showDelayedElements", value: function showDelayedElements() { this.w.globals.delayedElements.forEach(function (d) { var ele = d.el; ele.classList.remove('apexcharts-element-hidden'); }); } }, { key: "animationCompleted", value: function animationCompleted(el) { var w = this.w; if (w.globals.animationEnded) return; w.globals.animationEnded = true; this.showDelayedElements(); if (typeof w.config.chart.events.animationEnd === 'function') { w.config.chart.events.animationEnd(this.ctx, { el: el, w: w }); } } // SVG.js animation for morphing one path to another }, { key: "morphSVG", value: function morphSVG(el, realIndex, j, fill, pathFrom, pathTo, speed, delay) { var _this = this; var w = this.w; if (!pathFrom) { pathFrom = el.attr('pathFrom'); } if (!pathTo) { pathTo = el.attr('pathTo'); } var disableAnimationForCorrupPath = function disableAnimationForCorrupPath(path) { if (w.config.chart.type === 'radar') { // radar chart drops the path to bottom and hence a corrup path looks ugly // therefore, disable animation for such a case speed = 1; } return "M 0 ".concat(w.globals.gridHeight); }; if (!pathFrom || pathFrom.indexOf('undefined') > -1 || pathFrom.indexOf('NaN') > -1) { pathFrom = disableAnimationForCorrupPath(); } if (!pathTo || pathTo.indexOf('undefined') > -1 || pathTo.indexOf('NaN') > -1) { pathTo = disableAnimationForCorrupPath(); } if (!w.globals.shouldAnimate) { speed = 1; } el.plot(pathFrom).animate(1, w.globals.easing, delay).plot(pathFrom).animate(speed, w.globals.easing, delay).plot(pathTo).afterAll(function () { // a flag to indicate that the original mount function can return true now as animation finished here if (Utils$1.isNumber(j)) { if (j === w.globals.series[w.globals.maxValsInArrayIndex].length - 2 && w.globals.shouldAnimate) { _this.animationCompleted(el); } } else if (fill !== 'none' && w.globals.shouldAnimate) { if (!w.globals.comboCharts && realIndex === w.globals.series.length - 1 || w.globals.comboCharts) { _this.animationCompleted(el); } } _this.showDelayedElements(); }); } }]); return Animations; }(); /** * ApexCharts Filters Class for setting hover/active states on the paths. * * @module Formatters **/ var Filters = /*#__PURE__*/function () { function Filters(ctx) { _classCallCheck(this, Filters); this.ctx = ctx; this.w = ctx.w; } // create a re-usable filter which can be appended other filter effects and applied to multiple elements _createClass(Filters, [{ key: "getDefaultFilter", value: function getDefaultFilter(el, i) { var w = this.w; el.unfilter(true); var filter = new window.SVG.Filter(); filter.size('120%', '180%', '-5%', '-40%'); if (w.config.states.normal.filter !== 'none') { this.applyFilter(el, i, w.config.states.normal.filter.type, w.config.states.normal.filter.value); } else { if (w.config.chart.dropShadow.enabled) { this.dropShadow(el, w.config.chart.dropShadow, i); } } } }, { key: "addNormalFilter", value: function addNormalFilter(el, i) { var w = this.w; // revert shadow if it was there // but, ignore marker as marker don't have dropshadow yet if (w.config.chart.dropShadow.enabled && !el.node.classList.contains('apexcharts-marker')) { this.dropShadow(el, w.config.chart.dropShadow, i); } } // appends dropShadow to the filter object which can be chained with other filter effects }, { key: "addLightenFilter", value: function addLightenFilter(el, i, attrs) { var _this = this; var w = this.w; var intensity = attrs.intensity; el.unfilter(true); var filter = new window.SVG.Filter(); el.filter(function (add) { var shadowAttr = w.config.chart.dropShadow; if (shadowAttr.enabled) { filter = _this.addShadow(add, i, shadowAttr); } else { filter = add; } filter.componentTransfer({ rgb: { type: 'linear', slope: 1.5, intercept: intensity } }); }); el.filterer.node.setAttribute('filterUnits', 'userSpaceOnUse'); this._scaleFilterSize(el.filterer.node); } // appends dropShadow to the filter object which can be chained with other filter effects }, { key: "addDarkenFilter", value: function addDarkenFilter(el, i, attrs) { var _this2 = this; var w = this.w; var intensity = attrs.intensity; el.unfilter(true); var filter = new window.SVG.Filter(); el.filter(function (add) { var shadowAttr = w.config.chart.dropShadow; if (shadowAttr.enabled) { filter = _this2.addShadow(add, i, shadowAttr); } else { filter = add; } filter.componentTransfer({ rgb: { type: 'linear', slope: intensity } }); }); el.filterer.node.setAttribute('filterUnits', 'userSpaceOnUse'); this._scaleFilterSize(el.filterer.node); } }, { key: "applyFilter", value: function applyFilter(el, i, filter) { var intensity = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0.5; switch (filter) { case 'none': { this.addNormalFilter(el, i); break; } case 'lighten': { this.addLightenFilter(el, i, { intensity: intensity }); break; } case 'darken': { this.addDarkenFilter(el, i, { intensity: intensity }); break; } } } // appends dropShadow to the filter object which can be chained with other filter effects }, { key: "addShadow", value: function addShadow(add, i, attrs) { var blur = attrs.blur, top = attrs.top, left = attrs.left, color = attrs.color, opacity = attrs.opacity; var shadowBlur = add.flood(Array.isArray(color) ? color[i] : color, opacity).composite(add.sourceAlpha, 'in').offset(left, top).gaussianBlur(blur).merge(add.source); return add.blend(add.source, shadowBlur); } // directly adds dropShadow to the element and returns the same element. // the only way it is different from the addShadow() function is that addShadow is chainable to other filters, while this function discards all filters and add dropShadow }, { key: "dropShadow", value: function dropShadow(el, attrs) { var i = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var top = attrs.top, left = attrs.left, blur = attrs.blur, color = attrs.color, opacity = attrs.opacity, noUserSpaceOnUse = attrs.noUserSpaceOnUse; var w = this.w; el.unfilter(true); if (Utils$1.isIE() && w.config.chart.type === 'radialBar') { // in radialbar charts, dropshadow is clipping actual drawing in IE return el; } color = Array.isArray(color) ? color[i] : color; el.filter(function (add) { var shadowBlur = null; if (Utils$1.isSafari() || Utils$1.isFirefox() || Utils$1.isIE()) { // safari/firefox/IE have some alternative way to use this filter shadowBlur = add.flood(color, opacity).composite(add.sourceAlpha, 'in').offset(left, top).gaussianBlur(blur); } else { shadowBlur = add.flood(color, opacity).composite(add.sourceAlpha, 'in').offset(left, top).gaussianBlur(blur).merge(add.source); } add.blend(add.source, shadowBlur); }); if (!noUserSpaceOnUse) { el.filterer.node.setAttribute('filterUnits', 'userSpaceOnUse'); } this._scaleFilterSize(el.filterer.node); return el; } }, { key: "setSelectionFilter", value: function setSelectionFilter(el, realIndex, dataPointIndex) { var w = this.w; if (typeof w.globals.selectedDataPoints[realIndex] !== 'undefined') { if (w.globals.selectedDataPoints[realIndex].indexOf(dataPointIndex) > -1) { el.node.setAttribute('selected', true); var activeFilter = w.config.states.active.filter; if (activeFilter !== 'none') { this.applyFilter(el, realIndex, activeFilter.type, activeFilter.value); } } } } }, { key: "_scaleFilterSize", value: function _scaleFilterSize(el) { var setAttributes = function setAttributes(attrs) { for (var key in attrs) { if (attrs.hasOwnProperty(key)) { el.setAttribute(key, attrs[key]); } } }; setAttributes({ width: '200%', height: '200%', x: '-50%', y: '-50%' }); } }]); return Filters; }(); /** * ApexCharts Graphics Class for all drawing operations. * * @module Graphics **/ var Graphics = /*#__PURE__*/function () { function Graphics(ctx) { _classCallCheck(this, Graphics); this.ctx = ctx; this.w = ctx.w; } /***************************************************************************** * * * SVG Path Rounding Function * * Copyright (C) 2014 Yona Appletree * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * *****************************************************************************/ /** * SVG Path rounding function. Takes an input path string and outputs a path * string where all line-line corners have been rounded. Only supports absolute * commands at the moment. * * @param pathString The SVG input path * @param radius The amount to round the corners, either a value in the SVG * coordinate space, or, if useFractionalRadius is true, a value * from 0 to 1. * @returns A new SVG path string with the rounding */ _createClass(Graphics, [{ key: "roundPathCorners", value: function roundPathCorners(pathString, radius) { function moveTowardsLength(movingPoint, targetPoint, amount) { var width = targetPoint.x - movingPoint.x; var height = targetPoint.y - movingPoint.y; var distance = Math.sqrt(width * width + height * height); return moveTowardsFractional(movingPoint, targetPoint, Math.min(1, amount / distance)); } function moveTowardsFractional(movingPoint, targetPoint, fraction) { return { x: movingPoint.x + (targetPoint.x - movingPoint.x) * fraction, y: movingPoint.y + (targetPoint.y - movingPoint.y) * fraction }; } // Adjusts the ending position of a command function adjustCommand(cmd, newPoint) { if (cmd.length > 2) { cmd[cmd.length - 2] = newPoint.x; cmd[cmd.length - 1] = newPoint.y; } } // Gives an {x, y} object for a command's ending position function pointForCommand(cmd) { return { x: parseFloat(cmd[cmd.length - 2]), y: parseFloat(cmd[cmd.length - 1]) }; } // Split apart the path, handing concatonated letters and numbers var pathParts = pathString.split(/[,\s]/).reduce(function (parts, part) { var match = part.match('([a-zA-Z])(.+)'); if (match) { parts.push(match[1]); parts.push(match[2]); } else { parts.push(part); } return parts; }, []); // Group the commands with their arguments for easier handling var commands = pathParts.reduce(function (commands, part) { if (parseFloat(part) == part && commands.length) { commands[commands.length - 1].push(part); } else { commands.push([part]); } return commands; }, []); // The resulting commands, also grouped var resultCommands = []; if (commands.length > 1) { var startPoint = pointForCommand(commands[0]); // Handle the close path case with a "virtual" closing line var virtualCloseLine = null; if (commands[commands.length - 1][0] == 'Z' && commands[0].length > 2) { virtualCloseLine = ['L', startPoint.x, startPoint.y]; commands[commands.length - 1] = virtualCloseLine; } // We always use the first command (but it may be mutated) resultCommands.push(commands[0]); for (var cmdIndex = 1; cmdIndex < commands.length; cmdIndex++) { var prevCmd = resultCommands[resultCommands.length - 1]; var curCmd = commands[cmdIndex]; // Handle closing case var nextCmd = curCmd == virtualCloseLine ? commands[1] : commands[cmdIndex + 1]; // Nasty logic to decide if this path is a candidite. if (nextCmd && prevCmd && prevCmd.length > 2 && curCmd[0] == 'L' && nextCmd.length > 2 && nextCmd[0] == 'L') { // Calc the points we're dealing with var prevPoint = pointForCommand(prevCmd); var curPoint = pointForCommand(curCmd); var nextPoint = pointForCommand(nextCmd); // The start and end of the cuve are just our point moved towards the previous and next points, respectivly var curveStart, curveEnd; curveStart = moveTowardsLength(curPoint, prevPoint, radius); curveEnd = moveTowardsLength(curPoint, nextPoint, radius); // Adjust the current command and add it adjustCommand(curCmd, curveStart); curCmd.origPoint = curPoint; resultCommands.push(curCmd); // The curve control points are halfway between the start/end of the curve and // the original point var startControl = moveTowardsFractional(curveStart, curPoint, 0.5); var endControl = moveTowardsFractional(curPoint, curveEnd, 0.5); // Create the curve var curveCmd = ['C', startControl.x, startControl.y, endControl.x, endControl.y, curveEnd.x, curveEnd.y]; // Save the original point for fractional calculations curveCmd.origPoint = curPoint; resultCommands.push(curveCmd); } else { // Pass through commands that don't qualify resultCommands.push(curCmd); } } // Fix up the starting point and restore the close path if the path was orignally closed if (virtualCloseLine) { var newStartPoint = pointForCommand(resultCommands[resultCommands.length - 1]); resultCommands.push(['Z']); adjustCommand(resultCommands[0], newStartPoint); } } else { resultCommands = commands; } return resultCommands.reduce(function (str, c) { return str + c.join(' ') + ' '; }, ''); } }, { key: "drawLine", value: function drawLine(x1, y1, x2, y2) { var lineColor = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '#a8a8a8'; var dashArray = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; var strokeWidth = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; var strokeLineCap = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 'butt'; var w = this.w; var line = w.globals.dom.Paper.line().attr({ x1: x1, y1: y1, x2: x2, y2: y2, stroke: lineColor, 'stroke-dasharray': dashArray, 'stroke-width': strokeWidth, 'stroke-linecap': strokeLineCap }); return line; } }, { key: "drawRect", value: function drawRect() { var x1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var y1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var x2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var y2 = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; var radius = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var color = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '#fefefe'; var opacity = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 1; var strokeWidth = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var strokeColor = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null; var strokeDashArray = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : 0; var w = this.w; var rect = w.globals.dom.Paper.rect(); rect.attr({ x: x1, y: y1, width: x2 > 0 ? x2 : 0, height: y2 > 0 ? y2 : 0, rx: radius, ry: radius, opacity: opacity, 'stroke-width': strokeWidth !== null ? strokeWidth : 0, stroke: strokeColor !== null ? strokeColor : 'none', 'stroke-dasharray': strokeDashArray }); // fix apexcharts.js#1410 rect.node.setAttribute('fill', color); return rect; } }, { key: "drawPolygon", value: function drawPolygon(polygonString) { var stroke = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '#e1e1e1'; var strokeWidth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; var fill = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'none'; var w = this.w; var polygon = w.globals.dom.Paper.polygon(polygonString).attr({ fill: fill, stroke: stroke, 'stroke-width': strokeWidth }); return polygon; } }, { key: "drawCircle", value: function drawCircle(radius) { var attrs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var w = this.w; if (radius < 0) radius = 0; var c = w.globals.dom.Paper.circle(radius * 2); if (attrs !== null) { c.attr(attrs); } return c; } }, { key: "drawPath", value: function drawPath(_ref) { var _ref$d = _ref.d, d = _ref$d === void 0 ? '' : _ref$d, _ref$stroke = _ref.stroke, stroke = _ref$stroke === void 0 ? '#a8a8a8' : _ref$stroke, _ref$strokeWidth = _ref.strokeWidth, strokeWidth = _ref$strokeWidth === void 0 ? 1 : _ref$strokeWidth, fill = _ref.fill, _ref$fillOpacity = _ref.fillOpacity, fillOpacity = _ref$fillOpacity === void 0 ? 1 : _ref$fillOpacity, _ref$strokeOpacity = _ref.strokeOpacity, strokeOpacity = _ref$strokeOpacity === void 0 ? 1 : _ref$strokeOpacity, classes = _ref.classes, _ref$strokeLinecap = _ref.strokeLinecap, strokeLinecap = _ref$strokeLinecap === void 0 ? null : _ref$strokeLinecap, _ref$strokeDashArray = _ref.strokeDashArray, strokeDashArray = _ref$strokeDashArray === void 0 ? 0 : _ref$strokeDashArray; var w = this.w; if (strokeLinecap === null) { strokeLinecap = w.config.stroke.lineCap; } if (d.indexOf('undefined') > -1 || d.indexOf('NaN') > -1) { d = "M 0 ".concat(w.globals.gridHeight); } var p = w.globals.dom.Paper.path(d).attr({ fill: fill, 'fill-opacity': fillOpacity, stroke: stroke, 'stroke-opacity': strokeOpacity, 'stroke-linecap': strokeLinecap, 'stroke-width': strokeWidth, 'stroke-dasharray': strokeDashArray, class: classes }); return p; } }, { key: "group", value: function group() { var attrs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var w = this.w; var g = w.globals.dom.Paper.group(); if (attrs !== null) { g.attr(attrs); } return g; } }, { key: "move", value: function move(x, y) { var move = ['M', x, y].join(' '); return move; } }, { key: "line", value: function line(x, y) { var hORv = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var line = null; if (hORv === null) { line = [' L', x, y].join(' '); } else if (hORv === 'H') { line = [' H', x].join(' '); } else if (hORv === 'V') { line = [' V', y].join(' '); } return line; } }, { key: "curve", value: function curve(x1, y1, x2, y2, x, y) { var curve = ['C', x1, y1, x2, y2, x, y].join(' '); return curve; } }, { key: "quadraticCurve", value: function quadraticCurve(x1, y1, x, y) { var curve = ['Q', x1, y1, x, y].join(' '); return curve; } }, { key: "arc", value: function arc(rx, ry, axisRotation, largeArcFlag, sweepFlag, x, y) { var relative = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false; var coord = 'A'; if (relative) coord = 'a'; var arc = [coord, rx, ry, axisRotation, largeArcFlag, sweepFlag, x, y].join(' '); return arc; } /** * @memberof Graphics * @param {object} * i = series's index * realIndex = realIndex is series's actual index when it was drawn time. After several redraws, the iterating "i" may change in loops, but realIndex doesn't * pathFrom = existing pathFrom to animateTo * pathTo = new Path to which d attr will be animated from pathFrom to pathTo * stroke = line Color * strokeWidth = width of path Line * fill = it can be gradient, single color, pattern or image * animationDelay = how much to delay when starting animation (in milliseconds) * dataChangeSpeed = for dynamic animations, when data changes * className = class attribute to add * @return {object} svg.js path object **/ }, { key: "renderPaths", value: function renderPaths(_ref2) { var j = _ref2.j, realIndex = _ref2.realIndex, pathFrom = _ref2.pathFrom, pathTo = _ref2.pathTo, stroke = _ref2.stroke, strokeWidth = _ref2.strokeWidth, strokeLinecap = _ref2.strokeLinecap, fill = _ref2.fill, animationDelay = _ref2.animationDelay, initialSpeed = _ref2.initialSpeed, dataChangeSpeed = _ref2.dataChangeSpeed, className = _ref2.className, _ref2$shouldClipToGri = _ref2.shouldClipToGrid, shouldClipToGrid = _ref2$shouldClipToGri === void 0 ? true : _ref2$shouldClipToGri, _ref2$bindEventsOnPat = _ref2.bindEventsOnPaths, bindEventsOnPaths = _ref2$bindEventsOnPat === void 0 ? true : _ref2$bindEventsOnPat, _ref2$drawShadow = _ref2.drawShadow, drawShadow = _ref2$drawShadow === void 0 ? true : _ref2$drawShadow; var w = this.w; var filters = new Filters(this.ctx); var anim = new Animations(this.ctx); var initialAnim = this.w.config.chart.animations.enabled; var dynamicAnim = initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled; var d; var shouldAnimate = !!(initialAnim && !w.globals.resized || dynamicAnim && w.globals.dataChanged && w.globals.shouldAnimate); if (shouldAnimate) { d = pathFrom; } else { d = pathTo; w.globals.animationEnded = true; } var strokeDashArrayOpt = w.config.stroke.dashArray; var strokeDashArray = 0; if (Array.isArray(strokeDashArrayOpt)) { strokeDashArray = strokeDashArrayOpt[realIndex]; } else { strokeDashArray = w.config.stroke.dashArray; } var el = this.drawPath({ d: d, stroke: stroke, strokeWidth: strokeWidth, fill: fill, fillOpacity: 1, classes: className, strokeLinecap: strokeLinecap, strokeDashArray: strokeDashArray }); el.attr('index', realIndex); if (shouldClipToGrid) { el.attr({ 'clip-path': "url(#gridRectMask".concat(w.globals.cuid, ")") }); } // const defaultFilter = el.filterer if (w.config.states.normal.filter.type !== 'none') { filters.getDefaultFilter(el, realIndex); } else { if (w.config.chart.dropShadow.enabled && drawShadow) { if (!w.config.chart.dropShadow.enabledOnSeries || w.config.chart.dropShadow.enabledOnSeries && w.config.chart.dropShadow.enabledOnSeries.indexOf(realIndex) !== -1) { var shadow = w.config.chart.dropShadow; filters.dropShadow(el, shadow, realIndex); } } } if (bindEventsOnPaths) { el.node.addEventListener('mouseenter', this.pathMouseEnter.bind(this, el)); el.node.addEventListener('mouseleave', this.pathMouseLeave.bind(this, el)); el.node.addEventListener('mousedown', this.pathMouseDown.bind(this, el)); } el.attr({ pathTo: pathTo, pathFrom: pathFrom }); var defaultAnimateOpts = { el: el, j: j, realIndex: realIndex, pathFrom: pathFrom, pathTo: pathTo, fill: fill, strokeWidth: strokeWidth, delay: animationDelay }; if (initialAnim && !w.globals.resized && !w.globals.dataChanged) { anim.animatePathsGradually(_objectSpread2(_objectSpread2({}, defaultAnimateOpts), {}, { speed: initialSpeed })); } else { if (w.globals.resized || !w.globals.dataChanged) { anim.showDelayedElements(); } } if (w.globals.dataChanged && dynamicAnim && shouldAnimate) { anim.animatePathsGradually(_objectSpread2(_objectSpread2({}, defaultAnimateOpts), {}, { speed: dataChangeSpeed })); } return el; } }, { key: "drawPattern", value: function drawPattern(style, width, height) { var stroke = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '#a8a8a8'; var strokeWidth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0; var w = this.w; var p = w.globals.dom.Paper.pattern(width, height, function (add) { if (style === 'horizontalLines') { add.line(0, 0, height, 0).stroke({ color: stroke, width: strokeWidth + 1 }); } else if (style === 'verticalLines') { add.line(0, 0, 0, width).stroke({ color: stroke, width: strokeWidth + 1 }); } else if (style === 'slantedLines') { add.line(0, 0, width, height).stroke({ color: stroke, width: strokeWidth }); } else if (style === 'squares') { add.rect(width, height).fill('none').stroke({ color: stroke, width: strokeWidth }); } else if (style === 'circles') { add.circle(width).fill('none').stroke({ color: stroke, width: strokeWidth }); } }); return p; } }, { key: "drawGradient", value: function drawGradient(style, gfrom, gto, opacityFrom, opacityTo) { var size = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; var stops = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : null; var colorStops = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null; var i = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 0; var w = this.w; var g; if (gfrom.length < 9 && gfrom.indexOf('#') === 0) { // if the hex contains alpha and is of 9 digit, skip the opacity gfrom = Utils$1.hexToRgba(gfrom, opacityFrom); } if (gto.length < 9 && gto.indexOf('#') === 0) { gto = Utils$1.hexToRgba(gto, opacityTo); } var stop1 = 0; var stop2 = 1; var stop3 = 1; var stop4 = null; if (stops !== null) { stop1 = typeof stops[0] !== 'undefined' ? stops[0] / 100 : 0; stop2 = typeof stops[1] !== 'undefined' ? stops[1] / 100 : 1; stop3 = typeof stops[2] !== 'undefined' ? stops[2] / 100 : 1; stop4 = typeof stops[3] !== 'undefined' ? stops[3] / 100 : null; } var radial = !!(w.config.chart.type === 'donut' || w.config.chart.type === 'pie' || w.config.chart.type === 'polarArea' || w.config.chart.type === 'bubble'); if (colorStops === null || colorStops.length === 0) { g = w.globals.dom.Paper.gradient(radial ? 'radial' : 'linear', function (stop) { stop.at(stop1, gfrom, opacityFrom); stop.at(stop2, gto, opacityTo); stop.at(stop3, gto, opacityTo); if (stop4 !== null) { stop.at(stop4, gfrom, opacityFrom); } }); } else { g = w.globals.dom.Paper.gradient(radial ? 'radial' : 'linear', function (stop) { var gradientStops = Array.isArray(colorStops[i]) ? colorStops[i] : colorStops; gradientStops.forEach(function (s) { stop.at(s.offset / 100, s.color, s.opacity); }); }); } if (!radial) { if (style === 'vertical') { g.from(0, 0).to(0, 1); } else if (style === 'diagonal') { g.from(0, 0).to(1, 1); } else if (style === 'horizontal') { g.from(0, 1).to(1, 1); } else if (style === 'diagonal2') { g.from(1, 0).to(0, 1); } } else { var offx = w.globals.gridWidth / 2; var offy = w.globals.gridHeight / 2; if (w.config.chart.type !== 'bubble') { g.attr({ gradientUnits: 'userSpaceOnUse', cx: offx, cy: offy, r: size }); } else { g.attr({ cx: 0.5, cy: 0.5, r: 0.8, fx: 0.2, fy: 0.2 }); } } return g; } }, { key: "getTextBasedOnMaxWidth", value: function getTextBasedOnMaxWidth(_ref3) { var text = _ref3.text, maxWidth = _ref3.maxWidth, fontSize = _ref3.fontSize, fontFamily = _ref3.fontFamily; var tRects = this.getTextRects(text, fontSize, fontFamily); var wordWidth = tRects.width / text.length; var wordsBasedOnWidth = Math.floor(maxWidth / wordWidth); if (maxWidth < tRects.width) { return text.slice(0, wordsBasedOnWidth - 3) + '...'; } return text; } }, { key: "drawText", value: function drawText(_ref4) { var _this = this; var x = _ref4.x, y = _ref4.y, text = _ref4.text, textAnchor = _ref4.textAnchor, fontSize = _ref4.fontSize, fontFamily = _ref4.fontFamily, fontWeight = _ref4.fontWeight, foreColor = _ref4.foreColor, opacity = _ref4.opacity, maxWidth = _ref4.maxWidth, _ref4$cssClass = _ref4.cssClass, cssClass = _ref4$cssClass === void 0 ? '' : _ref4$cssClass, _ref4$isPlainText = _ref4.isPlainText, isPlainText = _ref4$isPlainText === void 0 ? true : _ref4$isPlainText; var w = this.w; if (typeof text === 'undefined') text = ''; var truncatedText = text; if (!textAnchor) { textAnchor = 'start'; } if (!foreColor || !foreColor.length) { foreColor = w.config.chart.foreColor; } fontFamily = fontFamily || w.config.chart.fontFamily; fontSize = fontSize || '11px'; fontWeight = fontWeight || 'regular'; var commonProps = { maxWidth: maxWidth, fontSize: fontSize, fontFamily: fontFamily }; var elText; if (Array.isArray(text)) { elText = w.globals.dom.Paper.text(function (add) { for (var i = 0; i < text.length; i++) { truncatedText = text[i]; if (maxWidth) { truncatedText = _this.getTextBasedOnMaxWidth(_objectSpread2({ text: text[i] }, commonProps)); } i === 0 ? add.tspan(truncatedText) : add.tspan(truncatedText).newLine(); } }); } else { if (maxWidth) { truncatedText = this.getTextBasedOnMaxWidth(_objectSpread2({ text: text }, commonProps)); } elText = isPlainText ? w.globals.dom.Paper.plain(text) : w.globals.dom.Paper.text(function (add) { return add.tspan(truncatedText); }); } elText.attr({ x: x, y: y, 'text-anchor': textAnchor, 'dominant-baseline': 'auto', 'font-size': fontSize, 'font-family': fontFamily, 'font-weight': fontWeight, fill: foreColor, class: 'apexcharts-text ' + cssClass }); elText.node.style.fontFamily = fontFamily; elText.node.style.opacity = opacity; return elText; } }, { key: "drawMarker", value: function drawMarker(x, y, opts) { x = x || 0; var size = opts.pSize || 0; var elPoint = null; if (opts.shape === 'square' || opts.shape === 'rect') { var radius = opts.pRadius === undefined ? size / 2 : opts.pRadius; if (y === null || !size) { size = 0; radius = 0; } var nSize = size * 1.2 + radius; var p = this.drawRect(nSize, nSize, nSize, nSize, radius); p.attr({ x: x - nSize / 2, y: y - nSize / 2, cx: x, cy: y, class: opts.class ? opts.class : '', fill: opts.pointFillColor, 'fill-opacity': opts.pointFillOpacity ? opts.pointFillOpacity : 1, stroke: opts.pointStrokeColor, 'stroke-width': opts.pointStrokeWidth ? opts.pointStrokeWidth : 0, 'stroke-opacity': opts.pointStrokeOpacity ? opts.pointStrokeOpacity : 1 }); elPoint = p; } else if (opts.shape === 'circle' || !opts.shape) { if (!Utils$1.isNumber(y)) { size = 0; y = 0; } // let nSize = size - opts.pRadius / 2 < 0 ? 0 : size - opts.pRadius / 2 elPoint = this.drawCircle(size, { cx: x, cy: y, class: opts.class ? opts.class : '', stroke: opts.pointStrokeColor, fill: opts.pointFillColor, 'fill-opacity': opts.pointFillOpacity ? opts.pointFillOpacity : 1, 'stroke-width': opts.pointStrokeWidth ? opts.pointStrokeWidth : 0, 'stroke-opacity': opts.pointStrokeOpacity ? opts.pointStrokeOpacity : 1 }); } return elPoint; } }, { key: "pathMouseEnter", value: function pathMouseEnter(path, e) { var w = this.w; var filters = new Filters(this.ctx); var i = parseInt(path.node.getAttribute('index'), 10); var j = parseInt(path.node.getAttribute('j'), 10); if (typeof w.config.chart.events.dataPointMouseEnter === 'function') { w.config.chart.events.dataPointMouseEnter(e, this.ctx, { seriesIndex: i, dataPointIndex: j, w: w }); } this.ctx.events.fireEvent('dataPointMouseEnter', [e, this.ctx, { seriesIndex: i, dataPointIndex: j, w: w }]); if (w.config.states.active.filter.type !== 'none') { if (path.node.getAttribute('selected') === 'true') { return; } } if (w.config.states.hover.filter.type !== 'none') { if (!w.globals.isTouchDevice) { var hoverFilter = w.config.states.hover.filter; filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value); } } } }, { key: "pathMouseLeave", value: function pathMouseLeave(path, e) { var w = this.w; var filters = new Filters(this.ctx); var i = parseInt(path.node.getAttribute('index'), 10); var j = parseInt(path.node.getAttribute('j'), 10); if (typeof w.config.chart.events.dataPointMouseLeave === 'function') { w.config.chart.events.dataPointMouseLeave(e, this.ctx, { seriesIndex: i, dataPointIndex: j, w: w }); } this.ctx.events.fireEvent('dataPointMouseLeave', [e, this.ctx, { seriesIndex: i, dataPointIndex: j, w: w }]); if (w.config.states.active.filter.type !== 'none') { if (path.node.getAttribute('selected') === 'true') { return; } } if (w.config.states.hover.filter.type !== 'none') { filters.getDefaultFilter(path, i); } } }, { key: "pathMouseDown", value: function pathMouseDown(path, e) { var w = this.w; var filters = new Filters(this.ctx); var i = parseInt(path.node.getAttribute('index'), 10); var j = parseInt(path.node.getAttribute('j'), 10); var selected = 'false'; if (path.node.getAttribute('selected') === 'true') { path.node.setAttribute('selected', 'false'); if (w.globals.selectedDataPoints[i].indexOf(j) > -1) { var index = w.globals.selectedDataPoints[i].indexOf(j); w.globals.selectedDataPoints[i].splice(index, 1); } } else { if (!w.config.states.active.allowMultipleDataPointsSelection && w.globals.selectedDataPoints.length > 0) { w.globals.selectedDataPoints = []; var elPaths = w.globals.dom.Paper.select('.apexcharts-series path').members; var elCircles = w.globals.dom.Paper.select('.apexcharts-series circle, .apexcharts-series rect').members; var deSelect = function deSelect(els) { Array.prototype.forEach.call(els, function (el) { el.node.setAttribute('selected', 'false'); filters.getDefaultFilter(el, i); }); }; deSelect(elPaths); deSelect(elCircles); } path.node.setAttribute('selected', 'true'); selected = 'true'; if (typeof w.globals.selectedDataPoints[i] === 'undefined') { w.globals.selectedDataPoints[i] = []; } w.globals.selectedDataPoints[i].push(j); } if (selected === 'true') { var activeFilter = w.config.states.active.filter; if (activeFilter !== 'none') { filters.applyFilter(path, i, activeFilter.type, activeFilter.value); } else { // Reapply the hover filter in case it was removed by `deselect`when there is no active filter and it is not a touch device if (w.config.states.hover.filter !== 'none') { if (!w.globals.isTouchDevice) { var hoverFilter = w.config.states.hover.filter; filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value); } } } } else { // If the item was deselected, apply hover state filter if it is not a touch device if (w.config.states.active.filter.type !== 'none') { if (w.config.states.hover.filter.type !== 'none' && !w.globals.isTouchDevice) { var hoverFilter = w.config.states.hover.filter; filters.applyFilter(path, i, hoverFilter.type, hoverFilter.value); } else { filters.getDefaultFilter(path, i); } } } if (typeof w.config.chart.events.dataPointSelection === 'function') { w.config.chart.events.dataPointSelection(e, this.ctx, { selectedDataPoints: w.globals.selectedDataPoints, seriesIndex: i, dataPointIndex: j, w: w }); } if (e) { this.ctx.events.fireEvent('dataPointSelection', [e, this.ctx, { selectedDataPoints: w.globals.selectedDataPoints, seriesIndex: i, dataPointIndex: j, w: w }]); } } }, { key: "rotateAroundCenter", value: function rotateAroundCenter(el) { var coord = {}; if (el && typeof el.getBBox === 'function') { coord = el.getBBox(); } var x = coord.x + coord.width / 2; var y = coord.y + coord.height / 2; return { x: x, y: y }; } }, { key: "getTextRects", value: function getTextRects(text, fontSize, fontFamily, transform) { var useBBox = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; var w = this.w; var virtualText = this.drawText({ x: -200, y: -200, text: text, textAnchor: 'start', fontSize: fontSize, fontFamily: fontFamily, foreColor: '#fff', opacity: 0 }); if (transform) { virtualText.attr('transform', transform); } w.globals.dom.Paper.add(virtualText); var rect = virtualText.bbox(); if (!useBBox) { rect = virtualText.node.getBoundingClientRect(); } virtualText.remove(); return { width: rect.width, height: rect.height }; } /** * append ... to long text * http://stackoverflow.com/questions/9241315/trimming-text-to-a-given-pixel-width-in-svg * @memberof Graphics **/ }, { key: "placeTextWithEllipsis", value: function placeTextWithEllipsis(textObj, textString, width) { if (typeof textObj.getComputedTextLength !== 'function') return; textObj.textContent = textString; if (textString.length > 0) { // ellipsis is needed if (textObj.getComputedTextLength() >= width / 1.1) { for (var x = textString.length - 3; x > 0; x -= 3) { if (textObj.getSubStringLength(0, x) <= width / 1.1) { textObj.textContent = textString.substring(0, x) + '...'; return; } } textObj.textContent = '.'; // can't place at all } } } }], [{ key: "setAttrs", value: function setAttrs(el, attrs) { for (var key in attrs) { if (attrs.hasOwnProperty(key)) { el.setAttribute(key, attrs[key]); } } } }]); return Graphics; }(); /* ** Util functions which are dependent on ApexCharts instance */ var CoreUtils = /*#__PURE__*/function () { function CoreUtils(ctx) { _classCallCheck(this, CoreUtils); this.ctx = ctx; this.w = ctx.w; } _createClass(CoreUtils, [{ key: "getStackedSeriesTotals", value: /** * @memberof CoreUtils * returns the sum of all individual values in a multiple stacked series * Eg. w.globals.series = [[32,33,43,12], [2,3,5,1]] * @return [34,36,48,13] **/ function getStackedSeriesTotals() { var excludedSeriesIndices = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var w = this.w; var total = []; if (w.globals.series.length === 0) return total; for (var i = 0; i < w.globals.series[w.globals.maxValsInArrayIndex].length; i++) { var t = 0; for (var j = 0; j < w.globals.series.length; j++) { if (typeof w.globals.series[j][i] !== 'undefined' && excludedSeriesIndices.indexOf(j) === -1) { t += w.globals.series[j][i]; } } total.push(t); } return total; } // get total of the all values inside all series }, { key: "getSeriesTotalByIndex", value: function getSeriesTotalByIndex() { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; if (index === null) { // non-plot chart types - pie / donut / circle return this.w.config.series.reduce(function (acc, cur) { return acc + cur; }, 0); } else { // axis charts - supporting multiple series return this.w.globals.series[index].reduce(function (acc, cur) { return acc + cur; }, 0); } } }, { key: "isSeriesNull", value: function isSeriesNull() { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var r = []; if (index === null) { // non-plot chart types - pie / donut / circle r = this.w.config.series.filter(function (d) { return d !== null; }); } else { // axis charts - supporting multiple series r = this.w.config.series[index].data.filter(function (d) { return d !== null; }); } return r.length === 0; } }, { key: "seriesHaveSameValues", value: function seriesHaveSameValues(index) { return this.w.globals.series[index].every(function (val, i, arr) { return val === arr[0]; }); } }, { key: "getCategoryLabels", value: function getCategoryLabels(labels) { var w = this.w; var catLabels = labels.slice(); if (w.config.xaxis.convertedCatToNumeric) { catLabels = labels.map(function (i, li) { return w.config.xaxis.labels.formatter(i - w.globals.minX + 1); }); } return catLabels; } // maxValsInArrayIndex is the index of series[] which has the largest number of items }, { key: "getLargestSeries", value: function getLargestSeries() { var w = this.w; w.globals.maxValsInArrayIndex = w.globals.series.map(function (a) { return a.length; }).indexOf(Math.max.apply(Math, w.globals.series.map(function (a) { return a.length; }))); } }, { key: "getLargestMarkerSize", value: function getLargestMarkerSize() { var w = this.w; var size = 0; w.globals.markers.size.forEach(function (m) { size = Math.max(size, m); }); if (w.config.markers.discrete && w.config.markers.discrete.length) { w.config.markers.discrete.forEach(function (m) { size = Math.max(size, m.size); }); } if (size > 0) { size += w.config.markers.hover.sizeOffset + 1; } w.globals.markers.largestSize = size; return size; } /** * @memberof Core * returns the sum of all values in a series * Eg. w.globals.series = [[32,33,43,12], [2,3,5,1]] * @return [120, 11] **/ }, { key: "getSeriesTotals", value: function getSeriesTotals() { var w = this.w; w.globals.seriesTotals = w.globals.series.map(function (ser, index) { var total = 0; if (Array.isArray(ser)) { for (var j = 0; j < ser.length; j++) { total += ser[j]; } } else { // for pie/donuts/gauges total += ser; } return total; }); } }, { key: "getSeriesTotalsXRange", value: function getSeriesTotalsXRange(minX, maxX) { var w = this.w; var seriesTotalsXRange = w.globals.series.map(function (ser, index) { var total = 0; for (var j = 0; j < ser.length; j++) { if (w.globals.seriesX[index][j] > minX && w.globals.seriesX[index][j] < maxX) { total += ser[j]; } } return total; }); return seriesTotalsXRange; } /** * @memberof CoreUtils * returns the percentage value of all individual values which can be used in a 100% stacked series * Eg. w.globals.series = [[32, 33, 43, 12], [2, 3, 5, 1]] * @return [[94.11, 91.66, 89.58, 92.30], [5.88, 8.33, 10.41, 7.7]] **/ }, { key: "getPercentSeries", value: function getPercentSeries() { var w = this.w; w.globals.seriesPercent = w.globals.series.map(function (ser, index) { var seriesPercent = []; if (Array.isArray(ser)) { for (var j = 0; j < ser.length; j++) { var total = w.globals.stackedSeriesTotals[j]; var percent = 0; if (total) { percent = 100 * ser[j] / total; } seriesPercent.push(percent); } } else { var _total = w.globals.seriesTotals.reduce(function (acc, val) { return acc + val; }, 0); var _percent = 100 * ser / _total; seriesPercent.push(_percent); } return seriesPercent; }); } }, { key: "getCalculatedRatios", value: function getCalculatedRatios() { var gl = this.w.globals; var yRatio = []; var invertedYRatio = 0; var xRatio = 0; var initialXRatio = 0; var invertedXRatio = 0; var zRatio = 0; var baseLineY = []; var baseLineInvertedY = 0.1; var baseLineX = 0; gl.yRange = []; if (gl.isMultipleYAxis) { for (var i = 0; i < gl.minYArr.length; i++) { gl.yRange.push(Math.abs(gl.minYArr[i] - gl.maxYArr[i])); baseLineY.push(0); } } else { gl.yRange.push(Math.abs(gl.minY - gl.maxY)); } gl.xRange = Math.abs(gl.maxX - gl.minX); gl.zRange = Math.abs(gl.maxZ - gl.minZ); // multiple y axis for (var _i = 0; _i < gl.yRange.length; _i++) { yRatio.push(gl.yRange[_i] / gl.gridHeight); } xRatio = gl.xRange / gl.gridWidth; initialXRatio = Math.abs(gl.initialMaxX - gl.initialMinX) / gl.gridWidth; invertedYRatio = gl.yRange / gl.gridWidth; invertedXRatio = gl.xRange / gl.gridHeight; zRatio = gl.zRange / gl.gridHeight * 16; if (!zRatio) { zRatio = 1; } if (gl.minY !== Number.MIN_VALUE && Math.abs(gl.minY) !== 0) { // Negative numbers present in series gl.hasNegs = true; } if (gl.isMultipleYAxis) { baseLineY = []; // baseline variables is the 0 of the yaxis which will be needed when there are negatives for (var _i2 = 0; _i2 < yRatio.length; _i2++) { baseLineY.push(-gl.minYArr[_i2] / yRatio[_i2]); } } else { baseLineY.push(-gl.minY / yRatio[0]); if (gl.minY !== Number.MIN_VALUE && Math.abs(gl.minY) !== 0) { baseLineInvertedY = -gl.minY / invertedYRatio; // this is for bar chart baseLineX = gl.minX / xRatio; } } return { yRatio: yRatio, invertedYRatio: invertedYRatio, zRatio: zRatio, xRatio: xRatio, initialXRatio: initialXRatio, invertedXRatio: invertedXRatio, baseLineInvertedY: baseLineInvertedY, baseLineY: baseLineY, baseLineX: baseLineX }; } }, { key: "getLogSeries", value: function getLogSeries(series) { var _this = this; var w = this.w; w.globals.seriesLog = series.map(function (s, i) { if (w.config.yaxis[i] && w.config.yaxis[i].logarithmic) { return s.map(function (d) { if (d === null) return null; return _this.getLogVal(w.config.yaxis[i].logBase, d, i); }); } else { return s; } }); return w.globals.invalidLogScale ? series : w.globals.seriesLog; } }, { key: "getBaseLog", value: function getBaseLog(base, value) { return Math.log(value) / Math.log(base); } }, { key: "getLogVal", value: function getLogVal(b, d, yIndex) { if (d === 0) { return 0; } var w = this.w; var min_log_val = w.globals.minYArr[yIndex] === 0 ? -1 // make sure we dont calculate log of 0 : this.getBaseLog(b, w.globals.minYArr[yIndex]); var max_log_val = w.globals.maxYArr[yIndex] === 0 ? 0 // make sure we dont calculate log of 0 : this.getBaseLog(b, w.globals.maxYArr[yIndex]); var number_of_height_levels = max_log_val - min_log_val; if (d < 1) return d / number_of_height_levels; var log_height_value = this.getBaseLog(b, d) - min_log_val; return log_height_value / number_of_height_levels; } }, { key: "getLogYRatios", value: function getLogYRatios(yRatio) { var _this2 = this; var w = this.w; var gl = this.w.globals; gl.yLogRatio = yRatio.slice(); gl.logYRange = gl.yRange.map(function (yRange, i) { if (w.config.yaxis[i] && _this2.w.config.yaxis[i].logarithmic) { var maxY = -Number.MAX_VALUE; var minY = Number.MIN_VALUE; var range = 1; gl.seriesLog.forEach(function (s, si) { s.forEach(function (v) { if (w.config.yaxis[si] && w.config.yaxis[si].logarithmic) { maxY = Math.max(v, maxY); minY = Math.min(v, minY); } }); }); range = Math.pow(gl.yRange[i], Math.abs(minY - maxY) / gl.yRange[i]); gl.yLogRatio[i] = range / gl.gridHeight; return range; } }); return gl.invalidLogScale ? yRatio.slice() : gl.yLogRatio; } // Some config objects can be array - and we need to extend them correctly }], [{ key: "checkComboSeries", value: function checkComboSeries(series) { var comboCharts = false; var comboBarCount = 0; var comboCount = 0; // if user specified a type in series too, turn on comboCharts flag if (series.length && typeof series[0].type !== 'undefined') { series.forEach(function (s) { if (s.type === 'bar' || s.type === 'column' || s.type === 'candlestick' || s.type === 'boxPlot') { comboBarCount++; } if (typeof s.type !== 'undefined') { comboCount++; } }); } if (comboCount > 0) { comboCharts = true; } return { comboBarCount: comboBarCount, comboCharts: comboCharts }; } }, { key: "extendArrayProps", value: function extendArrayProps(configInstance, options, w) { if (options.yaxis) { options = configInstance.extendYAxis(options, w); } if (options.annotations) { if (options.annotations.yaxis) { options = configInstance.extendYAxisAnnotations(options); } if (options.annotations.xaxis) { options = configInstance.extendXAxisAnnotations(options); } if (options.annotations.points) { options = configInstance.extendPointAnnotations(options); } } return options; } }]); return CoreUtils; }(); var Helpers$4 = /*#__PURE__*/function () { function Helpers(annoCtx) { _classCallCheck(this, Helpers); this.w = annoCtx.w; this.annoCtx = annoCtx; } _createClass(Helpers, [{ key: "setOrientations", value: function setOrientations(anno) { var annoIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var w = this.w; if (anno.label.orientation === 'vertical') { var i = annoIndex !== null ? annoIndex : 0; var xAnno = w.globals.dom.baseEl.querySelector(".apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='".concat(i, "']")); if (xAnno !== null) { var xAnnoCoord = xAnno.getBoundingClientRect(); xAnno.setAttribute('x', parseFloat(xAnno.getAttribute('x')) - xAnnoCoord.height + 4); if (anno.label.position === 'top') { xAnno.setAttribute('y', parseFloat(xAnno.getAttribute('y')) + xAnnoCoord.width); } else { xAnno.setAttribute('y', parseFloat(xAnno.getAttribute('y')) - xAnnoCoord.width); } var annoRotatingCenter = this.annoCtx.graphics.rotateAroundCenter(xAnno); var x = annoRotatingCenter.x; var y = annoRotatingCenter.y; xAnno.setAttribute('transform', "rotate(-90 ".concat(x, " ").concat(y, ")")); } } } }, { key: "addBackgroundToAnno", value: function addBackgroundToAnno(annoEl, anno) { var w = this.w; if (!annoEl || typeof anno.label.text === 'undefined' || typeof anno.label.text !== 'undefined' && !String(anno.label.text).trim()) return null; var elGridRect = w.globals.dom.baseEl.querySelector('.apexcharts-grid').getBoundingClientRect(); var coords = annoEl.getBoundingClientRect(); var pleft = anno.label.style.padding.left; var pright = anno.label.style.padding.right; var ptop = anno.label.style.padding.top; var pbottom = anno.label.style.padding.bottom; if (anno.label.orientation === 'vertical') { ptop = anno.label.style.padding.left; pbottom = anno.label.style.padding.right; pleft = anno.label.style.padding.top; pright = anno.label.style.padding.bottom; } var x1 = coords.left - elGridRect.left - pleft; var y1 = coords.top - elGridRect.top - ptop; var elRect = this.annoCtx.graphics.drawRect(x1 - w.globals.barPadForNumericAxis, y1, coords.width + pleft + pright, coords.height + ptop + pbottom, anno.label.borderRadius, anno.label.style.background, 1, anno.label.borderWidth, anno.label.borderColor, 0); if (anno.id) { // don't escapeString for this ID as it causes duplicate rects elRect.node.classList.add(anno.id); } return elRect; } }, { key: "annotationsBackground", value: function annotationsBackground() { var _this = this; var w = this.w; var add = function add(anno, i, type) { var annoLabel = w.globals.dom.baseEl.querySelector(".apexcharts-".concat(type, "-annotations .apexcharts-").concat(type, "-annotation-label[rel='").concat(i, "']")); if (annoLabel) { var parent = annoLabel.parentNode; var elRect = _this.addBackgroundToAnno(annoLabel, anno); if (elRect) { parent.insertBefore(elRect.node, annoLabel); if (anno.label.mouseEnter) { elRect.node.addEventListener('mouseenter', anno.label.mouseEnter.bind(_this, anno)); } if (anno.label.mouseLeave) { elRect.node.addEventListener('mouseleave', anno.label.mouseLeave.bind(_this, anno)); } if (anno.label.click) { elRect.node.addEventListener('click', anno.label.click.bind(_this, anno)); } } } }; w.config.annotations.xaxis.map(function (anno, i) { add(anno, i, 'xaxis'); }); w.config.annotations.yaxis.map(function (anno, i) { add(anno, i, 'yaxis'); }); w.config.annotations.points.map(function (anno, i) { add(anno, i, 'point'); }); } }, { key: "getY1Y2", value: function getY1Y2(type, anno) { var y = type === 'y1' ? anno.y : anno.y2; var yP; var w = this.w; if (this.annoCtx.invertAxis) { var catIndex = w.globals.labels.indexOf(y); if (w.config.xaxis.convertedCatToNumeric) { catIndex = w.globals.categoryLabels.indexOf(y); } var xLabel = w.globals.dom.baseEl.querySelector('.apexcharts-yaxis-texts-g text:nth-child(' + (catIndex + 1) + ')'); if (xLabel) { yP = parseFloat(xLabel.getAttribute('y')); } } else { var yPos; if (w.config.yaxis[anno.yAxisIndex].logarithmic) { var coreUtils = new CoreUtils(this.annoCtx.ctx); y = coreUtils.getLogVal(y, anno.yAxisIndex); yPos = y / w.globals.yLogRatio[anno.yAxisIndex]; } else { yPos = (y - w.globals.minYArr[anno.yAxisIndex]) / (w.globals.yRange[anno.yAxisIndex] / w.globals.gridHeight); } yP = w.globals.gridHeight - yPos; if (anno.marker && (anno.y === undefined || anno.y === null)) { // point annotation yP = 0; } if (w.config.yaxis[anno.yAxisIndex] && w.config.yaxis[anno.yAxisIndex].reversed) { yP = yPos; } } if (typeof y === 'string' && y.indexOf('px') > -1) { yP = parseFloat(y); } return yP; } }, { key: "getX1X2", value: function getX1X2(type, anno) { var w = this.w; var min = this.annoCtx.invertAxis ? w.globals.minY : w.globals.minX; var max = this.annoCtx.invertAxis ? w.globals.maxY : w.globals.maxX; var range = this.annoCtx.invertAxis ? w.globals.yRange[0] : w.globals.xRange; var x1 = (anno.x - min) / (range / w.globals.gridWidth); if (this.annoCtx.inversedReversedAxis) { x1 = (max - anno.x) / (range / w.globals.gridWidth); } if ((w.config.xaxis.type === 'category' || w.config.xaxis.convertedCatToNumeric) && !this.annoCtx.invertAxis && !w.globals.dataFormatXNumeric) { x1 = this.getStringX(anno.x); } var x2 = (anno.x2 - min) / (range / w.globals.gridWidth); if (this.annoCtx.inversedReversedAxis) { x2 = (max - anno.x2) / (range / w.globals.gridWidth); } if ((w.config.xaxis.type === 'category' || w.config.xaxis.convertedCatToNumeric) && !this.annoCtx.invertAxis && !w.globals.dataFormatXNumeric) { x2 = this.getStringX(anno.x2); } if ((anno.x === undefined || anno.x === null) && anno.marker) { // point annotation in a horizontal chart x1 = w.globals.gridWidth; } if (type === 'x1' && typeof anno.x === 'string' && anno.x.indexOf('px') > -1) { x1 = parseFloat(anno.x); } if (type === 'x2' && typeof anno.x2 === 'string' && anno.x2.indexOf('px') > -1) { x2 = parseFloat(anno.x2); } return type === 'x1' ? x1 : x2; } }, { key: "getStringX", value: function getStringX(x) { var w = this.w; var rX = x; if (w.config.xaxis.convertedCatToNumeric && w.globals.categoryLabels.length) { x = w.globals.categoryLabels.indexOf(x) + 1; } var catIndex = w.globals.labels.indexOf(x); var xLabel = w.globals.dom.baseEl.querySelector('.apexcharts-xaxis-texts-g text:nth-child(' + (catIndex + 1) + ')'); if (xLabel) { rX = parseFloat(xLabel.getAttribute('x')); } return rX; } }]); return Helpers; }(); var XAnnotations = /*#__PURE__*/function () { function XAnnotations(annoCtx) { _classCallCheck(this, XAnnotations); this.w = annoCtx.w; this.annoCtx = annoCtx; this.invertAxis = this.annoCtx.invertAxis; this.helpers = new Helpers$4(this.annoCtx); } _createClass(XAnnotations, [{ key: "addXaxisAnnotation", value: function addXaxisAnnotation(anno, parent, index) { var w = this.w; var x1 = this.helpers.getX1X2('x1', anno); var x2; var text = anno.label.text; var strokeDashArray = anno.strokeDashArray; if (!Utils$1.isNumber(x1)) return; if (anno.x2 === null || typeof anno.x2 === 'undefined') { var line = this.annoCtx.graphics.drawLine(x1 + anno.offsetX, // x1 0 + anno.offsetY, // y1 x1 + anno.offsetX, // x2 w.globals.gridHeight + anno.offsetY, // y2 anno.borderColor, // lineColor strokeDashArray, //dashArray anno.borderWidth); parent.appendChild(line.node); if (anno.id) { line.node.classList.add(anno.id); } } else { x2 = this.helpers.getX1X2('x2', anno); if (x2 < x1) { var temp = x1; x1 = x2; x2 = temp; } var rect = this.annoCtx.graphics.drawRect(x1 + anno.offsetX, // x1 0 + anno.offsetY, // y1 x2 - x1, // x2 w.globals.gridHeight + anno.offsetY, // y2 0, // radius anno.fillColor, // color anno.opacity, // opacity, 1, // strokeWidth anno.borderColor, // strokeColor strokeDashArray // stokeDashArray ); rect.node.classList.add('apexcharts-annotation-rect'); rect.attr('clip-path', "url(#gridRectMask".concat(w.globals.cuid, ")")); parent.appendChild(rect.node); if (anno.id) { rect.node.classList.add(anno.id); } } var textRects = this.annoCtx.graphics.getTextRects(text, parseFloat(anno.label.style.fontSize)); var textY = anno.label.position === 'top' ? 4 : anno.label.position === 'center' ? w.globals.gridHeight / 2 + (anno.label.orientation === 'vertical' ? textRects.width / 2 : 0) : w.globals.gridHeight; var elText = this.annoCtx.graphics.drawText({ x: x1 + anno.label.offsetX, y: textY + anno.label.offsetY - (anno.label.orientation === 'vertical' ? anno.label.position === 'top' ? textRects.width / 2 - 12 : -textRects.width / 2 : 0), text: text, textAnchor: anno.label.textAnchor, fontSize: anno.label.style.fontSize, fontFamily: anno.label.style.fontFamily, fontWeight: anno.label.style.fontWeight, foreColor: anno.label.style.color, cssClass: "apexcharts-xaxis-annotation-label ".concat(anno.label.style.cssClass, " ").concat(anno.id ? anno.id : '') }); elText.attr({ rel: index }); parent.appendChild(elText.node); // after placing the annotations on svg, set any vertically placed annotations this.annoCtx.helpers.setOrientations(anno, index); } }, { key: "drawXAxisAnnotations", value: function drawXAxisAnnotations() { var _this = this; var w = this.w; var elg = this.annoCtx.graphics.group({ class: 'apexcharts-xaxis-annotations' }); w.config.annotations.xaxis.map(function (anno, index) { _this.addXaxisAnnotation(anno, elg.node, index); }); return elg; } }]); return XAnnotations; }(); var YAnnotations = /*#__PURE__*/function () { function YAnnotations(annoCtx) { _classCallCheck(this, YAnnotations); this.w = annoCtx.w; this.annoCtx = annoCtx; this.helpers = new Helpers$4(this.annoCtx); } _createClass(YAnnotations, [{ key: "addYaxisAnnotation", value: function addYaxisAnnotation(anno, parent, index) { var w = this.w; var strokeDashArray = anno.strokeDashArray; var y1 = this.helpers.getY1Y2('y1', anno); var y2; var text = anno.label.text; if (anno.y2 === null || typeof anno.y2 === 'undefined') { var line = this.annoCtx.graphics.drawLine(0 + anno.offsetX, // x1 y1 + anno.offsetY, // y1 this._getYAxisAnnotationWidth(anno), // x2 y1 + anno.offsetY, // y2 anno.borderColor, // lineColor strokeDashArray, // dashArray anno.borderWidth); parent.appendChild(line.node); if (anno.id) { line.node.classList.add(anno.id); } } else { y2 = this.helpers.getY1Y2('y2', anno); if (y2 > y1) { var temp = y1; y1 = y2; y2 = temp; } var rect = this.annoCtx.graphics.drawRect(0 + anno.offsetX, // x1 y2 + anno.offsetY, // y1 this._getYAxisAnnotationWidth(anno), // x2 y1 - y2, // y2 0, // radius anno.fillColor, // color anno.opacity, // opacity, 1, // strokeWidth anno.borderColor, // strokeColor strokeDashArray // stokeDashArray ); rect.node.classList.add('apexcharts-annotation-rect'); rect.attr('clip-path', "url(#gridRectMask".concat(w.globals.cuid, ")")); parent.appendChild(rect.node); if (anno.id) { rect.node.classList.add(anno.id); } } var textX = anno.label.position === 'right' ? w.globals.gridWidth : anno.label.position === 'center' ? w.globals.gridWidth / 2 : 0; var elText = this.annoCtx.graphics.drawText({ x: textX + anno.label.offsetX, y: (y2 != null ? y2 : y1) + anno.label.offsetY - 3, text: text, textAnchor: anno.label.textAnchor, fontSize: anno.label.style.fontSize, fontFamily: anno.label.style.fontFamily, fontWeight: anno.label.style.fontWeight, foreColor: anno.label.style.color, cssClass: "apexcharts-yaxis-annotation-label ".concat(anno.label.style.cssClass, " ").concat(anno.id ? anno.id : '') }); elText.attr({ rel: index }); parent.appendChild(elText.node); } }, { key: "_getYAxisAnnotationWidth", value: function _getYAxisAnnotationWidth(anno) { // issue apexcharts.js#2009 var w = this.w; var width = w.globals.gridWidth; if (anno.width.indexOf('%') > -1) { width = w.globals.gridWidth * parseInt(anno.width, 10) / 100; } else { width = parseInt(anno.width, 10); } return width + anno.offsetX; } }, { key: "drawYAxisAnnotations", value: function drawYAxisAnnotations() { var _this = this; var w = this.w; var elg = this.annoCtx.graphics.group({ class: 'apexcharts-yaxis-annotations' }); w.config.annotations.yaxis.map(function (anno, index) { _this.addYaxisAnnotation(anno, elg.node, index); }); return elg; } }]); return YAnnotations; }(); var PointAnnotations = /*#__PURE__*/function () { function PointAnnotations(annoCtx) { _classCallCheck(this, PointAnnotations); this.w = annoCtx.w; this.annoCtx = annoCtx; this.helpers = new Helpers$4(this.annoCtx); } _createClass(PointAnnotations, [{ key: "addPointAnnotation", value: function addPointAnnotation(anno, parent, index) { this.w; var x = this.helpers.getX1X2('x1', anno); var y = this.helpers.getY1Y2('y1', anno); if (!Utils$1.isNumber(x)) return; var optsPoints = { pSize: anno.marker.size, pointStrokeWidth: anno.marker.strokeWidth, pointFillColor: anno.marker.fillColor, pointStrokeColor: anno.marker.strokeColor, shape: anno.marker.shape, pRadius: anno.marker.radius, class: "apexcharts-point-annotation-marker ".concat(anno.marker.cssClass, " ").concat(anno.id ? anno.id : '') }; var point = this.annoCtx.graphics.drawMarker(x + anno.marker.offsetX, y + anno.marker.offsetY, optsPoints); parent.appendChild(point.node); var text = anno.label.text ? anno.label.text : ''; var elText = this.annoCtx.graphics.drawText({ x: x + anno.label.offsetX, y: y + anno.label.offsetY - anno.marker.size - parseFloat(anno.label.style.fontSize) / 1.6, text: text, textAnchor: anno.label.textAnchor, fontSize: anno.label.style.fontSize, fontFamily: anno.label.style.fontFamily, fontWeight: anno.label.style.fontWeight, foreColor: anno.label.style.color, cssClass: "apexcharts-point-annotation-label ".concat(anno.label.style.cssClass, " ").concat(anno.id ? anno.id : '') }); elText.attr({ rel: index }); parent.appendChild(elText.node); // TODO: deprecate this as we will use custom if (anno.customSVG.SVG) { var g = this.annoCtx.graphics.group({ class: 'apexcharts-point-annotations-custom-svg ' + anno.customSVG.cssClass }); g.attr({ transform: "translate(".concat(x + anno.customSVG.offsetX, ", ").concat(y + anno.customSVG.offsetY, ")") }); g.node.innerHTML = anno.customSVG.SVG; parent.appendChild(g.node); } if (anno.image.path) { var imgWidth = anno.image.width ? anno.image.width : 20; var imgHeight = anno.image.height ? anno.image.height : 20; point = this.annoCtx.addImage({ x: x + anno.image.offsetX - imgWidth / 2, y: y + anno.image.offsetY - imgHeight / 2, width: imgWidth, height: imgHeight, path: anno.image.path, appendTo: '.apexcharts-point-annotations' }); } if (anno.mouseEnter) { point.node.addEventListener('mouseenter', anno.mouseEnter.bind(this, anno)); } if (anno.mouseLeave) { point.node.addEventListener('mouseleave', anno.mouseLeave.bind(this, anno)); } if (anno.click) { point.node.addEventListener('click', anno.click.bind(this, anno)); } } }, { key: "drawPointAnnotations", value: function drawPointAnnotations() { var _this = this; var w = this.w; var elg = this.annoCtx.graphics.group({ class: 'apexcharts-point-annotations' }); w.config.annotations.points.map(function (anno, index) { _this.addPointAnnotation(anno, elg.node, index); }); return elg; } }]); return PointAnnotations; }(); const name = "en"; const options = { months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], toolbar: { exportToSVG: "Download SVG", exportToPNG: "Download PNG", exportToCSV: "Download CSV", menu: "Menu", selection: "Selection", selectionZoom: "Selection Zoom", zoomIn: "Zoom In", zoomOut: "Zoom Out", pan: "Panning", reset: "Reset Zoom" } }; var en = { name: name, options: options }; var Options = /*#__PURE__*/function () { function Options() { _classCallCheck(this, Options); this.yAxis = { show: true, showAlways: false, showForNullSeries: true, seriesName: undefined, opposite: false, reversed: false, logarithmic: false, logBase: 10, tickAmount: undefined, forceNiceScale: false, max: undefined, min: undefined, floating: false, decimalsInFloat: undefined, labels: { show: true, minWidth: 0, maxWidth: 160, offsetX: 0, offsetY: 0, align: undefined, rotate: 0, padding: 20, style: { colors: [], fontSize: '11px', fontWeight: 400, fontFamily: undefined, cssClass: '' }, formatter: undefined }, axisBorder: { show: false, color: '#e0e0e0', width: 1, offsetX: 0, offsetY: 0 }, axisTicks: { show: false, color: '#e0e0e0', width: 6, offsetX: 0, offsetY: 0 }, title: { text: undefined, rotate: -90, offsetY: 0, offsetX: 0, style: { color: undefined, fontSize: '11px', fontWeight: 900, fontFamily: undefined, cssClass: '' } }, tooltip: { enabled: false, offsetX: 0 }, crosshairs: { show: true, position: 'front', stroke: { color: '#b6b6b6', width: 1, dashArray: 0 } } }; this.pointAnnotation = { id: undefined, x: 0, y: null, yAxisIndex: 0, seriesIndex: 0, mouseEnter: undefined, mouseLeave: undefined, click: undefined, marker: { size: 4, fillColor: '#fff', strokeWidth: 2, strokeColor: '#333', shape: 'circle', offsetX: 0, offsetY: 0, radius: 2, cssClass: '' }, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'middle', offsetX: 0, offsetY: 0, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2 } } }, customSVG: { // this will be deprecated in the next major version as it is going to be replaced with a better alternative below SVG: undefined, cssClass: undefined, offsetX: 0, offsetY: 0 }, image: { path: undefined, width: 20, height: 20, offsetX: 0, offsetY: 0 } }; this.yAxisAnnotation = { id: undefined, y: 0, y2: null, strokeDashArray: 1, fillColor: '#c2c2c2', borderColor: '#c2c2c2', borderWidth: 1, opacity: 0.3, offsetX: 0, offsetY: 0, width: '100%', yAxisIndex: 0, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'end', position: 'right', offsetX: 0, offsetY: -3, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2 } } } }; this.xAxisAnnotation = { id: undefined, x: 0, x2: null, strokeDashArray: 1, fillColor: '#c2c2c2', borderColor: '#c2c2c2', borderWidth: 1, opacity: 0.3, offsetX: 0, offsetY: 0, label: { borderColor: '#c2c2c2', borderWidth: 1, borderRadius: 2, text: undefined, textAnchor: 'middle', orientation: 'vertical', position: 'top', offsetX: 0, offsetY: 0, mouseEnter: undefined, mouseLeave: undefined, click: undefined, style: { background: '#fff', color: undefined, fontSize: '11px', fontFamily: undefined, fontWeight: 400, cssClass: '', padding: { left: 5, right: 5, top: 2, bottom: 2 } } } }; this.text = { x: 0, y: 0, text: '', textAnchor: 'start', foreColor: undefined, fontSize: '13px', fontFamily: undefined, fontWeight: 400, appendTo: '.apexcharts-annotations', backgroundColor: 'transparent', borderColor: '#c2c2c2', borderRadius: 0, borderWidth: 0, paddingLeft: 4, paddingRight: 4, paddingTop: 2, paddingBottom: 2 }; } _createClass(Options, [{ key: "init", value: function init() { return { annotations: { yaxis: [this.yAxisAnnotation], xaxis: [this.xAxisAnnotation], points: [this.pointAnnotation], texts: [], images: [], shapes: [] }, chart: { animations: { enabled: true, easing: 'easeinout', // linear, easeout, easein, easeinout, swing, bounce, elastic speed: 800, animateGradually: { delay: 150, enabled: true }, dynamicAnimation: { enabled: true, speed: 350 } }, background: 'transparent', locales: [en], defaultLocale: 'en', dropShadow: { enabled: false, enabledOnSeries: undefined, top: 2, left: 2, blur: 4, color: '#000', opacity: 0.35 }, events: { animationEnd: undefined, beforeMount: undefined, mounted: undefined, updated: undefined, click: undefined, mouseMove: undefined, mouseLeave: undefined, xAxisLabelClick: undefined, legendClick: undefined, markerClick: undefined, selection: undefined, dataPointSelection: undefined, dataPointMouseEnter: undefined, dataPointMouseLeave: undefined, beforeZoom: undefined, beforeResetZoom: undefined, zoomed: undefined, scrolled: undefined, brushScrolled: undefined }, foreColor: '#373d3f', fontFamily: 'Helvetica, Arial, sans-serif', height: 'auto', parentHeightOffset: 15, redrawOnParentResize: true, redrawOnWindowResize: true, id: undefined, group: undefined, offsetX: 0, offsetY: 0, selection: { enabled: false, type: 'x', // selectedPoints: undefined, // default datapoints that should be selected automatically fill: { color: '#24292e', opacity: 0.1 }, stroke: { width: 1, color: '#24292e', opacity: 0.4, dashArray: 3 }, xaxis: { min: undefined, max: undefined }, yaxis: { min: undefined, max: undefined } }, sparkline: { enabled: false }, brush: { enabled: false, autoScaleYaxis: true, target: undefined }, stacked: false, stackType: 'normal', toolbar: { show: true, offsetX: 0, offsetY: 0, tools: { download: true, selection: true, zoom: true, zoomin: true, zoomout: true, pan: true, reset: true, customIcons: [] }, export: { csv: { filename: undefined, columnDelimiter: ',', headerCategory: 'category', headerValue: 'value', dateFormatter: function dateFormatter(timestamp) { return new Date(timestamp).toDateString(); } }, png: { filename: undefined }, svg: { filename: undefined } }, autoSelected: 'zoom' // accepts -> zoom, pan, selection }, type: 'line', width: '100%', zoom: { enabled: true, type: 'x', autoScaleYaxis: false, zoomedArea: { fill: { color: '#90CAF9', opacity: 0.4 }, stroke: { color: '#0D47A1', opacity: 0.4, width: 1 } } } }, plotOptions: { area: { fillTo: 'origin' }, bar: { horizontal: false, columnWidth: '70%', // should be in percent 0 - 100 barHeight: '70%', // should be in percent 0 - 100 distributed: false, borderRadius: 0, borderRadiusApplication: 'around', // [around, end] borderRadiusWhenStacked: 'last', // [all, last] rangeBarOverlap: true, rangeBarGroupRows: false, hideZeroBarsWhenGrouped: true, colors: { ranges: [], backgroundBarColors: [], backgroundBarOpacity: 1, backgroundBarRadius: 0 }, dataLabels: { position: 'top', // top, center, bottom maxItems: 100, hideOverflowingLabels: true, orientation: 'horizontal', total: { enabled: false, formatter: undefined, offsetX: 0, offsetY: 0, style: { color: '#373d3f', fontSize: '12px', fontFamily: undefined, fontWeight: 600 } } } }, bubble: { zScaling: true, minBubbleRadius: undefined, maxBubbleRadius: undefined }, candlestick: { colors: { upward: '#00B746', downward: '#EF403C' }, wick: { useFillColor: true } }, boxPlot: { colors: { upper: '#00E396', lower: '#008FFB' } }, heatmap: { radius: 2, enableShades: true, shadeIntensity: 0.5, reverseNegativeShade: false, distributed: false, useFillColorAsStroke: false, colorScale: { inverse: false, ranges: [], min: undefined, max: undefined } }, treemap: { enableShades: true, shadeIntensity: 0.5, distributed: false, reverseNegativeShade: false, useFillColorAsStroke: false, colorScale: { inverse: false, ranges: [], min: undefined, max: undefined } }, radialBar: { inverseOrder: false, startAngle: 0, endAngle: 360, offsetX: 0, offsetY: 0, hollow: { margin: 5, size: '50%', background: 'transparent', image: undefined, imageWidth: 150, imageHeight: 150, imageOffsetX: 0, imageOffsetY: 0, imageClipped: true, position: 'front', dropShadow: { enabled: false, top: 0, left: 0, blur: 3, color: '#000', opacity: 0.5 } }, track: { show: true, startAngle: undefined, endAngle: undefined, background: '#f2f2f2', strokeWidth: '97%', opacity: 1, margin: 5, // margin is in pixels dropShadow: { enabled: false, top: 0, left: 0, blur: 3, color: '#000', opacity: 0.5 } }, dataLabels: { show: true, name: { show: true, fontSize: '16px', fontFamily: undefined, fontWeight: 600, color: undefined, offsetY: 0, formatter: function formatter(val) { return val; } }, value: { show: true, fontSize: '14px', fontFamily: undefined, fontWeight: 400, color: undefined, offsetY: 16, formatter: function formatter(val) { return val + '%'; } }, total: { show: false, label: 'Total', fontSize: '16px', fontWeight: 600, fontFamily: undefined, color: undefined, formatter: function formatter(w) { return w.globals.seriesTotals.reduce(function (a, b) { return a + b; }, 0) / w.globals.series.length + '%'; } } } }, pie: { customScale: 1, offsetX: 0, offsetY: 0, startAngle: 0, endAngle: 360, expandOnClick: true, dataLabels: { // These are the percentage values which are displayed on slice offset: 0, // offset by which labels will move outside minAngleToShowLabel: 10 }, donut: { size: '65%', background: 'transparent', labels: { // These are the inner labels appearing inside donut show: false, name: { show: true, fontSize: '16px', fontFamily: undefined, fontWeight: 600, color: undefined, offsetY: -10, formatter: function formatter(val) { return val; } }, value: { show: true, fontSize: '20px', fontFamily: undefined, fontWeight: 400, color: undefined, offsetY: 10, formatter: function formatter(val) { return val; } }, total: { show: false, showAlways: false, label: 'Total', fontSize: '16px', fontWeight: 400, fontFamily: undefined, color: undefined, formatter: function formatter(w) { return w.globals.seriesTotals.reduce(function (a, b) { return a + b; }, 0); } } } } }, polarArea: { rings: { strokeWidth: 1, strokeColor: '#e8e8e8' }, spokes: { strokeWidth: 1, connectorColors: '#e8e8e8' } }, radar: { size: undefined, offsetX: 0, offsetY: 0, polygons: { // strokeColor: '#e8e8e8', // should be deprecated in the minor version i.e 3.2 strokeWidth: 1, strokeColors: '#e8e8e8', connectorColors: '#e8e8e8', fill: { colors: undefined } } } }, colors: undefined, dataLabels: { enabled: true, enabledOnSeries: undefined, formatter: function formatter(val) { return val !== null ? val : ''; }, textAnchor: 'middle', distributed: false, offsetX: 0, offsetY: 0, style: { fontSize: '12px', fontFamily: undefined, fontWeight: 600, colors: undefined }, background: { enabled: true, foreColor: '#fff', borderRadius: 2, padding: 4, opacity: 0.9, borderWidth: 1, borderColor: '#fff', dropShadow: { enabled: false, top: 1, left: 1, blur: 1, color: '#000', opacity: 0.45 } }, dropShadow: { enabled: false, top: 1, left: 1, blur: 1, color: '#000', opacity: 0.45 } }, fill: { type: 'solid', colors: undefined, // array of colors opacity: 0.85, gradient: { shade: 'dark', type: 'horizontal', shadeIntensity: 0.5, gradientToColors: undefined, inverseColors: true, opacityFrom: 1, opacityTo: 1, stops: [0, 50, 100], colorStops: [] }, image: { src: [], width: undefined, // optional height: undefined // optional }, pattern: { style: 'squares', // String | Array of Strings width: 6, height: 6, strokeWidth: 2 } }, forecastDataPoints: { count: 0, fillOpacity: 0.5, strokeWidth: undefined, dashArray: 4 }, grid: { show: true, borderColor: '#e0e0e0', strokeDashArray: 0, position: 'back', xaxis: { lines: { show: false } }, yaxis: { lines: { show: true } }, row: { colors: undefined, // takes as array which will be repeated on rows opacity: 0.5 }, column: { colors: undefined, // takes an array which will be repeated on columns opacity: 0.5 }, padding: { top: 0, right: 10, bottom: 0, left: 12 } }, labels: [], legend: { show: true, showForSingleSeries: false, showForNullSeries: true, showForZeroSeries: true, floating: false, position: 'bottom', // whether to position legends in 1 of 4 // direction - top, bottom, left, right horizontalAlign: 'center', // when position top/bottom, you can specify whether to align legends left, right or center inverseOrder: false, fontSize: '12px', fontFamily: undefined, fontWeight: 400, width: undefined, height: undefined, formatter: undefined, tooltipHoverFormatter: undefined, offsetX: -20, offsetY: 4, customLegendItems: [], labels: { colors: undefined, useSeriesColors: false }, markers: { width: 12, height: 12, strokeWidth: 0, fillColors: undefined, strokeColor: '#fff', radius: 12, customHTML: undefined, offsetX: 0, offsetY: 0, onClick: undefined }, itemMargin: { horizontal: 5, vertical: 2 }, onItemClick: { toggleDataSeries: true }, onItemHover: { highlightDataSeries: true } }, markers: { discrete: [], size: 0, colors: undefined, //strokeColor: '#fff', // TODO: deprecate in major version 4.0 strokeColors: '#fff', strokeWidth: 2, strokeOpacity: 0.9, strokeDashArray: 0, fillOpacity: 1, shape: 'circle', width: 8, // only applicable when shape is rect/square height: 8, // only applicable when shape is rect/square radius: 2, offsetX: 0, offsetY: 0, onClick: undefined, onDblClick: undefined, showNullDataPoints: true, hover: { size: undefined, sizeOffset: 3 } }, noData: { text: undefined, align: 'center', verticalAlign: 'middle', offsetX: 0, offsetY: 0, style: { color: undefined, fontSize: '14px', fontFamily: undefined } }, responsive: [], // breakpoints should follow ascending order 400, then 700, then 1000 series: undefined, states: { normal: { filter: { type: 'none', value: 0 } }, hover: { filter: { type: 'lighten', value: 0.1 } }, active: { allowMultipleDataPointsSelection: false, filter: { type: 'darken', value: 0.5 } } }, title: { text: undefined, align: 'left', margin: 5, offsetX: 0, offsetY: 0, floating: false, style: { fontSize: '14px', fontWeight: 900, fontFamily: undefined, color: undefined } }, subtitle: { text: undefined, align: 'left', margin: 5, offsetX: 0, offsetY: 30, floating: false, style: { fontSize: '12px', fontWeight: 400, fontFamily: undefined, color: undefined } }, stroke: { show: true, curve: 'smooth', // "smooth" / "straight" / "stepline" lineCap: 'butt', // round, butt , square width: 2, colors: undefined, // array of colors dashArray: 0, // single value or array of values fill: { type: 'solid', colors: undefined, // array of colors opacity: 0.85, gradient: { shade: 'dark', type: 'horizontal', shadeIntensity: 0.5, gradientToColors: undefined, inverseColors: true, opacityFrom: 1, opacityTo: 1, stops: [0, 50, 100], colorStops: [] } } }, tooltip: { enabled: true, enabledOnSeries: undefined, shared: true, followCursor: false, // when disabled, the tooltip will show on top of the series instead of mouse position intersect: false, // when enabled, tooltip will only show when user directly hovers over point inverseOrder: false, custom: undefined, fillSeriesColor: false, theme: 'light', cssClass: '', style: { fontSize: '12px', fontFamily: undefined }, onDatasetHover: { highlightDataSeries: false }, x: { // x value show: true, format: 'dd MMM', // dd/MM, dd MMM yy, dd MMM yyyy formatter: undefined // a custom user supplied formatter function }, y: { formatter: undefined, title: { formatter: function formatter(seriesName) { return seriesName ? seriesName + ': ' : ''; } } }, z: { formatter: undefined, title: 'Size: ' }, marker: { show: true, fillColors: undefined }, items: { display: 'flex' }, fixed: { enabled: false, position: 'topRight', // topRight, topLeft, bottomRight, bottomLeft offsetX: 0, offsetY: 0 } }, xaxis: { type: 'category', categories: [], convertedCatToNumeric: false, // internal property which should not be altered outside offsetX: 0, offsetY: 0, overwriteCategories: undefined, labels: { show: true, rotate: -45, rotateAlways: false, hideOverlappingLabels: true, trim: false, minHeight: undefined, maxHeight: 120, showDuplicates: true, style: { colors: [], fontSize: '12px', fontWeight: 400, fontFamily: undefined, cssClass: '' }, offsetX: 0, offsetY: 0, format: undefined, formatter: undefined, // custom formatter function which will override format datetimeUTC: true, datetimeFormatter: { year: 'yyyy', month: "MMM 'yy", day: 'dd MMM', hour: 'HH:mm', minute: 'HH:mm:ss', second: 'HH:mm:ss' } }, group: { groups: [], style: { colors: [], fontSize: '12px', fontWeight: 400, fontFamily: undefined, cssClass: '' } }, axisBorder: { show: true, color: '#e0e0e0', width: '100%', height: 1, offsetX: 0, offsetY: 0 }, axisTicks: { show: true, color: '#e0e0e0', height: 6, offsetX: 0, offsetY: 0 }, tickAmount: undefined, tickPlacement: 'on', min: undefined, max: undefined, range: undefined, floating: false, decimalsInFloat: undefined, position: 'bottom', title: { text: undefined, offsetX: 0, offsetY: 0, style: { color: undefined, fontSize: '12px', fontWeight: 900, fontFamily: undefined, cssClass: '' } }, crosshairs: { show: true, width: 1, // tickWidth/barWidth or an integer position: 'back', opacity: 0.9, stroke: { color: '#b6b6b6', width: 1, dashArray: 3 }, fill: { type: 'solid', // solid, gradient color: '#B1B9C4', gradient: { colorFrom: '#D8E3F0', colorTo: '#BED1E6', stops: [0, 100], opacityFrom: 0.4, opacityTo: 0.5 } }, dropShadow: { enabled: false, left: 0, top: 0, blur: 1, opacity: 0.4 } }, tooltip: { enabled: true, offsetY: 0, formatter: undefined, style: { fontSize: '12px', fontFamily: undefined } } }, yaxis: this.yAxis, theme: { mode: 'light', palette: 'palette1', // If defined, it will overwrite globals.colors variable monochrome: { // monochrome allows you to select just 1 color and fill out the rest with light/dark shade (intensity can be selected) enabled: false, color: '#008FFB', shadeTo: 'light', shadeIntensity: 0.65 } } }; } }]); return Options; }(); /** * ApexCharts Annotations Class for drawing lines/rects on both xaxis and yaxis. * * @module Annotations **/ var Annotations = /*#__PURE__*/function () { function Annotations(ctx) { _classCallCheck(this, Annotations); this.ctx = ctx; this.w = ctx.w; this.graphics = new Graphics(this.ctx); if (this.w.globals.isBarHorizontal) { this.invertAxis = true; } this.helpers = new Helpers$4(this); this.xAxisAnnotations = new XAnnotations(this); this.yAxisAnnotations = new YAnnotations(this); this.pointsAnnotations = new PointAnnotations(this); if (this.w.globals.isBarHorizontal && this.w.config.yaxis[0].reversed) { this.inversedReversedAxis = true; } this.xDivision = this.w.globals.gridWidth / this.w.globals.dataPoints; } _createClass(Annotations, [{ key: "drawAxesAnnotations", value: function drawAxesAnnotations() { var w = this.w; if (w.globals.axisCharts) { var yAnnotations = this.yAxisAnnotations.drawYAxisAnnotations(); var xAnnotations = this.xAxisAnnotations.drawXAxisAnnotations(); var pointAnnotations = this.pointsAnnotations.drawPointAnnotations(); var initialAnim = w.config.chart.animations.enabled; var annoArray = [yAnnotations, xAnnotations, pointAnnotations]; var annoElArray = [xAnnotations.node, yAnnotations.node, pointAnnotations.node]; for (var i = 0; i < 3; i++) { w.globals.dom.elGraphical.add(annoArray[i]); if (initialAnim && !w.globals.resized && !w.globals.dataChanged) { // fixes apexcharts/apexcharts.js#685 if (w.config.chart.type !== 'scatter' && w.config.chart.type !== 'bubble' && w.globals.dataPoints > 1) { annoElArray[i].classList.add('apexcharts-element-hidden'); } } w.globals.delayedElements.push({ el: annoElArray[i], index: 0 }); } // background sizes needs to be calculated after text is drawn, so calling them last this.helpers.annotationsBackground(); } } }, { key: "drawImageAnnos", value: function drawImageAnnos() { var _this = this; var w = this.w; w.config.annotations.images.map(function (s, index) { _this.addImage(s, index); }); } }, { key: "drawTextAnnos", value: function drawTextAnnos() { var _this2 = this; var w = this.w; w.config.annotations.texts.map(function (t, index) { _this2.addText(t, index); }); } }, { key: "addXaxisAnnotation", value: function addXaxisAnnotation(anno, parent, index) { this.xAxisAnnotations.addXaxisAnnotation(anno, parent, index); } }, { key: "addYaxisAnnotation", value: function addYaxisAnnotation(anno, parent, index) { this.yAxisAnnotations.addYaxisAnnotation(anno, parent, index); } }, { key: "addPointAnnotation", value: function addPointAnnotation(anno, parent, index) { this.pointsAnnotations.addPointAnnotation(anno, parent, index); } }, { key: "addText", value: function addText(params, index) { var x = params.x, y = params.y, text = params.text, textAnchor = params.textAnchor, foreColor = params.foreColor, fontSize = params.fontSize, fontFamily = params.fontFamily, fontWeight = params.fontWeight, cssClass = params.cssClass, backgroundColor = params.backgroundColor, borderWidth = params.borderWidth, strokeDashArray = params.strokeDashArray, borderRadius = params.borderRadius, borderColor = params.borderColor, _params$appendTo = params.appendTo, appendTo = _params$appendTo === void 0 ? '.apexcharts-annotations' : _params$appendTo, _params$paddingLeft = params.paddingLeft, paddingLeft = _params$paddingLeft === void 0 ? 4 : _params$paddingLeft, _params$paddingRight = params.paddingRight, paddingRight = _params$paddingRight === void 0 ? 4 : _params$paddingRight, _params$paddingBottom = params.paddingBottom, paddingBottom = _params$paddingBottom === void 0 ? 2 : _params$paddingBottom, _params$paddingTop = params.paddingTop, paddingTop = _params$paddingTop === void 0 ? 2 : _params$paddingTop; var w = this.w; var elText = this.graphics.drawText({ x: x, y: y, text: text, textAnchor: textAnchor || 'start', fontSize: fontSize || '12px', fontWeight: fontWeight || 'regular', fontFamily: fontFamily || w.config.chart.fontFamily, foreColor: foreColor || w.config.chart.foreColor, cssClass: 'apexcharts-text ' + cssClass ? cssClass : '' }); var parent = w.globals.dom.baseEl.querySelector(appendTo); if (parent) { parent.appendChild(elText.node); } var textRect = elText.bbox(); if (text) { var elRect = this.graphics.drawRect(textRect.x - paddingLeft, textRect.y - paddingTop, textRect.width + paddingLeft + paddingRight, textRect.height + paddingBottom + paddingTop, borderRadius, backgroundColor ? backgroundColor : 'transparent', 1, borderWidth, borderColor, strokeDashArray); parent.insertBefore(elRect.node, elText.node); } } }, { key: "addImage", value: function addImage(params, index) { var w = this.w; var path = params.path, _params$x = params.x, x = _params$x === void 0 ? 0 : _params$x, _params$y = params.y, y = _params$y === void 0 ? 0 : _params$y, _params$width = params.width, width = _params$width === void 0 ? 20 : _params$width, _params$height = params.height, height = _params$height === void 0 ? 20 : _params$height, _params$appendTo2 = params.appendTo, appendTo = _params$appendTo2 === void 0 ? '.apexcharts-annotations' : _params$appendTo2; var img = w.globals.dom.Paper.image(path); img.size(width, height).move(x, y); var parent = w.globals.dom.baseEl.querySelector(appendTo); if (parent) { parent.appendChild(img.node); } return img; } // The addXaxisAnnotation method requires a parent class, and user calling this method externally on the chart instance may not specify parent, hence a different method }, { key: "addXaxisAnnotationExternal", value: function addXaxisAnnotationExternal(params, pushToMemory, context) { this.addAnnotationExternal({ params: params, pushToMemory: pushToMemory, context: context, type: 'xaxis', contextMethod: context.addXaxisAnnotation }); return context; } }, { key: "addYaxisAnnotationExternal", value: function addYaxisAnnotationExternal(params, pushToMemory, context) { this.addAnnotationExternal({ params: params, pushToMemory: pushToMemory, context: context, type: 'yaxis', contextMethod: context.addYaxisAnnotation }); return context; } }, { key: "addPointAnnotationExternal", value: function addPointAnnotationExternal(params, pushToMemory, context) { if (typeof this.invertAxis === 'undefined') { this.invertAxis = context.w.globals.isBarHorizontal; } this.addAnnotationExternal({ params: params, pushToMemory: pushToMemory, context: context, type: 'point', contextMethod: context.addPointAnnotation }); return context; } }, { key: "addAnnotationExternal", value: function addAnnotationExternal(_ref) { var params = _ref.params, pushToMemory = _ref.pushToMemory, context = _ref.context, type = _ref.type, contextMethod = _ref.contextMethod; var me = context; var w = me.w; var parent = w.globals.dom.baseEl.querySelector(".apexcharts-".concat(type, "-annotations")); var index = parent.childNodes.length + 1; var options = new Options(); var axesAnno = Object.assign({}, type === 'xaxis' ? options.xAxisAnnotation : type === 'yaxis' ? options.yAxisAnnotation : options.pointAnnotation); var anno = Utils$1.extend(axesAnno, params); switch (type) { case 'xaxis': this.addXaxisAnnotation(anno, parent, index); break; case 'yaxis': this.addYaxisAnnotation(anno, parent, index); break; case 'point': this.addPointAnnotation(anno, parent, index); break; } // add background var axesAnnoLabel = w.globals.dom.baseEl.querySelector(".apexcharts-".concat(type, "-annotations .apexcharts-").concat(type, "-annotation-label[rel='").concat(index, "']")); var elRect = this.helpers.addBackgroundToAnno(axesAnnoLabel, anno); if (elRect) { parent.insertBefore(elRect.node, axesAnnoLabel); } if (pushToMemory) { w.globals.memory.methodsToExec.push({ context: me, id: anno.id ? anno.id : Utils$1.randomId(), method: contextMethod, label: 'addAnnotation', params: params }); } return context; } }, { key: "clearAnnotations", value: function clearAnnotations(ctx) { var w = ctx.w; var annos = w.globals.dom.baseEl.querySelectorAll('.apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations'); // annotations added externally should be cleared out too w.globals.memory.methodsToExec.map(function (m, i) { if (m.label === 'addText' || m.label === 'addAnnotation') { w.globals.memory.methodsToExec.splice(i, 1); } }); annos = Utils$1.listToArray(annos); // delete the DOM elements Array.prototype.forEach.call(annos, function (a) { while (a.firstChild) { a.removeChild(a.firstChild); } }); } }, { key: "removeAnnotation", value: function removeAnnotation(ctx, id) { var w = ctx.w; var annos = w.globals.dom.baseEl.querySelectorAll(".".concat(id)); if (annos) { w.globals.memory.methodsToExec.map(function (m, i) { if (m.id === id) { w.globals.memory.methodsToExec.splice(i, 1); } }); Array.prototype.forEach.call(annos, function (a) { a.parentElement.removeChild(a); }); } } }]); return Annotations; }(); /** * DateTime Class to manipulate datetime values. * * @module DateTime **/ var DateTime = /*#__PURE__*/function () { function DateTime(ctx) { _classCallCheck(this, DateTime); this.ctx = ctx; this.w = ctx.w; this.months31 = [1, 3, 5, 7, 8, 10, 12]; this.months30 = [2, 4, 6, 9, 11]; this.daysCntOfYear = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]; } _createClass(DateTime, [{ key: "isValidDate", value: function isValidDate(date) { return !isNaN(this.parseDate(date)); } }, { key: "getTimeStamp", value: function getTimeStamp(dateStr) { if (!Date.parse(dateStr)) { return dateStr; } var utc = this.w.config.xaxis.labels.datetimeUTC; return !utc ? new Date(dateStr).getTime() : new Date(new Date(dateStr).toISOString().substr(0, 25)).getTime(); } }, { key: "getDate", value: function getDate(timestamp) { var utc = this.w.config.xaxis.labels.datetimeUTC; return utc ? new Date(new Date(timestamp).toUTCString()) : new Date(timestamp); } }, { key: "parseDate", value: function parseDate(dateStr) { var parsed = Date.parse(dateStr); if (!isNaN(parsed)) { return this.getTimeStamp(dateStr); } var output = Date.parse(dateStr.replace(/-/g, '/').replace(/[a-z]+/gi, ' ')); output = this.getTimeStamp(output); return output; } // This fixes the difference of x-axis labels between chrome/safari // Fixes #1726, #1544, #1485, #1255 }, { key: "parseDateWithTimezone", value: function parseDateWithTimezone(dateStr) { return Date.parse(dateStr.replace(/-/g, '/').replace(/[a-z]+/gi, ' ')); } // http://stackoverflow.com/questions/14638018/current-time-formatting-with-javascript#answer-14638191 }, { key: "formatDate", value: function formatDate(date, format) { var locale = this.w.globals.locale; var utc = this.w.config.xaxis.labels.datetimeUTC; var MMMM = ['\x00'].concat(_toConsumableArray(locale.months)); var MMM = ['\x01'].concat(_toConsumableArray(locale.shortMonths)); var dddd = ['\x02'].concat(_toConsumableArray(locale.days)); var ddd = ['\x03'].concat(_toConsumableArray(locale.shortDays)); function ii(i, len) { var s = i + ''; len = len || 2; while (s.length < len) { s = '0' + s; } return s; } var y = utc ? date.getUTCFullYear() : date.getFullYear(); format = format.replace(/(^|[^\\])yyyy+/g, '$1' + y); format = format.replace(/(^|[^\\])yy/g, '$1' + y.toString().substr(2, 2)); format = format.replace(/(^|[^\\])y/g, '$1' + y); var M = (utc ? date.getUTCMonth() : date.getMonth()) + 1; format = format.replace(/(^|[^\\])MMMM+/g, '$1' + MMMM[0]); format = format.replace(/(^|[^\\])MMM/g, '$1' + MMM[0]); format = format.replace(/(^|[^\\])MM/g, '$1' + ii(M)); format = format.replace(/(^|[^\\])M/g, '$1' + M); var d = utc ? date.getUTCDate() : date.getDate(); format = format.replace(/(^|[^\\])dddd+/g, '$1' + dddd[0]); format = format.replace(/(^|[^\\])ddd/g, '$1' + ddd[0]); format = format.replace(/(^|[^\\])dd/g, '$1' + ii(d)); format = format.replace(/(^|[^\\])d/g, '$1' + d); var H = utc ? date.getUTCHours() : date.getHours(); format = format.replace(/(^|[^\\])HH+/g, '$1' + ii(H)); format = format.replace(/(^|[^\\])H/g, '$1' + H); var h = H > 12 ? H - 12 : H === 0 ? 12 : H; format = format.replace(/(^|[^\\])hh+/g, '$1' + ii(h)); format = format.replace(/(^|[^\\])h/g, '$1' + h); var m = utc ? date.getUTCMinutes() : date.getMinutes(); format = format.replace(/(^|[^\\])mm+/g, '$1' + ii(m)); format = format.replace(/(^|[^\\])m/g, '$1' + m); var s = utc ? date.getUTCSeconds() : date.getSeconds(); format = format.replace(/(^|[^\\])ss+/g, '$1' + ii(s)); format = format.replace(/(^|[^\\])s/g, '$1' + s); var f = utc ? date.getUTCMilliseconds() : date.getMilliseconds(); format = format.replace(/(^|[^\\])fff+/g, '$1' + ii(f, 3)); f = Math.round(f / 10); format = format.replace(/(^|[^\\])ff/g, '$1' + ii(f)); f = Math.round(f / 10); format = format.replace(/(^|[^\\])f/g, '$1' + f); var T = H < 12 ? 'AM' : 'PM'; format = format.replace(/(^|[^\\])TT+/g, '$1' + T); format = format.replace(/(^|[^\\])T/g, '$1' + T.charAt(0)); var t = T.toLowerCase(); format = format.replace(/(^|[^\\])tt+/g, '$1' + t); format = format.replace(/(^|[^\\])t/g, '$1' + t.charAt(0)); var tz = -date.getTimezoneOffset(); var K = utc || !tz ? 'Z' : tz > 0 ? '+' : '-'; if (!utc) { tz = Math.abs(tz); var tzHrs = Math.floor(tz / 60); var tzMin = tz % 60; K += ii(tzHrs) + ':' + ii(tzMin); } format = format.replace(/(^|[^\\])K/g, '$1' + K); var day = (utc ? date.getUTCDay() : date.getDay()) + 1; format = format.replace(new RegExp(dddd[0], 'g'), dddd[day]); format = format.replace(new RegExp(ddd[0], 'g'), ddd[day]); format = format.replace(new RegExp(MMMM[0], 'g'), MMMM[M]); format = format.replace(new RegExp(MMM[0], 'g'), MMM[M]); format = format.replace(/\\(.)/g, '$1'); return format; } }, { key: "getTimeUnitsfromTimestamp", value: function getTimeUnitsfromTimestamp(minX, maxX, utc) { var w = this.w; if (w.config.xaxis.min !== undefined) { minX = w.config.xaxis.min; } if (w.config.xaxis.max !== undefined) { maxX = w.config.xaxis.max; } var tsMin = this.getDate(minX); var tsMax = this.getDate(maxX); var minD = this.formatDate(tsMin, 'yyyy MM dd HH mm ss fff').split(' '); var maxD = this.formatDate(tsMax, 'yyyy MM dd HH mm ss fff').split(' '); return { minMillisecond: parseInt(minD[6], 10), maxMillisecond: parseInt(maxD[6], 10), minSecond: parseInt(minD[5], 10), maxSecond: parseInt(maxD[5], 10), minMinute: parseInt(minD[4], 10), maxMinute: parseInt(maxD[4], 10), minHour: parseInt(minD[3], 10), maxHour: parseInt(maxD[3], 10), minDate: parseInt(minD[2], 10), maxDate: parseInt(maxD[2], 10), minMonth: parseInt(minD[1], 10) - 1, maxMonth: parseInt(maxD[1], 10) - 1, minYear: parseInt(minD[0], 10), maxYear: parseInt(maxD[0], 10) }; } }, { key: "isLeapYear", value: function isLeapYear(year) { return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; } }, { key: "calculcateLastDaysOfMonth", value: function calculcateLastDaysOfMonth(month, year, subtract) { var days = this.determineDaysOfMonths(month, year); // whatever days we get, subtract the number of days asked return days - subtract; } }, { key: "determineDaysOfYear", value: function determineDaysOfYear(year) { var days = 365; if (this.isLeapYear(year)) { days = 366; } return days; } }, { key: "determineRemainingDaysOfYear", value: function determineRemainingDaysOfYear(year, month, date) { var dayOfYear = this.daysCntOfYear[month] + date; if (month > 1 && this.isLeapYear()) dayOfYear++; return dayOfYear; } }, { key: "determineDaysOfMonths", value: function determineDaysOfMonths(month, year) { var days = 30; month = Utils$1.monthMod(month); switch (true) { case this.months30.indexOf(month) > -1: if (month === 2) { if (this.isLeapYear(year)) { days = 29; } else { days = 28; } } break; case this.months31.indexOf(month) > -1: days = 31; break; default: days = 31; break; } return days; } }]); return DateTime; }(); /** * ApexCharts Formatter Class for setting value formatters for axes as well as tooltips. * * @module Formatters **/ var Formatters = /*#__PURE__*/function () { function Formatters(ctx) { _classCallCheck(this, Formatters); this.ctx = ctx; this.w = ctx.w; this.tooltipKeyFormat = 'dd MMM'; } _createClass(Formatters, [{ key: "xLabelFormat", value: function xLabelFormat(fn, val, timestamp, opts) { var w = this.w; if (w.config.xaxis.type === 'datetime') { if (w.config.xaxis.labels.formatter === undefined) { // if user has not specified a custom formatter, use the default tooltip.x.format if (w.config.tooltip.x.formatter === undefined) { var datetimeObj = new DateTime(this.ctx); return datetimeObj.formatDate(datetimeObj.getDate(val), w.config.tooltip.x.format); } } } return fn(val, timestamp, opts); } }, { key: "defaultGeneralFormatter", value: function defaultGeneralFormatter(val) { if (Array.isArray(val)) { return val.map(function (v) { return v; }); } else { return val; } } }, { key: "defaultYFormatter", value: function defaultYFormatter(v, yaxe, i) { var w = this.w; if (Utils$1.isNumber(v)) { if (w.globals.yValueDecimal !== 0) { v = v.toFixed(yaxe.decimalsInFloat !== undefined ? yaxe.decimalsInFloat : w.globals.yValueDecimal); } else if (w.globals.maxYArr[i] - w.globals.minYArr[i] < 5) { v = v.toFixed(1); } else { v = v.toFixed(0); } } return v; } }, { key: "setLabelFormatters", value: function setLabelFormatters() { var _this = this; var w = this.w; w.globals.xaxisTooltipFormatter = function (val) { return _this.defaultGeneralFormatter(val); }; w.globals.ttKeyFormatter = function (val) { return _this.defaultGeneralFormatter(val); }; w.globals.ttZFormatter = function (val) { return val; }; w.globals.legendFormatter = function (val) { return _this.defaultGeneralFormatter(val); }; // formatter function will always overwrite format property if (w.config.xaxis.labels.formatter !== undefined) { w.globals.xLabelFormatter = w.config.xaxis.labels.formatter; } else { w.globals.xLabelFormatter = function (val) { if (Utils$1.isNumber(val)) { if (!w.config.xaxis.convertedCatToNumeric && w.config.xaxis.type === 'numeric') { if (Utils$1.isNumber(w.config.xaxis.decimalsInFloat)) { return val.toFixed(w.config.xaxis.decimalsInFloat); } else { var diff = w.globals.maxX - w.globals.minX; if (diff > 0 && diff < 100) { return val.toFixed(1); } return val.toFixed(0); } } if (w.globals.isBarHorizontal) { var range = w.globals.maxY - w.globals.minYArr; if (range < 4) { return val.toFixed(1); } } return val.toFixed(0); } return val; }; } if (typeof w.config.tooltip.x.formatter === 'function') { w.globals.ttKeyFormatter = w.config.tooltip.x.formatter; } else { w.globals.ttKeyFormatter = w.globals.xLabelFormatter; } if (typeof w.config.xaxis.tooltip.formatter === 'function') { w.globals.xaxisTooltipFormatter = w.config.xaxis.tooltip.formatter; } if (Array.isArray(w.config.tooltip.y)) { w.globals.ttVal = w.config.tooltip.y; } else { if (w.config.tooltip.y.formatter !== undefined) { w.globals.ttVal = w.config.tooltip.y; } } if (w.config.tooltip.z.formatter !== undefined) { w.globals.ttZFormatter = w.config.tooltip.z.formatter; } // legend formatter - if user wants to append any global values of series to legend text if (w.config.legend.formatter !== undefined) { w.globals.legendFormatter = w.config.legend.formatter; } // formatter function will always overwrite format property w.config.yaxis.forEach(function (yaxe, i) { if (yaxe.labels.formatter !== undefined) { w.globals.yLabelFormatters[i] = yaxe.labels.formatter; } else { w.globals.yLabelFormatters[i] = function (val) { if (!w.globals.xyCharts) return val; if (Array.isArray(val)) { return val.map(function (v) { return _this.defaultYFormatter(v, yaxe, i); }); } else { return _this.defaultYFormatter(val, yaxe, i); } }; } }); return w.globals; } }, { key: "heatmapLabelFormatters", value: function heatmapLabelFormatters() { var w = this.w; if (w.config.chart.type === 'heatmap') { w.globals.yAxisScale[0].result = w.globals.seriesNames.slice(); // get the longest string from the labels array and also apply label formatter to it var longest = w.globals.seriesNames.reduce(function (a, b) { return a.length > b.length ? a : b; }, 0); w.globals.yAxisScale[0].niceMax = longest; w.globals.yAxisScale[0].niceMin = longest; } } }]); return Formatters; }(); /** * ApexCharts Default Class for setting default options for all chart types. * * @module Defaults **/ var getRangeValues = function getRangeValues(_ref) { var _w$config$series$seri; var isTimeline = _ref.isTimeline, ctx = _ref.ctx, seriesIndex = _ref.seriesIndex, dataPointIndex = _ref.dataPointIndex, y1 = _ref.y1, y2 = _ref.y2, w = _ref.w; var start = w.globals.seriesRangeStart[seriesIndex][dataPointIndex]; var end = w.globals.seriesRangeEnd[seriesIndex][dataPointIndex]; var ylabel = w.globals.labels[dataPointIndex]; var seriesName = w.config.series[seriesIndex].name ? w.config.series[seriesIndex].name : ''; var yLbFormatter = w.globals.ttKeyFormatter; var yLbTitleFormatter = w.config.tooltip.y.title.formatter; var opts = { w: w, seriesIndex: seriesIndex, dataPointIndex: dataPointIndex, start: start, end: end }; if (typeof yLbTitleFormatter === 'function') { seriesName = yLbTitleFormatter(seriesName, opts); } if ((_w$config$series$seri = w.config.series[seriesIndex].data[dataPointIndex]) !== null && _w$config$series$seri !== void 0 && _w$config$series$seri.x) { ylabel = w.config.series[seriesIndex].data[dataPointIndex].x; } if (!isTimeline) { if (w.config.xaxis.type === 'datetime') { var xFormat = new Formatters(ctx); ylabel = xFormat.xLabelFormat(w.globals.ttKeyFormatter, ylabel, ylabel, { i: undefined, dateFormatter: new DateTime(ctx).formatDate, w: w }); } } if (typeof yLbFormatter === 'function') { ylabel = yLbFormatter(ylabel, opts); } if (Number.isFinite(y1) && Number.isFinite(y2)) { start = y1; end = y2; } var startVal = ''; var endVal = ''; var color = w.globals.colors[seriesIndex]; if (w.config.tooltip.x.formatter === undefined) { if (w.config.xaxis.type === 'datetime') { var datetimeObj = new DateTime(ctx); startVal = datetimeObj.formatDate(datetimeObj.getDate(start), w.config.tooltip.x.format); endVal = datetimeObj.formatDate(datetimeObj.getDate(end), w.config.tooltip.x.format); } else { startVal = start; endVal = end; } } else { startVal = w.config.tooltip.x.formatter(start); endVal = w.config.tooltip.x.formatter(end); } return { start: start, end: end, startVal: startVal, endVal: endVal, ylabel: ylabel, color: color, seriesName: seriesName }; }; var buildRangeTooltipHTML = function buildRangeTooltipHTML(opts) { var color = opts.color, seriesName = opts.seriesName, ylabel = opts.ylabel, start = opts.start, end = opts.end, seriesIndex = opts.seriesIndex, dataPointIndex = opts.dataPointIndex; var formatter = opts.ctx.tooltip.tooltipLabels.getFormatters(seriesIndex); start = formatter.yLbFormatter(start); end = formatter.yLbFormatter(end); var val = formatter.yLbFormatter(opts.w.globals.series[seriesIndex][dataPointIndex]); var valueHTML = ''; var rangeValues = "\n ".concat(start, "\n - \n ").concat(end, "\n "); if (opts.w.globals.comboCharts) { if (opts.w.config.series[seriesIndex].type === 'rangeArea' || opts.w.config.series[seriesIndex].type === 'rangeBar') { valueHTML = rangeValues; } else { valueHTML = "".concat(val, ""); } } else { valueHTML = rangeValues; } return '
    ' + '
    ' + (seriesName ? seriesName : '') + '
    ' + '
    ' + ylabel + ': ' + valueHTML + '
    ' + '
    '; }; var Defaults = /*#__PURE__*/function () { function Defaults(opts) { _classCallCheck(this, Defaults); this.opts = opts; } _createClass(Defaults, [{ key: "line", value: function line() { return { chart: { animations: { easing: 'swing' } }, dataLabels: { enabled: false }, stroke: { width: 5, curve: 'straight' }, markers: { size: 0, hover: { sizeOffset: 6 } }, xaxis: { crosshairs: { width: 1 } } }; } }, { key: "sparkline", value: function sparkline(defaults) { this.opts.yaxis[0].show = false; this.opts.yaxis[0].title.text = ''; this.opts.yaxis[0].axisBorder.show = false; this.opts.yaxis[0].axisTicks.show = false; this.opts.yaxis[0].floating = true; var ret = { grid: { show: false, padding: { left: 0, right: 0, top: 0, bottom: 0 } }, legend: { show: false }, xaxis: { labels: { show: false }, tooltip: { enabled: false }, axisBorder: { show: false }, axisTicks: { show: false } }, chart: { toolbar: { show: false }, zoom: { enabled: false } }, dataLabels: { enabled: false } }; return Utils$1.extend(defaults, ret); } }, { key: "bar", value: function bar() { return { chart: { stacked: false, animations: { easing: 'swing' } }, plotOptions: { bar: { dataLabels: { position: 'center' } } }, dataLabels: { style: { colors: ['#fff'] }, background: { enabled: false } }, stroke: { width: 0, lineCap: 'round' }, fill: { opacity: 0.85 }, legend: { markers: { shape: 'square', radius: 2, size: 8 } }, tooltip: { shared: false, intersect: true }, xaxis: { tooltip: { enabled: false }, tickPlacement: 'between', crosshairs: { width: 'barWidth', position: 'back', fill: { type: 'gradient' }, dropShadow: { enabled: false }, stroke: { width: 0 } } } }; } }, { key: "candlestick", value: function candlestick() { var _this = this; return { stroke: { width: 1, colors: ['#333'] }, fill: { opacity: 1 }, dataLabels: { enabled: false }, tooltip: { shared: true, custom: function custom(_ref2) { var seriesIndex = _ref2.seriesIndex, dataPointIndex = _ref2.dataPointIndex, w = _ref2.w; return _this._getBoxTooltip(w, seriesIndex, dataPointIndex, ['Open', 'High', '', 'Low', 'Close'], 'candlestick'); } }, states: { active: { filter: { type: 'none' } } }, xaxis: { crosshairs: { width: 1 } } }; } }, { key: "boxPlot", value: function boxPlot() { var _this2 = this; return { chart: { animations: { dynamicAnimation: { enabled: false } } }, stroke: { width: 1, colors: ['#24292e'] }, dataLabels: { enabled: false }, tooltip: { shared: true, custom: function custom(_ref3) { var seriesIndex = _ref3.seriesIndex, dataPointIndex = _ref3.dataPointIndex, w = _ref3.w; return _this2._getBoxTooltip(w, seriesIndex, dataPointIndex, ['Minimum', 'Q1', 'Median', 'Q3', 'Maximum'], 'boxPlot'); } }, markers: { size: 5, strokeWidth: 1, strokeColors: '#111' }, xaxis: { crosshairs: { width: 1 } } }; } }, { key: "rangeBar", value: function rangeBar() { var handleTimelineTooltip = function handleTimelineTooltip(opts) { var _getRangeValues = getRangeValues(_objectSpread2(_objectSpread2({}, opts), {}, { isTimeline: true })), color = _getRangeValues.color, seriesName = _getRangeValues.seriesName, ylabel = _getRangeValues.ylabel, startVal = _getRangeValues.startVal, endVal = _getRangeValues.endVal; return buildRangeTooltipHTML(_objectSpread2(_objectSpread2({}, opts), {}, { color: color, seriesName: seriesName, ylabel: ylabel, start: startVal, end: endVal })); }; var handleRangeColumnTooltip = function handleRangeColumnTooltip(opts) { var _getRangeValues2 = getRangeValues(opts), color = _getRangeValues2.color, seriesName = _getRangeValues2.seriesName, ylabel = _getRangeValues2.ylabel, start = _getRangeValues2.start, end = _getRangeValues2.end; return buildRangeTooltipHTML(_objectSpread2(_objectSpread2({}, opts), {}, { color: color, seriesName: seriesName, ylabel: ylabel, start: start, end: end })); }; return { stroke: { width: 0, lineCap: 'square' }, plotOptions: { bar: { borderRadius: 0, dataLabels: { position: 'center' } } }, dataLabels: { enabled: false, formatter: function formatter(val, _ref4) { _ref4.ctx; var seriesIndex = _ref4.seriesIndex, dataPointIndex = _ref4.dataPointIndex, w = _ref4.w; var getVal = function getVal() { var start = w.globals.seriesRangeStart[seriesIndex][dataPointIndex]; var end = w.globals.seriesRangeEnd[seriesIndex][dataPointIndex]; return end - start; }; if (w.globals.comboCharts) { if (w.config.series[seriesIndex].type === 'rangeBar' || w.config.series[seriesIndex].type === 'rangeArea') { return getVal(); } else { return val; } } else { return getVal(); } }, background: { enabled: false }, style: { colors: ['#fff'] } }, tooltip: { shared: false, followCursor: true, custom: function custom(opts) { if (opts.w.config.plotOptions && opts.w.config.plotOptions.bar && opts.w.config.plotOptions.bar.horizontal) { return handleTimelineTooltip(opts); } else { return handleRangeColumnTooltip(opts); } } }, xaxis: { tickPlacement: 'between', tooltip: { enabled: false }, crosshairs: { stroke: { width: 0 } } } }; } }, { key: "area", value: function area() { return { stroke: { width: 4, fill: { type: 'solid', gradient: { inverseColors: false, shade: 'light', type: 'vertical', opacityFrom: 0.65, opacityTo: 0.5, stops: [0, 100, 100] } } }, fill: { type: 'gradient', gradient: { inverseColors: false, shade: 'light', type: 'vertical', opacityFrom: 0.65, opacityTo: 0.5, stops: [0, 100, 100] } }, markers: { size: 0, hover: { sizeOffset: 6 } }, tooltip: { followCursor: false } }; } }, { key: "rangeArea", value: function rangeArea() { var handleRangeAreaTooltip = function handleRangeAreaTooltip(opts) { var _getRangeValues3 = getRangeValues(opts), color = _getRangeValues3.color, seriesName = _getRangeValues3.seriesName, ylabel = _getRangeValues3.ylabel, start = _getRangeValues3.start, end = _getRangeValues3.end; return buildRangeTooltipHTML(_objectSpread2(_objectSpread2({}, opts), {}, { color: color, seriesName: seriesName, ylabel: ylabel, start: start, end: end })); }; return { stroke: { curve: 'straight', width: 0 }, fill: { type: 'solid', opacity: 0.6 }, markers: { size: 0 }, states: { hover: { filter: { type: 'none' } }, active: { filter: { type: 'none' } } }, tooltip: { intersect: false, shared: true, followCursor: true, custom: function custom(opts) { return handleRangeAreaTooltip(opts); } } }; } }, { key: "brush", value: function brush(defaults) { var ret = { chart: { toolbar: { autoSelected: 'selection', show: false }, zoom: { enabled: false } }, dataLabels: { enabled: false }, stroke: { width: 1 }, tooltip: { enabled: false }, xaxis: { tooltip: { enabled: false } } }; return Utils$1.extend(defaults, ret); } }, { key: "stacked100", value: function stacked100(opts) { opts.dataLabels = opts.dataLabels || {}; opts.dataLabels.formatter = opts.dataLabels.formatter || undefined; var existingDataLabelFormatter = opts.dataLabels.formatter; opts.yaxis.forEach(function (yaxe, index) { opts.yaxis[index].min = 0; opts.yaxis[index].max = 100; }); var isBar = opts.chart.type === 'bar'; if (isBar) { opts.dataLabels.formatter = existingDataLabelFormatter || function (val) { if (typeof val === 'number') { return val ? val.toFixed(0) + '%' : val; } return val; }; } return opts; } }, { key: "stackedBars", value: function stackedBars() { var barDefaults = this.bar(); return _objectSpread2(_objectSpread2({}, barDefaults), {}, { plotOptions: _objectSpread2(_objectSpread2({}, barDefaults.plotOptions), {}, { bar: _objectSpread2(_objectSpread2({}, barDefaults.plotOptions.bar), {}, { borderRadiusApplication: 'end', borderRadiusWhenStacked: 'last' }) }) }); } // This function removes the left and right spacing in chart for line/area/scatter if xaxis type = category for those charts by converting xaxis = numeric. Numeric/Datetime xaxis prevents the unnecessary spacing in the left/right of the chart area }, { key: "convertCatToNumeric", value: function convertCatToNumeric(opts) { opts.xaxis.convertedCatToNumeric = true; return opts; } }, { key: "convertCatToNumericXaxis", value: function convertCatToNumericXaxis(opts, ctx, cats) { opts.xaxis.type = 'numeric'; opts.xaxis.labels = opts.xaxis.labels || {}; opts.xaxis.labels.formatter = opts.xaxis.labels.formatter || function (val) { return Utils$1.isNumber(val) ? Math.floor(val) : val; }; var defaultFormatter = opts.xaxis.labels.formatter; var labels = opts.xaxis.categories && opts.xaxis.categories.length ? opts.xaxis.categories : opts.labels; if (cats && cats.length) { labels = cats.map(function (c) { return Array.isArray(c) ? c : String(c); }); } if (labels && labels.length) { opts.xaxis.labels.formatter = function (val) { return Utils$1.isNumber(val) ? defaultFormatter(labels[Math.floor(val) - 1]) : defaultFormatter(val); }; } opts.xaxis.categories = []; opts.labels = []; opts.xaxis.tickAmount = opts.xaxis.tickAmount || 'dataPoints'; return opts; } }, { key: "bubble", value: function bubble() { return { dataLabels: { style: { colors: ['#fff'] } }, tooltip: { shared: false, intersect: true }, xaxis: { crosshairs: { width: 0 } }, fill: { type: 'solid', gradient: { shade: 'light', inverse: true, shadeIntensity: 0.55, opacityFrom: 0.4, opacityTo: 0.8 } } }; } }, { key: "scatter", value: function scatter() { return { dataLabels: { enabled: false }, tooltip: { shared: false, intersect: true }, markers: { size: 6, strokeWidth: 1, hover: { sizeOffset: 2 } } }; } }, { key: "heatmap", value: function heatmap() { return { chart: { stacked: false }, fill: { opacity: 1 }, dataLabels: { style: { colors: ['#fff'] } }, stroke: { colors: ['#fff'] }, tooltip: { followCursor: true, marker: { show: false }, x: { show: false } }, legend: { position: 'top', markers: { shape: 'square', size: 10, offsetY: 2 } }, grid: { padding: { right: 20 } } }; } }, { key: "treemap", value: function treemap() { return { chart: { zoom: { enabled: false } }, dataLabels: { style: { fontSize: 14, fontWeight: 600, colors: ['#fff'] } }, stroke: { show: true, width: 2, colors: ['#fff'] }, legend: { show: false }, fill: { gradient: { stops: [0, 100] } }, tooltip: { followCursor: true, x: { show: false } }, grid: { padding: { left: 0, right: 0 } }, xaxis: { crosshairs: { show: false }, tooltip: { enabled: false } } }; } }, { key: "pie", value: function pie() { return { chart: { toolbar: { show: false } }, plotOptions: { pie: { donut: { labels: { show: false } } } }, dataLabels: { formatter: function formatter(val) { return val.toFixed(1) + '%'; }, style: { colors: ['#fff'] }, background: { enabled: false }, dropShadow: { enabled: true } }, stroke: { colors: ['#fff'] }, fill: { opacity: 1, gradient: { shade: 'light', stops: [0, 100] } }, tooltip: { theme: 'dark', fillSeriesColor: true }, legend: { position: 'right' } }; } }, { key: "donut", value: function donut() { return { chart: { toolbar: { show: false } }, dataLabels: { formatter: function formatter(val) { return val.toFixed(1) + '%'; }, style: { colors: ['#fff'] }, background: { enabled: false }, dropShadow: { enabled: true } }, stroke: { colors: ['#fff'] }, fill: { opacity: 1, gradient: { shade: 'light', shadeIntensity: 0.35, stops: [80, 100], opacityFrom: 1, opacityTo: 1 } }, tooltip: { theme: 'dark', fillSeriesColor: true }, legend: { position: 'right' } }; } }, { key: "polarArea", value: function polarArea() { this.opts.yaxis[0].tickAmount = this.opts.yaxis[0].tickAmount ? this.opts.yaxis[0].tickAmount : 6; return { chart: { toolbar: { show: false } }, dataLabels: { formatter: function formatter(val) { return val.toFixed(1) + '%'; }, enabled: false }, stroke: { show: true, width: 2 }, fill: { opacity: 0.7 }, tooltip: { theme: 'dark', fillSeriesColor: true }, legend: { position: 'right' } }; } }, { key: "radar", value: function radar() { this.opts.yaxis[0].labels.offsetY = this.opts.yaxis[0].labels.offsetY ? this.opts.yaxis[0].labels.offsetY : 6; return { dataLabels: { enabled: false, style: { fontSize: '11px' } }, stroke: { width: 2 }, markers: { size: 3, strokeWidth: 1, strokeOpacity: 1 }, fill: { opacity: 0.2 }, tooltip: { shared: false, intersect: true, followCursor: true }, grid: { show: false }, xaxis: { labels: { formatter: function formatter(val) { return val; }, style: { colors: ['#a8a8a8'], fontSize: '11px' } }, tooltip: { enabled: false }, crosshairs: { show: false } } }; } }, { key: "radialBar", value: function radialBar() { return { chart: { animations: { dynamicAnimation: { enabled: true, speed: 800 } }, toolbar: { show: false } }, fill: { gradient: { shade: 'dark', shadeIntensity: 0.4, inverseColors: false, type: 'diagonal2', opacityFrom: 1, opacityTo: 1, stops: [70, 98, 100] } }, legend: { show: false, position: 'right' }, tooltip: { enabled: false, fillSeriesColor: true } }; } }, { key: "_getBoxTooltip", value: function _getBoxTooltip(w, seriesIndex, dataPointIndex, labels, chartType) { var o = w.globals.seriesCandleO[seriesIndex][dataPointIndex]; var h = w.globals.seriesCandleH[seriesIndex][dataPointIndex]; var m = w.globals.seriesCandleM[seriesIndex][dataPointIndex]; var l = w.globals.seriesCandleL[seriesIndex][dataPointIndex]; var c = w.globals.seriesCandleC[seriesIndex][dataPointIndex]; if (w.config.series[seriesIndex].type && w.config.series[seriesIndex].type !== chartType) { return "
    \n ".concat(w.config.series[seriesIndex].name ? w.config.series[seriesIndex].name : 'series-' + (seriesIndex + 1), ": ").concat(w.globals.series[seriesIndex][dataPointIndex], "\n
    "); } else { return "
    ") + "
    ".concat(labels[0], ": ") + o + '
    ' + "
    ".concat(labels[1], ": ") + h + '
    ' + (m ? "
    ".concat(labels[2], ": ") + m + '
    ' : '') + "
    ".concat(labels[3], ": ") + l + '
    ' + "
    ".concat(labels[4], ": ") + c + '
    ' + '
    '; } } }]); return Defaults; }(); /** * ApexCharts Config Class for extending user options with pre-defined ApexCharts config. * * @module Config **/ var Config = /*#__PURE__*/function () { function Config(opts) { _classCallCheck(this, Config); this.opts = opts; } _createClass(Config, [{ key: "init", value: function init(_ref) { var responsiveOverride = _ref.responsiveOverride; var opts = this.opts; var options = new Options(); var defaults = new Defaults(opts); this.chartType = opts.chart.type; opts = this.extendYAxis(opts); opts = this.extendAnnotations(opts); var config = options.init(); var newDefaults = {}; if (opts && _typeof(opts) === 'object') { var chartDefaults = {}; var chartTypes = ['line', 'area', 'bar', 'candlestick', 'boxPlot', 'rangeBar', 'rangeArea', 'bubble', 'scatter', 'heatmap', 'treemap', 'pie', 'polarArea', 'donut', 'radar', 'radialBar']; if (chartTypes.indexOf(opts.chart.type) !== -1) { chartDefaults = defaults[opts.chart.type](); } else { chartDefaults = defaults.line(); } if (opts.chart.stacked && opts.chart.type === 'bar') { chartDefaults = defaults.stackedBars(); } if (opts.chart.brush && opts.chart.brush.enabled) { chartDefaults = defaults.brush(chartDefaults); } if (opts.chart.stacked && opts.chart.stackType === '100%') { opts = defaults.stacked100(opts); } // If user has specified a dark theme, make the tooltip dark too this.checkForDarkTheme(window.Apex); // check global window Apex options this.checkForDarkTheme(opts); // check locally passed options opts.xaxis = opts.xaxis || window.Apex.xaxis || {}; // an important boolean needs to be set here // otherwise all the charts will have this flag set to true window.Apex.xaxis is set globally if (!responsiveOverride) { opts.xaxis.convertedCatToNumeric = false; } opts = this.checkForCatToNumericXAxis(this.chartType, chartDefaults, opts); if (opts.chart.sparkline && opts.chart.sparkline.enabled || window.Apex.chart && window.Apex.chart.sparkline && window.Apex.chart.sparkline.enabled) { chartDefaults = defaults.sparkline(chartDefaults); } newDefaults = Utils$1.extend(config, chartDefaults); } // config should cascade in this fashion // default-config < global-apex-variable-config < user-defined-config // get GLOBALLY defined options and merge with the default config var mergedWithDefaultConfig = Utils$1.extend(newDefaults, window.Apex); // get the merged config and extend with user defined config config = Utils$1.extend(mergedWithDefaultConfig, opts); // some features are not supported. those mismatches should be handled config = this.handleUserInputErrors(config); return config; } }, { key: "checkForCatToNumericXAxis", value: function checkForCatToNumericXAxis(chartType, chartDefaults, opts) { var defaults = new Defaults(opts); var isBarHorizontal = (chartType === 'bar' || chartType === 'boxPlot') && opts.plotOptions && opts.plotOptions.bar && opts.plotOptions.bar.horizontal; var unsupportedZoom = chartType === 'pie' || chartType === 'polarArea' || chartType === 'donut' || chartType === 'radar' || chartType === 'radialBar' || chartType === 'heatmap'; var notNumericXAxis = opts.xaxis.type !== 'datetime' && opts.xaxis.type !== 'numeric'; var tickPlacement = opts.xaxis.tickPlacement ? opts.xaxis.tickPlacement : chartDefaults.xaxis && chartDefaults.xaxis.tickPlacement; if (!isBarHorizontal && !unsupportedZoom && notNumericXAxis && tickPlacement !== 'between') { opts = defaults.convertCatToNumeric(opts); } return opts; } }, { key: "extendYAxis", value: function extendYAxis(opts, w) { var options = new Options(); if (typeof opts.yaxis === 'undefined' || !opts.yaxis || Array.isArray(opts.yaxis) && opts.yaxis.length === 0) { opts.yaxis = {}; } // extend global yaxis config (only if object is provided / not an array) if (opts.yaxis.constructor !== Array && window.Apex.yaxis && window.Apex.yaxis.constructor !== Array) { opts.yaxis = Utils$1.extend(opts.yaxis, window.Apex.yaxis); } // as we can't extend nested object's array with extend, we need to do it first // user can provide either an array or object in yaxis config if (opts.yaxis.constructor !== Array) { // convert the yaxis to array if user supplied object opts.yaxis = [Utils$1.extend(options.yAxis, opts.yaxis)]; } else { opts.yaxis = Utils$1.extendArray(opts.yaxis, options.yAxis); } var isLogY = false; opts.yaxis.forEach(function (y) { if (y.logarithmic) { isLogY = true; } }); var series = opts.series; if (w && !series) { series = w.config.series; } // A logarithmic chart works correctly when each series has a corresponding y-axis // If this is not the case, we manually create yaxis for multi-series log chart if (isLogY && series.length !== opts.yaxis.length && series.length) { opts.yaxis = series.map(function (s, i) { if (!s.name) { series[i].name = "series-".concat(i + 1); } if (opts.yaxis[i]) { opts.yaxis[i].seriesName = series[i].name; return opts.yaxis[i]; } else { var newYaxis = Utils$1.extend(options.yAxis, opts.yaxis[0]); newYaxis.show = false; return newYaxis; } }); } if (isLogY && series.length > 1 && series.length !== opts.yaxis.length) { console.warn('A multi-series logarithmic chart should have equal number of series and y-axes. Please make sure to equalize both.'); } return opts; } // annotations also accepts array, so we need to extend them manually }, { key: "extendAnnotations", value: function extendAnnotations(opts) { if (typeof opts.annotations === 'undefined') { opts.annotations = {}; opts.annotations.yaxis = []; opts.annotations.xaxis = []; opts.annotations.points = []; } opts = this.extendYAxisAnnotations(opts); opts = this.extendXAxisAnnotations(opts); opts = this.extendPointAnnotations(opts); return opts; } }, { key: "extendYAxisAnnotations", value: function extendYAxisAnnotations(opts) { var options = new Options(); opts.annotations.yaxis = Utils$1.extendArray(typeof opts.annotations.yaxis !== 'undefined' ? opts.annotations.yaxis : [], options.yAxisAnnotation); return opts; } }, { key: "extendXAxisAnnotations", value: function extendXAxisAnnotations(opts) { var options = new Options(); opts.annotations.xaxis = Utils$1.extendArray(typeof opts.annotations.xaxis !== 'undefined' ? opts.annotations.xaxis : [], options.xAxisAnnotation); return opts; } }, { key: "extendPointAnnotations", value: function extendPointAnnotations(opts) { var options = new Options(); opts.annotations.points = Utils$1.extendArray(typeof opts.annotations.points !== 'undefined' ? opts.annotations.points : [], options.pointAnnotation); return opts; } }, { key: "checkForDarkTheme", value: function checkForDarkTheme(opts) { if (opts.theme && opts.theme.mode === 'dark') { if (!opts.tooltip) { opts.tooltip = {}; } if (opts.tooltip.theme !== 'light') { opts.tooltip.theme = 'dark'; } if (!opts.chart.foreColor) { opts.chart.foreColor = '#f6f7f8'; } if (!opts.chart.background) { opts.chart.background = '#424242'; } if (!opts.theme.palette) { opts.theme.palette = 'palette4'; } } } }, { key: "handleUserInputErrors", value: function handleUserInputErrors(opts) { var config = opts; // conflicting tooltip option. intersect makes sure to focus on 1 point at a time. Shared cannot be used along with it if (config.tooltip.shared && config.tooltip.intersect) { throw new Error('tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false.'); } if (config.chart.type === 'bar' && config.plotOptions.bar.horizontal) { // No multiple yaxis for bars if (config.yaxis.length > 1) { throw new Error('Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false'); } // if yaxis is reversed in horizontal bar chart, you should draw the y-axis on right side if (config.yaxis[0].reversed) { config.yaxis[0].opposite = true; } config.xaxis.tooltip.enabled = false; // no xaxis tooltip for horizontal bar config.yaxis[0].tooltip.enabled = false; // no xaxis tooltip for horizontal bar config.chart.zoom.enabled = false; // no zooming for horz bars } if (config.chart.type === 'bar' || config.chart.type === 'rangeBar') { if (config.tooltip.shared) { if (config.xaxis.crosshairs.width === 'barWidth' && config.series.length > 1) { config.xaxis.crosshairs.width = 'tickWidth'; } } } if (config.chart.type === 'candlestick' || config.chart.type === 'boxPlot') { if (config.yaxis[0].reversed) { console.warn("Reversed y-axis in ".concat(config.chart.type, " chart is not supported.")); config.yaxis[0].reversed = false; } } return config; } }]); return Config; }(); var Globals = /*#__PURE__*/function () { function Globals() { _classCallCheck(this, Globals); } _createClass(Globals, [{ key: "initGlobalVars", value: function initGlobalVars(gl) { gl.series = []; // the MAIN series array (y values) gl.seriesCandleO = []; gl.seriesCandleH = []; gl.seriesCandleM = []; gl.seriesCandleL = []; gl.seriesCandleC = []; gl.seriesRangeStart = []; gl.seriesRangeEnd = []; gl.seriesRange = []; gl.seriesPercent = []; gl.seriesGoals = []; gl.seriesX = []; gl.seriesZ = []; gl.seriesNames = []; gl.seriesTotals = []; gl.seriesLog = []; gl.seriesColors = []; gl.stackedSeriesTotals = []; gl.seriesXvalues = []; // we will need this in tooltip (it's x position) // when we will have unequal x values, we will need // some way to get x value depending on mouse pointer gl.seriesYvalues = []; // we will need this when deciding which series // user hovered on gl.labels = []; gl.hasGroups = false; gl.groups = []; gl.categoryLabels = []; gl.timescaleLabels = []; gl.noLabelsProvided = false; gl.resizeTimer = null; gl.selectionResizeTimer = null; gl.delayedElements = []; gl.pointsArray = []; gl.dataLabelsRects = []; gl.isXNumeric = false; gl.skipLastTimelinelabel = false; gl.skipFirstTimelinelabel = false; gl.isDataXYZ = false; gl.isMultiLineX = false; gl.isMultipleYAxis = false; gl.maxY = -Number.MAX_VALUE; gl.minY = Number.MIN_VALUE; gl.minYArr = []; gl.maxYArr = []; gl.maxX = -Number.MAX_VALUE; gl.minX = Number.MAX_VALUE; gl.initialMaxX = -Number.MAX_VALUE; gl.initialMinX = Number.MAX_VALUE; gl.maxDate = 0; gl.minDate = Number.MAX_VALUE; gl.minZ = Number.MAX_VALUE; gl.maxZ = -Number.MAX_VALUE; gl.minXDiff = Number.MAX_VALUE; gl.yAxisScale = []; gl.xAxisScale = null; gl.xAxisTicksPositions = []; gl.yLabelsCoords = []; gl.yTitleCoords = []; gl.barPadForNumericAxis = 0; gl.padHorizontal = 0; gl.xRange = 0; gl.yRange = []; gl.zRange = 0; gl.dataPoints = 0; gl.xTickAmount = 0; } }, { key: "globalVars", value: function globalVars(config) { return { chartID: null, // chart ID - apexcharts-cuid cuid: null, // chart ID - random numbers excluding "apexcharts" part events: { beforeMount: [], mounted: [], updated: [], clicked: [], selection: [], dataPointSelection: [], zoomed: [], scrolled: [] }, colors: [], clientX: null, clientY: null, fill: { colors: [] }, stroke: { colors: [] }, dataLabels: { style: { colors: [] } }, radarPolygons: { fill: { colors: [] } }, markers: { colors: [], size: config.markers.size, largestSize: 0 }, animationEnded: false, isTouchDevice: 'ontouchstart' in window || navigator.msMaxTouchPoints, isDirty: false, // chart has been updated after the initial render. This is different than dataChanged property. isDirty means user manually called some method to update isExecCalled: false, // whether user updated the chart through the exec method initialConfig: null, // we will store the first config user has set to go back when user finishes interactions like zooming and come out of it initialSeries: [], lastXAxis: [], lastYAxis: [], columnSeries: null, labels: [], // store the text to draw on x axis // Don't mutate the labels, many things including tooltips depends on it! timescaleLabels: [], // store the timescaleLabels Labels in another variable noLabelsProvided: false, // if user didn't provide any categories/labels or x values, fallback to 1,2,3,4... allSeriesCollapsed: false, collapsedSeries: [], // when user collapses a series, it goes into this array collapsedSeriesIndices: [], // this stores the index of the collapsedSeries instead of whole object for quick access ancillaryCollapsedSeries: [], // when user collapses an "alwaysVisible" series, it goes into this array ancillaryCollapsedSeriesIndices: [], // this stores the index of the ancillaryCollapsedSeries whose y-axis is always visible risingSeries: [], // when user re-opens a collapsed series, it goes here dataFormatXNumeric: false, // boolean value to indicate user has passed numeric x values capturedSeriesIndex: -1, capturedDataPointIndex: -1, selectedDataPoints: [], goldenPadding: 35, // this value is used at a lot of places for spacing purpose invalidLogScale: false, // if a user enabled log scale but the data provided is not valid to generate a log scale, turn on this flag ignoreYAxisIndexes: [], // when series are being collapsed in multiple y axes, ignore certain index yAxisSameScaleIndices: [], maxValsInArrayIndex: 0, radialSize: 0, selection: undefined, zoomEnabled: config.chart.toolbar.autoSelected === 'zoom' && config.chart.toolbar.tools.zoom && config.chart.zoom.enabled, panEnabled: config.chart.toolbar.autoSelected === 'pan' && config.chart.toolbar.tools.pan, selectionEnabled: config.chart.toolbar.autoSelected === 'selection' && config.chart.toolbar.tools.selection, yaxis: null, mousedown: false, lastClientPosition: {}, // don't reset this variable this the chart is destroyed. It is used to detect right or left mousemove in panning visibleXRange: undefined, yValueDecimal: 0, // are there floating numbers in the series. If yes, this represent the len of the decimals total: 0, SVGNS: 'http://www.w3.org/2000/svg', // svg namespace svgWidth: 0, // the whole svg width svgHeight: 0, // the whole svg height noData: false, // whether there is any data to display or not locale: {}, // the current locale values will be preserved here for global access dom: {}, // for storing all dom nodes in this particular property memory: { methodsToExec: [] }, shouldAnimate: true, skipLastTimelinelabel: false, // when last label is cropped, skip drawing it skipFirstTimelinelabel: false, // when first label is cropped, skip drawing it delayedElements: [], // element which appear after animation has finished axisCharts: true, // chart type = line or area or bar // (refer them also as plot charts in the code) isDataXYZ: false, // bool: data was provided in a {[x,y,z]} pattern resized: false, // bool: user has resized resizeTimer: null, // timeout function to make a small delay before // drawing when user resized comboCharts: false, // bool: whether it's a combination of line/column dataChanged: false, // bool: has data changed dynamically previousPaths: [], // array: when data is changed, it will animate from // previous paths allSeriesHasEqualX: true, pointsArray: [], // store the points positions here to draw later on hover // format is - [[x,y],[x,y]... [x,y]] dataLabelsRects: [], // store the positions of datalabels to prevent collision lastDrawnDataLabelsIndexes: [], hasNullValues: false, // bool: whether series contains null values easing: null, // function: animation effect to apply zoomed: false, // whether user has zoomed or not gridWidth: 0, // drawable width of actual graphs (series paths) gridHeight: 0, // drawable height of actual graphs (series paths) rotateXLabels: false, defaultLabels: false, xLabelFormatter: undefined, // formatter for x axis labels yLabelFormatters: [], xaxisTooltipFormatter: undefined, // formatter for x axis tooltip ttKeyFormatter: undefined, ttVal: undefined, ttZFormatter: undefined, LINE_HEIGHT_RATIO: 1.618, xAxisLabelsHeight: 0, xAxisGroupLabelsHeight: 0, xAxisLabelsWidth: 0, yAxisLabelsWidth: 0, scaleX: 1, scaleY: 1, translateX: 0, translateY: 0, translateYAxisX: [], yAxisWidths: [], translateXAxisY: 0, translateXAxisX: 0, tooltip: null }; } }, { key: "init", value: function init(config) { var globals = this.globalVars(config); this.initGlobalVars(globals); globals.initialConfig = Utils$1.extend({}, config); globals.initialSeries = Utils$1.clone(config.series); globals.lastXAxis = Utils$1.clone(globals.initialConfig.xaxis); globals.lastYAxis = Utils$1.clone(globals.initialConfig.yaxis); return globals; } }]); return Globals; }(); /** * ApexCharts Base Class for extending user options with pre-defined ApexCharts config. * * @module Base **/ var Base = /*#__PURE__*/function () { function Base(opts) { _classCallCheck(this, Base); this.opts = opts; } _createClass(Base, [{ key: "init", value: function init() { var config = new Config(this.opts).init({ responsiveOverride: false }); var globals = new Globals().init(config); var w = { config: config, globals: globals }; return w; } }]); return Base; }(); /** * ApexCharts Fill Class for setting fill options of the paths. * * @module Fill **/ var Fill = /*#__PURE__*/function () { function Fill(ctx) { _classCallCheck(this, Fill); this.ctx = ctx; this.w = ctx.w; this.opts = null; this.seriesIndex = 0; } _createClass(Fill, [{ key: "clippedImgArea", value: function clippedImgArea(params) { var w = this.w; var cnf = w.config; var svgW = parseInt(w.globals.gridWidth, 10); var svgH = parseInt(w.globals.gridHeight, 10); var size = svgW > svgH ? svgW : svgH; var fillImg = params.image; var imgWidth = 0; var imgHeight = 0; if (typeof params.width === 'undefined' && typeof params.height === 'undefined') { if (cnf.fill.image.width !== undefined && cnf.fill.image.height !== undefined) { imgWidth = cnf.fill.image.width + 1; imgHeight = cnf.fill.image.height; } else { imgWidth = size + 1; imgHeight = size; } } else { imgWidth = params.width; imgHeight = params.height; } var elPattern = document.createElementNS(w.globals.SVGNS, 'pattern'); Graphics.setAttrs(elPattern, { id: params.patternID, patternUnits: params.patternUnits ? params.patternUnits : 'userSpaceOnUse', width: imgWidth + 'px', height: imgHeight + 'px' }); var elImage = document.createElementNS(w.globals.SVGNS, 'image'); elPattern.appendChild(elImage); elImage.setAttributeNS(window.SVG.xlink, 'href', fillImg); Graphics.setAttrs(elImage, { x: 0, y: 0, preserveAspectRatio: 'none', width: imgWidth + 'px', height: imgHeight + 'px' }); elImage.style.opacity = params.opacity; w.globals.dom.elDefs.node.appendChild(elPattern); } }, { key: "getSeriesIndex", value: function getSeriesIndex(opts) { var w = this.w; if ((w.config.chart.type === 'bar' || w.config.chart.type === 'rangeBar') && w.config.plotOptions.bar.distributed || w.config.chart.type === 'heatmap' || w.config.chart.type === 'treemap') { this.seriesIndex = opts.seriesNumber; } else { this.seriesIndex = opts.seriesNumber % w.globals.series.length; } return this.seriesIndex; } }, { key: "fillPath", value: function fillPath(opts) { var w = this.w; this.opts = opts; var cnf = this.w.config; var pathFill; var patternFill, gradientFill; this.seriesIndex = this.getSeriesIndex(opts); var fillColors = this.getFillColors(); var fillColor = fillColors[this.seriesIndex]; //override fillcolor if user inputted color with data if (w.globals.seriesColors[this.seriesIndex] !== undefined) { fillColor = w.globals.seriesColors[this.seriesIndex]; } if (typeof fillColor === 'function') { fillColor = fillColor({ seriesIndex: this.seriesIndex, dataPointIndex: opts.dataPointIndex, value: opts.value, w: w }); } var fillType = opts.fillType ? opts.fillType : this.getFillType(this.seriesIndex); var fillOpacity = Array.isArray(cnf.fill.opacity) ? cnf.fill.opacity[this.seriesIndex] : cnf.fill.opacity; if (opts.color) { fillColor = opts.color; } var defaultColor = fillColor; if (fillColor.indexOf('rgb') === -1) { if (fillColor.length < 9) { // if the hex contains alpha and is of 9 digit, skip the opacity defaultColor = Utils$1.hexToRgba(fillColor, fillOpacity); } } else { if (fillColor.indexOf('rgba') > -1) { fillOpacity = Utils$1.getOpacityFromRGBA(fillColor); } } if (opts.opacity) fillOpacity = opts.opacity; if (fillType === 'pattern') { patternFill = this.handlePatternFill({ fillConfig: opts.fillConfig, patternFill: patternFill, fillColor: fillColor, fillOpacity: fillOpacity, defaultColor: defaultColor }); } if (fillType === 'gradient') { gradientFill = this.handleGradientFill({ fillConfig: opts.fillConfig, fillColor: fillColor, fillOpacity: fillOpacity, i: this.seriesIndex }); } if (fillType === 'image') { var imgSrc = cnf.fill.image.src; var patternID = opts.patternID ? opts.patternID : ''; this.clippedImgArea({ opacity: fillOpacity, image: Array.isArray(imgSrc) ? opts.seriesNumber < imgSrc.length ? imgSrc[opts.seriesNumber] : imgSrc[0] : imgSrc, width: opts.width ? opts.width : undefined, height: opts.height ? opts.height : undefined, patternUnits: opts.patternUnits, patternID: "pattern".concat(w.globals.cuid).concat(opts.seriesNumber + 1).concat(patternID) }); pathFill = "url(#pattern".concat(w.globals.cuid).concat(opts.seriesNumber + 1).concat(patternID, ")"); } else if (fillType === 'gradient') { pathFill = gradientFill; } else if (fillType === 'pattern') { pathFill = patternFill; } else { pathFill = defaultColor; } // override pattern/gradient if opts.solid is true if (opts.solid) { pathFill = defaultColor; } return pathFill; } }, { key: "getFillType", value: function getFillType(seriesIndex) { var w = this.w; if (Array.isArray(w.config.fill.type)) { return w.config.fill.type[seriesIndex]; } else { return w.config.fill.type; } } }, { key: "getFillColors", value: function getFillColors() { var w = this.w; var cnf = w.config; var opts = this.opts; var fillColors = []; if (w.globals.comboCharts) { if (w.config.series[this.seriesIndex].type === 'line') { if (Array.isArray(w.globals.stroke.colors)) { fillColors = w.globals.stroke.colors; } else { fillColors.push(w.globals.stroke.colors); } } else { if (Array.isArray(w.globals.fill.colors)) { fillColors = w.globals.fill.colors; } else { fillColors.push(w.globals.fill.colors); } } } else { if (cnf.chart.type === 'line') { if (Array.isArray(w.globals.stroke.colors)) { fillColors = w.globals.stroke.colors; } else { fillColors.push(w.globals.stroke.colors); } } else { if (Array.isArray(w.globals.fill.colors)) { fillColors = w.globals.fill.colors; } else { fillColors.push(w.globals.fill.colors); } } } // colors passed in arguments if (typeof opts.fillColors !== 'undefined') { fillColors = []; if (Array.isArray(opts.fillColors)) { fillColors = opts.fillColors.slice(); } else { fillColors.push(opts.fillColors); } } return fillColors; } }, { key: "handlePatternFill", value: function handlePatternFill(_ref) { var fillConfig = _ref.fillConfig, patternFill = _ref.patternFill, fillColor = _ref.fillColor, fillOpacity = _ref.fillOpacity, defaultColor = _ref.defaultColor; var fillCnf = this.w.config.fill; if (fillConfig) { fillCnf = fillConfig; } var opts = this.opts; var graphics = new Graphics(this.ctx); var patternStrokeWidth = Array.isArray(fillCnf.pattern.strokeWidth) ? fillCnf.pattern.strokeWidth[this.seriesIndex] : fillCnf.pattern.strokeWidth; var patternLineColor = fillColor; if (Array.isArray(fillCnf.pattern.style)) { if (typeof fillCnf.pattern.style[opts.seriesNumber] !== 'undefined') { var pf = graphics.drawPattern(fillCnf.pattern.style[opts.seriesNumber], fillCnf.pattern.width, fillCnf.pattern.height, patternLineColor, patternStrokeWidth, fillOpacity); patternFill = pf; } else { patternFill = defaultColor; } } else { patternFill = graphics.drawPattern(fillCnf.pattern.style, fillCnf.pattern.width, fillCnf.pattern.height, patternLineColor, patternStrokeWidth, fillOpacity); } return patternFill; } }, { key: "handleGradientFill", value: function handleGradientFill(_ref2) { var fillColor = _ref2.fillColor, fillOpacity = _ref2.fillOpacity, fillConfig = _ref2.fillConfig, i = _ref2.i; var fillCnf = this.w.config.fill; if (fillConfig) { fillCnf = _objectSpread2(_objectSpread2({}, fillCnf), fillConfig); } var opts = this.opts; var graphics = new Graphics(this.ctx); var utils = new Utils$1(); var type = fillCnf.gradient.type; var gradientFrom = fillColor; var gradientTo; var opacityFrom = fillCnf.gradient.opacityFrom === undefined ? fillOpacity : Array.isArray(fillCnf.gradient.opacityFrom) ? fillCnf.gradient.opacityFrom[i] : fillCnf.gradient.opacityFrom; if (gradientFrom.indexOf('rgba') > -1) { opacityFrom = Utils$1.getOpacityFromRGBA(gradientFrom); } var opacityTo = fillCnf.gradient.opacityTo === undefined ? fillOpacity : Array.isArray(fillCnf.gradient.opacityTo) ? fillCnf.gradient.opacityTo[i] : fillCnf.gradient.opacityTo; if (fillCnf.gradient.gradientToColors === undefined || fillCnf.gradient.gradientToColors.length === 0) { if (fillCnf.gradient.shade === 'dark') { gradientTo = utils.shadeColor(parseFloat(fillCnf.gradient.shadeIntensity) * -1, fillColor.indexOf('rgb') > -1 ? Utils$1.rgb2hex(fillColor) : fillColor); } else { gradientTo = utils.shadeColor(parseFloat(fillCnf.gradient.shadeIntensity), fillColor.indexOf('rgb') > -1 ? Utils$1.rgb2hex(fillColor) : fillColor); } } else { if (fillCnf.gradient.gradientToColors[opts.seriesNumber]) { var gToColor = fillCnf.gradient.gradientToColors[opts.seriesNumber]; gradientTo = gToColor; if (gToColor.indexOf('rgba') > -1) { opacityTo = Utils$1.getOpacityFromRGBA(gToColor); } } else { gradientTo = fillColor; } } if (fillCnf.gradient.gradientFrom) { gradientFrom = fillCnf.gradient.gradientFrom; } if (fillCnf.gradient.gradientTo) { gradientTo = fillCnf.gradient.gradientTo; } if (fillCnf.gradient.inverseColors) { var t = gradientFrom; gradientFrom = gradientTo; gradientTo = t; } if (gradientFrom.indexOf('rgb') > -1) { gradientFrom = Utils$1.rgb2hex(gradientFrom); } if (gradientTo.indexOf('rgb') > -1) { gradientTo = Utils$1.rgb2hex(gradientTo); } return graphics.drawGradient(type, gradientFrom, gradientTo, opacityFrom, opacityTo, opts.size, fillCnf.gradient.stops, fillCnf.gradient.colorStops, i); } }]); return Fill; }(); /** * ApexCharts Markers Class for drawing points on y values in axes charts. * * @module Markers **/ var Markers = /*#__PURE__*/function () { function Markers(ctx, opts) { _classCallCheck(this, Markers); this.ctx = ctx; this.w = ctx.w; } _createClass(Markers, [{ key: "setGlobalMarkerSize", value: function setGlobalMarkerSize() { var w = this.w; w.globals.markers.size = Array.isArray(w.config.markers.size) ? w.config.markers.size : [w.config.markers.size]; if (w.globals.markers.size.length > 0) { if (w.globals.markers.size.length < w.globals.series.length + 1) { for (var i = 0; i <= w.globals.series.length; i++) { if (typeof w.globals.markers.size[i] === 'undefined') { w.globals.markers.size.push(w.globals.markers.size[0]); } } } } else { w.globals.markers.size = w.config.series.map(function (s) { return w.config.markers.size; }); } } }, { key: "plotChartMarkers", value: function plotChartMarkers(pointsPos, seriesIndex, j, pSize) { var alwaysDrawMarker = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; var w = this.w; var i = seriesIndex; var p = pointsPos; var elPointsWrap = null; var graphics = new Graphics(this.ctx); var point; var hasDiscreteMarkers = w.config.markers.discrete && w.config.markers.discrete.length; if (w.globals.markers.size[seriesIndex] > 0 || alwaysDrawMarker || hasDiscreteMarkers) { elPointsWrap = graphics.group({ class: alwaysDrawMarker || hasDiscreteMarkers ? '' : 'apexcharts-series-markers' }); elPointsWrap.attr('clip-path', "url(#gridRectMarkerMask".concat(w.globals.cuid, ")")); } if (Array.isArray(p.x)) { for (var q = 0; q < p.x.length; q++) { var dataPointIndex = j; // a small hack as we have 2 points for the first val to connect it if (j === 1 && q === 0) dataPointIndex = 0; if (j === 1 && q === 1) dataPointIndex = 1; var PointClasses = 'apexcharts-marker'; if ((w.config.chart.type === 'line' || w.config.chart.type === 'area') && !w.globals.comboCharts && !w.config.tooltip.intersect) { PointClasses += ' no-pointer-events'; } var shouldMarkerDraw = Array.isArray(w.config.markers.size) ? w.globals.markers.size[seriesIndex] > 0 : w.config.markers.size > 0; if (shouldMarkerDraw || alwaysDrawMarker || hasDiscreteMarkers) { if (Utils$1.isNumber(p.y[q])) { PointClasses += " w".concat(Utils$1.randomId()); } else { PointClasses = 'apexcharts-nullpoint'; } var opts = this.getMarkerConfig({ cssClass: PointClasses, seriesIndex: seriesIndex, dataPointIndex: dataPointIndex }); if (w.config.series[i].data[dataPointIndex]) { if (w.config.series[i].data[dataPointIndex].fillColor) { opts.pointFillColor = w.config.series[i].data[dataPointIndex].fillColor; } if (w.config.series[i].data[dataPointIndex].strokeColor) { opts.pointStrokeColor = w.config.series[i].data[dataPointIndex].strokeColor; } } if (pSize) { opts.pSize = pSize; } point = graphics.drawMarker(p.x[q], p.y[q], opts); point.attr('rel', dataPointIndex); point.attr('j', dataPointIndex); point.attr('index', seriesIndex); point.node.setAttribute('default-marker-size', opts.pSize); var filters = new Filters(this.ctx); filters.setSelectionFilter(point, seriesIndex, dataPointIndex); this.addEvents(point); if (elPointsWrap) { elPointsWrap.add(point); } } else { // dynamic array creation - multidimensional if (typeof w.globals.pointsArray[seriesIndex] === 'undefined') w.globals.pointsArray[seriesIndex] = []; w.globals.pointsArray[seriesIndex].push([p.x[q], p.y[q]]); } } } return elPointsWrap; } }, { key: "getMarkerConfig", value: function getMarkerConfig(_ref) { var cssClass = _ref.cssClass, seriesIndex = _ref.seriesIndex, _ref$dataPointIndex = _ref.dataPointIndex, dataPointIndex = _ref$dataPointIndex === void 0 ? null : _ref$dataPointIndex, _ref$finishRadius = _ref.finishRadius, finishRadius = _ref$finishRadius === void 0 ? null : _ref$finishRadius; var w = this.w; var pStyle = this.getMarkerStyle(seriesIndex); var pSize = w.globals.markers.size[seriesIndex]; var m = w.config.markers; // discrete markers is an option where user can specify a particular marker with different shape, size and color if (dataPointIndex !== null && m.discrete.length) { m.discrete.map(function (marker) { if (marker.seriesIndex === seriesIndex && marker.dataPointIndex === dataPointIndex) { pStyle.pointStrokeColor = marker.strokeColor; pStyle.pointFillColor = marker.fillColor; pSize = marker.size; pStyle.pointShape = marker.shape; } }); } return { pSize: finishRadius === null ? pSize : finishRadius, pRadius: m.radius, width: Array.isArray(m.width) ? m.width[seriesIndex] : m.width, height: Array.isArray(m.height) ? m.height[seriesIndex] : m.height, pointStrokeWidth: Array.isArray(m.strokeWidth) ? m.strokeWidth[seriesIndex] : m.strokeWidth, pointStrokeColor: pStyle.pointStrokeColor, pointFillColor: pStyle.pointFillColor, shape: pStyle.pointShape || (Array.isArray(m.shape) ? m.shape[seriesIndex] : m.shape), class: cssClass, pointStrokeOpacity: Array.isArray(m.strokeOpacity) ? m.strokeOpacity[seriesIndex] : m.strokeOpacity, pointStrokeDashArray: Array.isArray(m.strokeDashArray) ? m.strokeDashArray[seriesIndex] : m.strokeDashArray, pointFillOpacity: Array.isArray(m.fillOpacity) ? m.fillOpacity[seriesIndex] : m.fillOpacity, seriesIndex: seriesIndex }; } }, { key: "addEvents", value: function addEvents(circle) { var w = this.w; var graphics = new Graphics(this.ctx); circle.node.addEventListener('mouseenter', graphics.pathMouseEnter.bind(this.ctx, circle)); circle.node.addEventListener('mouseleave', graphics.pathMouseLeave.bind(this.ctx, circle)); circle.node.addEventListener('mousedown', graphics.pathMouseDown.bind(this.ctx, circle)); circle.node.addEventListener('click', w.config.markers.onClick); circle.node.addEventListener('dblclick', w.config.markers.onDblClick); circle.node.addEventListener('touchstart', graphics.pathMouseDown.bind(this.ctx, circle), { passive: true }); } }, { key: "getMarkerStyle", value: function getMarkerStyle(seriesIndex) { var w = this.w; var colors = w.globals.markers.colors; var strokeColors = w.config.markers.strokeColor || w.config.markers.strokeColors; var pointStrokeColor = Array.isArray(strokeColors) ? strokeColors[seriesIndex] : strokeColors; var pointFillColor = Array.isArray(colors) ? colors[seriesIndex] : colors; return { pointStrokeColor: pointStrokeColor, pointFillColor: pointFillColor }; } }]); return Markers; }(); /** * ApexCharts Scatter Class. * This Class also handles bubbles chart as currently there is no major difference in drawing them, * @module Scatter **/ var Scatter = /*#__PURE__*/function () { function Scatter(ctx) { _classCallCheck(this, Scatter); this.ctx = ctx; this.w = ctx.w; this.initialAnim = this.w.config.chart.animations.enabled; this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled; } _createClass(Scatter, [{ key: "draw", value: function draw(elSeries, j, opts) { var w = this.w; var graphics = new Graphics(this.ctx); var realIndex = opts.realIndex; var pointsPos = opts.pointsPos; var zRatio = opts.zRatio; var elPointsMain = opts.elParent; var elPointsWrap = graphics.group({ class: "apexcharts-series-markers apexcharts-series-".concat(w.config.chart.type) }); elPointsWrap.attr('clip-path', "url(#gridRectMarkerMask".concat(w.globals.cuid, ")")); if (Array.isArray(pointsPos.x)) { for (var q = 0; q < pointsPos.x.length; q++) { var dataPointIndex = j + 1; var shouldDraw = true; // a small hack as we have 2 points for the first val to connect it if (j === 0 && q === 0) dataPointIndex = 0; if (j === 0 && q === 1) dataPointIndex = 1; var radius = 0; var finishRadius = w.globals.markers.size[realIndex]; if (zRatio !== Infinity) { // means we have a bubble var bubble = w.config.plotOptions.bubble; finishRadius = w.globals.seriesZ[realIndex][dataPointIndex]; if (bubble.zScaling) { finishRadius /= zRatio; } if (bubble.minBubbleRadius && finishRadius < bubble.minBubbleRadius) { finishRadius = bubble.minBubbleRadius; } if (bubble.maxBubbleRadius && finishRadius > bubble.maxBubbleRadius) { finishRadius = bubble.maxBubbleRadius; } } if (!w.config.chart.animations.enabled) { radius = finishRadius; } var x = pointsPos.x[q]; var y = pointsPos.y[q]; radius = radius || 0; if (y === null || typeof w.globals.series[realIndex][dataPointIndex] === 'undefined') { shouldDraw = false; } if (shouldDraw) { var point = this.drawPoint(x, y, radius, finishRadius, realIndex, dataPointIndex, j); elPointsWrap.add(point); } elPointsMain.add(elPointsWrap); } } } }, { key: "drawPoint", value: function drawPoint(x, y, radius, finishRadius, realIndex, dataPointIndex, j) { var w = this.w; var i = realIndex; var anim = new Animations(this.ctx); var filters = new Filters(this.ctx); var fill = new Fill(this.ctx); var markers = new Markers(this.ctx); var graphics = new Graphics(this.ctx); var markerConfig = markers.getMarkerConfig({ cssClass: 'apexcharts-marker', seriesIndex: i, dataPointIndex: dataPointIndex, finishRadius: w.config.chart.type === 'bubble' || w.globals.comboCharts && w.config.series[realIndex] && w.config.series[realIndex].type === 'bubble' ? finishRadius : null }); finishRadius = markerConfig.pSize; var pathFillCircle = fill.fillPath({ seriesNumber: realIndex, dataPointIndex: dataPointIndex, color: markerConfig.pointFillColor, patternUnits: 'objectBoundingBox', value: w.globals.series[realIndex][j] }); var el; if (markerConfig.shape === 'circle') { el = graphics.drawCircle(radius); } else if (markerConfig.shape === 'square' || markerConfig.shape === 'rect') { el = graphics.drawRect(0, 0, markerConfig.width - markerConfig.pointStrokeWidth / 2, markerConfig.height - markerConfig.pointStrokeWidth / 2, markerConfig.pRadius); } if (w.config.series[i].data[dataPointIndex]) { if (w.config.series[i].data[dataPointIndex].fillColor) { pathFillCircle = w.config.series[i].data[dataPointIndex].fillColor; } } el.attr({ x: x - markerConfig.width / 2 - markerConfig.pointStrokeWidth / 2, y: y - markerConfig.height / 2 - markerConfig.pointStrokeWidth / 2, cx: x, cy: y, fill: pathFillCircle, 'fill-opacity': markerConfig.pointFillOpacity, stroke: markerConfig.pointStrokeColor, r: finishRadius, 'stroke-width': markerConfig.pointStrokeWidth, 'stroke-dasharray': markerConfig.pointStrokeDashArray, 'stroke-opacity': markerConfig.pointStrokeOpacity }); if (w.config.chart.dropShadow.enabled) { var dropShadow = w.config.chart.dropShadow; filters.dropShadow(el, dropShadow, realIndex); } if (this.initialAnim && !w.globals.dataChanged && !w.globals.resized) { var speed = w.config.chart.animations.speed; anim.animateMarker(el, 0, markerConfig.shape === 'circle' ? finishRadius : { width: markerConfig.width, height: markerConfig.height }, speed, w.globals.easing, function () { window.setTimeout(function () { anim.animationCompleted(el); }, 100); }); } else { w.globals.animationEnded = true; } if (w.globals.dataChanged && markerConfig.shape === 'circle') { if (this.dynamicAnim) { var _speed = w.config.chart.animations.dynamicAnimation.speed; var prevX, prevY, prevR; var prevPathJ = null; prevPathJ = w.globals.previousPaths[realIndex] && w.globals.previousPaths[realIndex][j]; if (typeof prevPathJ !== 'undefined' && prevPathJ !== null) { // series containing less elements will ignore these values and revert to 0 prevX = prevPathJ.x; prevY = prevPathJ.y; prevR = typeof prevPathJ.r !== 'undefined' ? prevPathJ.r : finishRadius; } for (var cs = 0; cs < w.globals.collapsedSeries.length; cs++) { if (w.globals.collapsedSeries[cs].index === realIndex) { _speed = 1; finishRadius = 0; } } if (x === 0 && y === 0) finishRadius = 0; anim.animateCircle(el, { cx: prevX, cy: prevY, r: prevR }, { cx: x, cy: y, r: finishRadius }, _speed, w.globals.easing); } else { el.attr({ r: finishRadius }); } } el.attr({ rel: dataPointIndex, j: dataPointIndex, index: realIndex, 'default-marker-size': finishRadius }); filters.setSelectionFilter(el, realIndex, dataPointIndex); markers.addEvents(el); el.node.classList.add('apexcharts-marker'); return el; } }, { key: "centerTextInBubble", value: function centerTextInBubble(y) { var w = this.w; y = y + parseInt(w.config.dataLabels.style.fontSize, 10) / 4; return { y: y }; } }]); return Scatter; }(); /** * ApexCharts DataLabels Class for drawing dataLabels on Axes based Charts. * * @module DataLabels **/ var DataLabels = /*#__PURE__*/function () { function DataLabels(ctx) { _classCallCheck(this, DataLabels); this.ctx = ctx; this.w = ctx.w; } // When there are many datalabels to be printed, and some of them overlaps each other in the same series, this method will take care of that // Also, when datalabels exceeds the drawable area and get clipped off, we need to adjust and move some pixels to make them visible again _createClass(DataLabels, [{ key: "dataLabelsCorrection", value: function dataLabelsCorrection(x, y, val, i, dataPointIndex, alwaysDrawDataLabel, fontSize) { var w = this.w; var graphics = new Graphics(this.ctx); var drawnextLabel = false; // var textRects = graphics.getTextRects(val, fontSize); var width = textRects.width; var height = textRects.height; if (y < 0) y = 0; if (y > w.globals.gridHeight + height) y = w.globals.gridHeight + height / 2; // first value in series, so push an empty array if (typeof w.globals.dataLabelsRects[i] === 'undefined') w.globals.dataLabelsRects[i] = []; // then start pushing actual rects in that sub-array w.globals.dataLabelsRects[i].push({ x: x, y: y, width: width, height: height }); var len = w.globals.dataLabelsRects[i].length - 2; var lastDrawnIndex = typeof w.globals.lastDrawnDataLabelsIndexes[i] !== 'undefined' ? w.globals.lastDrawnDataLabelsIndexes[i][w.globals.lastDrawnDataLabelsIndexes[i].length - 1] : 0; if (typeof w.globals.dataLabelsRects[i][len] !== 'undefined') { var lastDataLabelRect = w.globals.dataLabelsRects[i][lastDrawnIndex]; if ( // next label forward and x not intersecting x > lastDataLabelRect.x + lastDataLabelRect.width + 2 || y > lastDataLabelRect.y + lastDataLabelRect.height + 2 || x + width < lastDataLabelRect.x // next label is going to be drawn backwards ) { // the 2 indexes don't override, so OK to draw next label drawnextLabel = true; } } if (dataPointIndex === 0 || alwaysDrawDataLabel) { drawnextLabel = true; } return { x: x, y: y, textRects: textRects, drawnextLabel: drawnextLabel }; } }, { key: "drawDataLabel", value: function drawDataLabel(_ref) { var _this = this; var type = _ref.type, pos = _ref.pos, i = _ref.i, j = _ref.j, isRangeStart = _ref.isRangeStart, _ref$strokeWidth = _ref.strokeWidth, strokeWidth = _ref$strokeWidth === void 0 ? 2 : _ref$strokeWidth; // this method handles line, area, bubble, scatter charts as those charts contains markers/points which have pre-defined x/y positions // all other charts like radar / bars / heatmaps will define their own drawDataLabel routine var w = this.w; var graphics = new Graphics(this.ctx); var dataLabelsConfig = w.config.dataLabels; var x = 0; var y = 0; var dataPointIndex = j; var elDataLabelsWrap = null; if (!dataLabelsConfig.enabled || !Array.isArray(pos.x)) { return elDataLabelsWrap; } elDataLabelsWrap = graphics.group({ class: 'apexcharts-data-labels' }); for (var q = 0; q < pos.x.length; q++) { x = pos.x[q] + dataLabelsConfig.offsetX; y = pos.y[q] + dataLabelsConfig.offsetY + strokeWidth; if (!isNaN(x)) { // a small hack as we have 2 points for the first val to connect it if (j === 1 && q === 0) dataPointIndex = 0; if (j === 1 && q === 1) dataPointIndex = 1; var val = w.globals.series[i][dataPointIndex]; if (type === 'rangeArea') { if (isRangeStart) { val = w.globals.seriesRangeStart[i][dataPointIndex]; } else { val = w.globals.seriesRangeEnd[i][dataPointIndex]; } } var text = ''; var getText = function getText(v) { return w.config.dataLabels.formatter(v, { ctx: _this.ctx, seriesIndex: i, dataPointIndex: dataPointIndex, w: w }); }; if (w.config.chart.type === 'bubble') { val = w.globals.seriesZ[i][dataPointIndex]; text = getText(val); y = pos.y[q]; var scatter = new Scatter(this.ctx); var centerTextInBubbleCoords = scatter.centerTextInBubble(y, i, dataPointIndex); y = centerTextInBubbleCoords.y; } else { if (typeof val !== 'undefined') { text = getText(val); } } this.plotDataLabelsText({ x: x, y: y, text: text, i: i, j: dataPointIndex, parent: elDataLabelsWrap, offsetCorrection: true, dataLabelsConfig: w.config.dataLabels }); } } return elDataLabelsWrap; } }, { key: "plotDataLabelsText", value: function plotDataLabelsText(opts) { var w = this.w; var graphics = new Graphics(this.ctx); var x = opts.x, y = opts.y, i = opts.i, j = opts.j, text = opts.text, textAnchor = opts.textAnchor, fontSize = opts.fontSize, parent = opts.parent, dataLabelsConfig = opts.dataLabelsConfig, color = opts.color, alwaysDrawDataLabel = opts.alwaysDrawDataLabel, offsetCorrection = opts.offsetCorrection; if (Array.isArray(w.config.dataLabels.enabledOnSeries)) { if (w.config.dataLabels.enabledOnSeries.indexOf(i) < 0) { return; } } var correctedLabels = { x: x, y: y, drawnextLabel: true, textRects: null }; if (offsetCorrection) { correctedLabels = this.dataLabelsCorrection(x, y, text, i, j, alwaysDrawDataLabel, parseInt(dataLabelsConfig.style.fontSize, 10)); } // when zoomed, we don't need to correct labels offsets, // but if normally, labels get cropped, correct them if (!w.globals.zoomed) { x = correctedLabels.x; y = correctedLabels.y; } if (correctedLabels.textRects) { // fixes #2264 if (x < -10 - correctedLabels.textRects.width || x > w.globals.gridWidth + correctedLabels.textRects.width + 10) { // datalabels fall outside drawing area, so draw a blank label text = ''; } } var dataLabelColor = w.globals.dataLabels.style.colors[i]; if ((w.config.chart.type === 'bar' || w.config.chart.type === 'rangeBar') && w.config.plotOptions.bar.distributed || w.config.dataLabels.distributed) { dataLabelColor = w.globals.dataLabels.style.colors[j]; } if (typeof dataLabelColor === 'function') { dataLabelColor = dataLabelColor({ series: w.globals.series, seriesIndex: i, dataPointIndex: j, w: w }); } if (color) { dataLabelColor = color; } var offX = dataLabelsConfig.offsetX; var offY = dataLabelsConfig.offsetY; if (w.config.chart.type === 'bar' || w.config.chart.type === 'rangeBar') { // for certain chart types, we handle offsets while calculating datalabels pos // why? because bars/column may have negative values and based on that // offsets becomes reversed offX = 0; offY = 0; } if (correctedLabels.drawnextLabel) { var dataLabelText = graphics.drawText({ width: 100, height: parseInt(dataLabelsConfig.style.fontSize, 10), x: x + offX, y: y + offY, foreColor: dataLabelColor, textAnchor: textAnchor || dataLabelsConfig.textAnchor, text: text, fontSize: fontSize || dataLabelsConfig.style.fontSize, fontFamily: dataLabelsConfig.style.fontFamily, fontWeight: dataLabelsConfig.style.fontWeight || 'normal' }); dataLabelText.attr({ class: 'apexcharts-datalabel', cx: x, cy: y }); if (dataLabelsConfig.dropShadow.enabled) { var textShadow = dataLabelsConfig.dropShadow; var filters = new Filters(this.ctx); filters.dropShadow(dataLabelText, textShadow); } parent.add(dataLabelText); if (typeof w.globals.lastDrawnDataLabelsIndexes[i] === 'undefined') { w.globals.lastDrawnDataLabelsIndexes[i] = []; } w.globals.lastDrawnDataLabelsIndexes[i].push(j); } } }, { key: "addBackgroundToDataLabel", value: function addBackgroundToDataLabel(el, coords) { var w = this.w; var bCnf = w.config.dataLabels.background; var paddingH = bCnf.padding; var paddingV = bCnf.padding / 2; var width = coords.width; var height = coords.height; var graphics = new Graphics(this.ctx); var elRect = graphics.drawRect(coords.x - paddingH, coords.y - paddingV / 2, width + paddingH * 2, height + paddingV, bCnf.borderRadius, w.config.chart.background === 'transparent' ? '#fff' : w.config.chart.background, bCnf.opacity, bCnf.borderWidth, bCnf.borderColor); if (bCnf.dropShadow.enabled) { var filters = new Filters(this.ctx); filters.dropShadow(elRect, bCnf.dropShadow); } return elRect; } }, { key: "dataLabelsBackground", value: function dataLabelsBackground() { var w = this.w; if (w.config.chart.type === 'bubble') return; var elDataLabels = w.globals.dom.baseEl.querySelectorAll('.apexcharts-datalabels text'); for (var i = 0; i < elDataLabels.length; i++) { var el = elDataLabels[i]; var coords = el.getBBox(); var elRect = null; if (coords.width && coords.height) { elRect = this.addBackgroundToDataLabel(el, coords); } if (elRect) { el.parentNode.insertBefore(elRect.node, el); var background = el.getAttribute('fill'); var shouldAnim = w.config.chart.animations.enabled && !w.globals.resized && !w.globals.dataChanged; if (shouldAnim) { elRect.animate().attr({ fill: background }); } else { elRect.attr({ fill: background }); } el.setAttribute('fill', w.config.dataLabels.background.foreColor); } } } }, { key: "bringForward", value: function bringForward() { var w = this.w; var elDataLabelsNodes = w.globals.dom.baseEl.querySelectorAll('.apexcharts-datalabels'); var elSeries = w.globals.dom.baseEl.querySelector('.apexcharts-plot-series:last-child'); for (var i = 0; i < elDataLabelsNodes.length; i++) { if (elSeries) { elSeries.insertBefore(elDataLabelsNodes[i], elSeries.nextSibling); } } } }]); return DataLabels; }(); /** * ApexCharts Series Class for interaction with the Series of the chart. * * @module Series **/ var Series = /*#__PURE__*/function () { function Series(ctx) { _classCallCheck(this, Series); this.ctx = ctx; this.w = ctx.w; this.legendInactiveClass = 'legend-mouseover-inactive'; } _createClass(Series, [{ key: "getAllSeriesEls", value: function getAllSeriesEls() { return this.w.globals.dom.baseEl.getElementsByClassName("apexcharts-series"); } }, { key: "getSeriesByName", value: function getSeriesByName(seriesName) { return this.w.globals.dom.baseEl.querySelector(".apexcharts-inner .apexcharts-series[seriesName='".concat(Utils$1.escapeString(seriesName), "']")); } }, { key: "isSeriesHidden", value: function isSeriesHidden(seriesName) { var targetElement = this.getSeriesByName(seriesName); var realIndex = parseInt(targetElement.getAttribute('data:realIndex'), 10); var isHidden = targetElement.classList.contains('apexcharts-series-collapsed'); return { isHidden: isHidden, realIndex: realIndex }; } }, { key: "addCollapsedClassToSeries", value: function addCollapsedClassToSeries(elSeries, index) { var w = this.w; function iterateOnAllCollapsedSeries(series) { for (var cs = 0; cs < series.length; cs++) { if (series[cs].index === index) { elSeries.node.classList.add('apexcharts-series-collapsed'); } } } iterateOnAllCollapsedSeries(w.globals.collapsedSeries); iterateOnAllCollapsedSeries(w.globals.ancillaryCollapsedSeries); } }, { key: "toggleSeries", value: function toggleSeries(seriesName) { var isSeriesHidden = this.isSeriesHidden(seriesName); this.ctx.legend.legendHelpers.toggleDataSeries(isSeriesHidden.realIndex, isSeriesHidden.isHidden); return isSeriesHidden.isHidden; } }, { key: "showSeries", value: function showSeries(seriesName) { var isSeriesHidden = this.isSeriesHidden(seriesName); if (isSeriesHidden.isHidden) { this.ctx.legend.legendHelpers.toggleDataSeries(isSeriesHidden.realIndex, true); } } }, { key: "hideSeries", value: function hideSeries(seriesName) { var isSeriesHidden = this.isSeriesHidden(seriesName); if (!isSeriesHidden.isHidden) { this.ctx.legend.legendHelpers.toggleDataSeries(isSeriesHidden.realIndex, false); } } }, { key: "resetSeries", value: function resetSeries() { var shouldUpdateChart = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var shouldResetZoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var shouldResetCollapsed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var w = this.w; var series = Utils$1.clone(w.globals.initialSeries); w.globals.previousPaths = []; if (shouldResetCollapsed) { w.globals.collapsedSeries = []; w.globals.ancillaryCollapsedSeries = []; w.globals.collapsedSeriesIndices = []; w.globals.ancillaryCollapsedSeriesIndices = []; } else { series = this.emptyCollapsedSeries(series); } w.config.series = series; if (shouldUpdateChart) { if (shouldResetZoom) { w.globals.zoomed = false; this.ctx.updateHelpers.revertDefaultAxisMinMax(); } this.ctx.updateHelpers._updateSeries(series, w.config.chart.animations.dynamicAnimation.enabled); } } }, { key: "emptyCollapsedSeries", value: function emptyCollapsedSeries(series) { var w = this.w; for (var i = 0; i < series.length; i++) { if (w.globals.collapsedSeriesIndices.indexOf(i) > -1) { series[i].data = []; } } return series; } }, { key: "toggleSeriesOnHover", value: function toggleSeriesOnHover(e, targetElement) { var w = this.w; if (!targetElement) targetElement = e.target; var allSeriesEls = w.globals.dom.baseEl.querySelectorAll(".apexcharts-series, .apexcharts-datalabels"); if (e.type === 'mousemove') { var seriesCnt = parseInt(targetElement.getAttribute('rel'), 10) - 1; var seriesEl = null; var dataLabelEl = null; if (w.globals.axisCharts || w.config.chart.type === 'radialBar') { if (w.globals.axisCharts) { seriesEl = w.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(seriesCnt, "']")); dataLabelEl = w.globals.dom.baseEl.querySelector(".apexcharts-datalabels[data\\:realIndex='".concat(seriesCnt, "']")); } else { seriesEl = w.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(seriesCnt + 1, "']")); } } else { seriesEl = w.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(seriesCnt + 1, "'] path")); } for (var se = 0; se < allSeriesEls.length; se++) { allSeriesEls[se].classList.add(this.legendInactiveClass); } if (seriesEl !== null) { if (!w.globals.axisCharts) { seriesEl.parentNode.classList.remove(this.legendInactiveClass); } seriesEl.classList.remove(this.legendInactiveClass); if (dataLabelEl !== null) { dataLabelEl.classList.remove(this.legendInactiveClass); } } } else if (e.type === 'mouseout') { for (var _se = 0; _se < allSeriesEls.length; _se++) { allSeriesEls[_se].classList.remove(this.legendInactiveClass); } } } }, { key: "highlightRangeInSeries", value: function highlightRangeInSeries(e, targetElement) { var _this = this; var w = this.w; var allHeatMapElements = w.globals.dom.baseEl.getElementsByClassName('apexcharts-heatmap-rect'); var activeInactive = function activeInactive(action) { for (var i = 0; i < allHeatMapElements.length; i++) { allHeatMapElements[i].classList[action](_this.legendInactiveClass); } }; var removeInactiveClassFromHoveredRange = function removeInactiveClassFromHoveredRange(range) { for (var i = 0; i < allHeatMapElements.length; i++) { var val = parseInt(allHeatMapElements[i].getAttribute('val'), 10); if (val >= range.from && val <= range.to) { allHeatMapElements[i].classList.remove(_this.legendInactiveClass); } } }; if (e.type === 'mousemove') { var seriesCnt = parseInt(targetElement.getAttribute('rel'), 10) - 1; activeInactive('add'); var range = w.config.plotOptions.heatmap.colorScale.ranges[seriesCnt]; removeInactiveClassFromHoveredRange(range); } else if (e.type === 'mouseout') { activeInactive('remove'); } } }, { key: "getActiveConfigSeriesIndex", value: function getActiveConfigSeriesIndex() { var order = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'asc'; var chartTypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var w = this.w; var activeIndex = 0; if (w.config.series.length > 1) { // active series flag is required to know if user has not deactivated via legend click var activeSeriesIndex = w.config.series.map(function (s, index) { var checkChartType = function checkChartType() { if (w.globals.comboCharts) { return chartTypes.length === 0 || chartTypes.length && chartTypes.indexOf(w.config.series[index].type) > -1; } return true; }; var hasData = s.data && s.data.length > 0 && w.globals.collapsedSeriesIndices.indexOf(index) === -1; return hasData && checkChartType() ? index : -1; }); for (var a = order === 'asc' ? 0 : activeSeriesIndex.length - 1; order === 'asc' ? a < activeSeriesIndex.length : a >= 0; order === 'asc' ? a++ : a--) { if (activeSeriesIndex[a] !== -1) { activeIndex = activeSeriesIndex[a]; break; } } } return activeIndex; } }, { key: "getBarSeriesIndices", value: function getBarSeriesIndices() { var w = this.w; if (w.globals.comboCharts) { return this.w.config.series.map(function (s, i) { return s.type === 'bar' || s.type === 'column' ? i : -1; }).filter(function (i) { return i !== -1; }); } return this.w.config.series.map(function (s, i) { return i; }); } }, { key: "getPreviousPaths", value: function getPreviousPaths() { var w = this.w; w.globals.previousPaths = []; function pushPaths(seriesEls, i, type) { var paths = seriesEls[i].childNodes; var dArr = { type: type, paths: [], realIndex: seriesEls[i].getAttribute('data:realIndex') }; for (var j = 0; j < paths.length; j++) { if (paths[j].hasAttribute('pathTo')) { var d = paths[j].getAttribute('pathTo'); dArr.paths.push({ d: d }); } } w.globals.previousPaths.push(dArr); } var getPaths = function getPaths(chartType) { return w.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(chartType, "-series .apexcharts-series")); }; var chartTypes = ['line', 'area', 'bar', 'rangebar', 'rangeArea', 'candlestick', 'radar']; chartTypes.forEach(function (type) { var paths = getPaths(type); for (var p = 0; p < paths.length; p++) { pushPaths(paths, p, type); } }); this.handlePrevBubbleScatterPaths('bubble'); this.handlePrevBubbleScatterPaths('scatter'); var heatTreeSeries = w.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(w.config.chart.type, " .apexcharts-series")); if (heatTreeSeries.length > 0) { var _loop = function _loop(h) { var seriesEls = w.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(w.config.chart.type, " .apexcharts-series[data\\:realIndex='").concat(h, "'] rect")); var dArr = []; var _loop2 = function _loop2(i) { var getAttr = function getAttr(x) { return seriesEls[i].getAttribute(x); }; var rect = { x: parseFloat(getAttr('x')), y: parseFloat(getAttr('y')), width: parseFloat(getAttr('width')), height: parseFloat(getAttr('height')) }; dArr.push({ rect: rect, color: seriesEls[i].getAttribute('color') }); }; for (var i = 0; i < seriesEls.length; i++) { _loop2(i); } w.globals.previousPaths.push(dArr); }; for (var h = 0; h < heatTreeSeries.length; h++) { _loop(h); } } if (!w.globals.axisCharts) { // for non-axis charts (i.e., circular charts, pathFrom is not usable. We need whole series) w.globals.previousPaths = w.globals.series; } } }, { key: "handlePrevBubbleScatterPaths", value: function handlePrevBubbleScatterPaths(type) { var w = this.w; var paths = w.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(type, "-series .apexcharts-series")); if (paths.length > 0) { for (var s = 0; s < paths.length; s++) { var seriesEls = w.globals.dom.baseEl.querySelectorAll(".apexcharts-".concat(type, "-series .apexcharts-series[data\\:realIndex='").concat(s, "'] circle")); var dArr = []; for (var i = 0; i < seriesEls.length; i++) { dArr.push({ x: seriesEls[i].getAttribute('cx'), y: seriesEls[i].getAttribute('cy'), r: seriesEls[i].getAttribute('r') }); } w.globals.previousPaths.push(dArr); } } } }, { key: "clearPreviousPaths", value: function clearPreviousPaths() { var w = this.w; w.globals.previousPaths = []; w.globals.allSeriesCollapsed = false; } }, { key: "handleNoData", value: function handleNoData() { var w = this.w; var me = this; var noDataOpts = w.config.noData; var graphics = new Graphics(me.ctx); var x = w.globals.svgWidth / 2; var y = w.globals.svgHeight / 2; var textAnchor = 'middle'; w.globals.noData = true; w.globals.animationEnded = true; if (noDataOpts.align === 'left') { x = 10; textAnchor = 'start'; } else if (noDataOpts.align === 'right') { x = w.globals.svgWidth - 10; textAnchor = 'end'; } if (noDataOpts.verticalAlign === 'top') { y = 50; } else if (noDataOpts.verticalAlign === 'bottom') { y = w.globals.svgHeight - 50; } x = x + noDataOpts.offsetX; y = y + parseInt(noDataOpts.style.fontSize, 10) + 2 + noDataOpts.offsetY; if (noDataOpts.text !== undefined && noDataOpts.text !== '') { var titleText = graphics.drawText({ x: x, y: y, text: noDataOpts.text, textAnchor: textAnchor, fontSize: noDataOpts.style.fontSize, fontFamily: noDataOpts.style.fontFamily, foreColor: noDataOpts.style.color, opacity: 1, class: 'apexcharts-text-nodata' }); w.globals.dom.Paper.add(titleText); } } // When user clicks on legends, the collapsed series is filled with [0,0,0,...,0] // This is because we don't want to alter the series' length as it is used at many places }, { key: "setNullSeriesToZeroValues", value: function setNullSeriesToZeroValues(series) { var w = this.w; for (var sl = 0; sl < series.length; sl++) { if (series[sl].length === 0) { for (var j = 0; j < series[w.globals.maxValsInArrayIndex].length; j++) { series[sl].push(0); } } } return series; } }, { key: "hasAllSeriesEqualX", value: function hasAllSeriesEqualX() { var equalLen = true; var w = this.w; var filteredSerX = this.filteredSeriesX(); for (var i = 0; i < filteredSerX.length - 1; i++) { if (filteredSerX[i][0] !== filteredSerX[i + 1][0]) { equalLen = false; break; } } w.globals.allSeriesHasEqualX = equalLen; return equalLen; } }, { key: "filteredSeriesX", value: function filteredSeriesX() { var w = this.w; var filteredSeriesX = w.globals.seriesX.map(function (ser) { return ser.length > 0 ? ser : []; }); return filteredSeriesX; } }]); return Series; }(); var Data = /*#__PURE__*/function () { function Data(ctx) { _classCallCheck(this, Data); this.ctx = ctx; this.w = ctx.w; this.twoDSeries = []; this.threeDSeries = []; this.twoDSeriesX = []; this.seriesGoals = []; this.coreUtils = new CoreUtils(this.ctx); } _createClass(Data, [{ key: "isMultiFormat", value: function isMultiFormat() { return this.isFormatXY() || this.isFormat2DArray(); } // given format is [{x, y}, {x, y}] }, { key: "isFormatXY", value: function isFormatXY() { var series = this.w.config.series.slice(); var sr = new Series(this.ctx); this.activeSeriesIndex = sr.getActiveConfigSeriesIndex(); if (typeof series[this.activeSeriesIndex].data !== 'undefined' && series[this.activeSeriesIndex].data.length > 0 && series[this.activeSeriesIndex].data[0] !== null && typeof series[this.activeSeriesIndex].data[0].x !== 'undefined' && series[this.activeSeriesIndex].data[0] !== null) { return true; } } // given format is [[x, y], [x, y]] }, { key: "isFormat2DArray", value: function isFormat2DArray() { var series = this.w.config.series.slice(); var sr = new Series(this.ctx); this.activeSeriesIndex = sr.getActiveConfigSeriesIndex(); if (typeof series[this.activeSeriesIndex].data !== 'undefined' && series[this.activeSeriesIndex].data.length > 0 && typeof series[this.activeSeriesIndex].data[0] !== 'undefined' && series[this.activeSeriesIndex].data[0] !== null && series[this.activeSeriesIndex].data[0].constructor === Array) { return true; } } }, { key: "handleFormat2DArray", value: function handleFormat2DArray(ser, i) { var cnf = this.w.config; var gl = this.w.globals; var isBoxPlot = cnf.chart.type === 'boxPlot' || cnf.series[i].type === 'boxPlot'; for (var j = 0; j < ser[i].data.length; j++) { if (typeof ser[i].data[j][1] !== 'undefined') { if (Array.isArray(ser[i].data[j][1]) && ser[i].data[j][1].length === 4 && !isBoxPlot) { // candlestick nested ohlc format this.twoDSeries.push(Utils$1.parseNumber(ser[i].data[j][1][3])); } else if (ser[i].data[j].length >= 5) { // candlestick non-nested ohlc format this.twoDSeries.push(Utils$1.parseNumber(ser[i].data[j][4])); } else { this.twoDSeries.push(Utils$1.parseNumber(ser[i].data[j][1])); } gl.dataFormatXNumeric = true; } if (cnf.xaxis.type === 'datetime') { // if timestamps are provided and xaxis type is datetime, var ts = new Date(ser[i].data[j][0]); ts = new Date(ts).getTime(); this.twoDSeriesX.push(ts); } else { this.twoDSeriesX.push(ser[i].data[j][0]); } } for (var _j = 0; _j < ser[i].data.length; _j++) { if (typeof ser[i].data[_j][2] !== 'undefined') { this.threeDSeries.push(ser[i].data[_j][2]); gl.isDataXYZ = true; } } } }, { key: "handleFormatXY", value: function handleFormatXY(ser, i) { var cnf = this.w.config; var gl = this.w.globals; var dt = new DateTime(this.ctx); var activeI = i; if (gl.collapsedSeriesIndices.indexOf(i) > -1) { // fix #368 activeI = this.activeSeriesIndex; } // get series for (var j = 0; j < ser[i].data.length; j++) { if (typeof ser[i].data[j].y !== 'undefined') { if (Array.isArray(ser[i].data[j].y)) { this.twoDSeries.push(Utils$1.parseNumber(ser[i].data[j].y[ser[i].data[j].y.length - 1])); } else { this.twoDSeries.push(Utils$1.parseNumber(ser[i].data[j].y)); } } if (typeof ser[i].data[j].goals !== 'undefined' && Array.isArray(ser[i].data[j].goals)) { if (typeof this.seriesGoals[i] === 'undefined') { this.seriesGoals[i] = []; } this.seriesGoals[i].push(ser[i].data[j].goals); } else { if (typeof this.seriesGoals[i] === 'undefined') { this.seriesGoals[i] = []; } this.seriesGoals[i].push(null); } } // get seriesX for (var _j2 = 0; _j2 < ser[activeI].data.length; _j2++) { var isXString = typeof ser[activeI].data[_j2].x === 'string'; var isXArr = Array.isArray(ser[activeI].data[_j2].x); var isXDate = !isXArr && !!dt.isValidDate(ser[activeI].data[_j2].x.toString()); if (isXString || isXDate) { // user supplied '01/01/2017' or a date string (a JS date object is not supported) if (isXString || cnf.xaxis.convertedCatToNumeric) { var isRangeColumn = gl.isBarHorizontal && gl.isRangeData; if (cnf.xaxis.type === 'datetime' && !isRangeColumn) { this.twoDSeriesX.push(dt.parseDate(ser[activeI].data[_j2].x)); } else { // a category and not a numeric x value this.fallbackToCategory = true; this.twoDSeriesX.push(ser[activeI].data[_j2].x); } } else { if (cnf.xaxis.type === 'datetime') { this.twoDSeriesX.push(dt.parseDate(ser[activeI].data[_j2].x.toString())); } else { gl.dataFormatXNumeric = true; gl.isXNumeric = true; this.twoDSeriesX.push(parseFloat(ser[activeI].data[_j2].x)); } } } else if (isXArr) { // a multiline label described in array format this.fallbackToCategory = true; this.twoDSeriesX.push(ser[activeI].data[_j2].x); } else { // a numeric value in x property gl.isXNumeric = true; gl.dataFormatXNumeric = true; this.twoDSeriesX.push(ser[activeI].data[_j2].x); } } if (ser[i].data[0] && typeof ser[i].data[0].z !== 'undefined') { for (var t = 0; t < ser[i].data.length; t++) { this.threeDSeries.push(ser[i].data[t].z); } gl.isDataXYZ = true; } } }, { key: "handleRangeData", value: function handleRangeData(ser, i) { var gl = this.w.globals; var range = {}; if (this.isFormat2DArray()) { range = this.handleRangeDataFormat('array', ser, i); } else if (this.isFormatXY()) { range = this.handleRangeDataFormat('xy', ser, i); } gl.seriesRangeStart.push(range.start); gl.seriesRangeEnd.push(range.end); gl.seriesRange.push(range.rangeUniques); // check for overlaps to avoid clashes in a timeline chart gl.seriesRange.forEach(function (sr, si) { if (sr) { sr.forEach(function (sarr, sarri) { sarr.y.forEach(function (arr, arri) { for (var sri = 0; sri < sarr.y.length; sri++) { if (arri !== sri) { var range1y1 = arr.y1; var range1y2 = arr.y2; var range2y1 = sarr.y[sri].y1; var range2y2 = sarr.y[sri].y2; if (range1y1 <= range2y2 && range2y1 <= range1y2) { if (sarr.overlaps.indexOf(arr.rangeName) < 0) { sarr.overlaps.push(arr.rangeName); } if (sarr.overlaps.indexOf(sarr.y[sri].rangeName) < 0) { sarr.overlaps.push(sarr.y[sri].rangeName); } } } } }); }); } }); return range; } }, { key: "handleCandleStickBoxData", value: function handleCandleStickBoxData(ser, i) { var gl = this.w.globals; var ohlc = {}; if (this.isFormat2DArray()) { ohlc = this.handleCandleStickBoxDataFormat('array', ser, i); } else if (this.isFormatXY()) { ohlc = this.handleCandleStickBoxDataFormat('xy', ser, i); } gl.seriesCandleO[i] = ohlc.o; gl.seriesCandleH[i] = ohlc.h; gl.seriesCandleM[i] = ohlc.m; gl.seriesCandleL[i] = ohlc.l; gl.seriesCandleC[i] = ohlc.c; return ohlc; } }, { key: "handleRangeDataFormat", value: function handleRangeDataFormat(format, ser, i) { var rangeStart = []; var rangeEnd = []; var uniqueKeys = ser[i].data.filter(function (thing, index, self) { return index === self.findIndex(function (t) { return t.x === thing.x; }); }).map(function (r, index) { return { x: r.x, overlaps: [], y: [] }; }); if (format === 'array') { for (var j = 0; j < ser[i].data.length; j++) { if (Array.isArray(ser[i].data[j])) { rangeStart.push(ser[i].data[j][1][0]); rangeEnd.push(ser[i].data[j][1][1]); } else { rangeStart.push(ser[i].data[j]); rangeEnd.push(ser[i].data[j]); } } } else if (format === 'xy') { var _loop = function _loop(_j3) { var isDataPoint2D = Array.isArray(ser[i].data[_j3].y); var id = Utils$1.randomId(); var x = ser[i].data[_j3].x; var y = { y1: isDataPoint2D ? ser[i].data[_j3].y[0] : ser[i].data[_j3].y, y2: isDataPoint2D ? ser[i].data[_j3].y[1] : ser[i].data[_j3].y, rangeName: id }; // mutating config object by adding a new property // TODO: As this is specifically for timeline rangebar charts, update the docs mentioning the series only supports xy format ser[i].data[_j3].rangeName = id; var uI = uniqueKeys.findIndex(function (t) { return t.x === x; }); uniqueKeys[uI].y.push(y); rangeStart.push(y.y1); rangeEnd.push(y.y2); }; for (var _j3 = 0; _j3 < ser[i].data.length; _j3++) { _loop(_j3); } } return { start: rangeStart, end: rangeEnd, rangeUniques: uniqueKeys }; } }, { key: "handleCandleStickBoxDataFormat", value: function handleCandleStickBoxDataFormat(format, ser, i) { var w = this.w; var isBoxPlot = w.config.chart.type === 'boxPlot' || w.config.series[i].type === 'boxPlot'; var serO = []; var serH = []; var serM = []; var serL = []; var serC = []; if (format === 'array') { if (isBoxPlot && ser[i].data[0].length === 6 || !isBoxPlot && ser[i].data[0].length === 5) { for (var j = 0; j < ser[i].data.length; j++) { serO.push(ser[i].data[j][1]); serH.push(ser[i].data[j][2]); if (isBoxPlot) { serM.push(ser[i].data[j][3]); serL.push(ser[i].data[j][4]); serC.push(ser[i].data[j][5]); } else { serL.push(ser[i].data[j][3]); serC.push(ser[i].data[j][4]); } } } else { for (var _j4 = 0; _j4 < ser[i].data.length; _j4++) { if (Array.isArray(ser[i].data[_j4][1])) { serO.push(ser[i].data[_j4][1][0]); serH.push(ser[i].data[_j4][1][1]); if (isBoxPlot) { serM.push(ser[i].data[_j4][1][2]); serL.push(ser[i].data[_j4][1][3]); serC.push(ser[i].data[_j4][1][4]); } else { serL.push(ser[i].data[_j4][1][2]); serC.push(ser[i].data[_j4][1][3]); } } } } } else if (format === 'xy') { for (var _j5 = 0; _j5 < ser[i].data.length; _j5++) { if (Array.isArray(ser[i].data[_j5].y)) { serO.push(ser[i].data[_j5].y[0]); serH.push(ser[i].data[_j5].y[1]); if (isBoxPlot) { serM.push(ser[i].data[_j5].y[2]); serL.push(ser[i].data[_j5].y[3]); serC.push(ser[i].data[_j5].y[4]); } else { serL.push(ser[i].data[_j5].y[2]); serC.push(ser[i].data[_j5].y[3]); } } } } return { o: serO, h: serH, m: serM, l: serL, c: serC }; } }, { key: "parseDataAxisCharts", value: function parseDataAxisCharts(ser) { var _this = this; var ctx = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.ctx; var cnf = this.w.config; var gl = this.w.globals; var dt = new DateTime(ctx); var xlabels = cnf.labels.length > 0 ? cnf.labels.slice() : cnf.xaxis.categories.slice(); gl.isRangeBar = cnf.chart.type === 'rangeBar' && gl.isBarHorizontal; gl.hasGroups = cnf.xaxis.type === 'category' && cnf.xaxis.group.groups.length > 0; if (gl.hasGroups) { gl.groups = cnf.xaxis.group.groups; } var handleDates = function handleDates() { for (var j = 0; j < xlabels.length; j++) { if (typeof xlabels[j] === 'string') { // user provided date strings var isDate = dt.isValidDate(xlabels[j]); if (isDate) { _this.twoDSeriesX.push(dt.parseDate(xlabels[j])); } else { throw new Error('You have provided invalid Date format. Please provide a valid JavaScript Date'); } } else { // user provided timestamps _this.twoDSeriesX.push(xlabels[j]); } } }; for (var i = 0; i < ser.length; i++) { this.twoDSeries = []; this.twoDSeriesX = []; this.threeDSeries = []; if (typeof ser[i].data === 'undefined') { console.error("It is a possibility that you may have not included 'data' property in series."); return; } if (cnf.chart.type === 'rangeBar' || cnf.chart.type === 'rangeArea' || ser[i].type === 'rangeBar' || ser[i].type === 'rangeArea') { gl.isRangeData = true; if (gl.isComboCharts) { if (ser[i].type === 'rangeBar' || ser[i].type === 'rangeArea') { this.handleRangeData(ser, i); } } else if (cnf.chart.type === 'rangeBar' || cnf.chart.type === 'rangeArea') { this.handleRangeData(ser, i); } } if (this.isMultiFormat()) { if (this.isFormat2DArray()) { this.handleFormat2DArray(ser, i); } else if (this.isFormatXY()) { this.handleFormatXY(ser, i); } if (cnf.chart.type === 'candlestick' || ser[i].type === 'candlestick' || cnf.chart.type === 'boxPlot' || ser[i].type === 'boxPlot') { this.handleCandleStickBoxData(ser, i); } gl.series.push(this.twoDSeries); gl.labels.push(this.twoDSeriesX); gl.seriesX.push(this.twoDSeriesX); gl.seriesGoals = this.seriesGoals; if (i === this.activeSeriesIndex && !this.fallbackToCategory) { gl.isXNumeric = true; } } else { if (cnf.xaxis.type === 'datetime') { // user didn't supplied [{x,y}] or [[x,y]], but single array in data. // Also labels/categories were supplied differently gl.isXNumeric = true; handleDates(); gl.seriesX.push(this.twoDSeriesX); } else if (cnf.xaxis.type === 'numeric') { gl.isXNumeric = true; if (xlabels.length > 0) { this.twoDSeriesX = xlabels; gl.seriesX.push(this.twoDSeriesX); } } gl.labels.push(this.twoDSeriesX); var singleArray = ser[i].data.map(function (d) { return Utils$1.parseNumber(d); }); gl.series.push(singleArray); } gl.seriesZ.push(this.threeDSeries); if (ser[i].name !== undefined) { gl.seriesNames.push(ser[i].name); } else { gl.seriesNames.push('series-' + parseInt(i + 1, 10)); } // overrided default color if user inputs color with series data if (ser[i].color !== undefined) { gl.seriesColors.push(ser[i].color); } else { gl.seriesColors.push(undefined); } } return this.w; } }, { key: "parseDataNonAxisCharts", value: function parseDataNonAxisCharts(ser) { var gl = this.w.globals; var cnf = this.w.config; gl.series = ser.slice(); gl.seriesNames = cnf.labels.slice(); for (var i = 0; i < gl.series.length; i++) { if (gl.seriesNames[i] === undefined) { gl.seriesNames.push('series-' + (i + 1)); } } return this.w; } /** User possibly set string categories in xaxis.categories or labels prop * Or didn't set xaxis labels at all - in which case we manually do it. * If user passed series data as [[3, 2], [4, 5]] or [{ x: 3, y: 55 }], * this shouldn't be called * @param {array} ser - the series which user passed to the config */ }, { key: "handleExternalLabelsData", value: function handleExternalLabelsData(ser) { var cnf = this.w.config; var gl = this.w.globals; if (cnf.xaxis.categories.length > 0) { // user provided labels in xaxis.category prop gl.labels = cnf.xaxis.categories; } else if (cnf.labels.length > 0) { // user provided labels in labels props gl.labels = cnf.labels.slice(); } else if (this.fallbackToCategory) { // user provided labels in x prop in [{ x: 3, y: 55 }] data, and those labels are already stored in gl.labels[0], so just re-arrange the gl.labels array gl.labels = gl.labels[0]; if (gl.seriesRange.length) { gl.seriesRange.map(function (srt) { srt.forEach(function (sr) { if (gl.labels.indexOf(sr.x) < 0 && sr.x) { gl.labels.push(sr.x); } }); }); gl.labels = gl.labels.filter(function (elem, pos, arr) { return arr.indexOf(elem) === pos; }); } if (cnf.xaxis.convertedCatToNumeric) { var defaults = new Defaults(cnf); defaults.convertCatToNumericXaxis(cnf, this.ctx, gl.seriesX[0]); this._generateExternalLabels(ser); } } else { this._generateExternalLabels(ser); } } }, { key: "_generateExternalLabels", value: function _generateExternalLabels(ser) { var gl = this.w.globals; var cnf = this.w.config; // user didn't provided any labels, fallback to 1-2-3-4-5 var labelArr = []; if (gl.axisCharts) { if (gl.series.length > 0) { if (this.isFormatXY()) { // in case there is a combo chart (boxplot/scatter) // and there are duplicated x values, we need to eliminate duplicates var seriesDataFiltered = cnf.series.map(function (serie, s) { return serie.data.filter(function (v, i, a) { return a.findIndex(function (t) { return t.x === v.x; }) === i; }); }); var len = seriesDataFiltered.reduce(function (p, c, i, a) { return a[p].length > c.length ? p : i; }, 0); for (var i = 0; i < seriesDataFiltered[len].length; i++) { labelArr.push(i + 1); } } else { for (var _i = 0; _i < gl.series[gl.maxValsInArrayIndex].length; _i++) { labelArr.push(_i + 1); } } } gl.seriesX = []; // create gl.seriesX as it will be used in calculations of x positions for (var _i2 = 0; _i2 < ser.length; _i2++) { gl.seriesX.push(labelArr); } // turn on the isXNumeric flag to allow minX and maxX to function properly gl.isXNumeric = true; } // no series to pull labels from, put a 0-10 series // possibly, user collapsed all series. Hence we can't work with above calc if (labelArr.length === 0) { labelArr = gl.axisCharts ? [] : gl.series.map(function (gls, glsi) { return glsi + 1; }); for (var _i3 = 0; _i3 < ser.length; _i3++) { gl.seriesX.push(labelArr); } } // Finally, pass the labelArr in gl.labels which will be printed on x-axis gl.labels = labelArr; if (cnf.xaxis.convertedCatToNumeric) { gl.categoryLabels = labelArr.map(function (l) { return cnf.xaxis.labels.formatter(l); }); } // Turn on this global flag to indicate no labels were provided by user gl.noLabelsProvided = true; } // Segregate user provided data into appropriate vars }, { key: "parseData", value: function parseData(ser) { var w = this.w; var cnf = w.config; var gl = w.globals; this.excludeCollapsedSeriesInYAxis(); // If we detected string in X prop of series, we fallback to category x-axis this.fallbackToCategory = false; this.ctx.core.resetGlobals(); this.ctx.core.isMultipleY(); if (gl.axisCharts) { // axisCharts includes line / area / column / scatter this.parseDataAxisCharts(ser); this.coreUtils.getLargestSeries(); } else { // non-axis charts are pie / donut this.parseDataNonAxisCharts(ser); } // set Null values to 0 in all series when user hides/shows some series if (cnf.chart.type === 'bar' && cnf.chart.stacked) { var series = new Series(this.ctx); gl.series = series.setNullSeriesToZeroValues(gl.series); } this.coreUtils.getSeriesTotals(); if (gl.axisCharts) { gl.stackedSeriesTotals = this.coreUtils.getStackedSeriesTotals(); } this.coreUtils.getPercentSeries(); if (!gl.dataFormatXNumeric && (!gl.isXNumeric || cnf.xaxis.type === 'numeric' && cnf.labels.length === 0 && cnf.xaxis.categories.length === 0)) { // x-axis labels couldn't be detected; hence try searching every option in config this.handleExternalLabelsData(ser); } // check for multiline xaxis var catLabels = this.coreUtils.getCategoryLabels(gl.labels); for (var l = 0; l < catLabels.length; l++) { if (Array.isArray(catLabels[l])) { gl.isMultiLineX = true; break; } } } }, { key: "excludeCollapsedSeriesInYAxis", value: function excludeCollapsedSeriesInYAxis() { var _this2 = this; var w = this.w; w.globals.ignoreYAxisIndexes = w.globals.collapsedSeries.map(function (collapsed, i) { // fix issue #1215 // if stacked, not returning collapsed.index to preserve yaxis if (_this2.w.globals.isMultipleYAxis && !w.config.chart.stacked) { return collapsed.index; } }); } }]); return Data; }(); var AxesUtils = /*#__PURE__*/function () { function AxesUtils(ctx) { _classCallCheck(this, AxesUtils); this.ctx = ctx; this.w = ctx.w; } // Based on the formatter function, get the label text and position _createClass(AxesUtils, [{ key: "getLabel", value: function getLabel(labels, timescaleLabels, x, i) { var drawnLabels = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : []; var fontSize = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : '12px'; var isLeafGroup = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : true; var w = this.w; var rawLabel = typeof labels[i] === 'undefined' ? '' : labels[i]; var label = rawLabel; var xlbFormatter = w.globals.xLabelFormatter; var customFormatter = w.config.xaxis.labels.formatter; var isBold = false; var xFormat = new Formatters(this.ctx); var timestamp = rawLabel; if (isLeafGroup) { label = xFormat.xLabelFormat(xlbFormatter, rawLabel, timestamp, { i: i, dateFormatter: new DateTime(this.ctx).formatDate, w: w }); if (customFormatter !== undefined) { label = customFormatter(rawLabel, labels[i], { i: i, dateFormatter: new DateTime(this.ctx).formatDate, w: w }); } } var determineHighestUnit = function determineHighestUnit(unit) { var highestUnit = null; timescaleLabels.forEach(function (t) { if (t.unit === 'month') { highestUnit = 'year'; } else if (t.unit === 'day') { highestUnit = 'month'; } else if (t.unit === 'hour') { highestUnit = 'day'; } else if (t.unit === 'minute') { highestUnit = 'hour'; } }); return highestUnit === unit; }; if (timescaleLabels.length > 0) { isBold = determineHighestUnit(timescaleLabels[i].unit); x = timescaleLabels[i].position; label = timescaleLabels[i].value; } else { if (w.config.xaxis.type === 'datetime' && customFormatter === undefined) { label = ''; } } if (typeof label === 'undefined') label = ''; label = Array.isArray(label) ? label : label.toString(); var graphics = new Graphics(this.ctx); var textRect = {}; if (w.globals.rotateXLabels && isLeafGroup) { textRect = graphics.getTextRects(label, parseInt(fontSize, 10), null, "rotate(".concat(w.config.xaxis.labels.rotate, " 0 0)"), false); } else { textRect = graphics.getTextRects(label, parseInt(fontSize, 10)); } var allowDuplicatesInTimeScale = !w.config.xaxis.labels.showDuplicates && this.ctx.timeScale; if (!Array.isArray(label) && (label.indexOf('NaN') === 0 || label.toLowerCase().indexOf('invalid') === 0 || label.toLowerCase().indexOf('infinity') >= 0 || drawnLabels.indexOf(label) >= 0 && allowDuplicatesInTimeScale)) { label = ''; } return { x: x, text: label, textRect: textRect, isBold: isBold }; } }, { key: "checkLabelBasedOnTickamount", value: function checkLabelBasedOnTickamount(i, label, labelsLen) { var w = this.w; var ticks = w.config.xaxis.tickAmount; if (ticks === 'dataPoints') ticks = Math.round(w.globals.gridWidth / 120); if (ticks > labelsLen) return label; var tickMultiple = Math.round(labelsLen / (ticks + 1)); if (i % tickMultiple === 0) { return label; } else { label.text = ''; } return label; } }, { key: "checkForOverflowingLabels", value: function checkForOverflowingLabels(i, label, labelsLen, drawnLabels, drawnLabelsRects) { var w = this.w; if (i === 0) { // check if first label is being truncated if (w.globals.skipFirstTimelinelabel) { label.text = ''; } } if (i === labelsLen - 1) { // check if last label is being truncated if (w.globals.skipLastTimelinelabel) { label.text = ''; } } if (w.config.xaxis.labels.hideOverlappingLabels && drawnLabels.length > 0) { var prev = drawnLabelsRects[drawnLabelsRects.length - 1]; if (label.x < prev.textRect.width / (w.globals.rotateXLabels ? Math.abs(w.config.xaxis.labels.rotate) / 12 : 1.01) + prev.x) { label.text = ''; } } return label; } }, { key: "checkForReversedLabels", value: function checkForReversedLabels(i, labels) { var w = this.w; if (w.config.yaxis[i] && w.config.yaxis[i].reversed) { labels.reverse(); } return labels; } }, { key: "isYAxisHidden", value: function isYAxisHidden(index) { var w = this.w; var coreUtils = new CoreUtils(this.ctx); return !w.config.yaxis[index].show || !w.config.yaxis[index].showForNullSeries && coreUtils.isSeriesNull(index) && w.globals.collapsedSeriesIndices.indexOf(index) === -1; } // get the label color for y-axis // realIndex is the actual series index, while i is the tick Index }, { key: "getYAxisForeColor", value: function getYAxisForeColor(yColors, realIndex) { var w = this.w; if (Array.isArray(yColors) && w.globals.yAxisScale[realIndex]) { this.ctx.theme.pushExtraColors(yColors, w.globals.yAxisScale[realIndex].result.length, false); } return yColors; } }, { key: "drawYAxisTicks", value: function drawYAxisTicks(x, tickAmount, axisBorder, axisTicks, realIndex, labelsDivider, elYaxis) { var w = this.w; var graphics = new Graphics(this.ctx); // initial label position = 0; var t = w.globals.translateY; if (axisTicks.show && tickAmount > 0) { if (w.config.yaxis[realIndex].opposite === true) x = x + axisTicks.width; for (var i = tickAmount; i >= 0; i--) { var tY = t + tickAmount / 10 + w.config.yaxis[realIndex].labels.offsetY - 1; if (w.globals.isBarHorizontal) { tY = labelsDivider * i; } if (w.config.chart.type === 'heatmap') { tY = tY + labelsDivider / 2; } var elTick = graphics.drawLine(x + axisBorder.offsetX - axisTicks.width + axisTicks.offsetX, tY + axisTicks.offsetY, x + axisBorder.offsetX + axisTicks.offsetX, tY + axisTicks.offsetY, axisTicks.color); elYaxis.add(elTick); t = t + labelsDivider; } } } }]); return AxesUtils; }(); var Exports = /*#__PURE__*/function () { function Exports(ctx) { _classCallCheck(this, Exports); this.ctx = ctx; this.w = ctx.w; } _createClass(Exports, [{ key: "scaleSvgNode", value: function scaleSvgNode(svg, scale) { // get current both width and height of the svg var svgWidth = parseFloat(svg.getAttributeNS(null, 'width')); var svgHeight = parseFloat(svg.getAttributeNS(null, 'height')); // set new width and height based on the scale svg.setAttributeNS(null, 'width', svgWidth * scale); svg.setAttributeNS(null, 'height', svgHeight * scale); svg.setAttributeNS(null, 'viewBox', '0 0 ' + svgWidth + ' ' + svgHeight); } }, { key: "fixSvgStringForIe11", value: function fixSvgStringForIe11(svgData) { // IE11 generates broken SVG that we have to fix by using regex if (!Utils$1.isIE11()) { // not IE11 - noop return svgData.replace(/ /g, ' '); } // replace second occurrence of "xmlns" attribute with "xmlns:xlink" with correct url + add xmlns:svgjs var nXmlnsSeen = 0; var result = svgData.replace(/xmlns="http:\/\/www.w3.org\/2000\/svg"/g, function (match) { nXmlnsSeen++; return nXmlnsSeen === 2 ? 'xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev"' : match; }); // remove the invalid empty namespace declarations result = result.replace(/xmlns:NS\d+=""/g, ''); // remove these broken namespaces from attributes result = result.replace(/NS\d+:(\w+:\w+=")/g, '$1'); return result; } }, { key: "getSvgString", value: function getSvgString(scale) { if (scale == undefined) { scale = 1; // if no scale is specified, don't scale... } var svgString = this.w.globals.dom.Paper.svg(); // in case the scale is different than 1, the svg needs to be rescaled if (scale !== 1) { // clone the svg node so it remains intact in the UI var svgNode = this.w.globals.dom.Paper.node.cloneNode(true); // scale the image this.scaleSvgNode(svgNode, scale); // get the string representation of the svgNode svgString = new XMLSerializer().serializeToString(svgNode); } return this.fixSvgStringForIe11(svgString); } }, { key: "cleanup", value: function cleanup() { var w = this.w; // hide some elements to avoid printing them on exported svg var xcrosshairs = w.globals.dom.baseEl.getElementsByClassName('apexcharts-xcrosshairs'); var ycrosshairs = w.globals.dom.baseEl.getElementsByClassName('apexcharts-ycrosshairs'); var zoomSelectionRects = w.globals.dom.baseEl.querySelectorAll('.apexcharts-zoom-rect, .apexcharts-selection-rect'); Array.prototype.forEach.call(zoomSelectionRects, function (z) { z.setAttribute('width', 0); }); if (xcrosshairs && xcrosshairs[0]) { xcrosshairs[0].setAttribute('x', -500); xcrosshairs[0].setAttribute('x1', -500); xcrosshairs[0].setAttribute('x2', -500); } if (ycrosshairs && ycrosshairs[0]) { ycrosshairs[0].setAttribute('y', -100); ycrosshairs[0].setAttribute('y1', -100); ycrosshairs[0].setAttribute('y2', -100); } } }, { key: "svgUrl", value: function svgUrl() { this.cleanup(); var svgData = this.getSvgString(); var svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' }); return URL.createObjectURL(svgBlob); } }, { key: "dataURI", value: function dataURI(options) { var _this = this; return new Promise(function (resolve) { var w = _this.w; var scale = options ? options.scale || options.width / w.globals.svgWidth : 1; _this.cleanup(); var canvas = document.createElement('canvas'); canvas.width = w.globals.svgWidth * scale; canvas.height = parseInt(w.globals.dom.elWrap.style.height, 10) * scale; // because of resizeNonAxisCharts var canvasBg = w.config.chart.background === 'transparent' ? '#fff' : w.config.chart.background; var ctx = canvas.getContext('2d'); ctx.fillStyle = canvasBg; ctx.fillRect(0, 0, canvas.width * scale, canvas.height * scale); var svgData = _this.getSvgString(scale); if (window.canvg && Utils$1.isIE11()) { // use canvg as a polyfill to workaround ie11 considering a canvas with loaded svg 'unsafe' // without ignoreClear we lose our background color; without ignoreDimensions some grid lines become invisible var v = window.canvg.Canvg.fromString(ctx, svgData, { ignoreClear: true, ignoreDimensions: true }); // render the svg to canvas v.start(); var blob = canvas.msToBlob(); // dispose - missing this will cause a memory leak v.stop(); resolve({ blob: blob }); } else { var svgUrl = 'data:image/svg+xml,' + encodeURIComponent(svgData); var img = new Image(); img.crossOrigin = 'anonymous'; img.onload = function () { ctx.drawImage(img, 0, 0); if (canvas.msToBlob) { // IE and Edge can't navigate to data urls, so we return the blob instead var _blob = canvas.msToBlob(); resolve({ blob: _blob }); } else { var imgURI = canvas.toDataURL('image/png'); resolve({ imgURI: imgURI }); } }; img.src = svgUrl; } }); } }, { key: "exportToSVG", value: function exportToSVG() { this.triggerDownload(this.svgUrl(), this.w.config.chart.toolbar.export.svg.filename, '.svg'); } }, { key: "exportToPng", value: function exportToPng() { var _this2 = this; this.dataURI().then(function (_ref) { var imgURI = _ref.imgURI, blob = _ref.blob; if (blob) { navigator.msSaveOrOpenBlob(blob, _this2.w.globals.chartID + '.png'); } else { _this2.triggerDownload(imgURI, _this2.w.config.chart.toolbar.export.png.filename, '.png'); } }); } }, { key: "exportToCSV", value: function exportToCSV(_ref2) { var _this3 = this; var series = _ref2.series, fileName = _ref2.fileName, _ref2$columnDelimiter = _ref2.columnDelimiter, columnDelimiter = _ref2$columnDelimiter === void 0 ? ',' : _ref2$columnDelimiter, _ref2$lineDelimiter = _ref2.lineDelimiter, lineDelimiter = _ref2$lineDelimiter === void 0 ? '\n' : _ref2$lineDelimiter; var w = this.w; if (!series) series = w.config.series; var columns = []; var rows = []; var result = ''; var universalBOM = "\uFEFF"; var gSeries = w.globals.series.map(function (s, i) { return w.globals.collapsedSeriesIndices.indexOf(i) === -1 ? s : []; }); var isTimeStamp = function isTimeStamp(num) { return w.config.xaxis.type === 'datetime' && String(num).length >= 10; }; var seriesMaxDataLength = Math.max.apply(Math, _toConsumableArray(series.map(function (s) { return s.data ? s.data.length : 0; }))); var dataFormat = new Data(this.ctx); var axesUtils = new AxesUtils(this.ctx); var getCat = function getCat(i) { var cat = ''; // pie / donut/ radial if (!w.globals.axisCharts) { cat = w.config.labels[i]; } else { // xy charts // non datetime if (w.config.xaxis.type === 'category' || w.config.xaxis.convertedCatToNumeric) { if (w.globals.isBarHorizontal) { var lbFormatter = w.globals.yLabelFormatters[0]; var sr = new Series(_this3.ctx); var activeSeries = sr.getActiveConfigSeriesIndex(); cat = lbFormatter(w.globals.labels[i], { seriesIndex: activeSeries, dataPointIndex: i, w: w }); } else { cat = axesUtils.getLabel(w.globals.labels, w.globals.timescaleLabels, 0, i).text; } } // datetime, but labels specified in categories or labels if (w.config.xaxis.type === 'datetime') { if (w.config.xaxis.categories.length) { cat = w.config.xaxis.categories[i]; } else if (w.config.labels.length) { cat = w.config.labels[i]; } } } if (Array.isArray(cat)) { cat = cat.join(' '); } return Utils$1.isNumber(cat) ? cat : cat.split(columnDelimiter).join(''); }; // Fix https://github.com/apexcharts/apexcharts.js/issues/3365 var getEmptyDataForCsvColumn = function getEmptyDataForCsvColumn() { return _toConsumableArray(Array(seriesMaxDataLength)).map(function () { return ''; }); }; var handleAxisRowsColumns = function handleAxisRowsColumns(s, sI) { if (columns.length && sI === 0) { // It's the first series. Go ahead and create the first row with header information. rows.push(columns.join(columnDelimiter)); } if (s.data) { // Use the data we have, or generate a properly sized empty array with empty data if some data is missing. s.data = s.data.length && s.data || getEmptyDataForCsvColumn(); for (var i = 0; i < s.data.length; i++) { // Reset the columns array so that we can start building columns for this row. columns = []; var cat = getCat(i); if (!cat) { if (dataFormat.isFormatXY()) { cat = series[sI].data[i].x; } else if (dataFormat.isFormat2DArray()) { cat = series[sI].data[i] ? series[sI].data[i][0] : ''; } } if (sI === 0) { // It's the first series. Also handle the category. columns.push(isTimeStamp(cat) ? w.config.chart.toolbar.export.csv.dateFormatter(cat) : Utils$1.isNumber(cat) ? cat : cat.split(columnDelimiter).join('')); for (var ci = 0; ci < w.globals.series.length; ci++) { if (dataFormat.isFormatXY()) { columns.push(series[ci].data[i].y); } else { columns.push(gSeries[ci][i]); } } } if (w.config.chart.type === 'candlestick' || s.type && s.type === 'candlestick') { columns.pop(); columns.push(w.globals.seriesCandleO[sI][i]); columns.push(w.globals.seriesCandleH[sI][i]); columns.push(w.globals.seriesCandleL[sI][i]); columns.push(w.globals.seriesCandleC[sI][i]); } if (w.config.chart.type === 'boxPlot' || s.type && s.type === 'boxPlot') { columns.pop(); columns.push(w.globals.seriesCandleO[sI][i]); columns.push(w.globals.seriesCandleH[sI][i]); columns.push(w.globals.seriesCandleM[sI][i]); columns.push(w.globals.seriesCandleL[sI][i]); columns.push(w.globals.seriesCandleC[sI][i]); } if (w.config.chart.type === 'rangeBar') { columns.pop(); columns.push(w.globals.seriesRangeStart[sI][i]); columns.push(w.globals.seriesRangeEnd[sI][i]); } if (columns.length) { rows.push(columns.join(columnDelimiter)); } } } }; columns.push(w.config.chart.toolbar.export.csv.headerCategory); if (w.config.chart.type === 'boxPlot') { columns.push('minimum'); columns.push('q1'); columns.push('median'); columns.push('q3'); columns.push('maximum'); } else if (w.config.chart.type === 'candlestick') { columns.push('open'); columns.push('high'); columns.push('low'); columns.push('close'); } else if (w.config.chart.type === 'rangeBar') { columns.push('minimum'); columns.push('maximum'); } else { series.map(function (s, sI) { var sname = s.name ? s.name : "series-".concat(sI); if (w.globals.axisCharts) { columns.push(sname.split(columnDelimiter).join('') ? sname.split(columnDelimiter).join('') : "series-".concat(sI)); } }); } if (!w.globals.axisCharts) { columns.push(w.config.chart.toolbar.export.csv.headerValue); rows.push(columns.join(columnDelimiter)); } series.map(function (s, sI) { if (w.globals.axisCharts) { handleAxisRowsColumns(s, sI); } else { columns = []; columns.push(w.globals.labels[sI].split(columnDelimiter).join('')); columns.push(gSeries[sI]); rows.push(columns.join(columnDelimiter)); } }); result += rows.join(lineDelimiter); this.triggerDownload('data:text/csv; charset=utf-8,' + encodeURIComponent(universalBOM + result), fileName ? fileName : w.config.chart.toolbar.export.csv.filename, '.csv'); } }, { key: "triggerDownload", value: function triggerDownload(href, filename, ext) { var downloadLink = document.createElement('a'); downloadLink.href = href; downloadLink.download = (filename ? filename : this.w.globals.chartID) + ext; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); } }]); return Exports; }(); /** * ApexCharts XAxis Class for drawing X-Axis. * * @module XAxis **/ var XAxis = /*#__PURE__*/function () { function XAxis(ctx, elgrid) { _classCallCheck(this, XAxis); this.ctx = ctx; this.elgrid = elgrid; this.w = ctx.w; var w = this.w; this.axesUtils = new AxesUtils(ctx); this.xaxisLabels = w.globals.labels.slice(); if (w.globals.timescaleLabels.length > 0 && !w.globals.isBarHorizontal) { // timeline labels are there and chart is not rangeabr timeline this.xaxisLabels = w.globals.timescaleLabels.slice(); } if (w.config.xaxis.overwriteCategories) { this.xaxisLabels = w.config.xaxis.overwriteCategories; } this.drawnLabels = []; this.drawnLabelsRects = []; if (w.config.xaxis.position === 'top') { this.offY = 0; } else { this.offY = w.globals.gridHeight + 1; } this.offY = this.offY + w.config.xaxis.axisBorder.offsetY; this.isCategoryBarHorizontal = w.config.chart.type === 'bar' && w.config.plotOptions.bar.horizontal; this.xaxisFontSize = w.config.xaxis.labels.style.fontSize; this.xaxisFontFamily = w.config.xaxis.labels.style.fontFamily; this.xaxisForeColors = w.config.xaxis.labels.style.colors; this.xaxisBorderWidth = w.config.xaxis.axisBorder.width; if (this.isCategoryBarHorizontal) { this.xaxisBorderWidth = w.config.yaxis[0].axisBorder.width.toString(); } if (this.xaxisBorderWidth.indexOf('%') > -1) { this.xaxisBorderWidth = w.globals.gridWidth * parseInt(this.xaxisBorderWidth, 10) / 100; } else { this.xaxisBorderWidth = parseInt(this.xaxisBorderWidth, 10); } this.xaxisBorderHeight = w.config.xaxis.axisBorder.height; // For bars, we will only consider single y xais, // as we are not providing multiple yaxis for bar charts this.yaxis = w.config.yaxis[0]; } _createClass(XAxis, [{ key: "drawXaxis", value: function drawXaxis() { var w = this.w; var graphics = new Graphics(this.ctx); var elXaxis = graphics.group({ class: 'apexcharts-xaxis', transform: "translate(".concat(w.config.xaxis.offsetX, ", ").concat(w.config.xaxis.offsetY, ")") }); var elXaxisTexts = graphics.group({ class: 'apexcharts-xaxis-texts-g', transform: "translate(".concat(w.globals.translateXAxisX, ", ").concat(w.globals.translateXAxisY, ")") }); elXaxis.add(elXaxisTexts); var labels = []; for (var i = 0; i < this.xaxisLabels.length; i++) { labels.push(this.xaxisLabels[i]); } this.drawXAxisLabelAndGroup(true, graphics, elXaxisTexts, labels, w.globals.isXNumeric, function (i, colWidth) { return colWidth; }); if (w.globals.hasGroups) { var labelsGroup = w.globals.groups; labels = []; for (var _i = 0; _i < labelsGroup.length; _i++) { labels.push(labelsGroup[_i].title); } var overwriteStyles = {}; if (w.config.xaxis.group.style) { overwriteStyles.xaxisFontSize = w.config.xaxis.group.style.fontSize; overwriteStyles.xaxisFontFamily = w.config.xaxis.group.style.fontFamily; overwriteStyles.xaxisForeColors = w.config.xaxis.group.style.colors; overwriteStyles.fontWeight = w.config.xaxis.group.style.fontWeight; overwriteStyles.cssClass = w.config.xaxis.group.style.cssClass; } this.drawXAxisLabelAndGroup(false, graphics, elXaxisTexts, labels, false, function (i, colWidth) { return labelsGroup[i].cols * colWidth; }, overwriteStyles); } if (w.config.xaxis.title.text !== undefined) { var elXaxisTitle = graphics.group({ class: 'apexcharts-xaxis-title' }); var elXAxisTitleText = graphics.drawText({ x: w.globals.gridWidth / 2 + w.config.xaxis.title.offsetX, y: this.offY + parseFloat(this.xaxisFontSize) + (w.config.xaxis.position === 'bottom' ? w.globals.xAxisLabelsHeight : -w.globals.xAxisLabelsHeight - 10) + w.config.xaxis.title.offsetY, text: w.config.xaxis.title.text, textAnchor: 'middle', fontSize: w.config.xaxis.title.style.fontSize, fontFamily: w.config.xaxis.title.style.fontFamily, fontWeight: w.config.xaxis.title.style.fontWeight, foreColor: w.config.xaxis.title.style.color, cssClass: 'apexcharts-xaxis-title-text ' + w.config.xaxis.title.style.cssClass }); elXaxisTitle.add(elXAxisTitleText); elXaxis.add(elXaxisTitle); } if (w.config.xaxis.axisBorder.show) { var offX = w.globals.barPadForNumericAxis; var elHorzLine = graphics.drawLine(w.globals.padHorizontal + w.config.xaxis.axisBorder.offsetX - offX, this.offY, this.xaxisBorderWidth + offX, this.offY, w.config.xaxis.axisBorder.color, 0, this.xaxisBorderHeight); if (this.elgrid && this.elgrid.elGridBorders) { this.elgrid.elGridBorders.add(elHorzLine); } else { elXaxis.add(elHorzLine); } } return elXaxis; } }, { key: "drawXAxisLabelAndGroup", value: function drawXAxisLabelAndGroup(isLeafGroup, graphics, elXaxisTexts, labels, isXNumeric, colWidthCb) { var _this = this; var overwriteStyles = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : {}; var drawnLabels = []; var drawnLabelsRects = []; var w = this.w; var xaxisFontSize = overwriteStyles.xaxisFontSize || this.xaxisFontSize; var xaxisFontFamily = overwriteStyles.xaxisFontFamily || this.xaxisFontFamily; var xaxisForeColors = overwriteStyles.xaxisForeColors || this.xaxisForeColors; var fontWeight = overwriteStyles.fontWeight || w.config.xaxis.labels.style.fontWeight; var cssClass = overwriteStyles.cssClass || w.config.xaxis.labels.style.cssClass; var colWidth; // initial x Position (keep adding column width in the loop) var xPos = w.globals.padHorizontal; var labelsLen = labels.length; /** * labelsLen can be different (whether you are drawing x-axis labels or x-axis group labels) * hence, we introduce dataPoints to be consistent. * Also, in datetime/numeric xaxis, dataPoints can be misleading, so we resort to labelsLen for such xaxis type */ var dataPoints = w.config.xaxis.type === 'category' ? w.globals.dataPoints : labelsLen; // when all series are collapsed, fixes #3381 if (dataPoints === 0 && labelsLen > dataPoints) dataPoints = labelsLen; if (isXNumeric) { var len = dataPoints > 1 ? dataPoints - 1 : dataPoints; colWidth = w.globals.gridWidth / len; xPos = xPos + colWidthCb(0, colWidth) / 2 + w.config.xaxis.labels.offsetX; } else { colWidth = w.globals.gridWidth / dataPoints; xPos = xPos + colWidthCb(0, colWidth) + w.config.xaxis.labels.offsetX; } var _loop = function _loop(i) { var x = xPos - colWidthCb(i, colWidth) / 2 + w.config.xaxis.labels.offsetX; if (i === 0 && labelsLen === 1 && colWidth / 2 === xPos && dataPoints === 1) { // single datapoint x = w.globals.gridWidth / 2; } var label = _this.axesUtils.getLabel(labels, w.globals.timescaleLabels, x, i, drawnLabels, xaxisFontSize, isLeafGroup); var offsetYCorrection = 28; if (w.globals.rotateXLabels && isLeafGroup) { offsetYCorrection = 22; } if (w.config.xaxis.title.text && w.config.xaxis.position === 'top') { offsetYCorrection += parseFloat(w.config.xaxis.title.style.fontSize) + 2; } if (!isLeafGroup) { offsetYCorrection = offsetYCorrection + parseFloat(xaxisFontSize) + (w.globals.xAxisLabelsHeight - w.globals.xAxisGroupLabelsHeight) + (w.globals.rotateXLabels ? 10 : 0); } var isCategoryTickAmounts = typeof w.config.xaxis.tickAmount !== 'undefined' && w.config.xaxis.tickAmount !== 'dataPoints' && w.config.xaxis.type !== 'datetime'; if (isCategoryTickAmounts) { label = _this.axesUtils.checkLabelBasedOnTickamount(i, label, labelsLen); } else { label = _this.axesUtils.checkForOverflowingLabels(i, label, labelsLen, drawnLabels, drawnLabelsRects); } var getCatForeColor = function getCatForeColor() { return isLeafGroup && w.config.xaxis.convertedCatToNumeric ? xaxisForeColors[w.globals.minX + i - 1] : xaxisForeColors[i]; }; if (w.config.xaxis.labels.show) { var elText = graphics.drawText({ x: label.x, y: _this.offY + w.config.xaxis.labels.offsetY + offsetYCorrection - (w.config.xaxis.position === 'top' ? w.globals.xAxisHeight + w.config.xaxis.axisTicks.height - 2 : 0), text: label.text, textAnchor: 'middle', fontWeight: label.isBold ? 600 : fontWeight, fontSize: xaxisFontSize, fontFamily: xaxisFontFamily, foreColor: Array.isArray(xaxisForeColors) ? getCatForeColor() : xaxisForeColors, isPlainText: false, cssClass: (isLeafGroup ? 'apexcharts-xaxis-label ' : 'apexcharts-xaxis-group-label ') + cssClass }); elXaxisTexts.add(elText); elText.on('click', function (e) { if (typeof w.config.chart.events.xAxisLabelClick === 'function') { var opts = Object.assign({}, w, { labelIndex: i }); w.config.chart.events.xAxisLabelClick(e, _this.ctx, opts); } }); if (isLeafGroup) { var elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title'); elTooltipTitle.textContent = Array.isArray(label.text) ? label.text.join(' ') : label.text; elText.node.appendChild(elTooltipTitle); if (label.text !== '') { drawnLabels.push(label.text); drawnLabelsRects.push(label); } } } if (i < labelsLen - 1) { xPos = xPos + colWidthCb(i + 1, colWidth); } }; for (var i = 0; i <= labelsLen - 1; i++) { _loop(i); } } // this actually becomes the vertical axis (for bar charts) }, { key: "drawXaxisInversed", value: function drawXaxisInversed(realIndex) { var _this2 = this; var w = this.w; var graphics = new Graphics(this.ctx); var translateYAxisX = w.config.yaxis[0].opposite ? w.globals.translateYAxisX[realIndex] : 0; var elYaxis = graphics.group({ class: 'apexcharts-yaxis apexcharts-xaxis-inversed', rel: realIndex }); var elYaxisTexts = graphics.group({ class: 'apexcharts-yaxis-texts-g apexcharts-xaxis-inversed-texts-g', transform: 'translate(' + translateYAxisX + ', 0)' }); elYaxis.add(elYaxisTexts); var colHeight; // initial x Position (keep adding column width in the loop) var yPos; var labels = []; if (w.config.yaxis[realIndex].show) { for (var i = 0; i < this.xaxisLabels.length; i++) { labels.push(this.xaxisLabels[i]); } } colHeight = w.globals.gridHeight / labels.length; yPos = -(colHeight / 2.2); var lbFormatter = w.globals.yLabelFormatters[0]; var ylabels = w.config.yaxis[0].labels; if (ylabels.show) { var _loop2 = function _loop2(_i2) { var label = typeof labels[_i2] === 'undefined' ? '' : labels[_i2]; label = lbFormatter(label, { seriesIndex: realIndex, dataPointIndex: _i2, w: w }); var yColors = _this2.axesUtils.getYAxisForeColor(ylabels.style.colors, realIndex); var getForeColor = function getForeColor() { return Array.isArray(yColors) ? yColors[_i2] : yColors; }; var multiY = 0; if (Array.isArray(label)) { multiY = label.length / 2 * parseInt(ylabels.style.fontSize, 10); } var offsetX = ylabels.offsetX - 15; var textAnchor = 'end'; if (_this2.yaxis.opposite) { textAnchor = 'start'; } if (w.config.yaxis[0].labels.align === 'left') { offsetX = ylabels.offsetX; textAnchor = 'start'; } else if (w.config.yaxis[0].labels.align === 'center') { offsetX = ylabels.offsetX; textAnchor = 'middle'; } else if (w.config.yaxis[0].labels.align === 'right') { textAnchor = 'end'; } var elLabel = graphics.drawText({ x: offsetX, y: yPos + colHeight + ylabels.offsetY - multiY, text: label, textAnchor: textAnchor, foreColor: getForeColor(), fontSize: ylabels.style.fontSize, fontFamily: ylabels.style.fontFamily, fontWeight: ylabels.style.fontWeight, isPlainText: false, cssClass: 'apexcharts-yaxis-label ' + ylabels.style.cssClass, maxWidth: ylabels.maxWidth }); elYaxisTexts.add(elLabel); elLabel.on('click', function (e) { if (typeof w.config.chart.events.xAxisLabelClick === 'function') { var opts = Object.assign({}, w, { labelIndex: _i2 }); w.config.chart.events.xAxisLabelClick(e, _this2.ctx, opts); } }); var elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title'); elTooltipTitle.textContent = Array.isArray(label) ? label.join(' ') : label; elLabel.node.appendChild(elTooltipTitle); if (w.config.yaxis[realIndex].labels.rotate !== 0) { var labelRotatingCenter = graphics.rotateAroundCenter(elLabel.node); elLabel.node.setAttribute('transform', "rotate(".concat(w.config.yaxis[realIndex].labels.rotate, " 0 ").concat(labelRotatingCenter.y, ")")); } yPos = yPos + colHeight; }; for (var _i2 = 0; _i2 <= labels.length - 1; _i2++) { _loop2(_i2); } } if (w.config.yaxis[0].title.text !== undefined) { var elXaxisTitle = graphics.group({ class: 'apexcharts-yaxis-title apexcharts-xaxis-title-inversed', transform: 'translate(' + translateYAxisX + ', 0)' }); var elXAxisTitleText = graphics.drawText({ x: w.config.yaxis[0].title.offsetX, y: w.globals.gridHeight / 2 + w.config.yaxis[0].title.offsetY, text: w.config.yaxis[0].title.text, textAnchor: 'middle', foreColor: w.config.yaxis[0].title.style.color, fontSize: w.config.yaxis[0].title.style.fontSize, fontWeight: w.config.yaxis[0].title.style.fontWeight, fontFamily: w.config.yaxis[0].title.style.fontFamily, cssClass: 'apexcharts-yaxis-title-text ' + w.config.yaxis[0].title.style.cssClass }); elXaxisTitle.add(elXAxisTitleText); elYaxis.add(elXaxisTitle); } var offX = 0; if (this.isCategoryBarHorizontal && w.config.yaxis[0].opposite) { offX = w.globals.gridWidth; } var axisBorder = w.config.xaxis.axisBorder; if (axisBorder.show) { var elVerticalLine = graphics.drawLine(w.globals.padHorizontal + axisBorder.offsetX + offX, 1 + axisBorder.offsetY, w.globals.padHorizontal + axisBorder.offsetX + offX, w.globals.gridHeight + axisBorder.offsetY, axisBorder.color, 0); if (this.elgrid && this.elgrid.elGridBorders) { this.elgrid.elGridBorders.add(elVerticalLine); } else { elYaxis.add(elVerticalLine); } } if (w.config.yaxis[0].axisTicks.show) { this.axesUtils.drawYAxisTicks(offX, labels.length, w.config.yaxis[0].axisBorder, w.config.yaxis[0].axisTicks, 0, colHeight, elYaxis); } return elYaxis; } }, { key: "drawXaxisTicks", value: function drawXaxisTicks(x1, y2, appendToElement) { var w = this.w; var x2 = x1; if (x1 < 0 || x1 - 2 > w.globals.gridWidth) return; var y1 = this.offY + w.config.xaxis.axisTicks.offsetY; y2 = y2 + y1 + w.config.xaxis.axisTicks.height; if (w.config.xaxis.position === 'top') { y2 = y1 - w.config.xaxis.axisTicks.height; } if (w.config.xaxis.axisTicks.show) { var graphics = new Graphics(this.ctx); var line = graphics.drawLine(x1 + w.config.xaxis.axisTicks.offsetX, y1 + w.config.xaxis.offsetY, x2 + w.config.xaxis.axisTicks.offsetX, y2 + w.config.xaxis.offsetY, w.config.xaxis.axisTicks.color); // we are not returning anything, but appending directly to the element passed in param appendToElement.add(line); line.node.classList.add('apexcharts-xaxis-tick'); } } }, { key: "getXAxisTicksPositions", value: function getXAxisTicksPositions() { var w = this.w; var xAxisTicksPositions = []; var xCount = this.xaxisLabels.length; var x1 = w.globals.padHorizontal; if (w.globals.timescaleLabels.length > 0) { for (var i = 0; i < xCount; i++) { x1 = this.xaxisLabels[i].position; xAxisTicksPositions.push(x1); } } else { var xCountForCategoryCharts = xCount; for (var _i3 = 0; _i3 < xCountForCategoryCharts; _i3++) { var x1Count = xCountForCategoryCharts; if (w.globals.isXNumeric && w.config.chart.type !== 'bar') { x1Count -= 1; } x1 = x1 + w.globals.gridWidth / x1Count; xAxisTicksPositions.push(x1); } } return xAxisTicksPositions; } // to rotate x-axis labels or to put ... for longer text in xaxis }, { key: "xAxisLabelCorrections", value: function xAxisLabelCorrections() { var w = this.w; var graphics = new Graphics(this.ctx); var xAxis = w.globals.dom.baseEl.querySelector('.apexcharts-xaxis-texts-g'); var xAxisTexts = w.globals.dom.baseEl.querySelectorAll('.apexcharts-xaxis-texts-g text:not(.apexcharts-xaxis-group-label)'); var yAxisTextsInversed = w.globals.dom.baseEl.querySelectorAll('.apexcharts-yaxis-inversed text'); var xAxisTextsInversed = w.globals.dom.baseEl.querySelectorAll('.apexcharts-xaxis-inversed-texts-g text tspan'); if (w.globals.rotateXLabels || w.config.xaxis.labels.rotateAlways) { for (var xat = 0; xat < xAxisTexts.length; xat++) { var textRotatingCenter = graphics.rotateAroundCenter(xAxisTexts[xat]); textRotatingCenter.y = textRotatingCenter.y - 1; // + tickWidth/4; textRotatingCenter.x = textRotatingCenter.x + 1; xAxisTexts[xat].setAttribute('transform', "rotate(".concat(w.config.xaxis.labels.rotate, " ").concat(textRotatingCenter.x, " ").concat(textRotatingCenter.y, ")")); xAxisTexts[xat].setAttribute('text-anchor', "end"); var offsetHeight = 10; xAxis.setAttribute('transform', "translate(0, ".concat(-offsetHeight, ")")); var tSpan = xAxisTexts[xat].childNodes; if (w.config.xaxis.labels.trim) { Array.prototype.forEach.call(tSpan, function (ts) { graphics.placeTextWithEllipsis(ts, ts.textContent, w.globals.xAxisLabelsHeight - (w.config.legend.position === 'bottom' ? 20 : 10)); }); } } } else { (function () { var width = w.globals.gridWidth / (w.globals.labels.length + 1); for (var _xat = 0; _xat < xAxisTexts.length; _xat++) { var _tSpan = xAxisTexts[_xat].childNodes; if (w.config.xaxis.labels.trim && w.config.xaxis.type !== 'datetime') { Array.prototype.forEach.call(_tSpan, function (ts) { graphics.placeTextWithEllipsis(ts, ts.textContent, width); }); } } })(); } if (yAxisTextsInversed.length > 0) { // truncate rotated y axis in bar chart (x axis) var firstLabelPosX = yAxisTextsInversed[yAxisTextsInversed.length - 1].getBBox(); var lastLabelPosX = yAxisTextsInversed[0].getBBox(); if (firstLabelPosX.x < -20) { yAxisTextsInversed[yAxisTextsInversed.length - 1].parentNode.removeChild(yAxisTextsInversed[yAxisTextsInversed.length - 1]); } if (lastLabelPosX.x + lastLabelPosX.width > w.globals.gridWidth && !w.globals.isBarHorizontal) { yAxisTextsInversed[0].parentNode.removeChild(yAxisTextsInversed[0]); } // truncate rotated x axis in bar chart (y axis) for (var _xat2 = 0; _xat2 < xAxisTextsInversed.length; _xat2++) { graphics.placeTextWithEllipsis(xAxisTextsInversed[_xat2], xAxisTextsInversed[_xat2].textContent, w.config.yaxis[0].labels.maxWidth - (w.config.yaxis[0].title.text ? parseFloat(w.config.yaxis[0].title.style.fontSize) * 2 : 0) - 15); } } } // renderXAxisBands() { // let w = this.w; // let plotBand = document.createElementNS(w.globals.SVGNS, 'rect') // w.globals.dom.elGraphical.add(plotBand) // } }]); return XAxis; }(); /** * ApexCharts Grid Class for drawing Cartesian Grid. * * @module Grid **/ var Grid = /*#__PURE__*/function () { function Grid(ctx) { _classCallCheck(this, Grid); this.ctx = ctx; this.w = ctx.w; var w = this.w; this.xaxisLabels = w.globals.labels.slice(); this.axesUtils = new AxesUtils(ctx); this.isRangeBar = w.globals.seriesRange.length; if (w.globals.timescaleLabels.length > 0) { // timescaleLabels labels are there this.xaxisLabels = w.globals.timescaleLabels.slice(); } } // when using sparklines or when showing no grid, we need to have a grid area which is reused at many places for other calculations as well _createClass(Grid, [{ key: "drawGridArea", value: function drawGridArea() { var elGrid = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var w = this.w; var graphics = new Graphics(this.ctx); if (elGrid === null) { elGrid = graphics.group({ class: 'apexcharts-grid' }); } var elVerticalLine = graphics.drawLine(w.globals.padHorizontal, 1, w.globals.padHorizontal, w.globals.gridHeight, 'transparent'); var elHorzLine = graphics.drawLine(w.globals.padHorizontal, w.globals.gridHeight, w.globals.gridWidth, w.globals.gridHeight, 'transparent'); elGrid.add(elHorzLine); elGrid.add(elVerticalLine); return elGrid; } }, { key: "drawGrid", value: function drawGrid() { var gl = this.w.globals; var elgrid = null; if (gl.axisCharts) { // grid is drawn after xaxis and yaxis are drawn elgrid = this.renderGrid(); this.drawGridArea(elgrid.el); } return elgrid; } // This mask will clip off overflowing graphics from the drawable area }, { key: "createGridMask", value: function createGridMask() { var w = this.w; var gl = w.globals; var graphics = new Graphics(this.ctx); var strokeSize = Array.isArray(w.config.stroke.width) ? 0 : w.config.stroke.width; if (Array.isArray(w.config.stroke.width)) { var strokeMaxSize = 0; w.config.stroke.width.forEach(function (m) { strokeMaxSize = Math.max(strokeMaxSize, m); }); strokeSize = strokeMaxSize; } gl.dom.elGridRectMask = document.createElementNS(gl.SVGNS, 'clipPath'); gl.dom.elGridRectMask.setAttribute('id', "gridRectMask".concat(gl.cuid)); gl.dom.elGridRectMarkerMask = document.createElementNS(gl.SVGNS, 'clipPath'); gl.dom.elGridRectMarkerMask.setAttribute('id', "gridRectMarkerMask".concat(gl.cuid)); gl.dom.elForecastMask = document.createElementNS(gl.SVGNS, 'clipPath'); gl.dom.elForecastMask.setAttribute('id', "forecastMask".concat(gl.cuid)); gl.dom.elNonForecastMask = document.createElementNS(gl.SVGNS, 'clipPath'); gl.dom.elNonForecastMask.setAttribute('id', "nonForecastMask".concat(gl.cuid)); // let barHalfWidth = 0 var type = w.config.chart.type; var hasBar = type === 'bar' || type === 'rangeBar' || type === 'candlestick' || type === 'boxPlot' || w.globals.comboBarCount > 0; var barWidthLeft = 0; var barWidthRight = 0; if (hasBar && w.globals.isXNumeric && !w.globals.isBarHorizontal) { barWidthLeft = w.config.grid.padding.left; barWidthRight = w.config.grid.padding.right; if (gl.barPadForNumericAxis > barWidthLeft) { barWidthLeft = gl.barPadForNumericAxis; barWidthRight = gl.barPadForNumericAxis; } } gl.dom.elGridRect = graphics.drawRect(-strokeSize / 2 - barWidthLeft - 2, -strokeSize / 2, gl.gridWidth + strokeSize + barWidthRight + barWidthLeft + 4, gl.gridHeight + strokeSize, 0, '#fff'); var markerSize = w.globals.markers.largestSize + 1; gl.dom.elGridRectMarker = graphics.drawRect(-markerSize * 2, -markerSize * 2, gl.gridWidth + markerSize * 4, gl.gridHeight + markerSize * 4, 0, '#fff'); gl.dom.elGridRectMask.appendChild(gl.dom.elGridRect.node); gl.dom.elGridRectMarkerMask.appendChild(gl.dom.elGridRectMarker.node); var defs = gl.dom.baseEl.querySelector('defs'); defs.appendChild(gl.dom.elGridRectMask); defs.appendChild(gl.dom.elForecastMask); defs.appendChild(gl.dom.elNonForecastMask); defs.appendChild(gl.dom.elGridRectMarkerMask); } }, { key: "_drawGridLines", value: function _drawGridLines(_ref) { var i = _ref.i, x1 = _ref.x1, y1 = _ref.y1, x2 = _ref.x2, y2 = _ref.y2, xCount = _ref.xCount, parent = _ref.parent; var w = this.w; var shouldDraw = function shouldDraw() { if (i === 0 && w.globals.skipFirstTimelinelabel) { return false; } if (i === xCount - 1 && w.globals.skipLastTimelinelabel && !w.config.xaxis.labels.formatter) { return false; } if (w.config.chart.type === 'radar') { return false; } return true; }; if (shouldDraw()) { if (w.config.grid.xaxis.lines.show) { this._drawGridLine({ i: i, x1: x1, y1: y1, x2: x2, y2: y2, xCount: xCount, parent: parent }); } var y_2 = 0; if (w.globals.hasGroups && w.config.xaxis.tickPlacement === 'between') { var groups = w.globals.groups; if (groups) { var gacc = 0; for (var gi = 0; gacc < i && gi < groups.length; gi++) { gacc += groups[gi].cols; } if (gacc === i) { y_2 = w.globals.xAxisLabelsHeight * 0.6; } } } var xAxis = new XAxis(this.ctx); xAxis.drawXaxisTicks(x1, y_2, w.globals.dom.elGraphical); } } }, { key: "_drawGridLine", value: function _drawGridLine(_ref2) { var i = _ref2.i, x1 = _ref2.x1, y1 = _ref2.y1, x2 = _ref2.x2, y2 = _ref2.y2, xCount = _ref2.xCount, parent = _ref2.parent; var w = this.w; var excludeBorders = false; var isHorzLine = parent.node.classList.contains('apexcharts-gridlines-horizontal'); var strokeDashArray = w.config.grid.strokeDashArray; var offX = w.globals.barPadForNumericAxis; if (y1 === 0 && y2 === 0 || x1 === 0 && x2 === 0) { excludeBorders = true; } if (y1 === w.globals.gridHeight && y2 === w.globals.gridHeight) { excludeBorders = true; } if (w.globals.isBarHorizontal && (i === 0 || i === xCount - 1)) { excludeBorders = true; } var graphics = new Graphics(this); var line = graphics.drawLine(x1 - (isHorzLine ? offX : 0), y1, x2 + (isHorzLine ? offX : 0), y2, w.config.grid.borderColor, strokeDashArray); line.node.classList.add('apexcharts-gridline'); if (excludeBorders) { this.elGridBorders.add(line); } else { parent.add(line); } } }, { key: "_drawGridBandRect", value: function _drawGridBandRect(_ref3) { var c = _ref3.c, x1 = _ref3.x1, y1 = _ref3.y1, x2 = _ref3.x2, y2 = _ref3.y2, type = _ref3.type; var w = this.w; var graphics = new Graphics(this.ctx); var offX = w.globals.barPadForNumericAxis; if (type === 'column' && w.config.xaxis.type === 'datetime') return; var color = w.config.grid[type].colors[c]; var rect = graphics.drawRect(x1 - (type === 'row' ? offX : 0), y1, x2 + (type === 'row' ? offX * 2 : 0), y2, 0, color, w.config.grid[type].opacity); this.elg.add(rect); rect.attr('clip-path', "url(#gridRectMask".concat(w.globals.cuid, ")")); rect.node.classList.add("apexcharts-grid-".concat(type)); } }, { key: "_drawXYLines", value: function _drawXYLines(_ref4) { var _this = this; var xCount = _ref4.xCount, tickAmount = _ref4.tickAmount; var w = this.w; var datetimeLines = function datetimeLines(_ref5) { var xC = _ref5.xC, x1 = _ref5.x1, y1 = _ref5.y1, x2 = _ref5.x2, y2 = _ref5.y2; for (var i = 0; i < xC; i++) { x1 = _this.xaxisLabels[i].position; x2 = _this.xaxisLabels[i].position; _this._drawGridLines({ i: i, x1: x1, y1: y1, x2: x2, y2: y2, xCount: xCount, parent: _this.elgridLinesV }); } }; var categoryLines = function categoryLines(_ref6) { var xC = _ref6.xC, x1 = _ref6.x1, y1 = _ref6.y1, x2 = _ref6.x2, y2 = _ref6.y2; for (var i = 0; i < xC + (w.globals.isXNumeric ? 0 : 1); i++) { if (i === 0 && xC === 1 && w.globals.dataPoints === 1) { // single datapoint x1 = w.globals.gridWidth / 2; x2 = x1; } _this._drawGridLines({ i: i, x1: x1, y1: y1, x2: x2, y2: y2, xCount: xCount, parent: _this.elgridLinesV }); x1 = x1 + w.globals.gridWidth / (w.globals.isXNumeric ? xC - 1 : xC); x2 = x1; } }; // draw vertical lines if (w.config.grid.xaxis.lines.show || w.config.xaxis.axisTicks.show) { var x1 = w.globals.padHorizontal; var y1 = 0; var x2; var y2 = w.globals.gridHeight; if (w.globals.timescaleLabels.length) { datetimeLines({ xC: xCount, x1: x1, y1: y1, x2: x2, y2: y2 }); } else { if (w.globals.isXNumeric) { xCount = w.globals.xAxisScale.result.length; } categoryLines({ xC: xCount, x1: x1, y1: y1, x2: x2, y2: y2 }); } } // draw horizontal lines if (w.config.grid.yaxis.lines.show) { var _x = 0; var _y = 0; var _y2 = 0; var _x2 = w.globals.gridWidth; var tA = tickAmount + 1; if (this.isRangeBar) { tA = w.globals.labels.length; } for (var i = 0; i < tA + (this.isRangeBar ? 1 : 0); i++) { this._drawGridLine({ i: i, xCount: tA + (this.isRangeBar ? 1 : 0), x1: _x, y1: _y, x2: _x2, y2: _y2, parent: this.elgridLinesH }); _y = _y + w.globals.gridHeight / (this.isRangeBar ? tA : tickAmount); _y2 = _y; } } } }, { key: "_drawInvertedXYLines", value: function _drawInvertedXYLines(_ref7) { var xCount = _ref7.xCount; var w = this.w; // draw vertical lines if (w.config.grid.xaxis.lines.show || w.config.xaxis.axisTicks.show) { var x1 = w.globals.padHorizontal; var y1 = 0; var x2; var y2 = w.globals.gridHeight; for (var i = 0; i < xCount + 1; i++) { if (w.config.grid.xaxis.lines.show) { this._drawGridLine({ i: i, xCount: xCount + 1, x1: x1, y1: y1, x2: x2, y2: y2, parent: this.elgridLinesV }); } var xAxis = new XAxis(this.ctx); xAxis.drawXaxisTicks(x1, 0, w.globals.dom.elGraphical); x1 = x1 + w.globals.gridWidth / xCount + 0.3; x2 = x1; } } // draw horizontal lines if (w.config.grid.yaxis.lines.show) { var _x3 = 0; var _y3 = 0; var _y4 = 0; var _x4 = w.globals.gridWidth; for (var _i = 0; _i < w.globals.dataPoints + 1; _i++) { this._drawGridLine({ i: _i, xCount: w.globals.dataPoints + 1, x1: _x3, y1: _y3, x2: _x4, y2: _y4, parent: this.elgridLinesH }); _y3 = _y3 + w.globals.gridHeight / w.globals.dataPoints; _y4 = _y3; } } } // actual grid rendering }, { key: "renderGrid", value: function renderGrid() { var w = this.w; var graphics = new Graphics(this.ctx); this.elg = graphics.group({ class: 'apexcharts-grid' }); this.elgridLinesH = graphics.group({ class: 'apexcharts-gridlines-horizontal' }); this.elgridLinesV = graphics.group({ class: 'apexcharts-gridlines-vertical' }); this.elGridBorders = graphics.group({ class: 'apexcharts-grid-borders' }); this.elg.add(this.elgridLinesH); this.elg.add(this.elgridLinesV); if (!w.config.grid.show) { this.elgridLinesV.hide(); this.elgridLinesH.hide(); this.elGridBorders.hide(); } var yTickAmount = w.globals.yAxisScale.length ? w.globals.yAxisScale[0].result.length - 1 : 5; for (var i = 0; i < w.globals.series.length; i++) { if (typeof w.globals.yAxisScale[i] !== 'undefined') { yTickAmount = w.globals.yAxisScale[i].result.length - 1; } if (yTickAmount > 2) break; } var xCount; if (!w.globals.isBarHorizontal || this.isRangeBar) { xCount = this.xaxisLabels.length; if (this.isRangeBar) { yTickAmount = w.globals.labels.length; if (w.config.xaxis.tickAmount && w.config.xaxis.labels.formatter) { xCount = w.config.xaxis.tickAmount; } } this._drawXYLines({ xCount: xCount, tickAmount: yTickAmount }); } else { xCount = yTickAmount; // for horizontal bar chart, get the xaxis tickamount yTickAmount = w.globals.xTickAmount; this._drawInvertedXYLines({ xCount: xCount, tickAmount: yTickAmount }); } this.drawGridBands(xCount, yTickAmount); return { el: this.elg, elGridBorders: this.elGridBorders, xAxisTickWidth: w.globals.gridWidth / xCount }; } }, { key: "drawGridBands", value: function drawGridBands(xCount, tickAmount) { var w = this.w; // rows background bands if (w.config.grid.row.colors !== undefined && w.config.grid.row.colors.length > 0) { var x1 = 0; var y1 = 0; var y2 = w.globals.gridHeight / tickAmount; var x2 = w.globals.gridWidth; for (var i = 0, c = 0; i < tickAmount; i++, c++) { if (c >= w.config.grid.row.colors.length) { c = 0; } this._drawGridBandRect({ c: c, x1: x1, y1: y1, x2: x2, y2: y2, type: 'row' }); y1 = y1 + w.globals.gridHeight / tickAmount; } } // columns background bands if (w.config.grid.column.colors !== undefined && w.config.grid.column.colors.length > 0) { var xc = !w.globals.isBarHorizontal && (w.config.xaxis.type === 'category' || w.config.xaxis.convertedCatToNumeric) ? xCount - 1 : xCount; var _x5 = w.globals.padHorizontal; var _y5 = 0; var _x6 = w.globals.padHorizontal + w.globals.gridWidth / xc; var _y6 = w.globals.gridHeight; for (var _i2 = 0, _c = 0; _i2 < xCount; _i2++, _c++) { if (_c >= w.config.grid.column.colors.length) { _c = 0; } this._drawGridBandRect({ c: _c, x1: _x5, y1: _y5, x2: _x6, y2: _y6, type: 'column' }); _x5 = _x5 + w.globals.gridWidth / xc; } } } }]); return Grid; }(); var Range$1 = /*#__PURE__*/function () { function Range(ctx) { _classCallCheck(this, Range); this.ctx = ctx; this.w = ctx.w; } // http://stackoverflow.com/questions/326679/choosing-an-attractive-linear-scale-for-a-graphs-y-axiss // This routine creates the Y axis values for a graph. _createClass(Range, [{ key: "niceScale", value: function niceScale(yMin, yMax) { var ticks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; var index = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; var NO_MIN_MAX_PROVIDED = arguments.length > 4 ? arguments[4] : undefined; var w = this.w; // Determine Range var range = Math.abs(yMax - yMin); ticks = this._adjustTicksForSmallRange(ticks, index, range); if (ticks === 'dataPoints') { ticks = w.globals.dataPoints - 1; } if (yMin === Number.MIN_VALUE && yMax === 0 || !Utils$1.isNumber(yMin) && !Utils$1.isNumber(yMax) || yMin === Number.MIN_VALUE && yMax === -Number.MAX_VALUE) { // when all values are 0 yMin = 0; yMax = ticks; var linearScale = this.linearScale(yMin, yMax, ticks); return linearScale; } if (yMin > yMax) { // if somehow due to some wrong config, user sent max less than min, // adjust the min/max again console.warn('axis.min cannot be greater than axis.max'); yMax = yMin + 0.1; } else if (yMin === yMax) { // If yMin and yMax are identical, then // adjust the yMin and yMax values to actually // make a graph. Also avoids division by zero errors. yMin = yMin === 0 ? 0 : yMin - 0.5; // some small value yMax = yMax === 0 ? 2 : yMax + 0.5; // some small value } // Calculate Min amd Max graphical labels and graph // increments. The number of ticks defaults to // 10 which is the SUGGESTED value. Any tick value // entered is used as a suggested value which is // adjusted to be a 'pretty' value. // // Output will be an array of the Y axis values that // encompass the Y values. var result = []; if (range < 1 && NO_MIN_MAX_PROVIDED && (w.config.chart.type === 'candlestick' || w.config.series[index].type === 'candlestick' || w.config.chart.type === 'boxPlot' || w.config.series[index].type === 'boxPlot' || w.globals.isRangeData)) { /* fix https://github.com/apexcharts/apexcharts.js/issues/430 */ yMax = yMax * 1.01; } var tiks = ticks + 1; // Adjust ticks if needed if (tiks < 2) { tiks = 2; } else if (tiks > 2) { tiks -= 2; } // Get raw step value var tempStep = range / tiks; // Calculate pretty step value var mag = Math.floor(Utils$1.log10(tempStep)); var magPow = Math.pow(10, mag); var magMsd = Math.round(tempStep / magPow); if (magMsd < 1) { magMsd = 1; } var stepSize = magMsd * magPow; // build Y label array. // Lower and upper bounds calculations var lb = stepSize * Math.floor(yMin / stepSize); var ub = stepSize * Math.ceil(yMax / stepSize); // Build array var val = lb; if (NO_MIN_MAX_PROVIDED && range > 2) { while (1) { result.push(val); val += stepSize; if (val > ub) { break; } } return { result: result, niceMin: result[0], niceMax: result[result.length - 1] }; } else { result = []; var v = yMin; result.push(v); var valuesDivider = Math.abs(yMax - yMin) / ticks; for (var i = 0; i <= ticks; i++) { v = v + valuesDivider; result.push(v); } if (result[result.length - 2] >= yMax) { result.pop(); } return { result: result, niceMin: result[0], niceMax: result[result.length - 1] }; } } }, { key: "linearScale", value: function linearScale(yMin, yMax) { var ticks = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10; var index = arguments.length > 3 ? arguments[3] : undefined; var range = Math.abs(yMax - yMin); ticks = this._adjustTicksForSmallRange(ticks, index, range); if (ticks === 'dataPoints') { ticks = this.w.globals.dataPoints - 1; } var step = range / ticks; if (ticks === Number.MAX_VALUE) { ticks = 10; step = 1; } var result = []; var v = yMin; while (ticks >= 0) { result.push(v); v = v + step; ticks -= 1; } return { result: result, niceMin: result[0], niceMax: result[result.length - 1] }; } }, { key: "logarithmicScaleNice", value: function logarithmicScaleNice(yMin, yMax, base) { // Basic validation to avoid for loop starting at -inf. if (yMax <= 0) yMax = Math.max(yMin, base); if (yMin <= 0) yMin = Math.min(yMax, base); var logs = []; var logMax = Math.ceil(Math.log(yMax) / Math.log(base) + 1); // Get powers of base for our max and min var logMin = Math.floor(Math.log(yMin) / Math.log(base)); for (var i = logMin; i < logMax; i++) { logs.push(Math.pow(base, i)); } return { result: logs, niceMin: logs[0], niceMax: logs[logs.length - 1] }; } }, { key: "logarithmicScale", value: function logarithmicScale(yMin, yMax, base) { // Basic validation to avoid for loop starting at -inf. if (yMax <= 0) yMax = Math.max(yMin, base); if (yMin <= 0) yMin = Math.min(yMax, base); var logs = []; // Get the logarithmic range. var logMax = Math.log(yMax) / Math.log(base); var logMin = Math.log(yMin) / Math.log(base); // Get the exact logarithmic range. // (This is the exact number of multiples of the base there are between yMin and yMax). var logRange = logMax - logMin; // Round the logarithmic range to get the number of ticks we will create. // If the chosen min/max values are multiples of each other WRT the base, this will be neat. // If the chosen min/max aren't, we will at least still provide USEFUL ticks. var ticks = Math.round(logRange); // Get the logarithmic spacing between ticks. var logTickSpacing = logRange / ticks; // Create as many ticks as there is range in the logs. for (var i = 0, logTick = logMin; i < ticks; i++, logTick += logTickSpacing) { logs.push(Math.pow(base, logTick)); } // Add a final tick at the yMax. logs.push(Math.pow(base, logMax)); return { result: logs, niceMin: yMin, niceMax: yMax }; } }, { key: "_adjustTicksForSmallRange", value: function _adjustTicksForSmallRange(ticks, index, range) { var newTicks = ticks; if (typeof index !== 'undefined' && this.w.config.yaxis[index].labels.formatter && this.w.config.yaxis[index].tickAmount === undefined) { var formattedVal = Number(this.w.config.yaxis[index].labels.formatter(1)); if (Utils$1.isNumber(formattedVal) && this.w.globals.yValueDecimal === 0) { newTicks = Math.ceil(range); } } return newTicks < ticks ? newTicks : ticks; } }, { key: "setYScaleForIndex", value: function setYScaleForIndex(index, minY, maxY) { var gl = this.w.globals; var cnf = this.w.config; var y = gl.isBarHorizontal ? cnf.xaxis : cnf.yaxis[index]; if (typeof gl.yAxisScale[index] === 'undefined') { gl.yAxisScale[index] = []; } var diff = Math.abs(maxY - minY); if (y.logarithmic && diff <= 5) { gl.invalidLogScale = true; } if (y.logarithmic && diff > 5) { gl.allSeriesCollapsed = false; gl.yAxisScale[index] = this.logarithmicScale(minY, maxY, y.logBase); gl.yAxisScale[index] = y.forceNiceScale ? this.logarithmicScaleNice(minY, maxY, y.logBase) : this.logarithmicScale(minY, maxY, y.logBase); } else { if (maxY === -Number.MAX_VALUE || !Utils$1.isNumber(maxY)) { // no data in the chart. Either all series collapsed or user passed a blank array gl.yAxisScale[index] = this.linearScale(0, 5, 5); } else { // there is some data. Turn off the allSeriesCollapsed flag gl.allSeriesCollapsed = false; if ((y.min !== undefined || y.max !== undefined) && !y.forceNiceScale) { // fix https://github.com/apexcharts/apexcharts.js/issues/492 gl.yAxisScale[index] = this.linearScale(minY, maxY, y.tickAmount, index); } else { var noMinMaxProvided = cnf.yaxis[index].max === undefined && cnf.yaxis[index].min === undefined || cnf.yaxis[index].forceNiceScale; gl.yAxisScale[index] = this.niceScale(minY, maxY, y.tickAmount ? y.tickAmount : diff < 5 && diff > 1 ? diff + 1 : 5, index, // fix https://github.com/apexcharts/apexcharts.js/issues/397 noMinMaxProvided); } } } } }, { key: "setXScale", value: function setXScale(minX, maxX) { var w = this.w; var gl = w.globals; var x = w.config.xaxis; var diff = Math.abs(maxX - minX); if (maxX === -Number.MAX_VALUE || !Utils$1.isNumber(maxX)) { // no data in the chart. Either all series collapsed or user passed a blank array gl.xAxisScale = this.linearScale(0, 5, 5); } else { gl.xAxisScale = this.linearScale(minX, maxX, x.tickAmount ? x.tickAmount : diff < 5 && diff > 1 ? diff + 1 : 5, 0); } return gl.xAxisScale; } }, { key: "setMultipleYScales", value: function setMultipleYScales() { var _this = this; var gl = this.w.globals; var cnf = this.w.config; var minYArr = gl.minYArr.concat([]); var maxYArr = gl.maxYArr.concat([]); var scalesIndices = []; // here, we loop through the yaxis array and find the item which has "seriesName" property cnf.yaxis.forEach(function (yaxe, i) { var index = i; cnf.series.forEach(function (s, si) { // if seriesName matches and that series is not collapsed, we use that scale // fix issue #1215 // proceed even if si is in gl.collapsedSeriesIndices if (s.name === yaxe.seriesName) { index = si; if (i !== si) { scalesIndices.push({ index: si, similarIndex: i, alreadyExists: true }); } else { scalesIndices.push({ index: si }); } } }); var minY = minYArr[index]; var maxY = maxYArr[index]; _this.setYScaleForIndex(i, minY, maxY); }); this.sameScaleInMultipleAxes(minYArr, maxYArr, scalesIndices); } }, { key: "sameScaleInMultipleAxes", value: function sameScaleInMultipleAxes(minYArr, maxYArr, scalesIndices) { var _this2 = this; var cnf = this.w.config; var gl = this.w.globals; // we got the scalesIndices array in the above code, but we need to filter out the items which doesn't have same scales var similarIndices = []; scalesIndices.forEach(function (scale) { if (scale.alreadyExists) { if (typeof similarIndices[scale.index] === 'undefined') { similarIndices[scale.index] = []; } similarIndices[scale.index].push(scale.index); similarIndices[scale.index].push(scale.similarIndex); } }); function intersect(a, b) { return a.filter(function (value) { return b.indexOf(value) !== -1; }); } gl.yAxisSameScaleIndices = similarIndices; similarIndices.forEach(function (si, i) { similarIndices.forEach(function (sj, j) { if (i !== j) { if (intersect(si, sj).length > 0) { similarIndices[i] = similarIndices[i].concat(similarIndices[j]); } } }); }); // then, we remove duplicates from the similarScale array var uniqueSimilarIndices = similarIndices.map(function (item) { return item.filter(function (i, pos) { return item.indexOf(i) === pos; }); }); // sort further to remove whole duplicate arrays later var sortedIndices = uniqueSimilarIndices.map(function (s) { return s.sort(); }); // remove undefined items similarIndices = similarIndices.filter(function (s) { return !!s; }); var indices = sortedIndices.slice(); var stringIndices = indices.map(function (ind) { return JSON.stringify(ind); }); indices = indices.filter(function (ind, p) { return stringIndices.indexOf(JSON.stringify(ind)) === p; }); var sameScaleMinYArr = []; var sameScaleMaxYArr = []; minYArr.forEach(function (minYValue, yi) { indices.forEach(function (scale, i) { // we compare only the yIndex which exists in the indices array if (scale.indexOf(yi) > -1) { if (typeof sameScaleMinYArr[i] === 'undefined') { sameScaleMinYArr[i] = []; sameScaleMaxYArr[i] = []; } sameScaleMinYArr[i].push({ key: yi, value: minYValue }); sameScaleMaxYArr[i].push({ key: yi, value: maxYArr[yi] }); } }); }); var sameScaleMin = Array.apply(null, Array(indices.length)).map(Number.prototype.valueOf, Number.MIN_VALUE); var sameScaleMax = Array.apply(null, Array(indices.length)).map(Number.prototype.valueOf, -Number.MAX_VALUE); sameScaleMinYArr.forEach(function (s, i) { s.forEach(function (sc, j) { sameScaleMin[i] = Math.min(sc.value, sameScaleMin[i]); }); }); sameScaleMaxYArr.forEach(function (s, i) { s.forEach(function (sc, j) { sameScaleMax[i] = Math.max(sc.value, sameScaleMax[i]); }); }); minYArr.forEach(function (min, i) { sameScaleMaxYArr.forEach(function (s, si) { var minY = sameScaleMin[si]; var maxY = sameScaleMax[si]; if (cnf.chart.stacked) { // for stacked charts, we need to add the values maxY = 0; s.forEach(function (ind, k) { // fix incorrectly adjust y scale issue #1215 if (ind.value !== -Number.MAX_VALUE) { maxY += ind.value; } if (minY !== Number.MIN_VALUE) { minY += sameScaleMinYArr[si][k].value; } }); } s.forEach(function (ind, k) { if (s[k].key === i) { if (cnf.yaxis[i].min !== undefined) { if (typeof cnf.yaxis[i].min === 'function') { minY = cnf.yaxis[i].min(gl.minY); } else { minY = cnf.yaxis[i].min; } } if (cnf.yaxis[i].max !== undefined) { if (typeof cnf.yaxis[i].max === 'function') { maxY = cnf.yaxis[i].max(gl.maxY); } else { maxY = cnf.yaxis[i].max; } } _this2.setYScaleForIndex(i, minY, maxY); } }); }); }); } // experimental feature which scales the y-axis to a min/max based on x-axis range }, { key: "autoScaleY", value: function autoScaleY(ctx, yaxis, e) { if (!ctx) { ctx = this; } var w = ctx.w; if (w.globals.isMultipleYAxis || w.globals.collapsedSeries.length) { // The autoScale option for multiple y-axis is turned off as it leads to buggy behavior. // Also, when a series is collapsed, it results in incorrect behavior. Hence turned it off for that too - fixes apexcharts.js#795 console.warn('autoScaleYaxis is not supported in a multi-yaxis chart.'); return yaxis; } var seriesX = w.globals.seriesX[0]; var isStacked = w.config.chart.stacked; yaxis.forEach(function (yaxe, yi) { var firstXIndex = 0; for (var xi = 0; xi < seriesX.length; xi++) { if (seriesX[xi] >= e.xaxis.min) { firstXIndex = xi; break; } } var initialMin = w.globals.minYArr[yi]; var initialMax = w.globals.maxYArr[yi]; var min, max; var stackedSer = w.globals.stackedSeriesTotals; w.globals.series.forEach(function (serie, sI) { var firstValue = serie[firstXIndex]; if (isStacked) { firstValue = stackedSer[firstXIndex]; min = max = firstValue; stackedSer.forEach(function (y, yI) { if (seriesX[yI] <= e.xaxis.max && seriesX[yI] >= e.xaxis.min) { if (y > max && y !== null) max = y; if (serie[yI] < min && serie[yI] !== null) min = serie[yI]; } }); } else { min = max = firstValue; serie.forEach(function (y, yI) { if (seriesX[yI] <= e.xaxis.max && seriesX[yI] >= e.xaxis.min) { var valMin = y; var valMax = y; w.globals.series.forEach(function (wS, wSI) { if (y !== null) { valMin = Math.min(wS[yI], valMin); valMax = Math.max(wS[yI], valMax); } }); if (valMax > max && valMax !== null) max = valMax; if (valMin < min && valMin !== null) min = valMin; } }); } if (min === undefined && max === undefined) { min = initialMin; max = initialMax; } min *= min < 0 ? 1.1 : 0.9; max *= max < 0 ? 0.9 : 1.1; if (min === 0 && max === 0) { min = -1; max = 1; } if (max < 0 && max < initialMax) { max = initialMax; } if (min < 0 && min > initialMin) { min = initialMin; } if (yaxis.length > 1) { yaxis[sI].min = yaxe.min === undefined ? min : yaxe.min; yaxis[sI].max = yaxe.max === undefined ? max : yaxe.max; } else { yaxis[0].min = yaxe.min === undefined ? min : yaxe.min; yaxis[0].max = yaxe.max === undefined ? max : yaxe.max; } }); }); return yaxis; } }]); return Range; }(); /** * Range is used to generates values between min and max. * * @module Range **/ var Range = /*#__PURE__*/function () { function Range(ctx) { _classCallCheck(this, Range); this.ctx = ctx; this.w = ctx.w; this.scales = new Range$1(ctx); } _createClass(Range, [{ key: "init", value: function init() { this.setYRange(); this.setXRange(); this.setZRange(); } }, { key: "getMinYMaxY", value: function getMinYMaxY(startingIndex) { var lowestY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Number.MAX_VALUE; var highestY = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : -Number.MAX_VALUE; var len = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var cnf = this.w.config; var gl = this.w.globals; var maxY = -Number.MAX_VALUE; var minY = Number.MIN_VALUE; if (len === null) { len = startingIndex + 1; } var series = gl.series; var seriesMin = series; var seriesMax = series; if (cnf.chart.type === 'candlestick') { seriesMin = gl.seriesCandleL; seriesMax = gl.seriesCandleH; } else if (cnf.chart.type === 'boxPlot') { seriesMin = gl.seriesCandleO; seriesMax = gl.seriesCandleC; } else if (gl.isRangeData) { seriesMin = gl.seriesRangeStart; seriesMax = gl.seriesRangeEnd; } for (var i = startingIndex; i < len; i++) { gl.dataPoints = Math.max(gl.dataPoints, series[i].length); if (gl.categoryLabels.length) { gl.dataPoints = gl.categoryLabels.filter(function (label) { return typeof label !== 'undefined'; }).length; } for (var j = 0; j < gl.series[i].length; j++) { var val = series[i][j]; if (val !== null && Utils$1.isNumber(val)) { if (typeof seriesMax[i][j] !== 'undefined') { maxY = Math.max(maxY, seriesMax[i][j]); lowestY = Math.min(lowestY, seriesMax[i][j]); } if (typeof seriesMin[i][j] !== 'undefined') { lowestY = Math.min(lowestY, seriesMin[i][j]); highestY = Math.max(highestY, seriesMin[i][j]); } if (this.w.config.chart.type === 'candlestick' || this.w.config.chart.type === 'boxPlot' || this.w.config.chart.type !== 'rangeArea' || this.w.config.chart.type !== 'rangeBar') { if (this.w.config.chart.type === 'candlestick' || this.w.config.chart.type === 'boxPlot') { if (typeof gl.seriesCandleC[i][j] !== 'undefined') { maxY = Math.max(maxY, gl.seriesCandleO[i][j]); maxY = Math.max(maxY, gl.seriesCandleH[i][j]); maxY = Math.max(maxY, gl.seriesCandleL[i][j]); maxY = Math.max(maxY, gl.seriesCandleC[i][j]); if (this.w.config.chart.type === 'boxPlot') { maxY = Math.max(maxY, gl.seriesCandleM[i][j]); } } } // there is a combo chart and the specified series in not either candlestick, boxplot, or rangeArea/rangeBar; find the max there if (cnf.series[i].type && (cnf.series[i].type !== 'candlestick' || cnf.series[i].type !== 'boxPlot' || cnf.series[i].type !== 'rangeArea' || cnf.series[i].type !== 'rangeBar')) { maxY = Math.max(maxY, gl.series[i][j]); lowestY = Math.min(lowestY, gl.series[i][j]); } highestY = maxY; } if (gl.seriesGoals[i] && gl.seriesGoals[i][j] && Array.isArray(gl.seriesGoals[i][j])) { gl.seriesGoals[i][j].forEach(function (g) { if (minY !== Number.MIN_VALUE) { minY = Math.min(minY, g.value); lowestY = minY; } maxY = Math.max(maxY, g.value); highestY = maxY; }); } if (Utils$1.isFloat(val)) { val = Utils$1.noExponents(val); gl.yValueDecimal = Math.max(gl.yValueDecimal, val.toString().split('.')[1].length); } if (minY > seriesMin[i][j] && seriesMin[i][j] < 0) { minY = seriesMin[i][j]; } } else { gl.hasNullValues = true; } } } if (cnf.chart.type === 'rangeBar' && gl.seriesRangeStart.length && gl.isBarHorizontal) { minY = lowestY; } if (cnf.chart.type === 'bar') { if (minY < 0 && maxY < 0) { // all negative values in a bar chart, hence make the max to 0 maxY = 0; } if (minY === Number.MIN_VALUE) { minY = 0; } } return { minY: minY, maxY: maxY, lowestY: lowestY, highestY: highestY }; } }, { key: "setYRange", value: function setYRange() { var gl = this.w.globals; var cnf = this.w.config; gl.maxY = -Number.MAX_VALUE; gl.minY = Number.MIN_VALUE; var lowestYInAllSeries = Number.MAX_VALUE; if (gl.isMultipleYAxis) { // we need to get minY and maxY for multiple y axis for (var i = 0; i < gl.series.length; i++) { var minYMaxYArr = this.getMinYMaxY(i, lowestYInAllSeries, null, i + 1); gl.minYArr.push(minYMaxYArr.minY); gl.maxYArr.push(minYMaxYArr.maxY); lowestYInAllSeries = minYMaxYArr.lowestY; } } // and then, get the minY and maxY from all series var minYMaxY = this.getMinYMaxY(0, lowestYInAllSeries, null, gl.series.length); gl.minY = minYMaxY.minY; gl.maxY = minYMaxY.maxY; lowestYInAllSeries = minYMaxY.lowestY; if (cnf.chart.stacked) { this._setStackedMinMax(); } // if the numbers are too big, reduce the range // for eg, if number is between 100000-110000, putting 0 as the lowest value is not so good idea. So change the gl.minY for line/area/candlesticks/boxPlot if (cnf.chart.type === 'line' || cnf.chart.type === 'area' || cnf.chart.type === 'candlestick' || cnf.chart.type === 'boxPlot' || cnf.chart.type === 'rangeBar' && !gl.isBarHorizontal) { if (gl.minY === Number.MIN_VALUE && lowestYInAllSeries !== -Number.MAX_VALUE && lowestYInAllSeries !== gl.maxY // single value possibility ) { var diff = gl.maxY - lowestYInAllSeries; if (lowestYInAllSeries >= 0 && lowestYInAllSeries <= 10 || cnf.yaxis[0].min !== undefined || cnf.yaxis[0].max !== undefined) { // if minY is already 0/low value, we don't want to go negatives here - so this check is essential. diff = 0; } gl.minY = lowestYInAllSeries - diff * 5 / 100; /* fix https://github.com/apexcharts/apexcharts.js/issues/614 */ /* fix https://github.com/apexcharts/apexcharts.js/issues/968 */ if (lowestYInAllSeries > 0 && gl.minY < 0) { gl.minY = 0; } /* fix https://github.com/apexcharts/apexcharts.js/issues/426 */ gl.maxY = gl.maxY + diff * 5 / 100; } } cnf.yaxis.forEach(function (yaxe, index) { // override all min/max values by user defined values (y axis) if (yaxe.max !== undefined) { if (typeof yaxe.max === 'number') { gl.maxYArr[index] = yaxe.max; } else if (typeof yaxe.max === 'function') { // fixes apexcharts.js/issues/2098 gl.maxYArr[index] = yaxe.max(gl.isMultipleYAxis ? gl.maxYArr[index] : gl.maxY); } // gl.maxY is for single y-axis chart, it will be ignored in multi-yaxis gl.maxY = gl.maxYArr[index]; } if (yaxe.min !== undefined) { if (typeof yaxe.min === 'number') { gl.minYArr[index] = yaxe.min; } else if (typeof yaxe.min === 'function') { // fixes apexcharts.js/issues/2098 gl.minYArr[index] = yaxe.min(gl.isMultipleYAxis ? gl.minYArr[index] === Number.MIN_VALUE ? 0 : gl.minYArr[index] : gl.minY); } // gl.minY is for single y-axis chart, it will be ignored in multi-yaxis gl.minY = gl.minYArr[index]; } }); // for horizontal bar charts, we need to check xaxis min/max as user may have specified there if (gl.isBarHorizontal) { var minmax = ['min', 'max']; minmax.forEach(function (m) { if (cnf.xaxis[m] !== undefined && typeof cnf.xaxis[m] === 'number') { m === 'min' ? gl.minY = cnf.xaxis[m] : gl.maxY = cnf.xaxis[m]; } }); } // for multi y-axis we need different scales for each if (gl.isMultipleYAxis) { this.scales.setMultipleYScales(); gl.minY = lowestYInAllSeries; gl.yAxisScale.forEach(function (scale, i) { gl.minYArr[i] = scale.niceMin; gl.maxYArr[i] = scale.niceMax; }); } else { this.scales.setYScaleForIndex(0, gl.minY, gl.maxY); gl.minY = gl.yAxisScale[0].niceMin; gl.maxY = gl.yAxisScale[0].niceMax; gl.minYArr[0] = gl.yAxisScale[0].niceMin; gl.maxYArr[0] = gl.yAxisScale[0].niceMax; } return { minY: gl.minY, maxY: gl.maxY, minYArr: gl.minYArr, maxYArr: gl.maxYArr, yAxisScale: gl.yAxisScale }; } }, { key: "setXRange", value: function setXRange() { var gl = this.w.globals; var cnf = this.w.config; var isXNumeric = cnf.xaxis.type === 'numeric' || cnf.xaxis.type === 'datetime' || cnf.xaxis.type === 'category' && !gl.noLabelsProvided || gl.noLabelsProvided || gl.isXNumeric; var getInitialMinXMaxX = function getInitialMinXMaxX() { for (var i = 0; i < gl.series.length; i++) { if (gl.labels[i]) { for (var j = 0; j < gl.labels[i].length; j++) { if (gl.labels[i][j] !== null && Utils$1.isNumber(gl.labels[i][j])) { gl.maxX = Math.max(gl.maxX, gl.labels[i][j]); gl.initialMaxX = Math.max(gl.maxX, gl.labels[i][j]); gl.minX = Math.min(gl.minX, gl.labels[i][j]); gl.initialMinX = Math.min(gl.minX, gl.labels[i][j]); } } } } }; // minX maxX starts here if (gl.isXNumeric) { getInitialMinXMaxX(); } if (gl.noLabelsProvided) { if (cnf.xaxis.categories.length === 0) { gl.maxX = gl.labels[gl.labels.length - 1]; gl.initialMaxX = gl.labels[gl.labels.length - 1]; gl.minX = 1; gl.initialMinX = 1; } } if (gl.isXNumeric || gl.noLabelsProvided || gl.dataFormatXNumeric) { var ticks; if (cnf.xaxis.tickAmount === undefined) { ticks = Math.round(gl.svgWidth / 150); // no labels provided and total number of dataPoints is less than 30 if (cnf.xaxis.type === 'numeric' && gl.dataPoints < 30) { ticks = gl.dataPoints - 1; } // this check is for when ticks exceeds total datapoints and that would result in duplicate labels if (ticks > gl.dataPoints && gl.dataPoints !== 0) { ticks = gl.dataPoints - 1; } } else if (cnf.xaxis.tickAmount === 'dataPoints') { if (gl.series.length > 1) { ticks = gl.series[gl.maxValsInArrayIndex].length - 1; } if (gl.isXNumeric) { ticks = gl.maxX - gl.minX - 1; } } else { ticks = cnf.xaxis.tickAmount; } gl.xTickAmount = ticks; // override all min/max values by user defined values (x axis) if (cnf.xaxis.max !== undefined && typeof cnf.xaxis.max === 'number') { gl.maxX = cnf.xaxis.max; } if (cnf.xaxis.min !== undefined && typeof cnf.xaxis.min === 'number') { gl.minX = cnf.xaxis.min; } // if range is provided, adjust the new minX if (cnf.xaxis.range !== undefined) { gl.minX = gl.maxX - cnf.xaxis.range; } if (gl.minX !== Number.MAX_VALUE && gl.maxX !== -Number.MAX_VALUE) { if (cnf.xaxis.convertedCatToNumeric && !gl.dataFormatXNumeric) { var catScale = []; for (var i = gl.minX - 1; i < gl.maxX; i++) { catScale.push(i + 1); } gl.xAxisScale = { result: catScale, niceMin: catScale[0], niceMax: catScale[catScale.length - 1] }; } else { gl.xAxisScale = this.scales.setXScale(gl.minX, gl.maxX); } } else { gl.xAxisScale = this.scales.linearScale(1, ticks, ticks); if (gl.noLabelsProvided && gl.labels.length > 0) { gl.xAxisScale = this.scales.linearScale(1, gl.labels.length, ticks - 1); // this is the only place seriesX is again mutated gl.seriesX = gl.labels.slice(); } } // we will still store these labels as the count for this will be different (to draw grid and labels placement) if (isXNumeric) { gl.labels = gl.xAxisScale.result.slice(); } } if (gl.isBarHorizontal && gl.labels.length) { gl.xTickAmount = gl.labels.length; } // single dataPoint this._handleSingleDataPoint(); // minimum x difference to calculate bar width in numeric bars this._getMinXDiff(); return { minX: gl.minX, maxX: gl.maxX }; } }, { key: "setZRange", value: function setZRange() { // minZ, maxZ starts here var gl = this.w.globals; if (!gl.isDataXYZ) return; for (var i = 0; i < gl.series.length; i++) { if (typeof gl.seriesZ[i] !== 'undefined') { for (var j = 0; j < gl.seriesZ[i].length; j++) { if (gl.seriesZ[i][j] !== null && Utils$1.isNumber(gl.seriesZ[i][j])) { gl.maxZ = Math.max(gl.maxZ, gl.seriesZ[i][j]); gl.minZ = Math.min(gl.minZ, gl.seriesZ[i][j]); } } } } } }, { key: "_handleSingleDataPoint", value: function _handleSingleDataPoint() { var gl = this.w.globals; var cnf = this.w.config; if (gl.minX === gl.maxX) { var datetimeObj = new DateTime(this.ctx); if (cnf.xaxis.type === 'datetime') { var newMinX = datetimeObj.getDate(gl.minX); if (cnf.xaxis.labels.datetimeUTC) { newMinX.setUTCDate(newMinX.getUTCDate() - 2); } else { newMinX.setDate(newMinX.getDate() - 2); } gl.minX = new Date(newMinX).getTime(); var newMaxX = datetimeObj.getDate(gl.maxX); if (cnf.xaxis.labels.datetimeUTC) { newMaxX.setUTCDate(newMaxX.getUTCDate() + 2); } else { newMaxX.setDate(newMaxX.getDate() + 2); } gl.maxX = new Date(newMaxX).getTime(); } else if (cnf.xaxis.type === 'numeric' || cnf.xaxis.type === 'category' && !gl.noLabelsProvided) { gl.minX = gl.minX - 2; gl.initialMinX = gl.minX; gl.maxX = gl.maxX + 2; gl.initialMaxX = gl.maxX; } } } }, { key: "_getMinXDiff", value: function _getMinXDiff() { var gl = this.w.globals; if (gl.isXNumeric) { // get the least x diff if numeric x axis is present gl.seriesX.forEach(function (sX, i) { if (sX.length === 1) { // a small hack to prevent overlapping multiple bars when there is just 1 datapoint in bar series. // fix #811 sX.push(gl.seriesX[gl.maxValsInArrayIndex][gl.seriesX[gl.maxValsInArrayIndex].length - 1]); } // fix #983 (clone the array to avoid side effects) var seriesX = sX.slice(); seriesX.sort(function (a, b) { return a - b; }); seriesX.forEach(function (s, j) { if (j > 0) { var xDiff = s - seriesX[j - 1]; if (xDiff > 0) { gl.minXDiff = Math.min(xDiff, gl.minXDiff); } } }); if (gl.dataPoints === 1 || gl.minXDiff === Number.MAX_VALUE) { // fixes apexcharts.js #1221 gl.minXDiff = 0.5; } }); } } }, { key: "_setStackedMinMax", value: function _setStackedMinMax() { var gl = this.w.globals; // for stacked charts, we calculate each series's parallel values. i.e, series[0][j] + series[1][j] .... [series[i.length][j]] and get the max out of it var stackedPoss = []; var stackedNegs = []; if (gl.series.length) { for (var j = 0; j < gl.series[gl.maxValsInArrayIndex].length; j++) { var poss = 0; var negs = 0; for (var i = 0; i < gl.series.length; i++) { if (gl.series[i][j] !== null && Utils$1.isNumber(gl.series[i][j])) { // 0.0001 fixes #185 when values are very small gl.series[i][j] > 0 ? poss = poss + parseFloat(gl.series[i][j]) + 0.0001 : negs = negs + parseFloat(gl.series[i][j]); } if (i === gl.series.length - 1) { // push all the totals to the array for future use stackedPoss.push(poss); stackedNegs.push(negs); } } } } // get the max/min out of the added parallel values for (var z = 0; z < stackedPoss.length; z++) { gl.maxY = Math.max(gl.maxY, stackedPoss[z]); gl.minY = Math.min(gl.minY, stackedNegs[z]); } } }]); return Range; }(); /** * ApexCharts YAxis Class for drawing Y-Axis. * * @module YAxis **/ var YAxis = /*#__PURE__*/function () { function YAxis(ctx, elgrid) { _classCallCheck(this, YAxis); this.ctx = ctx; this.elgrid = elgrid; this.w = ctx.w; var w = this.w; this.xaxisFontSize = w.config.xaxis.labels.style.fontSize; this.axisFontFamily = w.config.xaxis.labels.style.fontFamily; this.xaxisForeColors = w.config.xaxis.labels.style.colors; this.isCategoryBarHorizontal = w.config.chart.type === 'bar' && w.config.plotOptions.bar.horizontal; this.xAxisoffX = 0; if (w.config.xaxis.position === 'bottom') { this.xAxisoffX = w.globals.gridHeight; } this.drawnLabels = []; this.axesUtils = new AxesUtils(ctx); } _createClass(YAxis, [{ key: "drawYaxis", value: function drawYaxis(realIndex) { var _this = this; var w = this.w; var graphics = new Graphics(this.ctx); var yaxisStyle = w.config.yaxis[realIndex].labels.style; var yaxisFontSize = yaxisStyle.fontSize; var yaxisFontFamily = yaxisStyle.fontFamily; var yaxisFontWeight = yaxisStyle.fontWeight; var elYaxis = graphics.group({ class: 'apexcharts-yaxis', rel: realIndex, transform: 'translate(' + w.globals.translateYAxisX[realIndex] + ', 0)' }); if (this.axesUtils.isYAxisHidden(realIndex)) { return elYaxis; } var elYaxisTexts = graphics.group({ class: 'apexcharts-yaxis-texts-g' }); elYaxis.add(elYaxisTexts); var tickAmount = w.globals.yAxisScale[realIndex].result.length - 1; // labelsDivider is simply svg height/number of ticks var labelsDivider = w.globals.gridHeight / tickAmount; // initial label position = 0; var l = w.globals.translateY; var lbFormatter = w.globals.yLabelFormatters[realIndex]; var labels = w.globals.yAxisScale[realIndex].result.slice(); labels = this.axesUtils.checkForReversedLabels(realIndex, labels); var firstLabel = ''; if (w.config.yaxis[realIndex].labels.show) { var _loop = function _loop(i) { var val = labels[i]; val = lbFormatter(val, i, w); var xPad = w.config.yaxis[realIndex].labels.padding; if (w.config.yaxis[realIndex].opposite && w.config.yaxis.length !== 0) { xPad = xPad * -1; } var textAnchor = 'end'; if (w.config.yaxis[realIndex].opposite) { textAnchor = 'start'; } if (w.config.yaxis[realIndex].labels.align === 'left') { textAnchor = 'start'; } else if (w.config.yaxis[realIndex].labels.align === 'center') { textAnchor = 'middle'; } else if (w.config.yaxis[realIndex].labels.align === 'right') { textAnchor = 'end'; } var yColors = _this.axesUtils.getYAxisForeColor(yaxisStyle.colors, realIndex); var getForeColor = function getForeColor() { return Array.isArray(yColors) ? yColors[i] : yColors; }; var label = graphics.drawText({ x: xPad, y: l + tickAmount / 10 + w.config.yaxis[realIndex].labels.offsetY + 1, text: val, textAnchor: textAnchor, fontSize: yaxisFontSize, fontFamily: yaxisFontFamily, fontWeight: yaxisFontWeight, maxWidth: w.config.yaxis[realIndex].labels.maxWidth, foreColor: getForeColor(), isPlainText: false, cssClass: 'apexcharts-yaxis-label ' + yaxisStyle.cssClass }); if (i === tickAmount) { firstLabel = label; } elYaxisTexts.add(label); var elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title'); elTooltipTitle.textContent = Array.isArray(val) ? val.join(' ') : val; label.node.appendChild(elTooltipTitle); if (w.config.yaxis[realIndex].labels.rotate !== 0) { var firstabelRotatingCenter = graphics.rotateAroundCenter(firstLabel.node); var labelRotatingCenter = graphics.rotateAroundCenter(label.node); label.node.setAttribute('transform', "rotate(".concat(w.config.yaxis[realIndex].labels.rotate, " ").concat(firstabelRotatingCenter.x, " ").concat(labelRotatingCenter.y, ")")); } l = l + labelsDivider; }; for (var i = tickAmount; i >= 0; i--) { _loop(i); } } if (w.config.yaxis[realIndex].title.text !== undefined) { var elYaxisTitle = graphics.group({ class: 'apexcharts-yaxis-title' }); var _x = 0; if (w.config.yaxis[realIndex].opposite) { _x = w.globals.translateYAxisX[realIndex]; } var elYAxisTitleText = graphics.drawText({ x: _x, y: w.globals.gridHeight / 2 + w.globals.translateY + w.config.yaxis[realIndex].title.offsetY, text: w.config.yaxis[realIndex].title.text, textAnchor: 'end', foreColor: w.config.yaxis[realIndex].title.style.color, fontSize: w.config.yaxis[realIndex].title.style.fontSize, fontWeight: w.config.yaxis[realIndex].title.style.fontWeight, fontFamily: w.config.yaxis[realIndex].title.style.fontFamily, cssClass: 'apexcharts-yaxis-title-text ' + w.config.yaxis[realIndex].title.style.cssClass }); elYaxisTitle.add(elYAxisTitleText); elYaxis.add(elYaxisTitle); } var axisBorder = w.config.yaxis[realIndex].axisBorder; var x = 31 + axisBorder.offsetX; if (w.config.yaxis[realIndex].opposite) { x = -31 - axisBorder.offsetX; } if (axisBorder.show) { var elVerticalLine = graphics.drawLine(x, w.globals.translateY + axisBorder.offsetY - 2, x, w.globals.gridHeight + w.globals.translateY + axisBorder.offsetY + 2, axisBorder.color, 0, axisBorder.width); elYaxis.add(elVerticalLine); } if (w.config.yaxis[realIndex].axisTicks.show) { this.axesUtils.drawYAxisTicks(x, tickAmount, axisBorder, w.config.yaxis[realIndex].axisTicks, realIndex, labelsDivider, elYaxis); } return elYaxis; } // This actually becomes horizontal axis (for bar charts) }, { key: "drawYaxisInversed", value: function drawYaxisInversed(realIndex) { var w = this.w; var graphics = new Graphics(this.ctx); var elXaxis = graphics.group({ class: 'apexcharts-xaxis apexcharts-yaxis-inversed' }); var elXaxisTexts = graphics.group({ class: 'apexcharts-xaxis-texts-g', transform: "translate(".concat(w.globals.translateXAxisX, ", ").concat(w.globals.translateXAxisY, ")") }); elXaxis.add(elXaxisTexts); var tickAmount = w.globals.yAxisScale[realIndex].result.length - 1; // labelsDivider is simply svg width/number of ticks var labelsDivider = w.globals.gridWidth / tickAmount + 0.1; // initial label position; var l = labelsDivider + w.config.xaxis.labels.offsetX; var lbFormatter = w.globals.xLabelFormatter; var labels = w.globals.yAxisScale[realIndex].result.slice(); var timescaleLabels = w.globals.timescaleLabels; if (timescaleLabels.length > 0) { this.xaxisLabels = timescaleLabels.slice(); labels = timescaleLabels.slice(); tickAmount = labels.length; } labels = this.axesUtils.checkForReversedLabels(realIndex, labels); var tl = timescaleLabels.length; if (w.config.xaxis.labels.show) { for (var i = tl ? 0 : tickAmount; tl ? i < tl : i >= 0; tl ? i++ : i--) { var val = labels[i]; val = lbFormatter(val, i, w); var x = w.globals.gridWidth + w.globals.padHorizontal - (l - labelsDivider + w.config.xaxis.labels.offsetX); if (timescaleLabels.length) { var label = this.axesUtils.getLabel(labels, timescaleLabels, x, i, this.drawnLabels, this.xaxisFontSize); x = label.x; val = label.text; this.drawnLabels.push(label.text); if (i === 0 && w.globals.skipFirstTimelinelabel) { val = ''; } if (i === labels.length - 1 && w.globals.skipLastTimelinelabel) { val = ''; } } var elTick = graphics.drawText({ x: x, y: this.xAxisoffX + w.config.xaxis.labels.offsetY + 30 - (w.config.xaxis.position === 'top' ? w.globals.xAxisHeight + w.config.xaxis.axisTicks.height - 2 : 0), text: val, textAnchor: 'middle', foreColor: Array.isArray(this.xaxisForeColors) ? this.xaxisForeColors[realIndex] : this.xaxisForeColors, fontSize: this.xaxisFontSize, fontFamily: this.xaxisFontFamily, fontWeight: w.config.xaxis.labels.style.fontWeight, isPlainText: false, cssClass: 'apexcharts-xaxis-label ' + w.config.xaxis.labels.style.cssClass }); elXaxisTexts.add(elTick); elTick.tspan(val); var elTooltipTitle = document.createElementNS(w.globals.SVGNS, 'title'); elTooltipTitle.textContent = val; elTick.node.appendChild(elTooltipTitle); l = l + labelsDivider; } } this.inversedYAxisTitleText(elXaxis); this.inversedYAxisBorder(elXaxis); return elXaxis; } }, { key: "inversedYAxisBorder", value: function inversedYAxisBorder(parent) { var w = this.w; var graphics = new Graphics(this.ctx); var axisBorder = w.config.xaxis.axisBorder; if (axisBorder.show) { var lineCorrection = 0; if (w.config.chart.type === 'bar' && w.globals.isXNumeric) { lineCorrection = lineCorrection - 15; } var elHorzLine = graphics.drawLine(w.globals.padHorizontal + lineCorrection + axisBorder.offsetX, this.xAxisoffX, w.globals.gridWidth, this.xAxisoffX, axisBorder.color, 0, axisBorder.height); // in horizontal bars, we append axisBorder to elGridBorders element to avoid z-index issues if (this.elgrid && this.elgrid.elGridBorders) { this.elgrid.elGridBorders.add(elHorzLine); } else { parent.add(elHorzLine); } } } }, { key: "inversedYAxisTitleText", value: function inversedYAxisTitleText(parent) { var w = this.w; var graphics = new Graphics(this.ctx); if (w.config.xaxis.title.text !== undefined) { var elYaxisTitle = graphics.group({ class: 'apexcharts-xaxis-title apexcharts-yaxis-title-inversed' }); var elYAxisTitleText = graphics.drawText({ x: w.globals.gridWidth / 2 + w.config.xaxis.title.offsetX, y: this.xAxisoffX + parseFloat(this.xaxisFontSize) + parseFloat(w.config.xaxis.title.style.fontSize) + w.config.xaxis.title.offsetY + 20, text: w.config.xaxis.title.text, textAnchor: 'middle', fontSize: w.config.xaxis.title.style.fontSize, fontFamily: w.config.xaxis.title.style.fontFamily, fontWeight: w.config.xaxis.title.style.fontWeight, foreColor: w.config.xaxis.title.style.color, cssClass: 'apexcharts-xaxis-title-text ' + w.config.xaxis.title.style.cssClass }); elYaxisTitle.add(elYAxisTitleText); parent.add(elYaxisTitle); } } }, { key: "yAxisTitleRotate", value: function yAxisTitleRotate(realIndex, yAxisOpposite) { var w = this.w; var graphics = new Graphics(this.ctx); var yAxisLabelsCoord = { width: 0, height: 0 }; var yAxisTitleCoord = { width: 0, height: 0 }; var elYAxisLabelsWrap = w.globals.dom.baseEl.querySelector(" .apexcharts-yaxis[rel='".concat(realIndex, "'] .apexcharts-yaxis-texts-g")); if (elYAxisLabelsWrap !== null) { yAxisLabelsCoord = elYAxisLabelsWrap.getBoundingClientRect(); } var yAxisTitle = w.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(realIndex, "'] .apexcharts-yaxis-title text")); if (yAxisTitle !== null) { yAxisTitleCoord = yAxisTitle.getBoundingClientRect(); } if (yAxisTitle !== null) { var x = this.xPaddingForYAxisTitle(realIndex, yAxisLabelsCoord, yAxisTitleCoord, yAxisOpposite); yAxisTitle.setAttribute('x', x.xPos - (yAxisOpposite ? 10 : 0)); } if (yAxisTitle !== null) { var titleRotatingCenter = graphics.rotateAroundCenter(yAxisTitle); yAxisTitle.setAttribute('transform', "rotate(".concat(yAxisOpposite ? w.config.yaxis[realIndex].title.rotate * -1 : w.config.yaxis[realIndex].title.rotate, " ").concat(titleRotatingCenter.x, " ").concat(titleRotatingCenter.y, ")")); } } }, { key: "xPaddingForYAxisTitle", value: function xPaddingForYAxisTitle(realIndex, yAxisLabelsCoord, yAxisTitleCoord, yAxisOpposite) { var w = this.w; var oppositeAxisCount = 0; var x = 0; var padd = 10; if (w.config.yaxis[realIndex].title.text === undefined || realIndex < 0) { return { xPos: x, padd: 0 }; } if (yAxisOpposite) { x = yAxisLabelsCoord.width + w.config.yaxis[realIndex].title.offsetX + yAxisTitleCoord.width / 2 + padd / 2; oppositeAxisCount += 1; if (oppositeAxisCount === 0) { x = x - padd / 2; } } else { x = yAxisLabelsCoord.width * -1 + w.config.yaxis[realIndex].title.offsetX + padd / 2 + yAxisTitleCoord.width / 2; if (w.globals.isBarHorizontal) { padd = 25; x = yAxisLabelsCoord.width * -1 - w.config.yaxis[realIndex].title.offsetX - padd; } } return { xPos: x, padd: padd }; } // sets the x position of the y-axis by counting the labels width, title width and any offset }, { key: "setYAxisXPosition", value: function setYAxisXPosition(yaxisLabelCoords, yTitleCoords) { var w = this.w; var xLeft = 0; var xRight = 0; var leftOffsetX = 18; var rightOffsetX = 1; if (w.config.yaxis.length > 1) { this.multipleYs = true; } w.config.yaxis.map(function (yaxe, index) { var shouldNotDrawAxis = w.globals.ignoreYAxisIndexes.indexOf(index) > -1 || !yaxe.show || yaxe.floating || yaxisLabelCoords[index].width === 0; var axisWidth = yaxisLabelCoords[index].width + yTitleCoords[index].width; if (!yaxe.opposite) { xLeft = w.globals.translateX - leftOffsetX; if (!shouldNotDrawAxis) { leftOffsetX = leftOffsetX + axisWidth + 20; } w.globals.translateYAxisX[index] = xLeft + yaxe.labels.offsetX; } else { if (w.globals.isBarHorizontal) { xRight = w.globals.gridWidth + w.globals.translateX - 1; w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX; } else { xRight = w.globals.gridWidth + w.globals.translateX + rightOffsetX; if (!shouldNotDrawAxis) { rightOffsetX = rightOffsetX + axisWidth + 20; } w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX + 20; } } }); } }, { key: "setYAxisTextAlignments", value: function setYAxisTextAlignments() { var w = this.w; var yaxis = w.globals.dom.baseEl.getElementsByClassName("apexcharts-yaxis"); yaxis = Utils$1.listToArray(yaxis); yaxis.forEach(function (y, index) { var yaxe = w.config.yaxis[index]; // proceed only if user has specified alignment if (yaxe && !yaxe.floating && yaxe.labels.align !== undefined) { var yAxisInner = w.globals.dom.baseEl.querySelector(".apexcharts-yaxis[rel='".concat(index, "'] .apexcharts-yaxis-texts-g")); var yAxisTexts = w.globals.dom.baseEl.querySelectorAll(".apexcharts-yaxis[rel='".concat(index, "'] .apexcharts-yaxis-label")); yAxisTexts = Utils$1.listToArray(yAxisTexts); var rect = yAxisInner.getBoundingClientRect(); if (yaxe.labels.align === 'left') { yAxisTexts.forEach(function (label, lI) { label.setAttribute('text-anchor', 'start'); }); if (!yaxe.opposite) { yAxisInner.setAttribute('transform', "translate(-".concat(rect.width, ", 0)")); } } else if (yaxe.labels.align === 'center') { yAxisTexts.forEach(function (label, lI) { label.setAttribute('text-anchor', 'middle'); }); yAxisInner.setAttribute('transform', "translate(".concat(rect.width / 2 * (!yaxe.opposite ? -1 : 1), ", 0)")); } else if (yaxe.labels.align === 'right') { yAxisTexts.forEach(function (label, lI) { label.setAttribute('text-anchor', 'end'); }); if (yaxe.opposite) { yAxisInner.setAttribute('transform', "translate(".concat(rect.width, ", 0)")); } } } }); } }]); return YAxis; }(); var Events = /*#__PURE__*/function () { function Events(ctx) { _classCallCheck(this, Events); this.ctx = ctx; this.w = ctx.w; this.documentEvent = Utils$1.bind(this.documentEvent, this); } _createClass(Events, [{ key: "addEventListener", value: function addEventListener(name, handler) { var w = this.w; if (w.globals.events.hasOwnProperty(name)) { w.globals.events[name].push(handler); } else { w.globals.events[name] = [handler]; } } }, { key: "removeEventListener", value: function removeEventListener(name, handler) { var w = this.w; if (!w.globals.events.hasOwnProperty(name)) { return; } var index = w.globals.events[name].indexOf(handler); if (index !== -1) { w.globals.events[name].splice(index, 1); } } }, { key: "fireEvent", value: function fireEvent(name, args) { var w = this.w; if (!w.globals.events.hasOwnProperty(name)) { return; } if (!args || !args.length) { args = []; } var evs = w.globals.events[name]; var l = evs.length; for (var i = 0; i < l; i++) { evs[i].apply(null, args); } } }, { key: "setupEventHandlers", value: function setupEventHandlers() { var _this = this; var w = this.w; var me = this.ctx; var clickableArea = w.globals.dom.baseEl.querySelector(w.globals.chartClass); this.ctx.eventList.forEach(function (event) { clickableArea.addEventListener(event, function (e) { var opts = Object.assign({}, w, { seriesIndex: w.globals.capturedSeriesIndex, dataPointIndex: w.globals.capturedDataPointIndex }); if (e.type === 'mousemove' || e.type === 'touchmove') { if (typeof w.config.chart.events.mouseMove === 'function') { w.config.chart.events.mouseMove(e, me, opts); } } else if (e.type === 'mouseleave' || e.type === 'touchleave') { if (typeof w.config.chart.events.mouseLeave === 'function') { w.config.chart.events.mouseLeave(e, me, opts); } } else if (e.type === 'mouseup' && e.which === 1 || e.type === 'touchend') { if (typeof w.config.chart.events.click === 'function') { w.config.chart.events.click(e, me, opts); } me.ctx.events.fireEvent('click', [e, me, opts]); } }, { capture: false, passive: true }); }); this.ctx.eventList.forEach(function (event) { w.globals.dom.baseEl.addEventListener(event, _this.documentEvent, { passive: true }); }); this.ctx.core.setupBrushHandler(); } }, { key: "documentEvent", value: function documentEvent(e) { var w = this.w; var target = e.target.className; if (e.type === 'click') { var elMenu = w.globals.dom.baseEl.querySelector('.apexcharts-menu'); if (elMenu && elMenu.classList.contains('apexcharts-menu-open') && target !== 'apexcharts-menu-icon') { elMenu.classList.remove('apexcharts-menu-open'); } } w.globals.clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX; w.globals.clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY; } }]); return Events; }(); var Localization = /*#__PURE__*/function () { function Localization(ctx) { _classCallCheck(this, Localization); this.ctx = ctx; this.w = ctx.w; } _createClass(Localization, [{ key: "setCurrentLocaleValues", value: function setCurrentLocaleValues(localeName) { var locales = this.w.config.chart.locales; // check if user has specified locales in global Apex variable // if yes - then extend those with local chart's locale if (window.Apex.chart && window.Apex.chart.locales && window.Apex.chart.locales.length > 0) { locales = this.w.config.chart.locales.concat(window.Apex.chart.locales); } // find the locale from the array of locales which user has set (either by chart.defaultLocale or by calling setLocale() method.) var selectedLocale = locales.filter(function (c) { return c.name === localeName; })[0]; if (selectedLocale) { // create a complete locale object by extending defaults so you don't get undefined errors. var ret = Utils$1.extend(en, selectedLocale); // store these locale options in global var for ease access this.w.globals.locale = ret.options; } else { throw new Error('Wrong locale name provided. Please make sure you set the correct locale name in options'); } } }]); return Localization; }(); var Axes = /*#__PURE__*/function () { function Axes(ctx) { _classCallCheck(this, Axes); this.ctx = ctx; this.w = ctx.w; } _createClass(Axes, [{ key: "drawAxis", value: function drawAxis(type, elgrid) { var _this = this; var gl = this.w.globals; var cnf = this.w.config; var xAxis = new XAxis(this.ctx, elgrid); var yAxis = new YAxis(this.ctx, elgrid); if (gl.axisCharts && type !== 'radar') { var elXaxis, elYaxis; if (gl.isBarHorizontal) { elYaxis = yAxis.drawYaxisInversed(0); elXaxis = xAxis.drawXaxisInversed(0); gl.dom.elGraphical.add(elXaxis); gl.dom.elGraphical.add(elYaxis); } else { elXaxis = xAxis.drawXaxis(); gl.dom.elGraphical.add(elXaxis); cnf.yaxis.map(function (yaxe, index) { if (gl.ignoreYAxisIndexes.indexOf(index) === -1) { elYaxis = yAxis.drawYaxis(index); gl.dom.Paper.add(elYaxis); if (_this.w.config.grid.position === 'back') { var inner = gl.dom.Paper.children()[1]; inner.remove(); gl.dom.Paper.add(inner); } } }); } } } }]); return Axes; }(); var Crosshairs = /*#__PURE__*/function () { function Crosshairs(ctx) { _classCallCheck(this, Crosshairs); this.ctx = ctx; this.w = ctx.w; } _createClass(Crosshairs, [{ key: "drawXCrosshairs", value: function drawXCrosshairs() { var w = this.w; var graphics = new Graphics(this.ctx); var filters = new Filters(this.ctx); var crosshairGradient = w.config.xaxis.crosshairs.fill.gradient; var crosshairShadow = w.config.xaxis.crosshairs.dropShadow; var fillType = w.config.xaxis.crosshairs.fill.type; var gradientFrom = crosshairGradient.colorFrom; var gradientTo = crosshairGradient.colorTo; var opacityFrom = crosshairGradient.opacityFrom; var opacityTo = crosshairGradient.opacityTo; var stops = crosshairGradient.stops; var shadow = 'none'; var dropShadow = crosshairShadow.enabled; var shadowLeft = crosshairShadow.left; var shadowTop = crosshairShadow.top; var shadowBlur = crosshairShadow.blur; var shadowColor = crosshairShadow.color; var shadowOpacity = crosshairShadow.opacity; var xcrosshairsFill = w.config.xaxis.crosshairs.fill.color; if (w.config.xaxis.crosshairs.show) { if (fillType === 'gradient') { xcrosshairsFill = graphics.drawGradient('vertical', gradientFrom, gradientTo, opacityFrom, opacityTo, null, stops, null); } var xcrosshairs = graphics.drawRect(); if (w.config.xaxis.crosshairs.width === 1) { // to prevent drawing 2 lines, convert rect to line xcrosshairs = graphics.drawLine(); } var gridHeight = w.globals.gridHeight; if (!Utils$1.isNumber(gridHeight) || gridHeight < 0) { gridHeight = 0; } var crosshairsWidth = w.config.xaxis.crosshairs.width; if (!Utils$1.isNumber(crosshairsWidth) || crosshairsWidth < 0) { crosshairsWidth = 0; } xcrosshairs.attr({ class: 'apexcharts-xcrosshairs', x: 0, y: 0, y2: gridHeight, width: crosshairsWidth, height: gridHeight, fill: xcrosshairsFill, filter: shadow, 'fill-opacity': w.config.xaxis.crosshairs.opacity, stroke: w.config.xaxis.crosshairs.stroke.color, 'stroke-width': w.config.xaxis.crosshairs.stroke.width, 'stroke-dasharray': w.config.xaxis.crosshairs.stroke.dashArray }); if (dropShadow) { xcrosshairs = filters.dropShadow(xcrosshairs, { left: shadowLeft, top: shadowTop, blur: shadowBlur, color: shadowColor, opacity: shadowOpacity }); } w.globals.dom.elGraphical.add(xcrosshairs); } } }, { key: "drawYCrosshairs", value: function drawYCrosshairs() { var w = this.w; var graphics = new Graphics(this.ctx); var crosshair = w.config.yaxis[0].crosshairs; var offX = w.globals.barPadForNumericAxis; if (w.config.yaxis[0].crosshairs.show) { var ycrosshairs = graphics.drawLine(-offX, 0, w.globals.gridWidth + offX, 0, crosshair.stroke.color, crosshair.stroke.dashArray, crosshair.stroke.width); ycrosshairs.attr({ class: 'apexcharts-ycrosshairs' }); w.globals.dom.elGraphical.add(ycrosshairs); } // draw an invisible crosshair to help in positioning the yaxis tooltip var ycrosshairsHidden = graphics.drawLine(-offX, 0, w.globals.gridWidth + offX, 0, crosshair.stroke.color, 0, 0); ycrosshairsHidden.attr({ class: 'apexcharts-ycrosshairs-hidden' }); w.globals.dom.elGraphical.add(ycrosshairsHidden); } }]); return Crosshairs; }(); /** * ApexCharts Responsive Class to override options for different screen sizes. * * @module Responsive **/ var Responsive = /*#__PURE__*/function () { function Responsive(ctx) { _classCallCheck(this, Responsive); this.ctx = ctx; this.w = ctx.w; } // the opts parameter if not null has to be set overriding everything // as the opts is set by user externally _createClass(Responsive, [{ key: "checkResponsiveConfig", value: function checkResponsiveConfig(opts) { var _this = this; var w = this.w; var cnf = w.config; // check if responsive config exists if (cnf.responsive.length === 0) return; var res = cnf.responsive.slice(); res.sort(function (a, b) { return a.breakpoint > b.breakpoint ? 1 : b.breakpoint > a.breakpoint ? -1 : 0; }).reverse(); var config = new Config({}); var iterateResponsiveOptions = function iterateResponsiveOptions() { var newOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var largestBreakpoint = res[0].breakpoint; var width = window.innerWidth > 0 ? window.innerWidth : screen.width; if (width > largestBreakpoint) { var options = CoreUtils.extendArrayProps(config, w.globals.initialConfig, w); newOptions = Utils$1.extend(options, newOptions); newOptions = Utils$1.extend(w.config, newOptions); _this.overrideResponsiveOptions(newOptions); } else { for (var i = 0; i < res.length; i++) { if (width < res[i].breakpoint) { newOptions = CoreUtils.extendArrayProps(config, res[i].options, w); newOptions = Utils$1.extend(w.config, newOptions); _this.overrideResponsiveOptions(newOptions); } } } }; if (opts) { var options = CoreUtils.extendArrayProps(config, opts, w); options = Utils$1.extend(w.config, options); options = Utils$1.extend(options, opts); iterateResponsiveOptions(options); } else { iterateResponsiveOptions({}); } } }, { key: "overrideResponsiveOptions", value: function overrideResponsiveOptions(newOptions) { var newConfig = new Config(newOptions).init({ responsiveOverride: true }); this.w.config = newConfig; } }]); return Responsive; }(); /** * ApexCharts Theme Class for setting the colors and palettes. * * @module Theme **/ var Theme = /*#__PURE__*/function () { function Theme(ctx) { _classCallCheck(this, Theme); this.ctx = ctx; this.colors = []; this.w = ctx.w; var w = this.w; this.isColorFn = false; this.isHeatmapDistributed = w.config.chart.type === 'treemap' && w.config.plotOptions.treemap.distributed || w.config.chart.type === 'heatmap' && w.config.plotOptions.heatmap.distributed; this.isBarDistributed = w.config.plotOptions.bar.distributed && (w.config.chart.type === 'bar' || w.config.chart.type === 'rangeBar'); } _createClass(Theme, [{ key: "init", value: function init() { this.setDefaultColors(); } }, { key: "setDefaultColors", value: function setDefaultColors() { var _this = this; var w = this.w; var utils = new Utils$1(); w.globals.dom.elWrap.classList.add("apexcharts-theme-".concat(w.config.theme.mode)); if (w.config.colors === undefined) { w.globals.colors = this.predefined(); } else { w.globals.colors = w.config.colors; // if user provided a function in colors, we need to eval here if (Array.isArray(w.config.colors) && w.config.colors.length > 0 && typeof w.config.colors[0] === 'function') { w.globals.colors = w.config.series.map(function (s, i) { var c = w.config.colors[i]; if (!c) c = w.config.colors[0]; if (typeof c === 'function') { _this.isColorFn = true; return c({ value: w.globals.axisCharts ? w.globals.series[i][0] ? w.globals.series[i][0] : 0 : w.globals.series[i], seriesIndex: i, dataPointIndex: i, w: w }); } return c; }); } } // user defined colors in series array w.globals.seriesColors.map(function (c, i) { if (c) { w.globals.colors[i] = c; } }); if (w.config.theme.monochrome.enabled) { var monoArr = []; var glsCnt = w.globals.series.length; if (this.isBarDistributed || this.isHeatmapDistributed) { glsCnt = w.globals.series[0].length * w.globals.series.length; } var mainColor = w.config.theme.monochrome.color; var part = 1 / (glsCnt / w.config.theme.monochrome.shadeIntensity); var shade = w.config.theme.monochrome.shadeTo; var percent = 0; for (var gsl = 0; gsl < glsCnt; gsl++) { var newColor = void 0; if (shade === 'dark') { newColor = utils.shadeColor(percent * -1, mainColor); percent = percent + part; } else { newColor = utils.shadeColor(percent, mainColor); percent = percent + part; } monoArr.push(newColor); } w.globals.colors = monoArr.slice(); } var defaultColors = w.globals.colors.slice(); // if user specified fewer colors than no. of series, push the same colors again this.pushExtraColors(w.globals.colors); var colorTypes = ['fill', 'stroke']; colorTypes.forEach(function (c) { if (w.config[c].colors === undefined) { w.globals[c].colors = _this.isColorFn ? w.config.colors : defaultColors; } else { w.globals[c].colors = w.config[c].colors.slice(); } _this.pushExtraColors(w.globals[c].colors); }); if (w.config.dataLabels.style.colors === undefined) { w.globals.dataLabels.style.colors = defaultColors; } else { w.globals.dataLabels.style.colors = w.config.dataLabels.style.colors.slice(); } this.pushExtraColors(w.globals.dataLabels.style.colors, 50); if (w.config.plotOptions.radar.polygons.fill.colors === undefined) { w.globals.radarPolygons.fill.colors = [w.config.theme.mode === 'dark' ? '#424242' : 'none']; } else { w.globals.radarPolygons.fill.colors = w.config.plotOptions.radar.polygons.fill.colors.slice(); } this.pushExtraColors(w.globals.radarPolygons.fill.colors, 20); // The point colors if (w.config.markers.colors === undefined) { w.globals.markers.colors = defaultColors; } else { w.globals.markers.colors = w.config.markers.colors.slice(); } this.pushExtraColors(w.globals.markers.colors); } // When the number of colors provided is less than the number of series, this method // will push same colors to the list // params: // distributed is only valid for distributed column/bar charts }, { key: "pushExtraColors", value: function pushExtraColors(colorSeries, length) { var distributed = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var w = this.w; var len = length || w.globals.series.length; if (distributed === null) { distributed = this.isBarDistributed || this.isHeatmapDistributed || w.config.chart.type === 'heatmap' && w.config.plotOptions.heatmap.colorScale.inverse; } if (distributed && w.globals.series.length) { len = w.globals.series[w.globals.maxValsInArrayIndex].length * w.globals.series.length; } if (colorSeries.length < len) { var diff = len - colorSeries.length; for (var i = 0; i < diff; i++) { colorSeries.push(colorSeries[i]); } } } }, { key: "updateThemeOptions", value: function updateThemeOptions(options) { options.chart = options.chart || {}; options.tooltip = options.tooltip || {}; var mode = options.theme.mode || 'light'; var palette = options.theme.palette ? options.theme.palette : mode === 'dark' ? 'palette4' : 'palette1'; var foreColor = options.chart.foreColor ? options.chart.foreColor : mode === 'dark' ? '#f6f7f8' : '#373d3f'; options.tooltip.theme = mode; options.chart.foreColor = foreColor; options.theme.palette = palette; return options; } }, { key: "predefined", value: function predefined() { var palette = this.w.config.theme.palette; // D6E3F8, FCEFEF, DCE0D9, A5978B, EDDDD4, D6E3F8, FEF5EF switch (palette) { case 'palette1': this.colors = ['#008FFB', '#00E396', '#FEB019', '#FF4560', '#775DD0']; break; case 'palette2': this.colors = ['#3f51b5', '#03a9f4', '#4caf50', '#f9ce1d', '#FF9800']; break; case 'palette3': this.colors = ['#33b2df', '#546E7A', '#d4526e', '#13d8aa', '#A5978B']; break; case 'palette4': this.colors = ['#4ecdc4', '#c7f464', '#81D4FA', '#fd6a6a', '#546E7A']; break; case 'palette5': this.colors = ['#2b908f', '#f9a3a4', '#90ee7e', '#fa4443', '#69d2e7']; break; case 'palette6': this.colors = ['#449DD1', '#F86624', '#EA3546', '#662E9B', '#C5D86D']; break; case 'palette7': this.colors = ['#D7263D', '#1B998B', '#2E294E', '#F46036', '#E2C044']; break; case 'palette8': this.colors = ['#662E9B', '#F86624', '#F9C80E', '#EA3546', '#43BCCD']; break; case 'palette9': this.colors = ['#5C4742', '#A5978B', '#8D5B4C', '#5A2A27', '#C4BBAF']; break; case 'palette10': this.colors = ['#A300D6', '#7D02EB', '#5653FE', '#2983FF', '#00B1F2']; break; default: this.colors = ['#008FFB', '#00E396', '#FEB019', '#FF4560', '#775DD0']; break; } return this.colors; } }]); return Theme; }(); var TitleSubtitle = /*#__PURE__*/function () { function TitleSubtitle(ctx) { _classCallCheck(this, TitleSubtitle); this.ctx = ctx; this.w = ctx.w; } _createClass(TitleSubtitle, [{ key: "draw", value: function draw() { this.drawTitleSubtitle('title'); this.drawTitleSubtitle('subtitle'); } }, { key: "drawTitleSubtitle", value: function drawTitleSubtitle(type) { var w = this.w; var tsConfig = type === 'title' ? w.config.title : w.config.subtitle; var x = w.globals.svgWidth / 2; var y = tsConfig.offsetY; var textAnchor = 'middle'; if (tsConfig.align === 'left') { x = 10; textAnchor = 'start'; } else if (tsConfig.align === 'right') { x = w.globals.svgWidth - 10; textAnchor = 'end'; } x = x + tsConfig.offsetX; y = y + parseInt(tsConfig.style.fontSize, 10) + tsConfig.margin / 2; if (tsConfig.text !== undefined) { var graphics = new Graphics(this.ctx); var titleText = graphics.drawText({ x: x, y: y, text: tsConfig.text, textAnchor: textAnchor, fontSize: tsConfig.style.fontSize, fontFamily: tsConfig.style.fontFamily, fontWeight: tsConfig.style.fontWeight, foreColor: tsConfig.style.color, opacity: 1 }); titleText.node.setAttribute('class', "apexcharts-".concat(type, "-text")); w.globals.dom.Paper.add(titleText); } } }]); return TitleSubtitle; }(); var Helpers$3 = /*#__PURE__*/function () { function Helpers(dCtx) { _classCallCheck(this, Helpers); this.w = dCtx.w; this.dCtx = dCtx; } /** * Get Chart Title/Subtitle Dimensions * @memberof Dimensions * @return {{width, height}} **/ _createClass(Helpers, [{ key: "getTitleSubtitleCoords", value: function getTitleSubtitleCoords(type) { var w = this.w; var width = 0; var height = 0; var floating = type === 'title' ? w.config.title.floating : w.config.subtitle.floating; var el = w.globals.dom.baseEl.querySelector(".apexcharts-".concat(type, "-text")); if (el !== null && !floating) { var coord = el.getBoundingClientRect(); width = coord.width; height = w.globals.axisCharts ? coord.height + 5 : coord.height; } return { width: width, height: height }; } }, { key: "getLegendsRect", value: function getLegendsRect() { var w = this.w; var elLegendWrap = w.globals.dom.baseEl.querySelector('.apexcharts-legend'); if (!w.config.legend.height && (w.config.legend.position === 'top' || w.config.legend.position === 'bottom')) { // avoid legend to take up all the space elLegendWrap.style.maxHeight = w.globals.svgHeight / 2 + 'px'; } var lgRect = Object.assign({}, Utils$1.getBoundingClientRect(elLegendWrap)); if (elLegendWrap !== null && !w.config.legend.floating && w.config.legend.show) { this.dCtx.lgRect = { x: lgRect.x, y: lgRect.y, height: lgRect.height, width: lgRect.height === 0 ? 0 : lgRect.width }; } else { this.dCtx.lgRect = { x: 0, y: 0, height: 0, width: 0 }; } // if legend takes up all of the chart space, we need to restrict it. if (w.config.legend.position === 'left' || w.config.legend.position === 'right') { if (this.dCtx.lgRect.width * 1.5 > w.globals.svgWidth) { this.dCtx.lgRect.width = w.globals.svgWidth / 1.5; } } return this.dCtx.lgRect; } }, { key: "getLargestStringFromMultiArr", value: function getLargestStringFromMultiArr(val, arr) { var w = this.w; var valArr = val; if (w.globals.isMultiLineX) { // if the xaxis labels has multiline texts (array) var maxArrs = arr.map(function (xl, idx) { return Array.isArray(xl) ? xl.length : 1; }); var maxArrLen = Math.max.apply(Math, _toConsumableArray(maxArrs)); var maxArrIndex = maxArrs.indexOf(maxArrLen); valArr = arr[maxArrIndex]; } return valArr; } }]); return Helpers; }(); var DimXAxis = /*#__PURE__*/function () { function DimXAxis(dCtx) { _classCallCheck(this, DimXAxis); this.w = dCtx.w; this.dCtx = dCtx; } /** * Get X Axis Dimensions * @memberof Dimensions * @return {{width, height}} **/ _createClass(DimXAxis, [{ key: "getxAxisLabelsCoords", value: function getxAxisLabelsCoords() { var w = this.w; var xaxisLabels = w.globals.labels.slice(); if (w.config.xaxis.convertedCatToNumeric && xaxisLabels.length === 0) { xaxisLabels = w.globals.categoryLabels; } var rect; if (w.globals.timescaleLabels.length > 0) { var coords = this.getxAxisTimeScaleLabelsCoords(); rect = { width: coords.width, height: coords.height }; w.globals.rotateXLabels = false; } else { this.dCtx.lgWidthForSideLegends = (w.config.legend.position === 'left' || w.config.legend.position === 'right') && !w.config.legend.floating ? this.dCtx.lgRect.width : 0; // get the longest string from the labels array and also apply label formatter var xlbFormatter = w.globals.xLabelFormatter; // prevent changing xaxisLabels to avoid issues in multi-yaxes - fix #522 var val = Utils$1.getLargestStringFromArr(xaxisLabels); var valArr = this.dCtx.dimHelpers.getLargestStringFromMultiArr(val, xaxisLabels); // the labels gets changed for bar charts if (w.globals.isBarHorizontal) { val = w.globals.yAxisScale[0].result.reduce(function (a, b) { return a.length > b.length ? a : b; }, 0); valArr = val; } var xFormat = new Formatters(this.dCtx.ctx); var timestamp = val; val = xFormat.xLabelFormat(xlbFormatter, val, timestamp, { i: undefined, dateFormatter: new DateTime(this.dCtx.ctx).formatDate, w: w }); valArr = xFormat.xLabelFormat(xlbFormatter, valArr, timestamp, { i: undefined, dateFormatter: new DateTime(this.dCtx.ctx).formatDate, w: w }); if (w.config.xaxis.convertedCatToNumeric && typeof val === 'undefined' || String(val).trim() === '') { val = '1'; valArr = val; } var graphics = new Graphics(this.dCtx.ctx); var xLabelrect = graphics.getTextRects(val, w.config.xaxis.labels.style.fontSize); var xArrLabelrect = xLabelrect; if (val !== valArr) { xArrLabelrect = graphics.getTextRects(valArr, w.config.xaxis.labels.style.fontSize); } rect = { width: xLabelrect.width >= xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width, height: xLabelrect.height >= xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height }; if (rect.width * xaxisLabels.length > w.globals.svgWidth - this.dCtx.lgWidthForSideLegends - this.dCtx.yAxisWidth - this.dCtx.gridPad.left - this.dCtx.gridPad.right && w.config.xaxis.labels.rotate !== 0 || w.config.xaxis.labels.rotateAlways) { if (!w.globals.isBarHorizontal) { w.globals.rotateXLabels = true; var getRotatedTextRects = function getRotatedTextRects(text) { return graphics.getTextRects(text, w.config.xaxis.labels.style.fontSize, w.config.xaxis.labels.style.fontFamily, "rotate(".concat(w.config.xaxis.labels.rotate, " 0 0)"), false); }; xLabelrect = getRotatedTextRects(val); if (val !== valArr) { xArrLabelrect = getRotatedTextRects(valArr); } rect.height = (xLabelrect.height > xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height) / 1.5; rect.width = xLabelrect.width > xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width; } } else { w.globals.rotateXLabels = false; } } if (!w.config.xaxis.labels.show) { rect = { width: 0, height: 0 }; } return { width: rect.width, height: rect.height }; } /** * Get X Axis Label Group height * @memberof Dimensions * @return {{width, height}} */ }, { key: "getxAxisGroupLabelsCoords", value: function getxAxisGroupLabelsCoords() { var _w$config$xaxis$group; var w = this.w; if (!w.globals.hasGroups) { return { width: 0, height: 0 }; } var fontSize = ((_w$config$xaxis$group = w.config.xaxis.group.style) === null || _w$config$xaxis$group === void 0 ? void 0 : _w$config$xaxis$group.fontSize) || w.config.xaxis.labels.style.fontSize; var xaxisLabels = w.globals.groups.map(function (g) { return g.title; }); var rect; // prevent changing xaxisLabels to avoid issues in multi-yaxes - fix #522 var val = Utils$1.getLargestStringFromArr(xaxisLabels); var valArr = this.dCtx.dimHelpers.getLargestStringFromMultiArr(val, xaxisLabels); var graphics = new Graphics(this.dCtx.ctx); var xLabelrect = graphics.getTextRects(val, fontSize); var xArrLabelrect = xLabelrect; if (val !== valArr) { xArrLabelrect = graphics.getTextRects(valArr, fontSize); } rect = { width: xLabelrect.width >= xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width, height: xLabelrect.height >= xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height }; if (!w.config.xaxis.labels.show) { rect = { width: 0, height: 0 }; } return { width: rect.width, height: rect.height }; } /** * Get X Axis Title Dimensions * @memberof Dimensions * @return {{width, height}} **/ }, { key: "getxAxisTitleCoords", value: function getxAxisTitleCoords() { var w = this.w; var width = 0; var height = 0; if (w.config.xaxis.title.text !== undefined) { var graphics = new Graphics(this.dCtx.ctx); var rect = graphics.getTextRects(w.config.xaxis.title.text, w.config.xaxis.title.style.fontSize); width = rect.width; height = rect.height; } return { width: width, height: height }; } }, { key: "getxAxisTimeScaleLabelsCoords", value: function getxAxisTimeScaleLabelsCoords() { var w = this.w; var rect; this.dCtx.timescaleLabels = w.globals.timescaleLabels.slice(); var labels = this.dCtx.timescaleLabels.map(function (label) { return label.value; }); // get the longest string from the labels array and also apply label formatter to it var val = labels.reduce(function (a, b) { // if undefined, maybe user didn't pass the datetime(x) values if (typeof a === 'undefined') { console.error('You have possibly supplied invalid Date format. Please supply a valid JavaScript Date'); return 0; } else { return a.length > b.length ? a : b; } }, 0); var graphics = new Graphics(this.dCtx.ctx); rect = graphics.getTextRects(val, w.config.xaxis.labels.style.fontSize); var totalWidthRotated = rect.width * 1.05 * labels.length; if (totalWidthRotated > w.globals.gridWidth && w.config.xaxis.labels.rotate !== 0) { w.globals.overlappingXLabels = true; } return rect; } // In certain cases, the last labels gets cropped in xaxis. // Hence, we add some additional padding based on the label length to avoid the last label being cropped or we don't draw it at all }, { key: "additionalPaddingXLabels", value: function additionalPaddingXLabels(xaxisLabelCoords) { var _this = this; var w = this.w; var gl = w.globals; var cnf = w.config; var xtype = cnf.xaxis.type; var lbWidth = xaxisLabelCoords.width; gl.skipLastTimelinelabel = false; gl.skipFirstTimelinelabel = false; var isBarOpposite = w.config.yaxis[0].opposite && w.globals.isBarHorizontal; var isCollapsed = function isCollapsed(i) { return gl.collapsedSeriesIndices.indexOf(i) !== -1; }; var rightPad = function rightPad(yaxe) { if (_this.dCtx.timescaleLabels && _this.dCtx.timescaleLabels.length) { // for timeline labels, we take the last label and check if it exceeds gridWidth var firstimescaleLabel = _this.dCtx.timescaleLabels[0]; var lastTimescaleLabel = _this.dCtx.timescaleLabels[_this.dCtx.timescaleLabels.length - 1]; var lastLabelPosition = lastTimescaleLabel.position + lbWidth / 1.75 - _this.dCtx.yAxisWidthRight; var firstLabelPosition = firstimescaleLabel.position - lbWidth / 1.75 + _this.dCtx.yAxisWidthLeft; var lgRightRectWidth = w.config.legend.position === 'right' && _this.dCtx.lgRect.width > 0 ? _this.dCtx.lgRect.width : 0; if (lastLabelPosition > gl.svgWidth - gl.translateX - lgRightRectWidth) { gl.skipLastTimelinelabel = true; } if (firstLabelPosition < -((!yaxe.show || yaxe.floating) && (cnf.chart.type === 'bar' || cnf.chart.type === 'candlestick' || cnf.chart.type === 'rangeBar' || cnf.chart.type === 'boxPlot') ? lbWidth / 1.75 : 10)) { gl.skipFirstTimelinelabel = true; } } else if (xtype === 'datetime') { // If user has enabled DateTime, but uses own's formatter if (_this.dCtx.gridPad.right < lbWidth && !gl.rotateXLabels) { gl.skipLastTimelinelabel = true; } } else if (xtype !== 'datetime') { if (_this.dCtx.gridPad.right < lbWidth / 2 - _this.dCtx.yAxisWidthRight && !gl.rotateXLabels && !w.config.xaxis.labels.trim && (w.config.xaxis.tickPlacement !== 'between' || w.globals.isBarHorizontal)) { _this.dCtx.xPadRight = lbWidth / 2 + 1; } } }; var padYAxe = function padYAxe(yaxe, i) { if (isCollapsed(i)) return; // the code below causes issue apexcharts.js#1989 // after testing with other use-cases, this has no actual value, hence commented // if (xtype !== 'datetime') { // if ( // this.dCtx.gridPad.left < lbWidth / 2 - this.dCtx.yAxisWidthLeft && // !gl.rotateXLabels && // !cnf.xaxis.labels.trim // ) { // this.dCtx.xPadLeft = lbWidth / 2 + 1 // } // } rightPad(yaxe); }; cnf.yaxis.forEach(function (yaxe, i) { if (isBarOpposite) { if (_this.dCtx.gridPad.left < lbWidth) { _this.dCtx.xPadLeft = lbWidth / 2 + 1; } _this.dCtx.xPadRight = lbWidth / 2 + 1; } else { padYAxe(yaxe, i); } }); } }]); return DimXAxis; }(); var DimYAxis = /*#__PURE__*/function () { function DimYAxis(dCtx) { _classCallCheck(this, DimYAxis); this.w = dCtx.w; this.dCtx = dCtx; } /** * Get Y Axis Dimensions * @memberof Dimensions * @return {{width, height}} **/ _createClass(DimYAxis, [{ key: "getyAxisLabelsCoords", value: function getyAxisLabelsCoords() { var _this = this; var w = this.w; var width = 0; var height = 0; var ret = []; var labelPad = 10; var axesUtils = new AxesUtils(this.dCtx.ctx); w.config.yaxis.map(function (yaxe, index) { var yS = w.globals.yAxisScale[index]; var yAxisMinWidth = 0; if (!axesUtils.isYAxisHidden(index) && yaxe.labels.show && yaxe.labels.minWidth !== undefined) yAxisMinWidth = yaxe.labels.minWidth; if (!axesUtils.isYAxisHidden(index) && yaxe.labels.show && yS.result.length) { var lbFormatter = w.globals.yLabelFormatters[index]; var minV = yS.niceMin === Number.MIN_VALUE ? 0 : yS.niceMin; var longestStr = String(minV).length > String(yS.niceMax).length ? minV : yS.niceMax; // the second parameter -1 is the index of tick which user can use in the formatter var val = lbFormatter(longestStr, { seriesIndex: index, dataPointIndex: -1, w: w }); var valArr = val; // if user has specified a custom formatter, and the result is null or empty, we need to discard the formatter and take the value as it is. if (typeof val === 'undefined' || val.length === 0) { val = longestStr; } if (w.globals.isBarHorizontal) { labelPad = 0; var barYaxisLabels = w.globals.labels.slice(); // get the longest string from the labels array and also apply label formatter to it val = Utils$1.getLargestStringFromArr(barYaxisLabels); val = lbFormatter(val, { seriesIndex: index, dataPointIndex: -1, w: w }); valArr = _this.dCtx.dimHelpers.getLargestStringFromMultiArr(val, barYaxisLabels); } var graphics = new Graphics(_this.dCtx.ctx); var rotateStr = 'rotate('.concat(yaxe.labels.rotate, ' 0 0)'); var rect = graphics.getTextRects(val, yaxe.labels.style.fontSize, yaxe.labels.style.fontFamily, rotateStr, false); var arrLabelrect = rect; if (val !== valArr) { arrLabelrect = graphics.getTextRects(valArr, yaxe.labels.style.fontSize, yaxe.labels.style.fontFamily, rotateStr, false); } ret.push({ width: (yAxisMinWidth > arrLabelrect.width || yAxisMinWidth > rect.width ? yAxisMinWidth : arrLabelrect.width > rect.width ? arrLabelrect.width : rect.width) + labelPad, height: arrLabelrect.height > rect.height ? arrLabelrect.height : rect.height }); } else { ret.push({ width: width, height: height }); } }); return ret; } /** * Get Y Axis Dimensions * @memberof Dimensions * @return {{width, height}} **/ }, { key: "getyAxisTitleCoords", value: function getyAxisTitleCoords() { var _this2 = this; var w = this.w; var ret = []; w.config.yaxis.map(function (yaxe, index) { if (yaxe.show && yaxe.title.text !== undefined) { var graphics = new Graphics(_this2.dCtx.ctx); var rotateStr = 'rotate('.concat(yaxe.title.rotate, ' 0 0)'); var rect = graphics.getTextRects(yaxe.title.text, yaxe.title.style.fontSize, yaxe.title.style.fontFamily, rotateStr, false); ret.push({ width: rect.width, height: rect.height }); } else { ret.push({ width: 0, height: 0 }); } }); return ret; } }, { key: "getTotalYAxisWidth", value: function getTotalYAxisWidth() { var w = this.w; var yAxisWidth = 0; var yAxisWidthLeft = 0; var yAxisWidthRight = 0; var padding = w.globals.yAxisScale.length > 1 ? 10 : 0; var axesUtils = new AxesUtils(this.dCtx.ctx); var isHiddenYAxis = function isHiddenYAxis(index) { return w.globals.ignoreYAxisIndexes.indexOf(index) > -1; }; var padForLabelTitle = function padForLabelTitle(coord, index) { var floating = w.config.yaxis[index].floating; var width = 0; if (coord.width > 0 && !floating) { width = coord.width + padding; if (isHiddenYAxis(index)) { width = width - coord.width - padding; } } else { width = floating || axesUtils.isYAxisHidden(index) ? 0 : 5; } w.config.yaxis[index].opposite ? yAxisWidthRight = yAxisWidthRight + width : yAxisWidthLeft = yAxisWidthLeft + width; yAxisWidth = yAxisWidth + width; }; w.globals.yLabelsCoords.map(function (yLabelCoord, index) { padForLabelTitle(yLabelCoord, index); }); w.globals.yTitleCoords.map(function (yTitleCoord, index) { padForLabelTitle(yTitleCoord, index); }); if (w.globals.isBarHorizontal && !w.config.yaxis[0].floating) { yAxisWidth = w.globals.yLabelsCoords[0].width + w.globals.yTitleCoords[0].width + 15; } this.dCtx.yAxisWidthLeft = yAxisWidthLeft; this.dCtx.yAxisWidthRight = yAxisWidthRight; return yAxisWidth; } }]); return DimYAxis; }(); var DimGrid = /*#__PURE__*/function () { function DimGrid(dCtx) { _classCallCheck(this, DimGrid); this.w = dCtx.w; this.dCtx = dCtx; } _createClass(DimGrid, [{ key: "gridPadForColumnsInNumericAxis", value: function gridPadForColumnsInNumericAxis(gridWidth) { var w = this.w; if (w.globals.noData || w.globals.allSeriesCollapsed) { return 0; } var hasBar = function hasBar(type) { return type === 'bar' || type === 'rangeBar' || type === 'candlestick' || type === 'boxPlot'; }; var type = w.config.chart.type; var barWidth = 0; var seriesLen = hasBar(type) ? w.config.series.length : 1; if (w.globals.comboBarCount > 0) { seriesLen = w.globals.comboBarCount; } w.globals.collapsedSeries.forEach(function (c) { if (hasBar(c.type)) { seriesLen = seriesLen - 1; } }); if (w.config.chart.stacked) { seriesLen = 1; } var barsPresent = hasBar(type) || w.globals.comboBarCount > 0; if (barsPresent && w.globals.isXNumeric && !w.globals.isBarHorizontal && seriesLen > 0) { var xRatio = 0; var xRange = Math.abs(w.globals.initialMaxX - w.globals.initialMinX); if (xRange <= 3) { xRange = w.globals.dataPoints; } xRatio = xRange / gridWidth; var xDivision; // max barwidth should be equal to minXDiff to avoid overlap if (w.globals.minXDiff && w.globals.minXDiff / xRatio > 0) { xDivision = w.globals.minXDiff / xRatio; } if (xDivision > gridWidth / 2) { xDivision = xDivision / 2; } barWidth = xDivision / seriesLen * parseInt(w.config.plotOptions.bar.columnWidth, 10) / 100; if (barWidth < 1) { barWidth = 1; } barWidth = barWidth / (seriesLen > 1 ? 1 : 1.5) + 5; w.globals.barPadForNumericAxis = barWidth; } return barWidth; } }, { key: "gridPadFortitleSubtitle", value: function gridPadFortitleSubtitle() { var _this = this; var w = this.w; var gl = w.globals; var gridShrinkOffset = this.dCtx.isSparkline || !w.globals.axisCharts ? 0 : 10; var titleSubtitle = ['title', 'subtitle']; titleSubtitle.forEach(function (t) { if (w.config[t].text !== undefined) { gridShrinkOffset += w.config[t].margin; } else { gridShrinkOffset += _this.dCtx.isSparkline || !w.globals.axisCharts ? 0 : 5; } }); if (w.config.legend.show && w.config.legend.position === 'bottom' && !w.config.legend.floating && !w.globals.axisCharts) { gridShrinkOffset += 10; } var titleCoords = this.dCtx.dimHelpers.getTitleSubtitleCoords('title'); var subtitleCoords = this.dCtx.dimHelpers.getTitleSubtitleCoords('subtitle'); gl.gridHeight = gl.gridHeight - titleCoords.height - subtitleCoords.height - gridShrinkOffset; gl.translateY = gl.translateY + titleCoords.height + subtitleCoords.height + gridShrinkOffset; } }, { key: "setGridXPosForDualYAxis", value: function setGridXPosForDualYAxis(yTitleCoords, yaxisLabelCoords) { var w = this.w; var axesUtils = new AxesUtils(this.dCtx.ctx); w.config.yaxis.map(function (yaxe, index) { if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1 && !yaxe.floating && !axesUtils.isYAxisHidden(index)) { if (yaxe.opposite) { w.globals.translateX = w.globals.translateX - (yaxisLabelCoords[index].width + yTitleCoords[index].width) - parseInt(w.config.yaxis[index].labels.style.fontSize, 10) / 1.2 - 12; } // fixes apexcharts.js#1599 if (w.globals.translateX < 2) { w.globals.translateX = 2; } } }); } }]); return DimGrid; }(); /** * ApexCharts Dimensions Class for calculating rects of all elements that are drawn and will be drawn. * * @module Dimensions **/ var Dimensions = /*#__PURE__*/function () { function Dimensions(ctx) { _classCallCheck(this, Dimensions); this.ctx = ctx; this.w = ctx.w; this.lgRect = {}; this.yAxisWidth = 0; this.yAxisWidthLeft = 0; this.yAxisWidthRight = 0; this.xAxisHeight = 0; this.isSparkline = this.w.config.chart.sparkline.enabled; this.dimHelpers = new Helpers$3(this); this.dimYAxis = new DimYAxis(this); this.dimXAxis = new DimXAxis(this); this.dimGrid = new DimGrid(this); this.lgWidthForSideLegends = 0; this.gridPad = this.w.config.grid.padding; this.xPadRight = 0; this.xPadLeft = 0; } /** * @memberof Dimensions * @param {object} w - chart context **/ _createClass(Dimensions, [{ key: "plotCoords", value: function plotCoords() { var _this = this; var w = this.w; var gl = w.globals; this.lgRect = this.dimHelpers.getLegendsRect(); if (this.isSparkline && (w.config.markers.discrete.length > 0 || w.config.markers.size > 0)) { Object.entries(this.gridPad).forEach(function (_ref) { var _ref2 = _slicedToArray(_ref, 2), k = _ref2[0], v = _ref2[1]; _this.gridPad[k] = Math.max(v, _this.w.globals.markers.largestSize / 1.5); }); } if (gl.axisCharts) { // for line / area / scatter / column this.setDimensionsForAxisCharts(); } else { // for pie / donuts / circle this.setDimensionsForNonAxisCharts(); } this.dimGrid.gridPadFortitleSubtitle(); // after calculating everything, apply padding set by user gl.gridHeight = gl.gridHeight - this.gridPad.top - this.gridPad.bottom; gl.gridWidth = gl.gridWidth - this.gridPad.left - this.gridPad.right - this.xPadRight - this.xPadLeft; var barWidth = this.dimGrid.gridPadForColumnsInNumericAxis(gl.gridWidth); gl.gridWidth = gl.gridWidth - barWidth * 2; gl.translateX = gl.translateX + this.gridPad.left + this.xPadLeft + (barWidth > 0 ? barWidth + 4 : 0); gl.translateY = gl.translateY + this.gridPad.top; } }, { key: "setDimensionsForAxisCharts", value: function setDimensionsForAxisCharts() { var _this2 = this; var w = this.w; var gl = w.globals; var yaxisLabelCoords = this.dimYAxis.getyAxisLabelsCoords(); var yTitleCoords = this.dimYAxis.getyAxisTitleCoords(); w.globals.yLabelsCoords = []; w.globals.yTitleCoords = []; w.config.yaxis.map(function (yaxe, index) { // store the labels and titles coords in global vars w.globals.yLabelsCoords.push({ width: yaxisLabelCoords[index].width, index: index }); w.globals.yTitleCoords.push({ width: yTitleCoords[index].width, index: index }); }); this.yAxisWidth = this.dimYAxis.getTotalYAxisWidth(); var xaxisLabelCoords = this.dimXAxis.getxAxisLabelsCoords(); var xaxisGroupLabelCoords = this.dimXAxis.getxAxisGroupLabelsCoords(); var xtitleCoords = this.dimXAxis.getxAxisTitleCoords(); this.conditionalChecksForAxisCoords(xaxisLabelCoords, xtitleCoords, xaxisGroupLabelCoords); gl.translateXAxisY = w.globals.rotateXLabels ? this.xAxisHeight / 8 : -4; gl.translateXAxisX = w.globals.rotateXLabels && w.globals.isXNumeric && w.config.xaxis.labels.rotate <= -45 ? -this.xAxisWidth / 4 : 0; if (w.globals.isBarHorizontal) { gl.rotateXLabels = false; gl.translateXAxisY = -1 * (parseInt(w.config.xaxis.labels.style.fontSize, 10) / 1.5); } gl.translateXAxisY = gl.translateXAxisY + w.config.xaxis.labels.offsetY; gl.translateXAxisX = gl.translateXAxisX + w.config.xaxis.labels.offsetX; var yAxisWidth = this.yAxisWidth; var xAxisHeight = this.xAxisHeight; gl.xAxisLabelsHeight = this.xAxisHeight - xtitleCoords.height; gl.xAxisGroupLabelsHeight = gl.xAxisLabelsHeight - xaxisLabelCoords.height; gl.xAxisLabelsWidth = this.xAxisWidth; gl.xAxisHeight = this.xAxisHeight; var translateY = 10; if (w.config.chart.type === 'radar' || this.isSparkline) { yAxisWidth = 0; xAxisHeight = gl.goldenPadding; } if (this.isSparkline) { this.lgRect = { height: 0, width: 0 }; } if (this.isSparkline || w.config.chart.type === 'treemap') { yAxisWidth = 0; xAxisHeight = 0; translateY = 0; } if (!this.isSparkline) { this.dimXAxis.additionalPaddingXLabels(xaxisLabelCoords); } var legendTopBottom = function legendTopBottom() { gl.translateX = yAxisWidth; gl.gridHeight = gl.svgHeight - _this2.lgRect.height - xAxisHeight - (!_this2.isSparkline && w.config.chart.type !== 'treemap' ? w.globals.rotateXLabels ? 10 : 15 : 0); gl.gridWidth = gl.svgWidth - yAxisWidth; }; if (w.config.xaxis.position === 'top') translateY = gl.xAxisHeight - w.config.xaxis.axisTicks.height - 5; switch (w.config.legend.position) { case 'bottom': gl.translateY = translateY; legendTopBottom(); break; case 'top': gl.translateY = this.lgRect.height + translateY; legendTopBottom(); break; case 'left': gl.translateY = translateY; gl.translateX = this.lgRect.width + yAxisWidth; gl.gridHeight = gl.svgHeight - xAxisHeight - 12; gl.gridWidth = gl.svgWidth - this.lgRect.width - yAxisWidth; break; case 'right': gl.translateY = translateY; gl.translateX = yAxisWidth; gl.gridHeight = gl.svgHeight - xAxisHeight - 12; gl.gridWidth = gl.svgWidth - this.lgRect.width - yAxisWidth - 5; break; default: throw new Error('Legend position not supported'); } this.dimGrid.setGridXPosForDualYAxis(yTitleCoords, yaxisLabelCoords); // after drawing everything, set the Y axis positions var objyAxis = new YAxis(this.ctx); objyAxis.setYAxisXPosition(yaxisLabelCoords, yTitleCoords); } }, { key: "setDimensionsForNonAxisCharts", value: function setDimensionsForNonAxisCharts() { var w = this.w; var gl = w.globals; var cnf = w.config; var xPad = 0; if (w.config.legend.show && !w.config.legend.floating) { xPad = 20; } var type = cnf.chart.type === 'pie' || cnf.chart.type === 'polarArea' || cnf.chart.type === 'donut' ? 'pie' : 'radialBar'; var offY = cnf.plotOptions[type].offsetY; var offX = cnf.plotOptions[type].offsetX; if (!cnf.legend.show || cnf.legend.floating) { gl.gridHeight = gl.svgHeight - cnf.grid.padding.left + cnf.grid.padding.right; gl.gridWidth = gl.gridHeight; gl.translateY = offY; gl.translateX = offX + (gl.svgWidth - gl.gridWidth) / 2; return; } switch (cnf.legend.position) { case 'bottom': gl.gridHeight = gl.svgHeight - this.lgRect.height - gl.goldenPadding; gl.gridWidth = gl.svgWidth; gl.translateY = offY - 10; gl.translateX = offX + (gl.svgWidth - gl.gridWidth) / 2; break; case 'top': gl.gridHeight = gl.svgHeight - this.lgRect.height - gl.goldenPadding; gl.gridWidth = gl.svgWidth; gl.translateY = this.lgRect.height + offY + 10; gl.translateX = offX + (gl.svgWidth - gl.gridWidth) / 2; break; case 'left': gl.gridWidth = gl.svgWidth - this.lgRect.width - xPad; gl.gridHeight = cnf.chart.height !== 'auto' ? gl.svgHeight : gl.gridWidth; gl.translateY = offY; gl.translateX = offX + this.lgRect.width + xPad; break; case 'right': gl.gridWidth = gl.svgWidth - this.lgRect.width - xPad - 5; gl.gridHeight = cnf.chart.height !== 'auto' ? gl.svgHeight : gl.gridWidth; gl.translateY = offY; gl.translateX = offX + 10; break; default: throw new Error('Legend position not supported'); } } }, { key: "conditionalChecksForAxisCoords", value: function conditionalChecksForAxisCoords(xaxisLabelCoords, xtitleCoords, xaxisGroupLabelCoords) { var w = this.w; var xAxisNum = w.globals.hasGroups ? 2 : 1; var baseXAxisHeight = xaxisGroupLabelCoords.height + xaxisLabelCoords.height + xtitleCoords.height; var xAxisHeightMultiplicate = w.globals.isMultiLineX ? 1.2 : w.globals.LINE_HEIGHT_RATIO; var rotatedXAxisOffset = w.globals.rotateXLabels ? 22 : 10; var rotatedXAxisLegendOffset = w.globals.rotateXLabels && w.config.legend.position === 'bottom'; var additionalOffset = rotatedXAxisLegendOffset ? 10 : 0; this.xAxisHeight = baseXAxisHeight * xAxisHeightMultiplicate + xAxisNum * rotatedXAxisOffset + additionalOffset; this.xAxisWidth = xaxisLabelCoords.width; if (this.xAxisHeight - xtitleCoords.height > w.config.xaxis.labels.maxHeight) { this.xAxisHeight = w.config.xaxis.labels.maxHeight; } if (w.config.xaxis.labels.minHeight && this.xAxisHeight < w.config.xaxis.labels.minHeight) { this.xAxisHeight = w.config.xaxis.labels.minHeight; } if (w.config.xaxis.floating) { this.xAxisHeight = 0; } var minYAxisWidth = 0; var maxYAxisWidth = 0; w.config.yaxis.forEach(function (y) { minYAxisWidth += y.labels.minWidth; maxYAxisWidth += y.labels.maxWidth; }); if (this.yAxisWidth < minYAxisWidth) { this.yAxisWidth = minYAxisWidth; } if (this.yAxisWidth > maxYAxisWidth) { this.yAxisWidth = maxYAxisWidth; } } }]); return Dimensions; }(); var Helpers$2 = /*#__PURE__*/function () { function Helpers(lgCtx) { _classCallCheck(this, Helpers); this.w = lgCtx.w; this.lgCtx = lgCtx; } _createClass(Helpers, [{ key: "getLegendBBox", value: function getLegendBBox() { var w = this.w; var currLegendsWrap = w.globals.dom.baseEl.querySelector('.apexcharts-legend'); var currLegendsWrapRect = currLegendsWrap.getBoundingClientRect(); var currLegendsWrapWidth = currLegendsWrapRect.width; var currLegendsWrapHeight = currLegendsWrapRect.height; return { clwh: currLegendsWrapHeight, clww: currLegendsWrapWidth }; } }, { key: "toggleDataSeries", value: function toggleDataSeries(seriesCnt, isHidden) { var _this = this; var w = this.w; if (w.globals.axisCharts || w.config.chart.type === 'radialBar') { w.globals.resized = true; // we don't want initial animations again var seriesEl = null; var realIndex = null; // yes, make it null. 1 series will rise at a time w.globals.risingSeries = []; if (w.globals.axisCharts) { seriesEl = w.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(seriesCnt, "']")); realIndex = parseInt(seriesEl.getAttribute('data:realIndex'), 10); } else { seriesEl = w.globals.dom.baseEl.querySelector(".apexcharts-series[rel='".concat(seriesCnt + 1, "']")); realIndex = parseInt(seriesEl.getAttribute('rel'), 10) - 1; } if (isHidden) { var seriesToMakeVisible = [{ cs: w.globals.collapsedSeries, csi: w.globals.collapsedSeriesIndices }, { cs: w.globals.ancillaryCollapsedSeries, csi: w.globals.ancillaryCollapsedSeriesIndices }]; seriesToMakeVisible.forEach(function (r) { _this.riseCollapsedSeries(r.cs, r.csi, realIndex); }); } else { this.hideSeries({ seriesEl: seriesEl, realIndex: realIndex }); } } else { // for non-axis charts i.e pie / donuts var _seriesEl = w.globals.dom.Paper.select(" .apexcharts-series[rel='".concat(seriesCnt + 1, "'] path")); var type = w.config.chart.type; if (type === 'pie' || type === 'polarArea' || type === 'donut') { var dataLabels = w.config.plotOptions.pie.donut.labels; var graphics = new Graphics(this.lgCtx.ctx); graphics.pathMouseDown(_seriesEl.members[0], null); this.lgCtx.ctx.pie.printDataLabelsInner(_seriesEl.members[0].node, dataLabels); } _seriesEl.fire('click'); } } }, { key: "hideSeries", value: function hideSeries(_ref) { var seriesEl = _ref.seriesEl, realIndex = _ref.realIndex; var w = this.w; var series = Utils$1.clone(w.config.series); if (w.globals.axisCharts) { var shouldNotHideYAxis = false; if (w.config.yaxis[realIndex] && w.config.yaxis[realIndex].show && w.config.yaxis[realIndex].showAlways) { shouldNotHideYAxis = true; if (w.globals.ancillaryCollapsedSeriesIndices.indexOf(realIndex) < 0) { w.globals.ancillaryCollapsedSeries.push({ index: realIndex, data: series[realIndex].data.slice(), type: seriesEl.parentNode.className.baseVal.split('-')[1] }); w.globals.ancillaryCollapsedSeriesIndices.push(realIndex); } } if (!shouldNotHideYAxis) { w.globals.collapsedSeries.push({ index: realIndex, data: series[realIndex].data.slice(), type: seriesEl.parentNode.className.baseVal.split('-')[1] }); w.globals.collapsedSeriesIndices.push(realIndex); var removeIndexOfRising = w.globals.risingSeries.indexOf(realIndex); w.globals.risingSeries.splice(removeIndexOfRising, 1); } } else { w.globals.collapsedSeries.push({ index: realIndex, data: series[realIndex] }); w.globals.collapsedSeriesIndices.push(realIndex); } var seriesChildren = seriesEl.childNodes; for (var sc = 0; sc < seriesChildren.length; sc++) { if (seriesChildren[sc].classList.contains('apexcharts-series-markers-wrap')) { if (seriesChildren[sc].classList.contains('apexcharts-hide')) { seriesChildren[sc].classList.remove('apexcharts-hide'); } else { seriesChildren[sc].classList.add('apexcharts-hide'); } } } w.globals.allSeriesCollapsed = w.globals.collapsedSeries.length === w.config.series.length; series = this._getSeriesBasedOnCollapsedState(series); this.lgCtx.ctx.updateHelpers._updateSeries(series, w.config.chart.animations.dynamicAnimation.enabled); } }, { key: "riseCollapsedSeries", value: function riseCollapsedSeries(collapsedSeries, seriesIndices, realIndex) { var w = this.w; var series = Utils$1.clone(w.config.series); if (collapsedSeries.length > 0) { for (var c = 0; c < collapsedSeries.length; c++) { if (collapsedSeries[c].index === realIndex) { if (w.globals.axisCharts) { series[realIndex].data = collapsedSeries[c].data.slice(); collapsedSeries.splice(c, 1); seriesIndices.splice(c, 1); w.globals.risingSeries.push(realIndex); } else { series[realIndex] = collapsedSeries[c].data; collapsedSeries.splice(c, 1); seriesIndices.splice(c, 1); w.globals.risingSeries.push(realIndex); } } } series = this._getSeriesBasedOnCollapsedState(series); this.lgCtx.ctx.updateHelpers._updateSeries(series, w.config.chart.animations.dynamicAnimation.enabled); } } }, { key: "_getSeriesBasedOnCollapsedState", value: function _getSeriesBasedOnCollapsedState(series) { var w = this.w; if (w.globals.axisCharts) { series.forEach(function (s, sI) { if (w.globals.collapsedSeriesIndices.indexOf(sI) > -1) { series[sI].data = []; } }); } else { series.forEach(function (s, sI) { if (w.globals.collapsedSeriesIndices.indexOf(sI) > -1) { series[sI] = 0; } }); } return series; } }]); return Helpers; }(); /** * ApexCharts Legend Class to draw legend. * * @module Legend **/ var Legend = /*#__PURE__*/function () { function Legend(ctx) { _classCallCheck(this, Legend); this.ctx = ctx; this.w = ctx.w; this.onLegendClick = this.onLegendClick.bind(this); this.onLegendHovered = this.onLegendHovered.bind(this); this.isBarsDistributed = this.w.config.chart.type === 'bar' && this.w.config.plotOptions.bar.distributed && this.w.config.series.length === 1; this.legendHelpers = new Helpers$2(this); } _createClass(Legend, [{ key: "init", value: function init() { var w = this.w; var gl = w.globals; var cnf = w.config; var showLegendAlways = cnf.legend.showForSingleSeries && gl.series.length === 1 || this.isBarsDistributed || gl.series.length > 1; if ((showLegendAlways || !gl.axisCharts) && cnf.legend.show) { while (gl.dom.elLegendWrap.firstChild) { gl.dom.elLegendWrap.removeChild(gl.dom.elLegendWrap.firstChild); } this.drawLegends(); if (cnf.legend.position === 'bottom' || cnf.legend.position === 'top') { this.legendAlignHorizontal(); } else if (cnf.legend.position === 'right' || cnf.legend.position === 'left') { this.legendAlignVertical(); } } } }, { key: "drawLegends", value: function drawLegends() { var me = this; var w = this.w; var fontFamily = w.config.legend.fontFamily; var legendNames = w.globals.seriesNames; var fillcolor = w.globals.colors.slice(); if (w.config.chart.type === 'heatmap') { var ranges = w.config.plotOptions.heatmap.colorScale.ranges; legendNames = ranges.map(function (colorScale) { return colorScale.name ? colorScale.name : colorScale.from + ' - ' + colorScale.to; }); fillcolor = ranges.map(function (color) { return color.color; }); } else if (this.isBarsDistributed) { legendNames = w.globals.labels.slice(); } if (w.config.legend.customLegendItems.length) { legendNames = w.config.legend.customLegendItems; } var legendFormatter = w.globals.legendFormatter; var isLegendInversed = w.config.legend.inverseOrder; for (var i = isLegendInversed ? legendNames.length - 1 : 0; isLegendInversed ? i >= 0 : i <= legendNames.length - 1; isLegendInversed ? i-- : i++) { var text = legendFormatter(legendNames[i], { seriesIndex: i, w: w }); var collapsedSeries = false; var ancillaryCollapsedSeries = false; if (w.globals.collapsedSeries.length > 0) { for (var c = 0; c < w.globals.collapsedSeries.length; c++) { if (w.globals.collapsedSeries[c].index === i) { collapsedSeries = true; } } } if (w.globals.ancillaryCollapsedSeriesIndices.length > 0) { for (var _c = 0; _c < w.globals.ancillaryCollapsedSeriesIndices.length; _c++) { if (w.globals.ancillaryCollapsedSeriesIndices[_c] === i) { ancillaryCollapsedSeries = true; } } } var elMarker = document.createElement('span'); elMarker.classList.add('apexcharts-legend-marker'); var mOffsetX = w.config.legend.markers.offsetX; var mOffsetY = w.config.legend.markers.offsetY; var mHeight = w.config.legend.markers.height; var mWidth = w.config.legend.markers.width; var mBorderWidth = w.config.legend.markers.strokeWidth; var mBorderColor = w.config.legend.markers.strokeColor; var mBorderRadius = w.config.legend.markers.radius; var mStyle = elMarker.style; mStyle.background = fillcolor[i]; mStyle.color = fillcolor[i]; mStyle.setProperty('background', fillcolor[i], 'important'); // override fill color with custom legend.markers.fillColors if (w.config.legend.markers.fillColors && w.config.legend.markers.fillColors[i]) { mStyle.background = w.config.legend.markers.fillColors[i]; } // override with data color if (w.globals.seriesColors[i] !== undefined) { mStyle.background = w.globals.seriesColors[i]; mStyle.color = w.globals.seriesColors[i]; } mStyle.height = Array.isArray(mHeight) ? parseFloat(mHeight[i]) + 'px' : parseFloat(mHeight) + 'px'; mStyle.width = Array.isArray(mWidth) ? parseFloat(mWidth[i]) + 'px' : parseFloat(mWidth) + 'px'; mStyle.left = (Array.isArray(mOffsetX) ? parseFloat(mOffsetX[i]) : parseFloat(mOffsetX)) + 'px'; mStyle.top = (Array.isArray(mOffsetY) ? parseFloat(mOffsetY[i]) : parseFloat(mOffsetY)) + 'px'; mStyle.borderWidth = Array.isArray(mBorderWidth) ? mBorderWidth[i] : mBorderWidth; mStyle.borderColor = Array.isArray(mBorderColor) ? mBorderColor[i] : mBorderColor; mStyle.borderRadius = Array.isArray(mBorderRadius) ? parseFloat(mBorderRadius[i]) + 'px' : parseFloat(mBorderRadius) + 'px'; if (w.config.legend.markers.customHTML) { if (Array.isArray(w.config.legend.markers.customHTML)) { if (w.config.legend.markers.customHTML[i]) { elMarker.innerHTML = w.config.legend.markers.customHTML[i](); } } else { elMarker.innerHTML = w.config.legend.markers.customHTML(); } } Graphics.setAttrs(elMarker, { rel: i + 1, 'data:collapsed': collapsedSeries || ancillaryCollapsedSeries }); if (collapsedSeries || ancillaryCollapsedSeries) { elMarker.classList.add('apexcharts-inactive-legend'); } var elLegend = document.createElement('div'); var elLegendText = document.createElement('span'); elLegendText.classList.add('apexcharts-legend-text'); elLegendText.innerHTML = Array.isArray(text) ? text.join(' ') : text; var textColor = w.config.legend.labels.useSeriesColors ? w.globals.colors[i] : w.config.legend.labels.colors; if (!textColor) { textColor = w.config.chart.foreColor; } elLegendText.style.color = textColor; elLegendText.style.fontSize = parseFloat(w.config.legend.fontSize) + 'px'; elLegendText.style.fontWeight = w.config.legend.fontWeight; elLegendText.style.fontFamily = fontFamily || w.config.chart.fontFamily; Graphics.setAttrs(elLegendText, { rel: i + 1, i: i, 'data:default-text': encodeURIComponent(text), 'data:collapsed': collapsedSeries || ancillaryCollapsedSeries }); elLegend.appendChild(elMarker); elLegend.appendChild(elLegendText); var coreUtils = new CoreUtils(this.ctx); if (!w.config.legend.showForZeroSeries) { var total = coreUtils.getSeriesTotalByIndex(i); if (total === 0 && coreUtils.seriesHaveSameValues(i) && !coreUtils.isSeriesNull(i) && w.globals.collapsedSeriesIndices.indexOf(i) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1) { elLegend.classList.add('apexcharts-hidden-zero-series'); } } if (!w.config.legend.showForNullSeries) { if (coreUtils.isSeriesNull(i) && w.globals.collapsedSeriesIndices.indexOf(i) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1) { elLegend.classList.add('apexcharts-hidden-null-series'); } } w.globals.dom.elLegendWrap.appendChild(elLegend); w.globals.dom.elLegendWrap.classList.add("apexcharts-align-".concat(w.config.legend.horizontalAlign)); w.globals.dom.elLegendWrap.classList.add('apx-legend-position-' + w.config.legend.position); elLegend.classList.add('apexcharts-legend-series'); elLegend.style.margin = "".concat(w.config.legend.itemMargin.vertical, "px ").concat(w.config.legend.itemMargin.horizontal, "px"); w.globals.dom.elLegendWrap.style.width = w.config.legend.width ? w.config.legend.width + 'px' : ''; w.globals.dom.elLegendWrap.style.height = w.config.legend.height ? w.config.legend.height + 'px' : ''; Graphics.setAttrs(elLegend, { rel: i + 1, seriesName: Utils$1.escapeString(legendNames[i]), 'data:collapsed': collapsedSeries || ancillaryCollapsedSeries }); if (collapsedSeries || ancillaryCollapsedSeries) { elLegend.classList.add('apexcharts-inactive-legend'); } if (!w.config.legend.onItemClick.toggleDataSeries) { elLegend.classList.add('apexcharts-no-click'); } } w.globals.dom.elWrap.addEventListener('click', me.onLegendClick, true); w.globals.dom.elWrap.appendChild(w.globals.dom.elLegendWrap); if (w.config.legend.onItemHover.highlightDataSeries && w.config.legend.customLegendItems.length === 0) { w.globals.dom.elWrap.addEventListener('mousemove', me.onLegendHovered, true); w.globals.dom.elWrap.addEventListener('mouseout', me.onLegendHovered, true); } } }, { key: "setLegendWrapXY", value: function setLegendWrapXY(offsetX, offsetY) { var w = this.w; var elLegendWrap = w.globals.dom.elLegendWrap; var legendRect = elLegendWrap.getBoundingClientRect(); var x = 0; var y = 0; if (w.config.legend.position === 'bottom') { y = y + (w.globals.svgHeight - legendRect.height / 2); } else if (w.config.legend.position === 'top') { var dim = new Dimensions(this.ctx); var titleH = dim.dimHelpers.getTitleSubtitleCoords('title').height; var subtitleH = dim.dimHelpers.getTitleSubtitleCoords('subtitle').height; y = y + (titleH > 0 ? titleH - 10 : 0) + (subtitleH > 0 ? subtitleH - 10 : 0); } elLegendWrap.style.position = 'absolute'; x = x + offsetX + w.config.legend.offsetX; y = y + offsetY + w.config.legend.offsetY; elLegendWrap.style.left = x + 'px'; elLegendWrap.style.top = y + 'px'; if (w.config.legend.position === 'bottom') { elLegendWrap.style.top = 'auto'; elLegendWrap.style.bottom = 5 - w.config.legend.offsetY + 'px'; } else if (w.config.legend.position === 'right') { elLegendWrap.style.left = 'auto'; elLegendWrap.style.right = 25 + w.config.legend.offsetX + 'px'; } var fixedHeigthWidth = ['width', 'height']; fixedHeigthWidth.forEach(function (hw) { if (elLegendWrap.style[hw]) { elLegendWrap.style[hw] = parseInt(w.config.legend[hw], 10) + 'px'; } }); } }, { key: "legendAlignHorizontal", value: function legendAlignHorizontal() { var w = this.w; var elLegendWrap = w.globals.dom.elLegendWrap; elLegendWrap.style.right = 0; var lRect = this.legendHelpers.getLegendBBox(); var dimensions = new Dimensions(this.ctx); var titleRect = dimensions.dimHelpers.getTitleSubtitleCoords('title'); var subtitleRect = dimensions.dimHelpers.getTitleSubtitleCoords('subtitle'); var offsetX = 20; var offsetY = 0; // the whole legend box is set to bottom if (w.config.legend.position === 'bottom') { offsetY = -lRect.clwh / 1.8; } else if (w.config.legend.position === 'top') { offsetY = titleRect.height + subtitleRect.height + w.config.title.margin + w.config.subtitle.margin - 10; } this.setLegendWrapXY(offsetX, offsetY); } }, { key: "legendAlignVertical", value: function legendAlignVertical() { var w = this.w; var lRect = this.legendHelpers.getLegendBBox(); var offsetY = 20; var offsetX = 0; if (w.config.legend.position === 'left') { offsetX = 20; } if (w.config.legend.position === 'right') { offsetX = w.globals.svgWidth - lRect.clww - 10; } this.setLegendWrapXY(offsetX, offsetY); } }, { key: "onLegendHovered", value: function onLegendHovered(e) { var w = this.w; var hoverOverLegend = e.target.classList.contains('apexcharts-legend-text') || e.target.classList.contains('apexcharts-legend-marker'); if (w.config.chart.type !== 'heatmap' && !this.isBarsDistributed) { if (!e.target.classList.contains('apexcharts-inactive-legend') && hoverOverLegend) { var series = new Series(this.ctx); series.toggleSeriesOnHover(e, e.target); } } else { // for heatmap handling if (hoverOverLegend) { var seriesCnt = parseInt(e.target.getAttribute('rel'), 10) - 1; this.ctx.events.fireEvent('legendHover', [this.ctx, seriesCnt, this.w]); var _series = new Series(this.ctx); _series.highlightRangeInSeries(e, e.target); } } } }, { key: "onLegendClick", value: function onLegendClick(e) { var w = this.w; if (w.config.legend.customLegendItems.length) return; if (e.target.classList.contains('apexcharts-legend-text') || e.target.classList.contains('apexcharts-legend-marker')) { var seriesCnt = parseInt(e.target.getAttribute('rel'), 10) - 1; var isHidden = e.target.getAttribute('data:collapsed') === 'true'; var legendClick = this.w.config.chart.events.legendClick; if (typeof legendClick === 'function') { legendClick(this.ctx, seriesCnt, this.w); } this.ctx.events.fireEvent('legendClick', [this.ctx, seriesCnt, this.w]); var markerClick = this.w.config.legend.markers.onClick; if (typeof markerClick === 'function' && e.target.classList.contains('apexcharts-legend-marker')) { markerClick(this.ctx, seriesCnt, this.w); this.ctx.events.fireEvent('legendMarkerClick', [this.ctx, seriesCnt, this.w]); } // for now - just prevent click on heatmap legend - and allow hover only var clickAllowed = w.config.chart.type !== 'treemap' && w.config.chart.type !== 'heatmap' && !this.isBarsDistributed; if (clickAllowed && w.config.legend.onItemClick.toggleDataSeries) { this.legendHelpers.toggleDataSeries(seriesCnt, isHidden); } } } }]); return Legend; }(); var icoPan = "\n \n \n \n \n \n \n \n"; var icoZoom = "\n \n \n \n"; var icoReset = "\n \n \n"; var icoZoomIn = "\n \n \n\n"; var icoZoomOut = "\n \n \n\n"; var icoSelect = "\n \n \n"; var icoMenu = ""; /** * ApexCharts Toolbar Class for creating toolbar in axis based charts. * * @module Toolbar **/ var Toolbar = /*#__PURE__*/function () { function Toolbar(ctx) { _classCallCheck(this, Toolbar); this.ctx = ctx; this.w = ctx.w; var w = this.w; this.ev = this.w.config.chart.events; this.selectedClass = 'apexcharts-selected'; this.localeValues = this.w.globals.locale.toolbar; this.minX = w.globals.minX; this.maxX = w.globals.maxX; } _createClass(Toolbar, [{ key: "createToolbar", value: function createToolbar() { var _this = this; var w = this.w; var createDiv = function createDiv() { return document.createElement('div'); }; var elToolbarWrap = createDiv(); elToolbarWrap.setAttribute('class', 'apexcharts-toolbar'); elToolbarWrap.style.top = w.config.chart.toolbar.offsetY + 'px'; elToolbarWrap.style.right = -w.config.chart.toolbar.offsetX + 3 + 'px'; w.globals.dom.elWrap.appendChild(elToolbarWrap); this.elZoom = createDiv(); this.elZoomIn = createDiv(); this.elZoomOut = createDiv(); this.elPan = createDiv(); this.elSelection = createDiv(); this.elZoomReset = createDiv(); this.elMenuIcon = createDiv(); this.elMenu = createDiv(); this.elCustomIcons = []; this.t = w.config.chart.toolbar.tools; if (Array.isArray(this.t.customIcons)) { for (var i = 0; i < this.t.customIcons.length; i++) { this.elCustomIcons.push(createDiv()); } } var toolbarControls = []; var appendZoomControl = function appendZoomControl(type, el, ico) { var tool = type.toLowerCase(); if (_this.t[tool] && w.config.chart.zoom.enabled) { toolbarControls.push({ el: el, icon: typeof _this.t[tool] === 'string' ? _this.t[tool] : ico, title: _this.localeValues[type], class: "apexcharts-".concat(tool, "-icon") }); } }; appendZoomControl('zoomIn', this.elZoomIn, icoZoomIn); appendZoomControl('zoomOut', this.elZoomOut, icoZoomOut); var zoomSelectionCtrls = function zoomSelectionCtrls(z) { if (_this.t[z] && w.config.chart[z].enabled) { toolbarControls.push({ el: z === 'zoom' ? _this.elZoom : _this.elSelection, icon: typeof _this.t[z] === 'string' ? _this.t[z] : z === 'zoom' ? icoZoom : icoSelect, title: _this.localeValues[z === 'zoom' ? 'selectionZoom' : 'selection'], class: w.globals.isTouchDevice ? 'apexcharts-element-hidden' : "apexcharts-".concat(z, "-icon") }); } }; zoomSelectionCtrls('zoom'); zoomSelectionCtrls('selection'); if (this.t.pan && w.config.chart.zoom.enabled) { toolbarControls.push({ el: this.elPan, icon: typeof this.t.pan === 'string' ? this.t.pan : icoPan, title: this.localeValues.pan, class: w.globals.isTouchDevice ? 'apexcharts-element-hidden' : 'apexcharts-pan-icon' }); } appendZoomControl('reset', this.elZoomReset, icoReset); if (this.t.download) { toolbarControls.push({ el: this.elMenuIcon, icon: typeof this.t.download === 'string' ? this.t.download : icoMenu, title: this.localeValues.menu, class: 'apexcharts-menu-icon' }); } for (var _i = 0; _i < this.elCustomIcons.length; _i++) { toolbarControls.push({ el: this.elCustomIcons[_i], icon: this.t.customIcons[_i].icon, title: this.t.customIcons[_i].title, index: this.t.customIcons[_i].index, class: 'apexcharts-toolbar-custom-icon ' + this.t.customIcons[_i].class }); } toolbarControls.forEach(function (t, index) { if (t.index) { Utils$1.moveIndexInArray(toolbarControls, index, t.index); } }); for (var _i2 = 0; _i2 < toolbarControls.length; _i2++) { Graphics.setAttrs(toolbarControls[_i2].el, { class: toolbarControls[_i2].class, title: toolbarControls[_i2].title }); toolbarControls[_i2].el.innerHTML = toolbarControls[_i2].icon; elToolbarWrap.appendChild(toolbarControls[_i2].el); } this._createHamburgerMenu(elToolbarWrap); if (w.globals.zoomEnabled) { this.elZoom.classList.add(this.selectedClass); } else if (w.globals.panEnabled) { this.elPan.classList.add(this.selectedClass); } else if (w.globals.selectionEnabled) { this.elSelection.classList.add(this.selectedClass); } this.addToolbarEventListeners(); } }, { key: "_createHamburgerMenu", value: function _createHamburgerMenu(parent) { this.elMenuItems = []; parent.appendChild(this.elMenu); Graphics.setAttrs(this.elMenu, { class: 'apexcharts-menu' }); var menuItems = [{ name: 'exportSVG', title: this.localeValues.exportToSVG }, { name: 'exportPNG', title: this.localeValues.exportToPNG }, { name: 'exportCSV', title: this.localeValues.exportToCSV }]; if (!this.w.globals.allSeriesHasEqualX) { // if it is a multi series, and all series have variable x values, export CSV won't work menuItems.splice(2, 1); } for (var i = 0; i < menuItems.length; i++) { this.elMenuItems.push(document.createElement('div')); this.elMenuItems[i].innerHTML = menuItems[i].title; Graphics.setAttrs(this.elMenuItems[i], { class: "apexcharts-menu-item ".concat(menuItems[i].name), title: menuItems[i].title }); this.elMenu.appendChild(this.elMenuItems[i]); } } }, { key: "addToolbarEventListeners", value: function addToolbarEventListeners() { var _this2 = this; this.elZoomReset.addEventListener('click', this.handleZoomReset.bind(this)); this.elSelection.addEventListener('click', this.toggleZoomSelection.bind(this, 'selection')); this.elZoom.addEventListener('click', this.toggleZoomSelection.bind(this, 'zoom')); this.elZoomIn.addEventListener('click', this.handleZoomIn.bind(this)); this.elZoomOut.addEventListener('click', this.handleZoomOut.bind(this)); this.elPan.addEventListener('click', this.togglePanning.bind(this)); this.elMenuIcon.addEventListener('click', this.toggleMenu.bind(this)); this.elMenuItems.forEach(function (m) { if (m.classList.contains('exportSVG')) { m.addEventListener('click', _this2.handleDownload.bind(_this2, 'svg')); } else if (m.classList.contains('exportPNG')) { m.addEventListener('click', _this2.handleDownload.bind(_this2, 'png')); } else if (m.classList.contains('exportCSV')) { m.addEventListener('click', _this2.handleDownload.bind(_this2, 'csv')); } }); for (var i = 0; i < this.t.customIcons.length; i++) { this.elCustomIcons[i].addEventListener('click', this.t.customIcons[i].click.bind(this, this.ctx, this.ctx.w)); } } }, { key: "toggleZoomSelection", value: function toggleZoomSelection(type) { var charts = this.ctx.getSyncedCharts(); charts.forEach(function (ch) { ch.ctx.toolbar.toggleOtherControls(); var el = type === 'selection' ? ch.ctx.toolbar.elSelection : ch.ctx.toolbar.elZoom; var enabledType = type === 'selection' ? 'selectionEnabled' : 'zoomEnabled'; ch.w.globals[enabledType] = !ch.w.globals[enabledType]; if (!el.classList.contains(ch.ctx.toolbar.selectedClass)) { el.classList.add(ch.ctx.toolbar.selectedClass); } else { el.classList.remove(ch.ctx.toolbar.selectedClass); } }); } }, { key: "getToolbarIconsReference", value: function getToolbarIconsReference() { var w = this.w; if (!this.elZoom) { this.elZoom = w.globals.dom.baseEl.querySelector('.apexcharts-zoom-icon'); } if (!this.elPan) { this.elPan = w.globals.dom.baseEl.querySelector('.apexcharts-pan-icon'); } if (!this.elSelection) { this.elSelection = w.globals.dom.baseEl.querySelector('.apexcharts-selection-icon'); } } }, { key: "enableZoomPanFromToolbar", value: function enableZoomPanFromToolbar(type) { this.toggleOtherControls(); type === 'pan' ? this.w.globals.panEnabled = true : this.w.globals.zoomEnabled = true; var el = type === 'pan' ? this.elPan : this.elZoom; var el2 = type === 'pan' ? this.elZoom : this.elPan; if (el) { el.classList.add(this.selectedClass); } if (el2) { el2.classList.remove(this.selectedClass); } } }, { key: "togglePanning", value: function togglePanning() { var charts = this.ctx.getSyncedCharts(); charts.forEach(function (ch) { ch.ctx.toolbar.toggleOtherControls(); ch.w.globals.panEnabled = !ch.w.globals.panEnabled; if (!ch.ctx.toolbar.elPan.classList.contains(ch.ctx.toolbar.selectedClass)) { ch.ctx.toolbar.elPan.classList.add(ch.ctx.toolbar.selectedClass); } else { ch.ctx.toolbar.elPan.classList.remove(ch.ctx.toolbar.selectedClass); } }); } }, { key: "toggleOtherControls", value: function toggleOtherControls() { var _this3 = this; var w = this.w; w.globals.panEnabled = false; w.globals.zoomEnabled = false; w.globals.selectionEnabled = false; this.getToolbarIconsReference(); var toggleEls = [this.elPan, this.elSelection, this.elZoom]; toggleEls.forEach(function (el) { if (el) { el.classList.remove(_this3.selectedClass); } }); } }, { key: "handleZoomIn", value: function handleZoomIn() { var w = this.w; if (w.globals.isRangeBar) { this.minX = w.globals.minY; this.maxX = w.globals.maxY; } var centerX = (this.minX + this.maxX) / 2; var newMinX = (this.minX + centerX) / 2; var newMaxX = (this.maxX + centerX) / 2; var newMinXMaxX = this._getNewMinXMaxX(newMinX, newMaxX); if (!w.globals.disableZoomIn) { this.zoomUpdateOptions(newMinXMaxX.minX, newMinXMaxX.maxX); } } }, { key: "handleZoomOut", value: function handleZoomOut() { var w = this.w; if (w.globals.isRangeBar) { this.minX = w.globals.minY; this.maxX = w.globals.maxY; } // avoid zooming out beyond 1000 which may result in NaN values being printed on x-axis if (w.config.xaxis.type === 'datetime' && new Date(this.minX).getUTCFullYear() < 1000) { return; } var centerX = (this.minX + this.maxX) / 2; var newMinX = this.minX - (centerX - this.minX); var newMaxX = this.maxX - (centerX - this.maxX); var newMinXMaxX = this._getNewMinXMaxX(newMinX, newMaxX); if (!w.globals.disableZoomOut) { this.zoomUpdateOptions(newMinXMaxX.minX, newMinXMaxX.maxX); } } }, { key: "_getNewMinXMaxX", value: function _getNewMinXMaxX(newMinX, newMaxX) { var shouldFloor = this.w.config.xaxis.convertedCatToNumeric; return { minX: shouldFloor ? Math.floor(newMinX) : newMinX, maxX: shouldFloor ? Math.floor(newMaxX) : newMaxX }; } }, { key: "zoomUpdateOptions", value: function zoomUpdateOptions(newMinX, newMaxX) { var w = this.w; if (newMinX === undefined && newMaxX === undefined) { this.handleZoomReset(); return; } if (w.config.xaxis.convertedCatToNumeric) { // in category charts, avoid zooming out beyond min and max if (newMinX < 1) { newMinX = 1; newMaxX = w.globals.dataPoints; } if (newMaxX - newMinX < 2) { return; } } var xaxis = { min: newMinX, max: newMaxX }; var beforeZoomRange = this.getBeforeZoomRange(xaxis); if (beforeZoomRange) { xaxis = beforeZoomRange.xaxis; } var options = { xaxis: xaxis }; var yaxis = Utils$1.clone(w.globals.initialConfig.yaxis); if (w.config.chart.zoom.autoScaleYaxis) { var scale = new Range$1(this.ctx); yaxis = scale.autoScaleY(this.ctx, yaxis, { xaxis: xaxis }); } if (!w.config.chart.group) { // if chart in a group, prevent yaxis update here // fix issue #650 options.yaxis = yaxis; } this.w.globals.zoomed = true; this.ctx.updateHelpers._updateOptions(options, false, this.w.config.chart.animations.dynamicAnimation.enabled); this.zoomCallback(xaxis, yaxis); } }, { key: "zoomCallback", value: function zoomCallback(xaxis, yaxis) { if (typeof this.ev.zoomed === 'function') { this.ev.zoomed(this.ctx, { xaxis: xaxis, yaxis: yaxis }); } } }, { key: "getBeforeZoomRange", value: function getBeforeZoomRange(xaxis, yaxis) { var newRange = null; if (typeof this.ev.beforeZoom === 'function') { newRange = this.ev.beforeZoom(this, { xaxis: xaxis, yaxis: yaxis }); } return newRange; } }, { key: "toggleMenu", value: function toggleMenu() { var _this4 = this; window.setTimeout(function () { if (_this4.elMenu.classList.contains('apexcharts-menu-open')) { _this4.elMenu.classList.remove('apexcharts-menu-open'); } else { _this4.elMenu.classList.add('apexcharts-menu-open'); } }, 0); } }, { key: "handleDownload", value: function handleDownload(type) { var w = this.w; var exprt = new Exports(this.ctx); switch (type) { case 'svg': exprt.exportToSVG(this.ctx); break; case 'png': exprt.exportToPng(this.ctx); break; case 'csv': exprt.exportToCSV({ series: w.config.series, columnDelimiter: w.config.chart.toolbar.export.csv.columnDelimiter }); break; } } }, { key: "handleZoomReset", value: function handleZoomReset(e) { var charts = this.ctx.getSyncedCharts(); charts.forEach(function (ch) { var w = ch.w; // forget lastXAxis min/max as reset button isn't resetting the x-axis completely if zoomX is called before w.globals.lastXAxis.min = undefined; w.globals.lastXAxis.max = undefined; ch.updateHelpers.revertDefaultAxisMinMax(); if (typeof w.config.chart.events.beforeResetZoom === 'function') { // here, user get an option to control xaxis and yaxis when resetZoom is called // at this point, whatever is returned from w.config.chart.events.beforeResetZoom // is set as the new xaxis/yaxis min/max var resetZoomRange = w.config.chart.events.beforeResetZoom(ch, w); if (resetZoomRange) { ch.updateHelpers.revertDefaultAxisMinMax(resetZoomRange); } } if (typeof w.config.chart.events.zoomed === 'function') { ch.ctx.toolbar.zoomCallback({ min: w.config.xaxis.min, max: w.config.xaxis.max }); } w.globals.zoomed = false; // if user has some series collapsed before hitting zoom reset button, // those series should stay collapsed var series = ch.ctx.series.emptyCollapsedSeries(Utils$1.clone(w.globals.initialSeries)); ch.updateHelpers._updateSeries(series, w.config.chart.animations.dynamicAnimation.enabled); }); } }, { key: "destroy", value: function destroy() { this.elZoom = null; this.elZoomIn = null; this.elZoomOut = null; this.elPan = null; this.elSelection = null; this.elZoomReset = null; this.elMenuIcon = null; } }]); return Toolbar; }(); /** * ApexCharts Zoom Class for handling zooming and panning on axes based charts. * * @module ZoomPanSelection **/ var ZoomPanSelection = /*#__PURE__*/function (_Toolbar) { _inherits(ZoomPanSelection, _Toolbar); var _super = _createSuper(ZoomPanSelection); function ZoomPanSelection(ctx) { var _this; _classCallCheck(this, ZoomPanSelection); _this = _super.call(this, ctx); _this.ctx = ctx; _this.w = ctx.w; _this.dragged = false; _this.graphics = new Graphics(_this.ctx); _this.eventList = ['mousedown', 'mouseleave', 'mousemove', 'touchstart', 'touchmove', 'mouseup', 'touchend']; _this.clientX = 0; _this.clientY = 0; _this.startX = 0; _this.endX = 0; _this.dragX = 0; _this.startY = 0; _this.endY = 0; _this.dragY = 0; _this.moveDirection = 'none'; return _this; } _createClass(ZoomPanSelection, [{ key: "init", value: function init(_ref) { var _this2 = this; var xyRatios = _ref.xyRatios; var w = this.w; var me = this; this.xyRatios = xyRatios; this.zoomRect = this.graphics.drawRect(0, 0, 0, 0); this.selectionRect = this.graphics.drawRect(0, 0, 0, 0); this.gridRect = w.globals.dom.baseEl.querySelector('.apexcharts-grid'); this.zoomRect.node.classList.add('apexcharts-zoom-rect'); this.selectionRect.node.classList.add('apexcharts-selection-rect'); w.globals.dom.elGraphical.add(this.zoomRect); w.globals.dom.elGraphical.add(this.selectionRect); if (w.config.chart.selection.type === 'x') { this.slDraggableRect = this.selectionRect.draggable({ minX: 0, minY: 0, maxX: w.globals.gridWidth, maxY: w.globals.gridHeight }).on('dragmove', this.selectionDragging.bind(this, 'dragging')); } else if (w.config.chart.selection.type === 'y') { this.slDraggableRect = this.selectionRect.draggable({ minX: 0, maxX: w.globals.gridWidth }).on('dragmove', this.selectionDragging.bind(this, 'dragging')); } else { this.slDraggableRect = this.selectionRect.draggable().on('dragmove', this.selectionDragging.bind(this, 'dragging')); } this.preselectedSelection(); this.hoverArea = w.globals.dom.baseEl.querySelector("".concat(w.globals.chartClass, " .apexcharts-svg")); this.hoverArea.classList.add('apexcharts-zoomable'); this.eventList.forEach(function (event) { _this2.hoverArea.addEventListener(event, me.svgMouseEvents.bind(me, xyRatios), { capture: false, passive: true }); }); } // remove the event listeners which were previously added on hover area }, { key: "destroy", value: function destroy() { if (this.slDraggableRect) { this.slDraggableRect.draggable(false); this.slDraggableRect.off(); this.selectionRect.off(); } this.selectionRect = null; this.zoomRect = null; this.gridRect = null; } }, { key: "svgMouseEvents", value: function svgMouseEvents(xyRatios, e) { var w = this.w; var me = this; var toolbar = this.ctx.toolbar; var zoomtype = w.globals.zoomEnabled ? w.config.chart.zoom.type : w.config.chart.selection.type; var autoSelected = w.config.chart.toolbar.autoSelected; if (e.shiftKey) { this.shiftWasPressed = true; toolbar.enableZoomPanFromToolbar(autoSelected === 'pan' ? 'zoom' : 'pan'); } else { if (this.shiftWasPressed) { toolbar.enableZoomPanFromToolbar(autoSelected); this.shiftWasPressed = false; } } if (!e.target) return; var tc = e.target.classList; var pc; if (e.target.parentNode && e.target.parentNode !== null) { pc = e.target.parentNode.classList; } var falsePositives = tc.contains('apexcharts-selection-rect') || tc.contains('apexcharts-legend-marker') || tc.contains('apexcharts-legend-text') || pc && pc.contains('apexcharts-toolbar'); if (falsePositives) return; me.clientX = e.type === 'touchmove' || e.type === 'touchstart' ? e.touches[0].clientX : e.type === 'touchend' ? e.changedTouches[0].clientX : e.clientX; me.clientY = e.type === 'touchmove' || e.type === 'touchstart' ? e.touches[0].clientY : e.type === 'touchend' ? e.changedTouches[0].clientY : e.clientY; if (e.type === 'mousedown' && e.which === 1) { var gridRectDim = me.gridRect.getBoundingClientRect(); me.startX = me.clientX - gridRectDim.left; me.startY = me.clientY - gridRectDim.top; me.dragged = false; me.w.globals.mousedown = true; } if (e.type === 'mousemove' && e.which === 1 || e.type === 'touchmove') { me.dragged = true; if (w.globals.panEnabled) { w.globals.selection = null; if (me.w.globals.mousedown) { me.panDragging({ context: me, zoomtype: zoomtype, xyRatios: xyRatios }); } } else { if (me.w.globals.mousedown && w.globals.zoomEnabled || me.w.globals.mousedown && w.globals.selectionEnabled) { me.selection = me.selectionDrawing({ context: me, zoomtype: zoomtype }); } } } if (e.type === 'mouseup' || e.type === 'touchend' || e.type === 'mouseleave') { // we will be calling getBoundingClientRect on each mousedown/mousemove/mouseup var _gridRectDim = me.gridRect.getBoundingClientRect(); if (me.w.globals.mousedown) { // user released the drag, now do all the calculations me.endX = me.clientX - _gridRectDim.left; me.endY = me.clientY - _gridRectDim.top; me.dragX = Math.abs(me.endX - me.startX); me.dragY = Math.abs(me.endY - me.startY); if (w.globals.zoomEnabled || w.globals.selectionEnabled) { me.selectionDrawn({ context: me, zoomtype: zoomtype }); } if (w.globals.panEnabled && w.config.xaxis.convertedCatToNumeric) { me.delayedPanScrolled(); } } if (w.globals.zoomEnabled) { me.hideSelectionRect(this.selectionRect); } me.dragged = false; me.w.globals.mousedown = false; } this.makeSelectionRectDraggable(); } }, { key: "makeSelectionRectDraggable", value: function makeSelectionRectDraggable() { var w = this.w; if (!this.selectionRect) return; var rectDim = this.selectionRect.node.getBoundingClientRect(); if (rectDim.width > 0 && rectDim.height > 0) { this.slDraggableRect.selectize({ points: 'l, r', pointSize: 8, pointType: 'rect' }).resize({ constraint: { minX: 0, minY: 0, maxX: w.globals.gridWidth, maxY: w.globals.gridHeight } }).on('resizing', this.selectionDragging.bind(this, 'resizing')); } } }, { key: "preselectedSelection", value: function preselectedSelection() { var w = this.w; var xyRatios = this.xyRatios; if (!w.globals.zoomEnabled) { if (typeof w.globals.selection !== 'undefined' && w.globals.selection !== null) { this.drawSelectionRect(w.globals.selection); } else { if (w.config.chart.selection.xaxis.min !== undefined && w.config.chart.selection.xaxis.max !== undefined) { var x = (w.config.chart.selection.xaxis.min - w.globals.minX) / xyRatios.xRatio; var width = w.globals.gridWidth - (w.globals.maxX - w.config.chart.selection.xaxis.max) / xyRatios.xRatio - x; var selectionRect = { x: x, y: 0, width: width, height: w.globals.gridHeight, translateX: 0, translateY: 0, selectionEnabled: true }; this.drawSelectionRect(selectionRect); this.makeSelectionRectDraggable(); if (typeof w.config.chart.events.selection === 'function') { w.config.chart.events.selection(this.ctx, { xaxis: { min: w.config.chart.selection.xaxis.min, max: w.config.chart.selection.xaxis.max }, yaxis: {} }); } } } } } }, { key: "drawSelectionRect", value: function drawSelectionRect(_ref2) { var x = _ref2.x, y = _ref2.y, width = _ref2.width, height = _ref2.height, _ref2$translateX = _ref2.translateX, translateX = _ref2$translateX === void 0 ? 0 : _ref2$translateX, _ref2$translateY = _ref2.translateY, translateY = _ref2$translateY === void 0 ? 0 : _ref2$translateY; var w = this.w; var zoomRect = this.zoomRect; var selectionRect = this.selectionRect; if (this.dragged || w.globals.selection !== null) { var scalingAttrs = { transform: 'translate(' + translateX + ', ' + translateY + ')' }; // change styles based on zoom or selection // zoom is Enabled and user has dragged, so draw blue rect if (w.globals.zoomEnabled && this.dragged) { if (width < 0) width = 1; // fixes apexcharts.js#1168 zoomRect.attr({ x: x, y: y, width: width, height: height, fill: w.config.chart.zoom.zoomedArea.fill.color, 'fill-opacity': w.config.chart.zoom.zoomedArea.fill.opacity, stroke: w.config.chart.zoom.zoomedArea.stroke.color, 'stroke-width': w.config.chart.zoom.zoomedArea.stroke.width, 'stroke-opacity': w.config.chart.zoom.zoomedArea.stroke.opacity }); Graphics.setAttrs(zoomRect.node, scalingAttrs); } // selection is enabled if (w.globals.selectionEnabled) { selectionRect.attr({ x: x, y: y, width: width > 0 ? width : 0, height: height > 0 ? height : 0, fill: w.config.chart.selection.fill.color, 'fill-opacity': w.config.chart.selection.fill.opacity, stroke: w.config.chart.selection.stroke.color, 'stroke-width': w.config.chart.selection.stroke.width, 'stroke-dasharray': w.config.chart.selection.stroke.dashArray, 'stroke-opacity': w.config.chart.selection.stroke.opacity }); Graphics.setAttrs(selectionRect.node, scalingAttrs); } } } }, { key: "hideSelectionRect", value: function hideSelectionRect(rect) { if (rect) { rect.attr({ x: 0, y: 0, width: 0, height: 0 }); } } }, { key: "selectionDrawing", value: function selectionDrawing(_ref3) { var context = _ref3.context, zoomtype = _ref3.zoomtype; var w = this.w; var me = context; var gridRectDim = this.gridRect.getBoundingClientRect(); var startX = me.startX - 1; var startY = me.startY; var inversedX = false; var inversedY = false; var selectionWidth = me.clientX - gridRectDim.left - startX; var selectionHeight = me.clientY - gridRectDim.top - startY; var selectionRect = {}; if (Math.abs(selectionWidth + startX) > w.globals.gridWidth) { // user dragged the mouse outside drawing area to the right selectionWidth = w.globals.gridWidth - startX; } else if (me.clientX - gridRectDim.left < 0) { // user dragged the mouse outside drawing area to the left selectionWidth = startX; } // inverse selection X if (startX > me.clientX - gridRectDim.left) { inversedX = true; selectionWidth = Math.abs(selectionWidth); } // inverse selection Y if (startY > me.clientY - gridRectDim.top) { inversedY = true; selectionHeight = Math.abs(selectionHeight); } if (zoomtype === 'x') { selectionRect = { x: inversedX ? startX - selectionWidth : startX, y: 0, width: selectionWidth, height: w.globals.gridHeight }; } else if (zoomtype === 'y') { selectionRect = { x: 0, y: inversedY ? startY - selectionHeight : startY, width: w.globals.gridWidth, height: selectionHeight }; } else { selectionRect = { x: inversedX ? startX - selectionWidth : startX, y: inversedY ? startY - selectionHeight : startY, width: selectionWidth, height: selectionHeight }; } me.drawSelectionRect(selectionRect); me.selectionDragging('resizing'); return selectionRect; } }, { key: "selectionDragging", value: function selectionDragging(type, e) { var _this3 = this; var w = this.w; var xyRatios = this.xyRatios; var selRect = this.selectionRect; var timerInterval = 0; if (type === 'resizing') { timerInterval = 30; } // update selection when selection rect is dragged var getSelAttr = function getSelAttr(attr) { return parseFloat(selRect.node.getAttribute(attr)); }; var draggedProps = { x: getSelAttr('x'), y: getSelAttr('y'), width: getSelAttr('width'), height: getSelAttr('height') }; w.globals.selection = draggedProps; // update selection ends if (typeof w.config.chart.events.selection === 'function' && w.globals.selectionEnabled) { // a small debouncer is required when resizing to avoid freezing the chart clearTimeout(this.w.globals.selectionResizeTimer); this.w.globals.selectionResizeTimer = window.setTimeout(function () { var gridRectDim = _this3.gridRect.getBoundingClientRect(); var selectionRect = selRect.node.getBoundingClientRect(); var minX = w.globals.xAxisScale.niceMin + (selectionRect.left - gridRectDim.left) * xyRatios.xRatio; var maxX = w.globals.xAxisScale.niceMin + (selectionRect.right - gridRectDim.left) * xyRatios.xRatio; var minY = w.globals.yAxisScale[0].niceMin + (gridRectDim.bottom - selectionRect.bottom) * xyRatios.yRatio[0]; var maxY = w.globals.yAxisScale[0].niceMax - (selectionRect.top - gridRectDim.top) * xyRatios.yRatio[0]; var xyAxis = { xaxis: { min: minX, max: maxX }, yaxis: { min: minY, max: maxY } }; w.config.chart.events.selection(_this3.ctx, xyAxis); if (w.config.chart.brush.enabled && w.config.chart.events.brushScrolled !== undefined) { w.config.chart.events.brushScrolled(_this3.ctx, xyAxis); } }, timerInterval); } } }, { key: "selectionDrawn", value: function selectionDrawn(_ref4) { var context = _ref4.context, zoomtype = _ref4.zoomtype; var w = this.w; var me = context; var xyRatios = this.xyRatios; var toolbar = this.ctx.toolbar; if (me.startX > me.endX) { var tempX = me.startX; me.startX = me.endX; me.endX = tempX; } if (me.startY > me.endY) { var tempY = me.startY; me.startY = me.endY; me.endY = tempY; } var xLowestValue = undefined; var xHighestValue = undefined; if (!w.globals.isRangeBar) { xLowestValue = w.globals.xAxisScale.niceMin + me.startX * xyRatios.xRatio; xHighestValue = w.globals.xAxisScale.niceMin + me.endX * xyRatios.xRatio; } else { xLowestValue = w.globals.yAxisScale[0].niceMin + me.startX * xyRatios.invertedYRatio; xHighestValue = w.globals.yAxisScale[0].niceMin + me.endX * xyRatios.invertedYRatio; } // TODO: we will consider the 1st y axis values here for getting highest and lowest y var yHighestValue = []; var yLowestValue = []; w.config.yaxis.forEach(function (yaxe, index) { yHighestValue.push(w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[index] * me.startY); yLowestValue.push(w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[index] * me.endY); }); if (me.dragged && (me.dragX > 10 || me.dragY > 10) && xLowestValue !== xHighestValue) { if (w.globals.zoomEnabled) { var yaxis = Utils$1.clone(w.globals.initialConfig.yaxis); var xaxis = Utils$1.clone(w.globals.initialConfig.xaxis); w.globals.zoomed = true; if (w.config.xaxis.convertedCatToNumeric) { xLowestValue = Math.floor(xLowestValue); xHighestValue = Math.floor(xHighestValue); if (xLowestValue < 1) { xLowestValue = 1; xHighestValue = w.globals.dataPoints; } if (xHighestValue - xLowestValue < 2) { xHighestValue = xLowestValue + 1; } } if (zoomtype === 'xy' || zoomtype === 'x') { xaxis = { min: xLowestValue, max: xHighestValue }; } if (zoomtype === 'xy' || zoomtype === 'y') { yaxis.forEach(function (yaxe, index) { yaxis[index].min = yLowestValue[index]; yaxis[index].max = yHighestValue[index]; }); } if (w.config.chart.zoom.autoScaleYaxis) { var scale = new Range$1(me.ctx); yaxis = scale.autoScaleY(me.ctx, yaxis, { xaxis: xaxis }); } if (toolbar) { var beforeZoomRange = toolbar.getBeforeZoomRange(xaxis, yaxis); if (beforeZoomRange) { xaxis = beforeZoomRange.xaxis ? beforeZoomRange.xaxis : xaxis; yaxis = beforeZoomRange.yaxis ? beforeZoomRange.yaxis : yaxis; } } var options = { xaxis: xaxis }; if (!w.config.chart.group) { // if chart in a group, prevent yaxis update here // fix issue #650 options.yaxis = yaxis; } me.ctx.updateHelpers._updateOptions(options, false, me.w.config.chart.animations.dynamicAnimation.enabled); if (typeof w.config.chart.events.zoomed === 'function') { toolbar.zoomCallback(xaxis, yaxis); } } else if (w.globals.selectionEnabled) { var _yaxis = null; var _xaxis = null; _xaxis = { min: xLowestValue, max: xHighestValue }; if (zoomtype === 'xy' || zoomtype === 'y') { _yaxis = Utils$1.clone(w.config.yaxis); _yaxis.forEach(function (yaxe, index) { _yaxis[index].min = yLowestValue[index]; _yaxis[index].max = yHighestValue[index]; }); } w.globals.selection = me.selection; if (typeof w.config.chart.events.selection === 'function') { w.config.chart.events.selection(me.ctx, { xaxis: _xaxis, yaxis: _yaxis }); } } } } }, { key: "panDragging", value: function panDragging(_ref5) { var context = _ref5.context; var w = this.w; var me = context; // check to make sure there is data to compare against if (typeof w.globals.lastClientPosition.x !== 'undefined') { // get the change from last position to this position var deltaX = w.globals.lastClientPosition.x - me.clientX; var deltaY = w.globals.lastClientPosition.y - me.clientY; // check which direction had the highest amplitude and then figure out direction by checking if the value is greater or less than zero if (Math.abs(deltaX) > Math.abs(deltaY) && deltaX > 0) { this.moveDirection = 'left'; } else if (Math.abs(deltaX) > Math.abs(deltaY) && deltaX < 0) { this.moveDirection = 'right'; } else if (Math.abs(deltaY) > Math.abs(deltaX) && deltaY > 0) { this.moveDirection = 'up'; } else if (Math.abs(deltaY) > Math.abs(deltaX) && deltaY < 0) { this.moveDirection = 'down'; } } // set the new last position to the current for next time (to get the position of drag) w.globals.lastClientPosition = { x: me.clientX, y: me.clientY }; var xLowestValue = w.globals.isRangeBar ? w.globals.minY : w.globals.minX; var xHighestValue = w.globals.isRangeBar ? w.globals.maxY : w.globals.maxX; // on a category, we don't pan continuosly as it causes bugs if (!w.config.xaxis.convertedCatToNumeric) { me.panScrolled(xLowestValue, xHighestValue); } } }, { key: "delayedPanScrolled", value: function delayedPanScrolled() { var w = this.w; var newMinX = w.globals.minX; var newMaxX = w.globals.maxX; var centerX = (w.globals.maxX - w.globals.minX) / 2; if (this.moveDirection === 'left') { newMinX = w.globals.minX + centerX; newMaxX = w.globals.maxX + centerX; } else if (this.moveDirection === 'right') { newMinX = w.globals.minX - centerX; newMaxX = w.globals.maxX - centerX; } newMinX = Math.floor(newMinX); newMaxX = Math.floor(newMaxX); this.updateScrolledChart({ xaxis: { min: newMinX, max: newMaxX } }, newMinX, newMaxX); } }, { key: "panScrolled", value: function panScrolled(xLowestValue, xHighestValue) { var w = this.w; var xyRatios = this.xyRatios; var yaxis = Utils$1.clone(w.globals.initialConfig.yaxis); var xRatio = xyRatios.xRatio; var minX = w.globals.minX; var maxX = w.globals.maxX; if (w.globals.isRangeBar) { xRatio = xyRatios.invertedYRatio; minX = w.globals.minY; maxX = w.globals.maxY; } if (this.moveDirection === 'left') { xLowestValue = minX + w.globals.gridWidth / 15 * xRatio; xHighestValue = maxX + w.globals.gridWidth / 15 * xRatio; } else if (this.moveDirection === 'right') { xLowestValue = minX - w.globals.gridWidth / 15 * xRatio; xHighestValue = maxX - w.globals.gridWidth / 15 * xRatio; } if (!w.globals.isRangeBar) { if (xLowestValue < w.globals.initialMinX || xHighestValue > w.globals.initialMaxX) { xLowestValue = minX; xHighestValue = maxX; } } var xaxis = { min: xLowestValue, max: xHighestValue }; if (w.config.chart.zoom.autoScaleYaxis) { var scale = new Range$1(this.ctx); yaxis = scale.autoScaleY(this.ctx, yaxis, { xaxis: xaxis }); } var options = { xaxis: { min: xLowestValue, max: xHighestValue } }; if (!w.config.chart.group) { // if chart in a group, prevent yaxis update here // fix issue #650 options.yaxis = yaxis; } this.updateScrolledChart(options, xLowestValue, xHighestValue); } }, { key: "updateScrolledChart", value: function updateScrolledChart(options, xLowestValue, xHighestValue) { var w = this.w; this.ctx.updateHelpers._updateOptions(options, false, false); if (typeof w.config.chart.events.scrolled === 'function') { w.config.chart.events.scrolled(this.ctx, { xaxis: { min: xLowestValue, max: xHighestValue } }); } } }]); return ZoomPanSelection; }(Toolbar); /** * ApexCharts Tooltip.Utils Class to support Tooltip functionality. * * @module Tooltip.Utils **/ var Utils = /*#__PURE__*/function () { function Utils(tooltipContext) { _classCallCheck(this, Utils); this.w = tooltipContext.w; this.ttCtx = tooltipContext; this.ctx = tooltipContext.ctx; } /** ** When hovering over series, you need to capture which series is being hovered on. ** This function will return both capturedseries index as well as inner index of that series * @memberof Utils * @param {object} * - hoverArea = the rect on which user hovers * - elGrid = dimensions of the hover rect (it can be different than hoverarea) */ _createClass(Utils, [{ key: "getNearestValues", value: function getNearestValues(_ref) { var hoverArea = _ref.hoverArea, elGrid = _ref.elGrid, clientX = _ref.clientX, clientY = _ref.clientY; var w = this.w; var seriesBound = elGrid.getBoundingClientRect(); var hoverWidth = seriesBound.width; var hoverHeight = seriesBound.height; var xDivisor = hoverWidth / (w.globals.dataPoints - 1); var yDivisor = hoverHeight / w.globals.dataPoints; var hasBars = this.hasBars(); if ((w.globals.comboCharts || hasBars) && !w.config.xaxis.convertedCatToNumeric) { xDivisor = hoverWidth / w.globals.dataPoints; } var hoverX = clientX - seriesBound.left - w.globals.barPadForNumericAxis; var hoverY = clientY - seriesBound.top; var notInRect = hoverX < 0 || hoverY < 0 || hoverX > hoverWidth || hoverY > hoverHeight; if (notInRect) { hoverArea.classList.remove('hovering-zoom'); hoverArea.classList.remove('hovering-pan'); } else { if (w.globals.zoomEnabled) { hoverArea.classList.remove('hovering-pan'); hoverArea.classList.add('hovering-zoom'); } else if (w.globals.panEnabled) { hoverArea.classList.remove('hovering-zoom'); hoverArea.classList.add('hovering-pan'); } } var j = Math.round(hoverX / xDivisor); var jHorz = Math.floor(hoverY / yDivisor); if (hasBars && !w.config.xaxis.convertedCatToNumeric) { j = Math.ceil(hoverX / xDivisor); j = j - 1; } var capturedSeries = null; var closest = null; var seriesXValArr = []; var seriesYValArr = []; //add extra values to show markers for the first points. Included both axes to avoid incorrect positioning of the marker w.globals.seriesXvalues.forEach(function (value) { seriesXValArr.push([value[0] + 0.000001].concat(value)); }); w.globals.seriesYvalues.forEach(function (value) { seriesYValArr.push([value[0] + 0.000001].concat(value)); }); seriesXValArr = seriesXValArr.map(function (seriesXVal) { return seriesXVal.filter(function (s) { return Utils$1.isNumber(s); }); }); seriesYValArr = seriesYValArr.map(function (seriesYVal) { return seriesYVal.filter(function (s) { return Utils$1.isNumber(s); }); }); // if X axis type is not category and tooltip is not shared, then we need to find the cursor position and get the nearest value if (w.globals.isXNumeric) { // Change origin of cursor position so that we can compute the relative nearest point to the cursor on our chart // we only need to scale because all points are relative to the bounds.left and bounds.top => origin is virtually (0, 0) var chartGridEl = this.ttCtx.getElGrid(); var chartGridElBoundingRect = chartGridEl.getBoundingClientRect(); var transformedHoverX = hoverX * (chartGridElBoundingRect.width / hoverWidth); var transformedHoverY = hoverY * (chartGridElBoundingRect.height / hoverHeight); closest = this.closestInMultiArray(transformedHoverX, transformedHoverY, seriesXValArr, seriesYValArr); capturedSeries = closest.index; j = closest.j; if (capturedSeries !== null) { // initial push, it should be a little smaller than the 1st val seriesXValArr = w.globals.seriesXvalues[capturedSeries]; closest = this.closestInArray(transformedHoverX, seriesXValArr); j = closest.index; } } w.globals.capturedSeriesIndex = capturedSeries === null ? -1 : capturedSeries; if (!j || j < 1) j = 0; if (w.globals.isBarHorizontal) { w.globals.capturedDataPointIndex = jHorz; } else { w.globals.capturedDataPointIndex = j; } return { capturedSeries: capturedSeries, j: w.globals.isBarHorizontal ? jHorz : j, hoverX: hoverX, hoverY: hoverY }; } }, { key: "closestInMultiArray", value: function closestInMultiArray(hoverX, hoverY, Xarrays, Yarrays) { var w = this.w; var activeIndex = 0; var currIndex = null; var j = -1; if (w.globals.series.length > 1) { activeIndex = this.getFirstActiveXArray(Xarrays); } else { currIndex = 0; } var currX = Xarrays[activeIndex][0]; var diffX = Math.abs(hoverX - currX); // find nearest point on x-axis Xarrays.forEach(function (arrX) { arrX.forEach(function (x, iX) { var newDiff = Math.abs(hoverX - x); if (newDiff < diffX) { diffX = newDiff; j = iX; } }); }); if (j !== -1) { // find nearest graph on y-axis relevanted to nearest point on x-axis var currY = Yarrays[activeIndex][j]; var diffY = Math.abs(hoverY - currY); currIndex = activeIndex; Yarrays.forEach(function (arrY, iAY) { var newDiff = Math.abs(hoverY - arrY[j]); if (newDiff < diffY) { diffY = newDiff; currIndex = iAY; } }); } return { index: currIndex, j: j }; } }, { key: "getFirstActiveXArray", value: function getFirstActiveXArray(Xarrays) { var w = this.w; var activeIndex = 0; var firstActiveSeriesIndex = Xarrays.map(function (xarr, index) { return xarr.length > 0 ? index : -1; }); for (var a = 0; a < firstActiveSeriesIndex.length; a++) { if (firstActiveSeriesIndex[a] !== -1 && w.globals.collapsedSeriesIndices.indexOf(a) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(a) === -1) { activeIndex = firstActiveSeriesIndex[a]; break; } } return activeIndex; } }, { key: "closestInArray", value: function closestInArray(val, arr) { var curr = arr[0]; var currIndex = null; var diff = Math.abs(val - curr); for (var i = 0; i < arr.length; i++) { var newdiff = Math.abs(val - arr[i]); if (newdiff < diff) { diff = newdiff; currIndex = i; } } return { index: currIndex }; } /** * When there are multiple series, it is possible to have different x values for each series. * But it may be possible in those multiple series, that there is same x value for 2 or more * series. * @memberof Utils * @param {int} * - j = is the inner index of series -> (series[i][j]) * @return {bool} */ }, { key: "isXoverlap", value: function isXoverlap(j) { var w = this.w; var xSameForAllSeriesJArr = []; var seriesX = w.globals.seriesX.filter(function (s) { return typeof s[0] !== 'undefined'; }); if (seriesX.length > 0) { for (var i = 0; i < seriesX.length - 1; i++) { if (typeof seriesX[i][j] !== 'undefined' && typeof seriesX[i + 1][j] !== 'undefined') { if (seriesX[i][j] !== seriesX[i + 1][j]) { xSameForAllSeriesJArr.push('unEqual'); } } } } if (xSameForAllSeriesJArr.length === 0) { return true; } return false; } }, { key: "isInitialSeriesSameLen", value: function isInitialSeriesSameLen() { var sameLen = true; var initialSeries = this.w.globals.initialSeries; for (var i = 0; i < initialSeries.length - 1; i++) { if (initialSeries[i].data.length !== initialSeries[i + 1].data.length) { sameLen = false; break; } } return sameLen; } }, { key: "getBarsHeight", value: function getBarsHeight(allbars) { var bars = _toConsumableArray(allbars); var totalHeight = bars.reduce(function (acc, bar) { return acc + bar.getBBox().height; }, 0); return totalHeight; } }, { key: "getElMarkers", value: function getElMarkers() { return this.w.globals.dom.baseEl.querySelectorAll(' .apexcharts-series-markers'); } }, { key: "getAllMarkers", value: function getAllMarkers() { // first get all marker parents. This parent class contains series-index // which helps to sort the markers as they are dynamic var markersWraps = this.w.globals.dom.baseEl.querySelectorAll('.apexcharts-series-markers-wrap'); markersWraps = _toConsumableArray(markersWraps); markersWraps.sort(function (a, b) { var indexA = Number(a.getAttribute('data:realIndex')); var indexB = Number(b.getAttribute('data:realIndex')); return indexB < indexA ? 1 : indexB > indexA ? -1 : 0; }); var markers = []; markersWraps.forEach(function (m) { markers.push(m.querySelector('.apexcharts-marker')); }); return markers; } }, { key: "hasMarkers", value: function hasMarkers() { var markers = this.getElMarkers(); return markers.length > 0; } }, { key: "getElBars", value: function getElBars() { return this.w.globals.dom.baseEl.querySelectorAll('.apexcharts-bar-series, .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series'); } }, { key: "hasBars", value: function hasBars() { var bars = this.getElBars(); return bars.length > 0; } }, { key: "getHoverMarkerSize", value: function getHoverMarkerSize(index) { var w = this.w; var hoverSize = w.config.markers.hover.size; if (hoverSize === undefined) { hoverSize = w.globals.markers.size[index] + w.config.markers.hover.sizeOffset; } return hoverSize; } }, { key: "toggleAllTooltipSeriesGroups", value: function toggleAllTooltipSeriesGroups(state) { var w = this.w; var ttCtx = this.ttCtx; if (ttCtx.allTooltipSeriesGroups.length === 0) { ttCtx.allTooltipSeriesGroups = w.globals.dom.baseEl.querySelectorAll('.apexcharts-tooltip-series-group'); } var allTooltipSeriesGroups = ttCtx.allTooltipSeriesGroups; for (var i = 0; i < allTooltipSeriesGroups.length; i++) { if (state === 'enable') { allTooltipSeriesGroups[i].classList.add('apexcharts-active'); allTooltipSeriesGroups[i].style.display = w.config.tooltip.items.display; } else { allTooltipSeriesGroups[i].classList.remove('apexcharts-active'); allTooltipSeriesGroups[i].style.display = 'none'; } } } }]); return Utils; }(); /** * ApexCharts Tooltip.Labels Class to draw texts on the tooltip. * This file deals with printing actual text on the tooltip. * * @module Tooltip.Labels **/ var Labels = /*#__PURE__*/function () { function Labels(tooltipContext) { _classCallCheck(this, Labels); this.w = tooltipContext.w; this.ctx = tooltipContext.ctx; this.ttCtx = tooltipContext; this.tooltipUtil = new Utils(tooltipContext); } _createClass(Labels, [{ key: "drawSeriesTexts", value: function drawSeriesTexts(_ref) { var _ref$shared = _ref.shared, shared = _ref$shared === void 0 ? true : _ref$shared, ttItems = _ref.ttItems, _ref$i = _ref.i, i = _ref$i === void 0 ? 0 : _ref$i, _ref$j = _ref.j, j = _ref$j === void 0 ? null : _ref$j, y1 = _ref.y1, y2 = _ref.y2, e = _ref.e; var w = this.w; if (w.config.tooltip.custom !== undefined) { this.handleCustomTooltip({ i: i, j: j, y1: y1, y2: y2, w: w }); } else { this.toggleActiveInactiveSeries(shared); } var values = this.getValuesToPrint({ i: i, j: j }); this.printLabels({ i: i, j: j, values: values, ttItems: ttItems, shared: shared, e: e }); // Re-calculate tooltip dimensions now that we have drawn the text var tooltipEl = this.ttCtx.getElTooltip(); this.ttCtx.tooltipRect.ttWidth = tooltipEl.getBoundingClientRect().width; this.ttCtx.tooltipRect.ttHeight = tooltipEl.getBoundingClientRect().height; } }, { key: "printLabels", value: function printLabels(_ref2) { var _this = this; var i = _ref2.i, j = _ref2.j, values = _ref2.values, ttItems = _ref2.ttItems, shared = _ref2.shared, e = _ref2.e; var w = this.w; var val; var goalVals = []; var hasGoalValues = function hasGoalValues(gi) { return w.globals.seriesGoals[gi] && w.globals.seriesGoals[gi][j] && Array.isArray(w.globals.seriesGoals[gi][j]); }; var xVal = values.xVal, zVal = values.zVal, xAxisTTVal = values.xAxisTTVal; var seriesName = ''; var pColor = w.globals.colors[i]; // The pColor here is for the markers inside tooltip if (j !== null && w.config.plotOptions.bar.distributed) { pColor = w.globals.colors[j]; } var _loop = function _loop(t, inverset) { var f = _this.getFormatters(i); seriesName = _this.getSeriesName({ fn: f.yLbTitleFormatter, index: i, seriesIndex: i, j: j }); if (w.config.chart.type === 'treemap') { seriesName = f.yLbTitleFormatter(String(w.config.series[i].data[j].x), { series: w.globals.series, seriesIndex: i, dataPointIndex: j, w: w }); } var tIndex = w.config.tooltip.inverseOrder ? inverset : t; if (w.globals.axisCharts) { var getValBySeriesIndex = function getValBySeriesIndex(index) { var _val = ''; if (w.globals.isRangeData) { var _w$globals$seriesRang, _w$globals$seriesRang2; _val += f.yLbFormatter((_w$globals$seriesRang = w.globals.seriesRangeStart) === null || _w$globals$seriesRang === void 0 ? void 0 : (_w$globals$seriesRang2 = _w$globals$seriesRang[index]) === null || _w$globals$seriesRang2 === void 0 ? void 0 : _w$globals$seriesRang2[j], { series: w.globals.seriesRangeStart, seriesIndex: index, dataPointIndex: j, w: w }) + ' - '; } _val += f.yLbFormatter(w.globals.series[index][j], { series: w.globals.series, seriesIndex: index, dataPointIndex: j, w: w }); return _val; }; if (shared) { f = _this.getFormatters(tIndex); seriesName = _this.getSeriesName({ fn: f.yLbTitleFormatter, index: tIndex, seriesIndex: i, j: j }); pColor = w.globals.colors[tIndex]; val = getValBySeriesIndex(tIndex); if (hasGoalValues(tIndex)) { goalVals = w.globals.seriesGoals[tIndex][j].map(function (goal) { return { attrs: goal, val: f.yLbFormatter(goal.value, { seriesIndex: tIndex, dataPointIndex: j, w: w }) }; }); } } else { var _e$target; // get a color from a hover area (if it's a line pattern then get from a first line) var targetFill = e === null || e === void 0 ? void 0 : (_e$target = e.target) === null || _e$target === void 0 ? void 0 : _e$target.getAttribute('fill'); if (targetFill) { pColor = targetFill.indexOf('url') !== -1 ? document.querySelector(targetFill.substr(4).slice(0, -1)).childNodes[0].getAttribute('stroke') : targetFill; } val = getValBySeriesIndex(i); if (hasGoalValues(i) && Array.isArray(w.globals.seriesGoals[i][j])) { goalVals = w.globals.seriesGoals[i][j].map(function (goal) { return { attrs: goal, val: f.yLbFormatter(goal.value, { seriesIndex: i, dataPointIndex: j, w: w }) }; }); } } } // for pie / donuts if (j === null) { val = f.yLbFormatter(w.globals.series[i], _objectSpread2(_objectSpread2({}, w), {}, { seriesIndex: i, dataPointIndex: i })); } _this.DOMHandling({ i: i, t: tIndex, j: j, ttItems: ttItems, values: { val: val, goalVals: goalVals, xVal: xVal, xAxisTTVal: xAxisTTVal, zVal: zVal }, seriesName: seriesName, shared: shared, pColor: pColor }); }; for (var t = 0, inverset = w.globals.series.length - 1; t < w.globals.series.length; t++, inverset--) { _loop(t, inverset); } } }, { key: "getFormatters", value: function getFormatters(i) { var w = this.w; var yLbFormatter = w.globals.yLabelFormatters[i]; var yLbTitleFormatter; if (w.globals.ttVal !== undefined) { if (Array.isArray(w.globals.ttVal)) { yLbFormatter = w.globals.ttVal[i] && w.globals.ttVal[i].formatter; yLbTitleFormatter = w.globals.ttVal[i] && w.globals.ttVal[i].title && w.globals.ttVal[i].title.formatter; } else { yLbFormatter = w.globals.ttVal.formatter; if (typeof w.globals.ttVal.title.formatter === 'function') { yLbTitleFormatter = w.globals.ttVal.title.formatter; } } } else { yLbTitleFormatter = w.config.tooltip.y.title.formatter; } if (typeof yLbFormatter !== 'function') { if (w.globals.yLabelFormatters[0]) { yLbFormatter = w.globals.yLabelFormatters[0]; } else { yLbFormatter = function yLbFormatter(label) { return label; }; } } if (typeof yLbTitleFormatter !== 'function') { yLbTitleFormatter = function yLbTitleFormatter(label) { return label; }; } return { yLbFormatter: yLbFormatter, yLbTitleFormatter: yLbTitleFormatter }; } }, { key: "getSeriesName", value: function getSeriesName(_ref3) { var fn = _ref3.fn, index = _ref3.index, seriesIndex = _ref3.seriesIndex, j = _ref3.j; var w = this.w; return fn(String(w.globals.seriesNames[index]), { series: w.globals.series, seriesIndex: seriesIndex, dataPointIndex: j, w: w }); } }, { key: "DOMHandling", value: function DOMHandling(_ref4) { _ref4.i; var t = _ref4.t, j = _ref4.j, ttItems = _ref4.ttItems, values = _ref4.values, seriesName = _ref4.seriesName, shared = _ref4.shared, pColor = _ref4.pColor; var w = this.w; var ttCtx = this.ttCtx; var val = values.val, goalVals = values.goalVals, xVal = values.xVal, xAxisTTVal = values.xAxisTTVal, zVal = values.zVal; var ttItemsChildren = null; ttItemsChildren = ttItems[t].children; if (w.config.tooltip.fillSeriesColor) { ttItems[t].style.backgroundColor = pColor; ttItemsChildren[0].style.display = 'none'; } if (ttCtx.showTooltipTitle) { if (ttCtx.tooltipTitle === null) { // get it once if null, and store it in class property ttCtx.tooltipTitle = w.globals.dom.baseEl.querySelector('.apexcharts-tooltip-title'); } ttCtx.tooltipTitle.innerHTML = xVal; } // if xaxis tooltip is constructed, we need to replace the innerHTML if (ttCtx.isXAxisTooltipEnabled) { ttCtx.xaxisTooltipText.innerHTML = xAxisTTVal !== '' ? xAxisTTVal : xVal; } var ttYLabel = ttItems[t].querySelector('.apexcharts-tooltip-text-y-label'); if (ttYLabel) { ttYLabel.innerHTML = seriesName ? seriesName : ''; } var ttYVal = ttItems[t].querySelector('.apexcharts-tooltip-text-y-value'); if (ttYVal) { ttYVal.innerHTML = typeof val !== 'undefined' ? val : ''; } if (ttItemsChildren[0] && ttItemsChildren[0].classList.contains('apexcharts-tooltip-marker')) { if (w.config.tooltip.marker.fillColors && Array.isArray(w.config.tooltip.marker.fillColors)) { pColor = w.config.tooltip.marker.fillColors[t]; } ttItemsChildren[0].style.backgroundColor = pColor; } if (!w.config.tooltip.marker.show) { ttItemsChildren[0].style.display = 'none'; } var ttGLabel = ttItems[t].querySelector('.apexcharts-tooltip-text-goals-label'); var ttGVal = ttItems[t].querySelector('.apexcharts-tooltip-text-goals-value'); if (goalVals.length && w.globals.seriesGoals[t]) { var createGoalsHtml = function createGoalsHtml() { var gLabels = '
    '; var gVals = '
    '; goalVals.forEach(function (goal, gi) { gLabels += "
    ").concat(goal.attrs.name, "
    "); gVals += "
    ".concat(goal.val, "
    "); }); ttGLabel.innerHTML = gLabels + "
    "; ttGVal.innerHTML = gVals + "
    "; }; if (shared) { if (w.globals.seriesGoals[t][j] && Array.isArray(w.globals.seriesGoals[t][j])) { createGoalsHtml(); } else { ttGLabel.innerHTML = ''; ttGVal.innerHTML = ''; } } else { createGoalsHtml(); } } else { ttGLabel.innerHTML = ''; ttGVal.innerHTML = ''; } if (zVal !== null) { var ttZLabel = ttItems[t].querySelector('.apexcharts-tooltip-text-z-label'); ttZLabel.innerHTML = w.config.tooltip.z.title; var ttZVal = ttItems[t].querySelector('.apexcharts-tooltip-text-z-value'); ttZVal.innerHTML = typeof zVal !== 'undefined' ? zVal : ''; } if (shared && ttItemsChildren[0]) { // hide when no Val or series collapsed if (typeof val === 'undefined' || val === null || w.globals.ancillaryCollapsedSeriesIndices.indexOf(t) > -1 || w.globals.collapsedSeriesIndices.indexOf(t) > -1) { ttItemsChildren[0].parentNode.style.display = 'none'; } else { ttItemsChildren[0].parentNode.style.display = w.config.tooltip.items.display; } } } }, { key: "toggleActiveInactiveSeries", value: function toggleActiveInactiveSeries(shared) { var w = this.w; if (shared) { // make all tooltips active this.tooltipUtil.toggleAllTooltipSeriesGroups('enable'); } else { // disable all tooltip text groups this.tooltipUtil.toggleAllTooltipSeriesGroups('disable'); // enable the first tooltip text group var firstTooltipSeriesGroup = w.globals.dom.baseEl.querySelector('.apexcharts-tooltip-series-group'); if (firstTooltipSeriesGroup) { firstTooltipSeriesGroup.classList.add('apexcharts-active'); firstTooltipSeriesGroup.style.display = w.config.tooltip.items.display; } } } }, { key: "getValuesToPrint", value: function getValuesToPrint(_ref5) { var i = _ref5.i, j = _ref5.j; var w = this.w; var filteredSeriesX = this.ctx.series.filteredSeriesX(); var xVal = ''; var xAxisTTVal = ''; var zVal = null; var val = null; var customFormatterOpts = { series: w.globals.series, seriesIndex: i, dataPointIndex: j, w: w }; var zFormatter = w.globals.ttZFormatter; if (j === null) { val = w.globals.series[i]; } else { if (w.globals.isXNumeric && w.config.chart.type !== 'treemap') { xVal = filteredSeriesX[i][j]; if (filteredSeriesX[i].length === 0) { // a series (possibly the first one) might be collapsed, so get the next active index var firstActiveSeriesIndex = this.tooltipUtil.getFirstActiveXArray(filteredSeriesX); xVal = filteredSeriesX[firstActiveSeriesIndex][j]; } } else { xVal = typeof w.globals.labels[j] !== 'undefined' ? w.globals.labels[j] : ''; } } var bufferXVal = xVal; if (w.globals.isXNumeric && w.config.xaxis.type === 'datetime') { var xFormat = new Formatters(this.ctx); xVal = xFormat.xLabelFormat(w.globals.ttKeyFormatter, bufferXVal, bufferXVal, { i: undefined, dateFormatter: new DateTime(this.ctx).formatDate, w: this.w }); } else { if (w.globals.isBarHorizontal) { xVal = w.globals.yLabelFormatters[0](bufferXVal, customFormatterOpts); } else { xVal = w.globals.xLabelFormatter(bufferXVal, customFormatterOpts); } } // override default x-axis formatter with tooltip formatter if (w.config.tooltip.x.formatter !== undefined) { xVal = w.globals.ttKeyFormatter(bufferXVal, customFormatterOpts); } if (w.globals.seriesZ.length > 0 && w.globals.seriesZ[i].length > 0) { zVal = zFormatter(w.globals.seriesZ[i][j], w); } if (typeof w.config.xaxis.tooltip.formatter === 'function') { xAxisTTVal = w.globals.xaxisTooltipFormatter(bufferXVal, customFormatterOpts); } else { xAxisTTVal = xVal; } return { val: Array.isArray(val) ? val.join(' ') : val, xVal: Array.isArray(xVal) ? xVal.join(' ') : xVal, xAxisTTVal: Array.isArray(xAxisTTVal) ? xAxisTTVal.join(' ') : xAxisTTVal, zVal: zVal }; } }, { key: "handleCustomTooltip", value: function handleCustomTooltip(_ref6) { var i = _ref6.i, j = _ref6.j, y1 = _ref6.y1, y2 = _ref6.y2, w = _ref6.w; var tooltipEl = this.ttCtx.getElTooltip(); var fn = w.config.tooltip.custom; if (Array.isArray(fn) && fn[i]) { fn = fn[i]; } // override everything with a custom html tooltip and replace it tooltipEl.innerHTML = fn({ ctx: this.ctx, series: w.globals.series, seriesIndex: i, dataPointIndex: j, y1: y1, y2: y2, w: w }); } }]); return Labels; }(); /** * ApexCharts Tooltip.Position Class to move the tooltip based on x and y position. * * @module Tooltip.Position **/ var Position = /*#__PURE__*/function () { function Position(tooltipContext) { _classCallCheck(this, Position); this.ttCtx = tooltipContext; this.ctx = tooltipContext.ctx; this.w = tooltipContext.w; } /** * This will move the crosshair (the vertical/horz line that moves along with mouse) * Along with this, this function also calls the xaxisMove function * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move crosshair */ _createClass(Position, [{ key: "moveXCrosshairs", value: function moveXCrosshairs(cx) { var j = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var ttCtx = this.ttCtx; var w = this.w; var xcrosshairs = ttCtx.getElXCrosshairs(); var x = cx - ttCtx.xcrosshairsWidth / 2; var tickAmount = w.globals.labels.slice().length; if (j !== null) { x = w.globals.gridWidth / tickAmount * j; } if (xcrosshairs !== null && !w.globals.isBarHorizontal) { xcrosshairs.setAttribute('x', x); xcrosshairs.setAttribute('x1', x); xcrosshairs.setAttribute('x2', x); xcrosshairs.setAttribute('y2', w.globals.gridHeight); xcrosshairs.classList.add('apexcharts-active'); } if (x < 0) { x = 0; } if (x > w.globals.gridWidth) { x = w.globals.gridWidth; } if (ttCtx.isXAxisTooltipEnabled) { var tx = x; if (w.config.xaxis.crosshairs.width === 'tickWidth' || w.config.xaxis.crosshairs.width === 'barWidth') { tx = x + ttCtx.xcrosshairsWidth / 2; } this.moveXAxisTooltip(tx); } } /** * This will move the crosshair (the vertical/horz line that moves along with mouse) * Along with this, this function also calls the xaxisMove function * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move crosshair */ }, { key: "moveYCrosshairs", value: function moveYCrosshairs(cy) { var ttCtx = this.ttCtx; if (ttCtx.ycrosshairs !== null) { Graphics.setAttrs(ttCtx.ycrosshairs, { y1: cy, y2: cy }); } if (ttCtx.ycrosshairsHidden !== null) { Graphics.setAttrs(ttCtx.ycrosshairsHidden, { y1: cy, y2: cy }); } } /** ** AxisTooltip is the small rectangle which appears on x axis with x value, when user moves * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move */ }, { key: "moveXAxisTooltip", value: function moveXAxisTooltip(cx) { var w = this.w; var ttCtx = this.ttCtx; if (ttCtx.xaxisTooltip !== null && ttCtx.xcrosshairsWidth !== 0) { ttCtx.xaxisTooltip.classList.add('apexcharts-active'); var cy = ttCtx.xaxisOffY + w.config.xaxis.tooltip.offsetY + w.globals.translateY + 1 + w.config.xaxis.offsetY; var xaxisTTText = ttCtx.xaxisTooltip.getBoundingClientRect(); var xaxisTTTextWidth = xaxisTTText.width; cx = cx - xaxisTTTextWidth / 2; if (!isNaN(cx)) { cx = cx + w.globals.translateX; var textRect = 0; var graphics = new Graphics(this.ctx); textRect = graphics.getTextRects(ttCtx.xaxisTooltipText.innerHTML); ttCtx.xaxisTooltipText.style.minWidth = textRect.width + 'px'; ttCtx.xaxisTooltip.style.left = cx + 'px'; ttCtx.xaxisTooltip.style.top = cy + 'px'; } } } }, { key: "moveYAxisTooltip", value: function moveYAxisTooltip(index) { var w = this.w; var ttCtx = this.ttCtx; if (ttCtx.yaxisTTEls === null) { ttCtx.yaxisTTEls = w.globals.dom.baseEl.querySelectorAll('.apexcharts-yaxistooltip'); } var ycrosshairsHiddenRectY1 = parseInt(ttCtx.ycrosshairsHidden.getAttribute('y1'), 10); var cy = w.globals.translateY + ycrosshairsHiddenRectY1; var yAxisTTRect = ttCtx.yaxisTTEls[index].getBoundingClientRect(); var yAxisTTHeight = yAxisTTRect.height; var cx = w.globals.translateYAxisX[index] - 2; if (w.config.yaxis[index].opposite) { cx = cx - 26; } cy = cy - yAxisTTHeight / 2; if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1) { ttCtx.yaxisTTEls[index].classList.add('apexcharts-active'); ttCtx.yaxisTTEls[index].style.top = cy + 'px'; ttCtx.yaxisTTEls[index].style.left = cx + w.config.yaxis[index].tooltip.offsetX + 'px'; } else { ttCtx.yaxisTTEls[index].classList.remove('apexcharts-active'); } } /** ** moves the whole tooltip by changing x, y attrs * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move tooltip * @param {int} - cy = point's y position, wherever point's y is, you need to move tooltip * @param {int} - r = point's radius */ }, { key: "moveTooltip", value: function moveTooltip(cx, cy) { var r = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var w = this.w; var ttCtx = this.ttCtx; var tooltipEl = ttCtx.getElTooltip(); var tooltipRect = ttCtx.tooltipRect; var pointR = r !== null ? parseFloat(r) : 1; var x = parseFloat(cx) + pointR + 5; var y = parseFloat(cy) + pointR / 2; // - tooltipRect.ttHeight / 2 if (x > w.globals.gridWidth / 2) { x = x - tooltipRect.ttWidth - pointR - 10; } if (x > w.globals.gridWidth - tooltipRect.ttWidth - 10) { x = w.globals.gridWidth - tooltipRect.ttWidth; } if (x < -20) { x = -20; } if (w.config.tooltip.followCursor) { var elGrid = ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); y = ttCtx.e.clientY + w.globals.translateY - seriesBound.top - tooltipRect.ttHeight / 2; } else { if (!w.globals.isBarHorizontal) { if (tooltipRect.ttHeight / 2 + y > w.globals.gridHeight) { y = w.globals.gridHeight - tooltipRect.ttHeight + w.globals.translateY; } } } if (!isNaN(x)) { x = x + w.globals.translateX; tooltipEl.style.left = x + 'px'; tooltipEl.style.top = y + 'px'; } } }, { key: "moveMarkers", value: function moveMarkers(i, j) { var w = this.w; var ttCtx = this.ttCtx; if (w.globals.markers.size[i] > 0) { var allPoints = w.globals.dom.baseEl.querySelectorAll(" .apexcharts-series[data\\:realIndex='".concat(i, "'] .apexcharts-marker")); for (var p = 0; p < allPoints.length; p++) { if (parseInt(allPoints[p].getAttribute('rel'), 10) === j) { ttCtx.marker.resetPointsSize(); ttCtx.marker.enlargeCurrentPoint(j, allPoints[p]); } } } else { ttCtx.marker.resetPointsSize(); this.moveDynamicPointOnHover(j, i); } } // This function is used when you need to show markers/points only on hover - // DIFFERENT X VALUES in multiple series }, { key: "moveDynamicPointOnHover", value: function moveDynamicPointOnHover(j, capturedSeries) { var w = this.w; var ttCtx = this.ttCtx; var cx = 0; var cy = 0; var pointsArr = w.globals.pointsArray; var hoverSize = ttCtx.tooltipUtil.getHoverMarkerSize(capturedSeries); var serType = w.config.series[capturedSeries].type; if (serType && (serType === 'column' || serType === 'candlestick' || serType === 'boxPlot')) { // fix error mentioned in #811 return; } cx = pointsArr[capturedSeries][j][0]; cy = pointsArr[capturedSeries][j][1] ? pointsArr[capturedSeries][j][1] : 0; var point = w.globals.dom.baseEl.querySelector(".apexcharts-series[data\\:realIndex='".concat(capturedSeries, "'] .apexcharts-series-markers circle")); if (point && cy < w.globals.gridHeight && cy > 0) { point.setAttribute('r', hoverSize); point.setAttribute('cx', cx); point.setAttribute('cy', cy); } // point.style.opacity = w.config.markers.hover.opacity this.moveXCrosshairs(cx); if (!ttCtx.fixedTooltip) { this.moveTooltip(cx, cy, hoverSize); } } // This function is used when you need to show markers/points only on hover - // SAME X VALUES in multiple series }, { key: "moveDynamicPointsOnHover", value: function moveDynamicPointsOnHover(j) { var ttCtx = this.ttCtx; var w = ttCtx.w; var cx = 0; var cy = 0; var activeSeries = 0; var pointsArr = w.globals.pointsArray; var series = new Series(this.ctx); activeSeries = series.getActiveConfigSeriesIndex('asc', ['line', 'area', 'scatter', 'bubble']); var hoverSize = ttCtx.tooltipUtil.getHoverMarkerSize(activeSeries); if (pointsArr[activeSeries]) { cx = pointsArr[activeSeries][j][0]; cy = pointsArr[activeSeries][j][1]; } var points = ttCtx.tooltipUtil.getAllMarkers(); if (points !== null) { for (var p = 0; p < w.globals.series.length; p++) { var pointArr = pointsArr[p]; if (w.globals.comboCharts) { // in a combo chart, if column charts are present, markers will not match with the number of series, hence this patch to push a null value in points array if (typeof pointArr === 'undefined') { // nodelist to array points.splice(p, 0, null); } } if (pointArr && pointArr.length) { var pcy = pointsArr[p][j][1]; var pcy2 = void 0; points[p].setAttribute('cx', cx); if (w.config.chart.type === 'rangeArea' && !w.globals.comboCharts) { var rangeStartIndex = j + w.globals.series[p].length; pcy2 = pointsArr[p][rangeStartIndex][1]; var pcyDiff = Math.abs(pcy - pcy2) / 2; pcy = pcy - pcyDiff; } if (pcy !== null && !isNaN(pcy) && pcy < w.globals.gridHeight + hoverSize && pcy + hoverSize > 0) { points[p] && points[p].setAttribute('r', hoverSize); points[p] && points[p].setAttribute('cy', pcy); } else { points[p] && points[p].setAttribute('r', 0); } } } } this.moveXCrosshairs(cx); if (!ttCtx.fixedTooltip) { var tcy = cy || w.globals.gridHeight; this.moveTooltip(cx, tcy, hoverSize); } } }, { key: "moveStickyTooltipOverBars", value: function moveStickyTooltipOverBars(j) { var w = this.w; var ttCtx = this.ttCtx; var barLen = w.globals.columnSeries ? w.globals.columnSeries.length : w.globals.series.length; var i = barLen >= 2 && barLen % 2 === 0 ? Math.floor(barLen / 2) : Math.floor(barLen / 2) + 1; if (w.globals.isBarHorizontal) { var series = new Series(this.ctx); i = series.getActiveConfigSeriesIndex('desc') + 1; } var jBar = w.globals.dom.baseEl.querySelector(".apexcharts-bar-series .apexcharts-series[rel='".concat(i, "'] path[j='").concat(j, "'], .apexcharts-candlestick-series .apexcharts-series[rel='").concat(i, "'] path[j='").concat(j, "'], .apexcharts-boxPlot-series .apexcharts-series[rel='").concat(i, "'] path[j='").concat(j, "'], .apexcharts-rangebar-series .apexcharts-series[rel='").concat(i, "'] path[j='").concat(j, "']")); var bcx = jBar ? parseFloat(jBar.getAttribute('cx')) : 0; var bcy = jBar ? parseFloat(jBar.getAttribute('cy')) : 0; var bw = jBar ? parseFloat(jBar.getAttribute('barWidth')) : 0; var elGrid = ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); var isBoxOrCandle = jBar.classList.contains('apexcharts-candlestick-area') || jBar.classList.contains('apexcharts-boxPlot-area'); if (w.globals.isXNumeric) { if (jBar && !isBoxOrCandle) { bcx = bcx - (barLen % 2 !== 0 ? bw / 2 : 0); } if (jBar && // fixes apexcharts.js#2354 isBoxOrCandle && w.globals.comboCharts) { bcx = bcx - bw / 2; } } else { if (!w.globals.isBarHorizontal) { bcx = ttCtx.xAxisTicksPositions[j - 1] + ttCtx.dataPointsDividedWidth / 2; if (isNaN(bcx)) { bcx = ttCtx.xAxisTicksPositions[j] - ttCtx.dataPointsDividedWidth / 2; } } } if (!w.globals.isBarHorizontal) { if (w.config.tooltip.followCursor) { bcy = ttCtx.e.clientY - seriesBound.top - ttCtx.tooltipRect.ttHeight / 2; } else { if (bcy + ttCtx.tooltipRect.ttHeight + 15 > w.globals.gridHeight) { bcy = w.globals.gridHeight; } } } else { bcy = bcy - ttCtx.tooltipRect.ttHeight; } if (!w.globals.isBarHorizontal) { this.moveXCrosshairs(bcx); } if (!ttCtx.fixedTooltip) { var tcy = bcy || w.globals.gridHeight; this.moveTooltip(bcx, tcy); } } }]); return Position; }(); /** * ApexCharts Tooltip.Marker Class to draw texts on the tooltip. * This file deals with the markers that appear near tooltip in line/area charts. * These markers helps the user to associate the data-points and the values * that are shown in the tooltip * * @module Tooltip.Marker **/ var Marker = /*#__PURE__*/function () { function Marker(tooltipContext) { _classCallCheck(this, Marker); this.w = tooltipContext.w; this.ttCtx = tooltipContext; this.ctx = tooltipContext.ctx; this.tooltipPosition = new Position(tooltipContext); } _createClass(Marker, [{ key: "drawDynamicPoints", value: function drawDynamicPoints() { var w = this.w; var graphics = new Graphics(this.ctx); var marker = new Markers(this.ctx); var elsSeries = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series'); elsSeries = _toConsumableArray(elsSeries); if (w.config.chart.stacked) { elsSeries.sort(function (a, b) { return parseFloat(a.getAttribute('data:realIndex')) - parseFloat(b.getAttribute('data:realIndex')); }); } for (var i = 0; i < elsSeries.length; i++) { var pointsMain = elsSeries[i].querySelector(".apexcharts-series-markers-wrap"); if (pointsMain !== null) { // it can be null as we have tooltips in donut/bar charts var point = void 0; var PointClasses = "apexcharts-marker w".concat((Math.random() + 1).toString(36).substring(4)); if ((w.config.chart.type === 'line' || w.config.chart.type === 'area') && !w.globals.comboCharts && !w.config.tooltip.intersect) { PointClasses += ' no-pointer-events'; } var elPointOptions = marker.getMarkerConfig({ cssClass: PointClasses, seriesIndex: Number(pointsMain.getAttribute('data:realIndex')) // fixes apexcharts/apexcharts.js #1427 }); point = graphics.drawMarker(0, 0, elPointOptions); point.node.setAttribute('default-marker-size', 0); var elPointsG = document.createElementNS(w.globals.SVGNS, 'g'); elPointsG.classList.add('apexcharts-series-markers'); elPointsG.appendChild(point.node); pointsMain.appendChild(elPointsG); } } } }, { key: "enlargeCurrentPoint", value: function enlargeCurrentPoint(rel, point) { var x = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var y = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var w = this.w; if (w.config.chart.type !== 'bubble') { this.newPointSize(rel, point); } var cx = point.getAttribute('cx'); var cy = point.getAttribute('cy'); if (x !== null && y !== null) { cx = x; cy = y; } this.tooltipPosition.moveXCrosshairs(cx); if (!this.fixedTooltip) { if (w.config.chart.type === 'radar') { var elGrid = this.ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); cx = this.ttCtx.e.clientX - seriesBound.left; } this.tooltipPosition.moveTooltip(cx, cy, w.config.markers.hover.size); } } }, { key: "enlargePoints", value: function enlargePoints(j) { var w = this.w; var me = this; var ttCtx = this.ttCtx; var col = j; var points = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker'); var newSize = w.config.markers.hover.size; for (var p = 0; p < points.length; p++) { var rel = points[p].getAttribute('rel'); var index = points[p].getAttribute('index'); if (newSize === undefined) { newSize = w.globals.markers.size[index] + w.config.markers.hover.sizeOffset; } if (col === parseInt(rel, 10)) { me.newPointSize(col, points[p]); var cx = points[p].getAttribute('cx'); var cy = points[p].getAttribute('cy'); me.tooltipPosition.moveXCrosshairs(cx); if (!ttCtx.fixedTooltip) { me.tooltipPosition.moveTooltip(cx, cy, newSize); } } else { me.oldPointSize(points[p]); } } } }, { key: "newPointSize", value: function newPointSize(rel, point) { var w = this.w; var newSize = w.config.markers.hover.size; var elPoint = rel === 0 ? point.parentNode.firstChild : point.parentNode.lastChild; if (elPoint.getAttribute('default-marker-size') !== '0') { var index = parseInt(elPoint.getAttribute('index'), 10); if (newSize === undefined) { newSize = w.globals.markers.size[index] + w.config.markers.hover.sizeOffset; } if (newSize < 0) newSize = 0; elPoint.setAttribute('r', newSize); } } }, { key: "oldPointSize", value: function oldPointSize(point) { var size = parseFloat(point.getAttribute('default-marker-size')); point.setAttribute('r', size); } }, { key: "resetPointsSize", value: function resetPointsSize() { var w = this.w; var points = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker'); for (var p = 0; p < points.length; p++) { var size = parseFloat(points[p].getAttribute('default-marker-size')); if (Utils$1.isNumber(size) && size >= 0) { points[p].setAttribute('r', size); } else { points[p].setAttribute('r', 0); } } } }]); return Marker; }(); /** * ApexCharts Tooltip.Intersect Class. * This file deals with functions related to intersecting tooltips * (tooltips that appear when user hovers directly over a data-point whether) * * @module Tooltip.Intersect **/ var Intersect = /*#__PURE__*/function () { function Intersect(tooltipContext) { _classCallCheck(this, Intersect); this.w = tooltipContext.w; this.ttCtx = tooltipContext; } // a helper function to get an element's attribute value _createClass(Intersect, [{ key: "getAttr", value: function getAttr(e, attr) { return parseFloat(e.target.getAttribute(attr)); } // handle tooltip for heatmaps and treemaps }, { key: "handleHeatTreeTooltip", value: function handleHeatTreeTooltip(_ref) { var e = _ref.e, opt = _ref.opt, x = _ref.x, y = _ref.y, type = _ref.type; var ttCtx = this.ttCtx; var w = this.w; if (e.target.classList.contains("apexcharts-".concat(type, "-rect"))) { var i = this.getAttr(e, 'i'); var j = this.getAttr(e, 'j'); var cx = this.getAttr(e, 'cx'); var cy = this.getAttr(e, 'cy'); var width = this.getAttr(e, 'width'); var height = this.getAttr(e, 'height'); ttCtx.tooltipLabels.drawSeriesTexts({ ttItems: opt.ttItems, i: i, j: j, shared: false, e: e }); w.globals.capturedSeriesIndex = i; w.globals.capturedDataPointIndex = j; x = cx + ttCtx.tooltipRect.ttWidth / 2 + width; y = cy + ttCtx.tooltipRect.ttHeight / 2 - height / 2; ttCtx.tooltipPosition.moveXCrosshairs(cx + width / 2); if (x > w.globals.gridWidth / 2) { x = cx - ttCtx.tooltipRect.ttWidth / 2 + width; } if (ttCtx.w.config.tooltip.followCursor) { var seriesBound = w.globals.dom.elWrap.getBoundingClientRect(); x = w.globals.clientX - seriesBound.left - (x > w.globals.gridWidth / 2 ? ttCtx.tooltipRect.ttWidth : 0); y = w.globals.clientY - seriesBound.top - (y > w.globals.gridHeight / 2 ? ttCtx.tooltipRect.ttHeight : 0); } } return { x: x, y: y }; } /** * handle tooltips for line/area/scatter charts where tooltip.intersect is true * when user hovers over the marker directly, this function is executed */ }, { key: "handleMarkerTooltip", value: function handleMarkerTooltip(_ref2) { var e = _ref2.e, opt = _ref2.opt, x = _ref2.x, y = _ref2.y; var w = this.w; var ttCtx = this.ttCtx; var i; var j; if (e.target.classList.contains('apexcharts-marker')) { var cx = parseInt(opt.paths.getAttribute('cx'), 10); var cy = parseInt(opt.paths.getAttribute('cy'), 10); var val = parseFloat(opt.paths.getAttribute('val')); j = parseInt(opt.paths.getAttribute('rel'), 10); i = parseInt(opt.paths.parentNode.parentNode.parentNode.getAttribute('rel'), 10) - 1; if (ttCtx.intersect) { var el = Utils$1.findAncestor(opt.paths, 'apexcharts-series'); if (el) { i = parseInt(el.getAttribute('data:realIndex'), 10); } } ttCtx.tooltipLabels.drawSeriesTexts({ ttItems: opt.ttItems, i: i, j: j, shared: ttCtx.showOnIntersect ? false : w.config.tooltip.shared, e: e }); if (e.type === 'mouseup') { ttCtx.markerClick(e, i, j); } w.globals.capturedSeriesIndex = i; w.globals.capturedDataPointIndex = j; x = cx; y = cy + w.globals.translateY - ttCtx.tooltipRect.ttHeight * 1.4; if (ttCtx.w.config.tooltip.followCursor) { var elGrid = ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); y = ttCtx.e.clientY + w.globals.translateY - seriesBound.top; } if (val < 0) { y = cy; } ttCtx.marker.enlargeCurrentPoint(j, opt.paths, x, y); } return { x: x, y: y }; } /** * handle tooltips for bar/column charts */ }, { key: "handleBarTooltip", value: function handleBarTooltip(_ref3) { var e = _ref3.e, opt = _ref3.opt; var w = this.w; var ttCtx = this.ttCtx; var tooltipEl = ttCtx.getElTooltip(); var bx = 0; var x = 0; var y = 0; var i = 0; var strokeWidth; var barXY = this.getBarTooltipXY({ e: e, opt: opt }); i = barXY.i; var barHeight = barXY.barHeight; var j = barXY.j; w.globals.capturedSeriesIndex = i; w.globals.capturedDataPointIndex = j; if (w.globals.isBarHorizontal && ttCtx.tooltipUtil.hasBars() || !w.config.tooltip.shared) { x = barXY.x; y = barXY.y; strokeWidth = Array.isArray(w.config.stroke.width) ? w.config.stroke.width[i] : w.config.stroke.width; bx = x; } else { if (!w.globals.comboCharts && !w.config.tooltip.shared) { // todo: re-check this condition as it's always 0 bx = bx / 2; } } // y is NaN, make it touch the bottom of grid area if (isNaN(y)) { y = w.globals.svgHeight - ttCtx.tooltipRect.ttHeight; } var seriesIndex = parseInt(opt.paths.parentNode.getAttribute('data:realIndex'), 10); var isReversed = w.globals.isMultipleYAxis ? w.config.yaxis[seriesIndex] && w.config.yaxis[seriesIndex].reversed : w.config.yaxis[0].reversed; if (x + ttCtx.tooltipRect.ttWidth > w.globals.gridWidth && !isReversed) { x = x - ttCtx.tooltipRect.ttWidth; } else if (x < 0) { x = 0; } if (ttCtx.w.config.tooltip.followCursor) { var elGrid = ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); y = ttCtx.e.clientY - seriesBound.top; } // if tooltip is still null, querySelector if (ttCtx.tooltip === null) { ttCtx.tooltip = w.globals.dom.baseEl.querySelector('.apexcharts-tooltip'); } if (!w.config.tooltip.shared) { if (w.globals.comboBarCount > 0) { ttCtx.tooltipPosition.moveXCrosshairs(bx + strokeWidth / 2); } else { ttCtx.tooltipPosition.moveXCrosshairs(bx); } } // move tooltip here if (!ttCtx.fixedTooltip && (!w.config.tooltip.shared || w.globals.isBarHorizontal && ttCtx.tooltipUtil.hasBars())) { if (isReversed) { x = x - ttCtx.tooltipRect.ttWidth; if (x < 0) { x = 0; } } if (isReversed && !(w.globals.isBarHorizontal && ttCtx.tooltipUtil.hasBars())) { y = y + barHeight - (w.globals.series[i][j] < 0 ? barHeight : 0) * 2; } y = y + w.globals.translateY - ttCtx.tooltipRect.ttHeight / 2; tooltipEl.style.left = x + w.globals.translateX + 'px'; tooltipEl.style.top = y + 'px'; } } }, { key: "getBarTooltipXY", value: function getBarTooltipXY(_ref4) { var e = _ref4.e, opt = _ref4.opt; var w = this.w; var j = null; var ttCtx = this.ttCtx; var i = 0; var x = 0; var y = 0; var barWidth = 0; var barHeight = 0; var cl = e.target.classList; if (cl.contains('apexcharts-bar-area') || cl.contains('apexcharts-candlestick-area') || cl.contains('apexcharts-boxPlot-area') || cl.contains('apexcharts-rangebar-area')) { var bar = e.target; var barRect = bar.getBoundingClientRect(); var seriesBound = opt.elGrid.getBoundingClientRect(); var bh = barRect.height; barHeight = barRect.height; var bw = barRect.width; var cx = parseInt(bar.getAttribute('cx'), 10); var cy = parseInt(bar.getAttribute('cy'), 10); barWidth = parseFloat(bar.getAttribute('barWidth')); var clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX; j = parseInt(bar.getAttribute('j'), 10); i = parseInt(bar.parentNode.getAttribute('rel'), 10) - 1; var y1 = bar.getAttribute('data-range-y1'); var y2 = bar.getAttribute('data-range-y2'); if (w.globals.comboCharts) { i = parseInt(bar.parentNode.getAttribute('data:realIndex'), 10); } // if (w.config.tooltip.shared) { // this check not needed at the moment // const yDivisor = w.globals.gridHeight / (w.globals.series.length) // const hoverY = ttCtx.clientY - ttCtx.seriesBound.top // j = Math.ceil(hoverY / yDivisor) // } ttCtx.tooltipLabels.drawSeriesTexts({ ttItems: opt.ttItems, i: i, j: j, y1: y1 ? parseInt(y1, 10) : null, y2: y2 ? parseInt(y2, 10) : null, shared: ttCtx.showOnIntersect ? false : w.config.tooltip.shared, e: e }); if (w.config.tooltip.followCursor) { if (w.globals.isBarHorizontal) { x = clientX - seriesBound.left + 15; y = cy - ttCtx.dataPointsDividedHeight + bh / 2 - ttCtx.tooltipRect.ttHeight / 2; } else { if (w.globals.isXNumeric) { x = cx - bw / 2; } else { x = cx - ttCtx.dataPointsDividedWidth + bw / 2; } y = e.clientY - seriesBound.top - ttCtx.tooltipRect.ttHeight / 2 - 15; } } else { if (w.globals.isBarHorizontal) { x = cx; if (x < ttCtx.xyRatios.baseLineInvertedY) { x = cx - ttCtx.tooltipRect.ttWidth; } y = cy - ttCtx.dataPointsDividedHeight + bh / 2 - ttCtx.tooltipRect.ttHeight / 2; } else { // if columns if (w.globals.isXNumeric) { x = cx - bw / 2; } else { x = cx - ttCtx.dataPointsDividedWidth + bw / 2; } y = cy; // - ttCtx.tooltipRect.ttHeight / 2 + 10 } } } return { x: x, y: y, barHeight: barHeight, barWidth: barWidth, i: i, j: j }; } }]); return Intersect; }(); /** * ApexCharts Tooltip.AxesTooltip Class. * This file deals with the x-axis and y-axis tooltips. * * @module Tooltip.AxesTooltip **/ var AxesTooltip = /*#__PURE__*/function () { function AxesTooltip(tooltipContext) { _classCallCheck(this, AxesTooltip); this.w = tooltipContext.w; this.ttCtx = tooltipContext; } /** * This method adds the secondary tooltip which appears below x axis * @memberof Tooltip **/ _createClass(AxesTooltip, [{ key: "drawXaxisTooltip", value: function drawXaxisTooltip() { var w = this.w; var ttCtx = this.ttCtx; var isBottom = w.config.xaxis.position === 'bottom'; ttCtx.xaxisOffY = isBottom ? w.globals.gridHeight + 1 : -w.globals.xAxisHeight - w.config.xaxis.axisTicks.height + 3; var tooltipCssClass = isBottom ? 'apexcharts-xaxistooltip apexcharts-xaxistooltip-bottom' : 'apexcharts-xaxistooltip apexcharts-xaxistooltip-top'; var renderTo = w.globals.dom.elWrap; if (ttCtx.isXAxisTooltipEnabled) { var xaxisTooltip = w.globals.dom.baseEl.querySelector('.apexcharts-xaxistooltip'); if (xaxisTooltip === null) { ttCtx.xaxisTooltip = document.createElement('div'); ttCtx.xaxisTooltip.setAttribute('class', tooltipCssClass + ' apexcharts-theme-' + w.config.tooltip.theme); renderTo.appendChild(ttCtx.xaxisTooltip); ttCtx.xaxisTooltipText = document.createElement('div'); ttCtx.xaxisTooltipText.classList.add('apexcharts-xaxistooltip-text'); ttCtx.xaxisTooltipText.style.fontFamily = w.config.xaxis.tooltip.style.fontFamily || w.config.chart.fontFamily; ttCtx.xaxisTooltipText.style.fontSize = w.config.xaxis.tooltip.style.fontSize; ttCtx.xaxisTooltip.appendChild(ttCtx.xaxisTooltipText); } } } /** * This method adds the secondary tooltip which appears below x axis * @memberof Tooltip **/ }, { key: "drawYaxisTooltip", value: function drawYaxisTooltip() { var w = this.w; var ttCtx = this.ttCtx; var _loop = function _loop(i) { var isRight = w.config.yaxis[i].opposite || w.config.yaxis[i].crosshairs.opposite; ttCtx.yaxisOffX = isRight ? w.globals.gridWidth + 1 : 1; var tooltipCssClass = isRight ? "apexcharts-yaxistooltip apexcharts-yaxistooltip-".concat(i, " apexcharts-yaxistooltip-right") : "apexcharts-yaxistooltip apexcharts-yaxistooltip-".concat(i, " apexcharts-yaxistooltip-left"); w.globals.yAxisSameScaleIndices.map(function (samescales, ssi) { samescales.map(function (s, si) { if (si === i) { tooltipCssClass += w.config.yaxis[si].show ? " " : " apexcharts-yaxistooltip-hidden"; } }); }); var renderTo = w.globals.dom.elWrap; var yaxisTooltip = w.globals.dom.baseEl.querySelector(".apexcharts-yaxistooltip apexcharts-yaxistooltip-".concat(i)); if (yaxisTooltip === null) { ttCtx.yaxisTooltip = document.createElement('div'); ttCtx.yaxisTooltip.setAttribute('class', tooltipCssClass + ' apexcharts-theme-' + w.config.tooltip.theme); renderTo.appendChild(ttCtx.yaxisTooltip); if (i === 0) ttCtx.yaxisTooltipText = []; ttCtx.yaxisTooltipText[i] = document.createElement('div'); ttCtx.yaxisTooltipText[i].classList.add('apexcharts-yaxistooltip-text'); ttCtx.yaxisTooltip.appendChild(ttCtx.yaxisTooltipText[i]); } }; for (var i = 0; i < w.config.yaxis.length; i++) { _loop(i); } } /** * @memberof Tooltip **/ }, { key: "setXCrosshairWidth", value: function setXCrosshairWidth() { var w = this.w; var ttCtx = this.ttCtx; // set xcrosshairs width var xcrosshairs = ttCtx.getElXCrosshairs(); ttCtx.xcrosshairsWidth = parseInt(w.config.xaxis.crosshairs.width, 10); if (!w.globals.comboCharts) { if (w.config.xaxis.crosshairs.width === 'tickWidth') { var count = w.globals.labels.length; ttCtx.xcrosshairsWidth = w.globals.gridWidth / count; } else if (w.config.xaxis.crosshairs.width === 'barWidth') { var bar = w.globals.dom.baseEl.querySelector('.apexcharts-bar-area'); if (bar !== null) { var barWidth = parseFloat(bar.getAttribute('barWidth')); ttCtx.xcrosshairsWidth = barWidth; } else { ttCtx.xcrosshairsWidth = 1; } } } else { var _bar = w.globals.dom.baseEl.querySelector('.apexcharts-bar-area'); if (_bar !== null && w.config.xaxis.crosshairs.width === 'barWidth') { var _barWidth = parseFloat(_bar.getAttribute('barWidth')); ttCtx.xcrosshairsWidth = _barWidth; } else { if (w.config.xaxis.crosshairs.width === 'tickWidth') { var _count = w.globals.labels.length; ttCtx.xcrosshairsWidth = w.globals.gridWidth / _count; } } } if (w.globals.isBarHorizontal) { ttCtx.xcrosshairsWidth = 0; } if (xcrosshairs !== null && ttCtx.xcrosshairsWidth > 0) { xcrosshairs.setAttribute('width', ttCtx.xcrosshairsWidth); } } }, { key: "handleYCrosshair", value: function handleYCrosshair() { var w = this.w; var ttCtx = this.ttCtx; // set ycrosshairs height ttCtx.ycrosshairs = w.globals.dom.baseEl.querySelector('.apexcharts-ycrosshairs'); ttCtx.ycrosshairsHidden = w.globals.dom.baseEl.querySelector('.apexcharts-ycrosshairs-hidden'); } }, { key: "drawYaxisTooltipText", value: function drawYaxisTooltipText(index, clientY, xyRatios) { var ttCtx = this.ttCtx; var w = this.w; var lbFormatter = w.globals.yLabelFormatters[index]; if (ttCtx.yaxisTooltips[index]) { var elGrid = ttCtx.getElGrid(); var seriesBound = elGrid.getBoundingClientRect(); var hoverY = (clientY - seriesBound.top) * xyRatios.yRatio[index]; var height = w.globals.maxYArr[index] - w.globals.minYArr[index]; var val = w.globals.minYArr[index] + (height - hoverY); ttCtx.tooltipPosition.moveYCrosshairs(clientY - seriesBound.top); ttCtx.yaxisTooltipText[index].innerHTML = lbFormatter(val); ttCtx.tooltipPosition.moveYAxisTooltip(index); } } }]); return AxesTooltip; }(); /** * ApexCharts Core Tooltip Class to handle the tooltip generation. * * @module Tooltip **/ var Tooltip = /*#__PURE__*/function () { function Tooltip(ctx) { _classCallCheck(this, Tooltip); this.ctx = ctx; this.w = ctx.w; var w = this.w; this.tConfig = w.config.tooltip; this.tooltipUtil = new Utils(this); this.tooltipLabels = new Labels(this); this.tooltipPosition = new Position(this); this.marker = new Marker(this); this.intersect = new Intersect(this); this.axesTooltip = new AxesTooltip(this); this.showOnIntersect = this.tConfig.intersect; this.showTooltipTitle = this.tConfig.x.show; this.fixedTooltip = this.tConfig.fixed.enabled; this.xaxisTooltip = null; this.yaxisTTEls = null; this.isBarShared = !w.globals.isBarHorizontal && this.tConfig.shared; this.lastHoverTime = Date.now(); } _createClass(Tooltip, [{ key: "getElTooltip", value: function getElTooltip(ctx) { if (!ctx) ctx = this; if (!ctx.w.globals.dom.baseEl) return null; return ctx.w.globals.dom.baseEl.querySelector('.apexcharts-tooltip'); } }, { key: "getElXCrosshairs", value: function getElXCrosshairs() { return this.w.globals.dom.baseEl.querySelector('.apexcharts-xcrosshairs'); } }, { key: "getElGrid", value: function getElGrid() { return this.w.globals.dom.baseEl.querySelector('.apexcharts-grid'); } }, { key: "drawTooltip", value: function drawTooltip(xyRatios) { var w = this.w; this.xyRatios = xyRatios; this.isXAxisTooltipEnabled = w.config.xaxis.tooltip.enabled && w.globals.axisCharts; this.yaxisTooltips = w.config.yaxis.map(function (y, i) { return y.show && y.tooltip.enabled && w.globals.axisCharts ? true : false; }); this.allTooltipSeriesGroups = []; if (!w.globals.axisCharts) { this.showTooltipTitle = false; } var tooltipEl = document.createElement('div'); tooltipEl.classList.add('apexcharts-tooltip'); if (w.config.tooltip.cssClass) { tooltipEl.classList.add(w.config.tooltip.cssClass); } tooltipEl.classList.add("apexcharts-theme-".concat(this.tConfig.theme)); w.globals.dom.elWrap.appendChild(tooltipEl); if (w.globals.axisCharts) { this.axesTooltip.drawXaxisTooltip(); this.axesTooltip.drawYaxisTooltip(); this.axesTooltip.setXCrosshairWidth(); this.axesTooltip.handleYCrosshair(); var xAxis = new XAxis(this.ctx); this.xAxisTicksPositions = xAxis.getXAxisTicksPositions(); } // we forcefully set intersect true for these conditions if ((w.globals.comboCharts || this.tConfig.intersect || w.config.chart.type === 'rangeBar') && !this.tConfig.shared) { this.showOnIntersect = true; } if (w.config.markers.size === 0 || w.globals.markers.largestSize === 0) { // when user don't want to show points all the time, but only on when hovering on series this.marker.drawDynamicPoints(this); } // no visible series, exit if (w.globals.collapsedSeries.length === w.globals.series.length) return; this.dataPointsDividedHeight = w.globals.gridHeight / w.globals.dataPoints; this.dataPointsDividedWidth = w.globals.gridWidth / w.globals.dataPoints; if (this.showTooltipTitle) { this.tooltipTitle = document.createElement('div'); this.tooltipTitle.classList.add('apexcharts-tooltip-title'); this.tooltipTitle.style.fontFamily = this.tConfig.style.fontFamily || w.config.chart.fontFamily; this.tooltipTitle.style.fontSize = this.tConfig.style.fontSize; tooltipEl.appendChild(this.tooltipTitle); } var ttItemsCnt = w.globals.series.length; // whether shared or not, default is shared if ((w.globals.xyCharts || w.globals.comboCharts) && this.tConfig.shared) { if (!this.showOnIntersect) { ttItemsCnt = w.globals.series.length; } else { ttItemsCnt = 1; } } this.legendLabels = w.globals.dom.baseEl.querySelectorAll('.apexcharts-legend-text'); this.ttItems = this.createTTElements(ttItemsCnt); this.addSVGEvents(); } }, { key: "createTTElements", value: function createTTElements(ttItemsCnt) { var _this = this; var w = this.w; var ttItems = []; var tooltipEl = this.getElTooltip(); var _loop = function _loop(i) { var gTxt = document.createElement('div'); gTxt.classList.add('apexcharts-tooltip-series-group'); gTxt.style.order = w.config.tooltip.inverseOrder ? ttItemsCnt - i : i + 1; if (_this.tConfig.shared && _this.tConfig.enabledOnSeries && Array.isArray(_this.tConfig.enabledOnSeries)) { if (_this.tConfig.enabledOnSeries.indexOf(i) < 0) { gTxt.classList.add('apexcharts-tooltip-series-group-hidden'); } } var point = document.createElement('span'); point.classList.add('apexcharts-tooltip-marker'); point.style.backgroundColor = w.globals.colors[i]; gTxt.appendChild(point); var gYZ = document.createElement('div'); gYZ.classList.add('apexcharts-tooltip-text'); gYZ.style.fontFamily = _this.tConfig.style.fontFamily || w.config.chart.fontFamily; gYZ.style.fontSize = _this.tConfig.style.fontSize; ['y', 'goals', 'z'].forEach(function (g) { var gValText = document.createElement('div'); gValText.classList.add("apexcharts-tooltip-".concat(g, "-group")); var txtLabel = document.createElement('span'); txtLabel.classList.add("apexcharts-tooltip-text-".concat(g, "-label")); gValText.appendChild(txtLabel); var txtValue = document.createElement('span'); txtValue.classList.add("apexcharts-tooltip-text-".concat(g, "-value")); gValText.appendChild(txtValue); gYZ.appendChild(gValText); }); gTxt.appendChild(gYZ); tooltipEl.appendChild(gTxt); ttItems.push(gTxt); }; for (var i = 0; i < ttItemsCnt; i++) { _loop(i); } return ttItems; } }, { key: "addSVGEvents", value: function addSVGEvents() { var w = this.w; var type = w.config.chart.type; var tooltipEl = this.getElTooltip(); var commonBar = !!(type === 'bar' || type === 'candlestick' || type === 'boxPlot' || type === 'rangeBar'); var chartWithmarkers = type === 'area' || type === 'line' || type === 'scatter' || type === 'bubble' || type === 'radar'; var hoverArea = w.globals.dom.Paper.node; var elGrid = this.getElGrid(); if (elGrid) { this.seriesBound = elGrid.getBoundingClientRect(); } var tooltipY = []; var tooltipX = []; var seriesHoverParams = { hoverArea: hoverArea, elGrid: elGrid, tooltipEl: tooltipEl, tooltipY: tooltipY, tooltipX: tooltipX, ttItems: this.ttItems }; var points; if (w.globals.axisCharts) { if (chartWithmarkers) { points = w.globals.dom.baseEl.querySelectorAll(".apexcharts-series[data\\:longestSeries='true'] .apexcharts-marker"); } else if (commonBar) { points = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series .apexcharts-bar-area, .apexcharts-series .apexcharts-candlestick-area, .apexcharts-series .apexcharts-boxPlot-area, .apexcharts-series .apexcharts-rangebar-area'); } else if (type === 'heatmap' || type === 'treemap') { points = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series .apexcharts-heatmap, .apexcharts-series .apexcharts-treemap'); } if (points && points.length) { for (var p = 0; p < points.length; p++) { tooltipY.push(points[p].getAttribute('cy')); tooltipX.push(points[p].getAttribute('cx')); } } } var validSharedChartTypes = w.globals.xyCharts && !this.showOnIntersect || w.globals.comboCharts && !this.showOnIntersect || commonBar && this.tooltipUtil.hasBars() && this.tConfig.shared; if (validSharedChartTypes) { this.addPathsEventListeners([hoverArea], seriesHoverParams); } else if (commonBar && !w.globals.comboCharts || chartWithmarkers && this.showOnIntersect) { this.addDatapointEventsListeners(seriesHoverParams); } else if (!w.globals.axisCharts || type === 'heatmap' || type === 'treemap') { var seriesAll = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series'); this.addPathsEventListeners(seriesAll, seriesHoverParams); } if (this.showOnIntersect) { var lineAreaPoints = w.globals.dom.baseEl.querySelectorAll('.apexcharts-line-series .apexcharts-marker, .apexcharts-area-series .apexcharts-marker'); if (lineAreaPoints.length > 0) { // if we find any lineSeries, addEventListeners for them this.addPathsEventListeners(lineAreaPoints, seriesHoverParams); } // combo charts may have bars, so add event listeners here too if (this.tooltipUtil.hasBars() && !this.tConfig.shared) { this.addDatapointEventsListeners(seriesHoverParams); } } } }, { key: "drawFixedTooltipRect", value: function drawFixedTooltipRect() { var w = this.w; var tooltipEl = this.getElTooltip(); var tooltipRect = tooltipEl.getBoundingClientRect(); var ttWidth = tooltipRect.width + 10; var ttHeight = tooltipRect.height + 10; var x = this.tConfig.fixed.offsetX; var y = this.tConfig.fixed.offsetY; var fixed = this.tConfig.fixed.position.toLowerCase(); if (fixed.indexOf('right') > -1) { x = x + w.globals.svgWidth - ttWidth + 10; } if (fixed.indexOf('bottom') > -1) { y = y + w.globals.svgHeight - ttHeight - 10; } tooltipEl.style.left = x + 'px'; tooltipEl.style.top = y + 'px'; return { x: x, y: y, ttWidth: ttWidth, ttHeight: ttHeight }; } }, { key: "addDatapointEventsListeners", value: function addDatapointEventsListeners(seriesHoverParams) { var w = this.w; var points = w.globals.dom.baseEl.querySelectorAll('.apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area'); this.addPathsEventListeners(points, seriesHoverParams); } }, { key: "addPathsEventListeners", value: function addPathsEventListeners(paths, opts) { var self = this; var _loop2 = function _loop2(p) { var extendedOpts = { paths: paths[p], tooltipEl: opts.tooltipEl, tooltipY: opts.tooltipY, tooltipX: opts.tooltipX, elGrid: opts.elGrid, hoverArea: opts.hoverArea, ttItems: opts.ttItems }; var events = ['mousemove', 'mouseup', 'touchmove', 'mouseout', 'touchend']; events.map(function (ev) { return paths[p].addEventListener(ev, self.onSeriesHover.bind(self, extendedOpts), { capture: false, passive: true }); }); }; for (var p = 0; p < paths.length; p++) { _loop2(p); } } /* ** Check to see if the tooltips should be updated based on a mouse / touch event */ }, { key: "onSeriesHover", value: function onSeriesHover(opt, e) { var _this2 = this; // If a user is moving their mouse quickly, don't bother updating the tooltip every single frame var targetDelay = 100; var timeSinceLastUpdate = Date.now() - this.lastHoverTime; if (timeSinceLastUpdate >= targetDelay) { // The tooltip was last updated over 100ms ago - redraw it even if the user is still moving their // mouse so they get some feedback that their moves are being registered this.seriesHover(opt, e); } else { // The tooltip was last updated less than 100ms ago // Cancel any other delayed draw, so we don't show stale data clearTimeout(this.seriesHoverTimeout); // Schedule the next draw so that it happens about 100ms after the last update this.seriesHoverTimeout = setTimeout(function () { _this2.seriesHover(opt, e); }, targetDelay - timeSinceLastUpdate); } } /* ** The actual series hover function */ }, { key: "seriesHover", value: function seriesHover(opt, e) { var _this3 = this; this.lastHoverTime = Date.now(); var chartGroups = []; var w = this.w; // if user has more than one charts in group, we need to sync if (w.config.chart.group) { chartGroups = this.ctx.getGroupedCharts(); } if (w.globals.axisCharts && (w.globals.minX === -Infinity && w.globals.maxX === Infinity || w.globals.dataPoints === 0)) { return; } if (chartGroups.length) { chartGroups.forEach(function (ch) { var tooltipEl = _this3.getElTooltip(ch); var newOpts = { paths: opt.paths, tooltipEl: tooltipEl, tooltipY: opt.tooltipY, tooltipX: opt.tooltipX, elGrid: opt.elGrid, hoverArea: opt.hoverArea, ttItems: ch.w.globals.tooltip.ttItems }; // all the charts should have the same minX and maxX (same xaxis) for multiple tooltips to work correctly if (ch.w.globals.minX === _this3.w.globals.minX && ch.w.globals.maxX === _this3.w.globals.maxX) { ch.w.globals.tooltip.seriesHoverByContext({ chartCtx: ch, ttCtx: ch.w.globals.tooltip, opt: newOpts, e: e }); } }); } else { this.seriesHoverByContext({ chartCtx: this.ctx, ttCtx: this.w.globals.tooltip, opt: opt, e: e }); } } }, { key: "seriesHoverByContext", value: function seriesHoverByContext(_ref) { var chartCtx = _ref.chartCtx, ttCtx = _ref.ttCtx, opt = _ref.opt, e = _ref.e; var w = chartCtx.w; var tooltipEl = this.getElTooltip(); if (!tooltipEl) return; // tooltipRect is calculated on every mousemove, because the text is dynamic ttCtx.tooltipRect = { x: 0, y: 0, ttWidth: tooltipEl.getBoundingClientRect().width, ttHeight: tooltipEl.getBoundingClientRect().height }; ttCtx.e = e; // highlight the current hovered bars if (ttCtx.tooltipUtil.hasBars() && !w.globals.comboCharts && !ttCtx.isBarShared) { if (this.tConfig.onDatasetHover.highlightDataSeries) { var series = new Series(chartCtx); series.toggleSeriesOnHover(e, e.target.parentNode); } } if (ttCtx.fixedTooltip) { ttCtx.drawFixedTooltipRect(); } if (w.globals.axisCharts) { ttCtx.axisChartsTooltips({ e: e, opt: opt, tooltipRect: ttCtx.tooltipRect }); } else { // non-plot charts i.e pie/donut/circle ttCtx.nonAxisChartsTooltips({ e: e, opt: opt, tooltipRect: ttCtx.tooltipRect }); } } // tooltip handling for line/area/bar/columns/scatter }, { key: "axisChartsTooltips", value: function axisChartsTooltips(_ref2) { var e = _ref2.e, opt = _ref2.opt; var w = this.w; var x, y; var seriesBound = opt.elGrid.getBoundingClientRect(); var clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX; var clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY; this.clientY = clientY; this.clientX = clientX; w.globals.capturedSeriesIndex = -1; w.globals.capturedDataPointIndex = -1; if (clientY < seriesBound.top || clientY > seriesBound.top + seriesBound.height) { this.handleMouseOut(opt); return; } if (Array.isArray(this.tConfig.enabledOnSeries) && !w.config.tooltip.shared) { var index = parseInt(opt.paths.getAttribute('index'), 10); if (this.tConfig.enabledOnSeries.indexOf(index) < 0) { this.handleMouseOut(opt); return; } } var tooltipEl = this.getElTooltip(); var xcrosshairs = this.getElXCrosshairs(); var isStickyTooltip = w.globals.xyCharts || w.config.chart.type === 'bar' && !w.globals.isBarHorizontal && this.tooltipUtil.hasBars() && this.tConfig.shared || w.globals.comboCharts && this.tooltipUtil.hasBars(); if (e.type === 'mousemove' || e.type === 'touchmove' || e.type === 'mouseup') { // there is no series to hover over if (w.globals.collapsedSeries.length + w.globals.ancillaryCollapsedSeries.length === w.globals.series.length) { return; } if (xcrosshairs !== null) { xcrosshairs.classList.add('apexcharts-active'); } var hasYAxisTooltip = this.yaxisTooltips.filter(function (b) { return b === true; }); if (this.ycrosshairs !== null && hasYAxisTooltip.length) { this.ycrosshairs.classList.add('apexcharts-active'); } if (isStickyTooltip && !this.showOnIntersect) { this.handleStickyTooltip(e, clientX, clientY, opt); } else { if (w.config.chart.type === 'heatmap' || w.config.chart.type === 'treemap') { var markerXY = this.intersect.handleHeatTreeTooltip({ e: e, opt: opt, x: x, y: y, type: w.config.chart.type }); x = markerXY.x; y = markerXY.y; tooltipEl.style.left = x + 'px'; tooltipEl.style.top = y + 'px'; } else { if (this.tooltipUtil.hasBars()) { this.intersect.handleBarTooltip({ e: e, opt: opt }); } if (this.tooltipUtil.hasMarkers()) { // intersect - line/area/scatter/bubble this.intersect.handleMarkerTooltip({ e: e, opt: opt, x: x, y: y }); } } } if (this.yaxisTooltips.length) { for (var yt = 0; yt < w.config.yaxis.length; yt++) { this.axesTooltip.drawYaxisTooltipText(yt, clientY, this.xyRatios); } } opt.tooltipEl.classList.add('apexcharts-active'); } else if (e.type === 'mouseout' || e.type === 'touchend') { this.handleMouseOut(opt); } } // tooltip handling for pie/donuts }, { key: "nonAxisChartsTooltips", value: function nonAxisChartsTooltips(_ref3) { var e = _ref3.e, opt = _ref3.opt, tooltipRect = _ref3.tooltipRect; var w = this.w; var rel = opt.paths.getAttribute('rel'); var tooltipEl = this.getElTooltip(); var seriesBound = w.globals.dom.elWrap.getBoundingClientRect(); if (e.type === 'mousemove' || e.type === 'touchmove') { tooltipEl.classList.add('apexcharts-active'); this.tooltipLabels.drawSeriesTexts({ ttItems: opt.ttItems, i: parseInt(rel, 10) - 1, shared: false }); var x = w.globals.clientX - seriesBound.left - tooltipRect.ttWidth / 2; var y = w.globals.clientY - seriesBound.top - tooltipRect.ttHeight - 10; tooltipEl.style.left = x + 'px'; tooltipEl.style.top = y + 'px'; if (w.config.legend.tooltipHoverFormatter) { var legendFormatter = w.config.legend.tooltipHoverFormatter; var i = rel - 1; var legendName = this.legendLabels[i].getAttribute('data:default-text'); var text = legendFormatter(legendName, { seriesIndex: i, dataPointIndex: i, w: w }); this.legendLabels[i].innerHTML = text; } } else if (e.type === 'mouseout' || e.type === 'touchend') { tooltipEl.classList.remove('apexcharts-active'); if (w.config.legend.tooltipHoverFormatter) { this.legendLabels.forEach(function (l) { var defaultText = l.getAttribute('data:default-text'); l.innerHTML = decodeURIComponent(defaultText); }); } } } }, { key: "handleStickyTooltip", value: function handleStickyTooltip(e, clientX, clientY, opt) { var w = this.w; var capj = this.tooltipUtil.getNearestValues({ context: this, hoverArea: opt.hoverArea, elGrid: opt.elGrid, clientX: clientX, clientY: clientY }); var j = capj.j; var capturedSeries = capj.capturedSeries; var bounds = opt.elGrid.getBoundingClientRect(); if (capj.hoverX < 0 || capj.hoverX > bounds.width) { this.handleMouseOut(opt); return; } if (capturedSeries !== null) { this.handleStickyCapturedSeries(e, capturedSeries, opt, j); } else { // couldn't capture any series. check if shared X is same, // if yes, draw a grouped tooltip if (this.tooltipUtil.isXoverlap(j) || w.globals.isBarHorizontal) { this.create(e, this, 0, j, opt.ttItems); } } } }, { key: "handleStickyCapturedSeries", value: function handleStickyCapturedSeries(e, capturedSeries, opt, j) { var w = this.w; if (!this.tConfig.shared) { var ignoreNull = w.globals.series[capturedSeries][j] === null; if (ignoreNull) { this.handleMouseOut(opt); return; } } if (typeof w.globals.series[capturedSeries][j] !== 'undefined') { if (this.tConfig.shared && this.tooltipUtil.isXoverlap(j) && this.tooltipUtil.isInitialSeriesSameLen()) { this.create(e, this, capturedSeries, j, opt.ttItems); } else { this.create(e, this, capturedSeries, j, opt.ttItems, false); } } else { if (this.tooltipUtil.isXoverlap(j)) { this.create(e, this, 0, j, opt.ttItems); } } } }, { key: "deactivateHoverFilter", value: function deactivateHoverFilter() { var w = this.w; var graphics = new Graphics(this.ctx); var allPaths = w.globals.dom.Paper.select(".apexcharts-bar-area"); for (var b = 0; b < allPaths.length; b++) { graphics.pathMouseLeave(allPaths[b]); } } }, { key: "handleMouseOut", value: function handleMouseOut(opt) { var w = this.w; var xcrosshairs = this.getElXCrosshairs(); opt.tooltipEl.classList.remove('apexcharts-active'); this.deactivateHoverFilter(); if (w.config.chart.type !== 'bubble') { this.marker.resetPointsSize(); } if (xcrosshairs !== null) { xcrosshairs.classList.remove('apexcharts-active'); } if (this.ycrosshairs !== null) { this.ycrosshairs.classList.remove('apexcharts-active'); } if (this.isXAxisTooltipEnabled) { this.xaxisTooltip.classList.remove('apexcharts-active'); } if (this.yaxisTooltips.length) { if (this.yaxisTTEls === null) { this.yaxisTTEls = w.globals.dom.baseEl.querySelectorAll('.apexcharts-yaxistooltip'); } for (var i = 0; i < this.yaxisTTEls.length; i++) { this.yaxisTTEls[i].classList.remove('apexcharts-active'); } } if (w.config.legend.tooltipHoverFormatter) { this.legendLabels.forEach(function (l) { var defaultText = l.getAttribute('data:default-text'); l.innerHTML = decodeURIComponent(defaultText); }); } } }, { key: "markerClick", value: function markerClick(e, seriesIndex, dataPointIndex) { var w = this.w; if (typeof w.config.chart.events.markerClick === 'function') { w.config.chart.events.markerClick(e, this.ctx, { seriesIndex: seriesIndex, dataPointIndex: dataPointIndex, w: w }); } this.ctx.events.fireEvent('markerClick', [e, this.ctx, { seriesIndex: seriesIndex, dataPointIndex: dataPointIndex, w: w }]); } }, { key: "create", value: function create(e, context, capturedSeries, j, ttItems) { var _w$globals$seriesRang, _w$globals$seriesRang2, _w$globals$seriesRang3, _w$globals$seriesRang4, _w$globals$seriesRang5, _w$globals$seriesRang6, _w$globals$seriesRang7, _w$globals$seriesRang8, _w$globals$seriesRang9, _w$globals$seriesRang10, _w$globals$seriesRang11, _w$globals$seriesRang12, _w$globals$seriesRang13, _w$globals$seriesRang14, _w$globals$seriesRang15, _w$globals$seriesRang16; var shared = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null; var w = this.w; var ttCtx = context; if (e.type === 'mouseup') { this.markerClick(e, capturedSeries, j); } if (shared === null) shared = this.tConfig.shared; var hasMarkers = this.tooltipUtil.hasMarkers(); var bars = this.tooltipUtil.getElBars(); if (w.config.legend.tooltipHoverFormatter) { var legendFormatter = w.config.legend.tooltipHoverFormatter; var els = Array.from(this.legendLabels); // reset all legend values first els.forEach(function (l) { var legendName = l.getAttribute('data:default-text'); l.innerHTML = decodeURIComponent(legendName); }); // for irregular time series for (var i = 0; i < els.length; i++) { var l = els[i]; var lsIndex = parseInt(l.getAttribute('i'), 10); var legendName = decodeURIComponent(l.getAttribute('data:default-text')); var text = legendFormatter(legendName, { seriesIndex: shared ? lsIndex : capturedSeries, dataPointIndex: j, w: w }); if (!shared) { l.innerHTML = lsIndex === capturedSeries ? text : legendName; if (capturedSeries === lsIndex) { break; } } else { l.innerHTML = w.globals.collapsedSeriesIndices.indexOf(lsIndex) < 0 ? text : legendName; } } } var commonSeriesTextsParams = _objectSpread2(_objectSpread2({ ttItems: ttItems, i: capturedSeries, j: j }, typeof ((_w$globals$seriesRang = w.globals.seriesRange) === null || _w$globals$seriesRang === void 0 ? void 0 : (_w$globals$seriesRang2 = _w$globals$seriesRang[capturedSeries]) === null || _w$globals$seriesRang2 === void 0 ? void 0 : (_w$globals$seriesRang3 = _w$globals$seriesRang2[j]) === null || _w$globals$seriesRang3 === void 0 ? void 0 : (_w$globals$seriesRang4 = _w$globals$seriesRang3.y[0]) === null || _w$globals$seriesRang4 === void 0 ? void 0 : _w$globals$seriesRang4.y1) !== 'undefined' && { y1: (_w$globals$seriesRang5 = w.globals.seriesRange) === null || _w$globals$seriesRang5 === void 0 ? void 0 : (_w$globals$seriesRang6 = _w$globals$seriesRang5[capturedSeries]) === null || _w$globals$seriesRang6 === void 0 ? void 0 : (_w$globals$seriesRang7 = _w$globals$seriesRang6[j]) === null || _w$globals$seriesRang7 === void 0 ? void 0 : (_w$globals$seriesRang8 = _w$globals$seriesRang7.y[0]) === null || _w$globals$seriesRang8 === void 0 ? void 0 : _w$globals$seriesRang8.y1 }), typeof ((_w$globals$seriesRang9 = w.globals.seriesRange) === null || _w$globals$seriesRang9 === void 0 ? void 0 : (_w$globals$seriesRang10 = _w$globals$seriesRang9[capturedSeries]) === null || _w$globals$seriesRang10 === void 0 ? void 0 : (_w$globals$seriesRang11 = _w$globals$seriesRang10[j]) === null || _w$globals$seriesRang11 === void 0 ? void 0 : (_w$globals$seriesRang12 = _w$globals$seriesRang11.y[0]) === null || _w$globals$seriesRang12 === void 0 ? void 0 : _w$globals$seriesRang12.y2) !== 'undefined' && { y2: (_w$globals$seriesRang13 = w.globals.seriesRange) === null || _w$globals$seriesRang13 === void 0 ? void 0 : (_w$globals$seriesRang14 = _w$globals$seriesRang13[capturedSeries]) === null || _w$globals$seriesRang14 === void 0 ? void 0 : (_w$globals$seriesRang15 = _w$globals$seriesRang14[j]) === null || _w$globals$seriesRang15 === void 0 ? void 0 : (_w$globals$seriesRang16 = _w$globals$seriesRang15.y[0]) === null || _w$globals$seriesRang16 === void 0 ? void 0 : _w$globals$seriesRang16.y2 }); if (shared) { ttCtx.tooltipLabels.drawSeriesTexts(_objectSpread2(_objectSpread2({}, commonSeriesTextsParams), {}, { shared: this.showOnIntersect ? false : this.tConfig.shared })); if (hasMarkers) { if (w.globals.markers.largestSize > 0) { ttCtx.marker.enlargePoints(j); } else { ttCtx.tooltipPosition.moveDynamicPointsOnHover(j); } } if (this.tooltipUtil.hasBars()) { this.barSeriesHeight = this.tooltipUtil.getBarsHeight(bars); if (this.barSeriesHeight > 0) { // hover state, activate snap filter var graphics = new Graphics(this.ctx); var paths = w.globals.dom.Paper.select(".apexcharts-bar-area[j='".concat(j, "']")); // de-activate first this.deactivateHoverFilter(); this.tooltipPosition.moveStickyTooltipOverBars(j); for (var b = 0; b < paths.length; b++) { graphics.pathMouseEnter(paths[b]); } } } } else { ttCtx.tooltipLabels.drawSeriesTexts(_objectSpread2({ shared: false }, commonSeriesTextsParams)); if (this.tooltipUtil.hasBars()) { ttCtx.tooltipPosition.moveStickyTooltipOverBars(j); } if (hasMarkers) { ttCtx.tooltipPosition.moveMarkers(capturedSeries, j); } } } }]); return Tooltip; }(); var BarDataLabels = /*#__PURE__*/function () { function BarDataLabels(barCtx) { _classCallCheck(this, BarDataLabels); this.w = barCtx.w; this.barCtx = barCtx; this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter; if (!this.totalFormatter) { this.totalFormatter = this.w.config.dataLabels.formatter; } } /** handleBarDataLabels is used to calculate the positions for the data-labels * It also sets the element's data attr for bars and calls drawCalculatedBarDataLabels() * After calculating, it also calls the function to draw data labels * @memberof Bar * @param {object} {barProps} most of the bar properties used throughout the bar * drawing function * @return {object} dataLabels node-element which you can append later **/ _createClass(BarDataLabels, [{ key: "handleBarDataLabels", value: function handleBarDataLabels(opts) { var x = opts.x, y = opts.y, y1 = opts.y1, y2 = opts.y2, i = opts.i, j = opts.j, realIndex = opts.realIndex, series = opts.series, barHeight = opts.barHeight, barWidth = opts.barWidth, barYPosition = opts.barYPosition, visibleSeries = opts.visibleSeries, renderedPath = opts.renderedPath; var w = this.w; var graphics = new Graphics(this.barCtx.ctx); var strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth; var bcx = x + parseFloat(barWidth * visibleSeries); var bcy = y + parseFloat(barHeight * visibleSeries); if (w.globals.isXNumeric && !w.globals.isBarHorizontal) { bcx = x + parseFloat(barWidth * (visibleSeries + 1)); bcy = y + parseFloat(barHeight * (visibleSeries + 1)) - strokeWidth; } var dataLabels = null; var totalDataLabels = null; var dataLabelsX = x; var dataLabelsY = y; var dataLabelsPos = {}; var dataLabelsConfig = w.config.dataLabels; var barDataLabelsConfig = this.barCtx.barOptions.dataLabels; var barTotalDataLabelsConfig = this.barCtx.barOptions.dataLabels.total; if (typeof barYPosition !== 'undefined' && this.barCtx.isRangeBar) { bcy = barYPosition; dataLabelsY = barYPosition; } var offX = dataLabelsConfig.offsetX; var offY = dataLabelsConfig.offsetY; var textRects = { width: 0, height: 0 }; if (w.config.dataLabels.enabled) { var yLabel = this.barCtx.series[i][j]; textRects = graphics.getTextRects(w.globals.yLabelFormatters[0](yLabel), parseFloat(dataLabelsConfig.style.fontSize)); } var params = { x: x, y: y, i: i, j: j, realIndex: realIndex, renderedPath: renderedPath, bcx: bcx, bcy: bcy, barHeight: barHeight, barWidth: barWidth, textRects: textRects, strokeWidth: strokeWidth, dataLabelsX: dataLabelsX, dataLabelsY: dataLabelsY, dataLabelsConfig: dataLabelsConfig, barDataLabelsConfig: barDataLabelsConfig, barTotalDataLabelsConfig: barTotalDataLabelsConfig, offX: offX, offY: offY }; if (this.barCtx.isHorizontal) { dataLabelsPos = this.calculateBarsDataLabelsPosition(params); } else { dataLabelsPos = this.calculateColumnsDataLabelsPosition(params); } renderedPath.attr({ cy: dataLabelsPos.bcy, cx: dataLabelsPos.bcx, j: j, val: series[i][j], barHeight: barHeight, barWidth: barWidth }); dataLabels = this.drawCalculatedDataLabels({ x: dataLabelsPos.dataLabelsX, y: dataLabelsPos.dataLabelsY, val: this.barCtx.isRangeBar ? [y1, y2] : series[i][j], i: realIndex, j: j, barWidth: barWidth, barHeight: barHeight, textRects: textRects, dataLabelsConfig: dataLabelsConfig }); if (w.config.chart.stacked && barTotalDataLabelsConfig.enabled) { totalDataLabels = this.drawTotalDataLabels({ x: dataLabelsPos.totalDataLabelsX, y: dataLabelsPos.totalDataLabelsY, realIndex: realIndex, textAnchor: dataLabelsPos.totalDataLabelsAnchor, val: this.getStackedTotalDataLabel({ realIndex: realIndex, j: j }), dataLabelsConfig: dataLabelsConfig, barTotalDataLabelsConfig: barTotalDataLabelsConfig }); } return { dataLabels: dataLabels, totalDataLabels: totalDataLabels }; } }, { key: "getStackedTotalDataLabel", value: function getStackedTotalDataLabel(_ref) { var realIndex = _ref.realIndex, j = _ref.j; var w = this.w; var val = this.barCtx.stackedSeriesTotals[j]; if (this.totalFormatter) { val = this.totalFormatter(val, _objectSpread2(_objectSpread2({}, w), {}, { seriesIndex: realIndex, dataPointIndex: j, w: w })); } return val; } }, { key: "calculateColumnsDataLabelsPosition", value: function calculateColumnsDataLabelsPosition(opts) { var w = this.w; var i = opts.i, j = opts.j, realIndex = opts.realIndex, y = opts.y, bcx = opts.bcx, barWidth = opts.barWidth, barHeight = opts.barHeight, textRects = opts.textRects, dataLabelsY = opts.dataLabelsY, dataLabelsConfig = opts.dataLabelsConfig, barDataLabelsConfig = opts.barDataLabelsConfig, barTotalDataLabelsConfig = opts.barTotalDataLabelsConfig, strokeWidth = opts.strokeWidth, offX = opts.offX, offY = opts.offY; var dataLabelsX; var totalDataLabelsY; var totalDataLabelsX; var totalDataLabelsAnchor = 'middle'; barHeight = Math.abs(barHeight); var vertical = w.config.plotOptions.bar.dataLabels.orientation === 'vertical'; bcx = bcx - strokeWidth / 2; var dataPointsDividedWidth = w.globals.gridWidth / w.globals.dataPoints; if (w.globals.isXNumeric) { dataLabelsX = bcx - barWidth / 2 + offX; } else { dataLabelsX = bcx - dataPointsDividedWidth + barWidth / 2 + offX; } if (vertical) { var offsetDLX = 2; dataLabelsX = dataLabelsX + textRects.height / 2 - strokeWidth / 2 - offsetDLX; } var valIsNegative = this.barCtx.series[i][j] < 0; var newY = y; if (this.barCtx.isReversed) { newY = y - barHeight + (valIsNegative ? barHeight * 2 : 0); y = y - barHeight; } switch (barDataLabelsConfig.position) { case 'center': if (vertical) { if (valIsNegative) { dataLabelsY = newY + barHeight / 2 + offY; } else { dataLabelsY = newY + barHeight / 2 - offY; } } else { if (valIsNegative) { dataLabelsY = newY - barHeight / 2 + textRects.height / 2 + offY; } else { dataLabelsY = newY + barHeight / 2 + textRects.height / 2 - offY; } } break; case 'bottom': if (vertical) { if (valIsNegative) { dataLabelsY = newY + barHeight + offY; } else { dataLabelsY = newY + barHeight - offY; } } else { if (valIsNegative) { dataLabelsY = newY - barHeight + textRects.height + strokeWidth + offY; } else { dataLabelsY = newY + barHeight - textRects.height / 2 + strokeWidth - offY; } } break; case 'top': if (vertical) { if (valIsNegative) { dataLabelsY = newY + offY; } else { dataLabelsY = newY - offY; } } else { if (valIsNegative) { dataLabelsY = newY - textRects.height / 2 - offY; } else { dataLabelsY = newY + textRects.height + offY; } } break; } if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) { var ADDITIONAL_OFFX = 18; var graphics = new Graphics(this.barCtx.ctx); var totalLabeltextRects = graphics.getTextRects(this.getStackedTotalDataLabel({ realIndex: realIndex, j: j }), dataLabelsConfig.fontSize); if (valIsNegative) { totalDataLabelsY = newY - totalLabeltextRects.height / 2 - offY - barTotalDataLabelsConfig.offsetY + ADDITIONAL_OFFX; } else { totalDataLabelsY = newY + totalLabeltextRects.height + offY + barTotalDataLabelsConfig.offsetY - ADDITIONAL_OFFX; } totalDataLabelsX = dataLabelsX + barTotalDataLabelsConfig.offsetX; } if (!w.config.chart.stacked) { if (dataLabelsY < 0) { dataLabelsY = 0 + strokeWidth; } else if (dataLabelsY + textRects.height / 3 > w.globals.gridHeight) { dataLabelsY = w.globals.gridHeight - strokeWidth; } } return { bcx: bcx, bcy: y, dataLabelsX: dataLabelsX, dataLabelsY: dataLabelsY, totalDataLabelsX: totalDataLabelsX, totalDataLabelsY: totalDataLabelsY, totalDataLabelsAnchor: totalDataLabelsAnchor }; } }, { key: "calculateBarsDataLabelsPosition", value: function calculateBarsDataLabelsPosition(opts) { var w = this.w; var x = opts.x, i = opts.i, j = opts.j, realIndex = opts.realIndex, bcy = opts.bcy, barHeight = opts.barHeight, barWidth = opts.barWidth, textRects = opts.textRects, dataLabelsX = opts.dataLabelsX, strokeWidth = opts.strokeWidth, dataLabelsConfig = opts.dataLabelsConfig, barDataLabelsConfig = opts.barDataLabelsConfig, barTotalDataLabelsConfig = opts.barTotalDataLabelsConfig, offX = opts.offX, offY = opts.offY; var dataPointsDividedHeight = w.globals.gridHeight / w.globals.dataPoints; barWidth = Math.abs(barWidth); var dataLabelsY = bcy - (this.barCtx.isRangeBar ? 0 : dataPointsDividedHeight) + barHeight / 2 + textRects.height / 2 + offY - 3; var totalDataLabelsX; var totalDataLabelsY; var totalDataLabelsAnchor = 'start'; var valIsNegative = this.barCtx.series[i][j] < 0; var newX = x; if (this.barCtx.isReversed) { newX = x + barWidth - (valIsNegative ? barWidth * 2 : 0); x = w.globals.gridWidth - barWidth; } switch (barDataLabelsConfig.position) { case 'center': if (valIsNegative) { dataLabelsX = newX + barWidth / 2 - offX; } else { dataLabelsX = Math.max(textRects.width / 2, newX - barWidth / 2) + offX; } break; case 'bottom': if (valIsNegative) { dataLabelsX = newX + barWidth - strokeWidth - Math.round(textRects.width / 2) - offX; } else { dataLabelsX = newX - barWidth + strokeWidth + Math.round(textRects.width / 2) + offX; } break; case 'top': if (valIsNegative) { dataLabelsX = newX - strokeWidth + Math.round(textRects.width / 2) - offX; } else { dataLabelsX = newX - strokeWidth - Math.round(textRects.width / 2) + offX; } break; } if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) { var ADDITIONAL_OFFX = 15; var graphics = new Graphics(this.barCtx.ctx); var totalLabeltextRects = graphics.getTextRects(this.getStackedTotalDataLabel({ realIndex: realIndex, j: j }), dataLabelsConfig.fontSize); if (valIsNegative) { totalDataLabelsX = newX - strokeWidth + Math.round(totalLabeltextRects.width / 2) - offX - barTotalDataLabelsConfig.offsetX - ADDITIONAL_OFFX; totalDataLabelsAnchor = 'end'; } else { totalDataLabelsX = newX - strokeWidth - Math.round(totalLabeltextRects.width / 2) + offX + barTotalDataLabelsConfig.offsetX + ADDITIONAL_OFFX; } totalDataLabelsY = dataLabelsY + barTotalDataLabelsConfig.offsetY; } if (!w.config.chart.stacked) { if (dataLabelsX < 0) { dataLabelsX = dataLabelsX + textRects.width + strokeWidth; } else if (dataLabelsX + textRects.width / 2 > w.globals.gridWidth) { dataLabelsX = w.globals.gridWidth - textRects.width - strokeWidth; } } return { bcx: x, bcy: bcy, dataLabelsX: dataLabelsX, dataLabelsY: dataLabelsY, totalDataLabelsX: totalDataLabelsX, totalDataLabelsY: totalDataLabelsY, totalDataLabelsAnchor: totalDataLabelsAnchor }; } }, { key: "drawCalculatedDataLabels", value: function drawCalculatedDataLabels(_ref2) { var x = _ref2.x, y = _ref2.y, val = _ref2.val, i = _ref2.i, j = _ref2.j, textRects = _ref2.textRects, barHeight = _ref2.barHeight, barWidth = _ref2.barWidth, dataLabelsConfig = _ref2.dataLabelsConfig; var w = this.w; var rotate = 'rotate(0)'; if (w.config.plotOptions.bar.dataLabels.orientation === 'vertical') rotate = "rotate(-90, ".concat(x, ", ").concat(y, ")"); var dataLabels = new DataLabels(this.barCtx.ctx); var graphics = new Graphics(this.barCtx.ctx); var formatter = dataLabelsConfig.formatter; var elDataLabelsWrap = null; var isSeriesNotCollapsed = w.globals.collapsedSeriesIndices.indexOf(i) > -1; if (dataLabelsConfig.enabled && !isSeriesNotCollapsed) { elDataLabelsWrap = graphics.group({ class: 'apexcharts-data-labels', transform: rotate }); var text = ''; if (typeof val !== 'undefined') { text = formatter(val, _objectSpread2(_objectSpread2({}, w), {}, { seriesIndex: i, dataPointIndex: j, w: w })); } var valIsNegative = w.globals.series[i][j] < 0; var position = w.config.plotOptions.bar.dataLabels.position; if (w.config.plotOptions.bar.dataLabels.orientation === 'vertical') { if (position === 'top') { if (valIsNegative) dataLabelsConfig.textAnchor = 'end';else dataLabelsConfig.textAnchor = 'start'; } if (position === 'center') { dataLabelsConfig.textAnchor = 'middle'; } if (position === 'bottom') { if (valIsNegative) dataLabelsConfig.textAnchor = 'end';else dataLabelsConfig.textAnchor = 'start'; } } if (this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) { // hide the datalabel if it cannot fit into the rect var txRect = graphics.getTextRects(text, parseFloat(dataLabelsConfig.style.fontSize)); if (barWidth < txRect.width) { text = ''; } } if (w.config.chart.stacked && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) { // if there is not enough space to draw the label in the bar/column rect, check hideOverflowingLabels property to prevent overflowing on wrong rect // Note: This issue is only seen in stacked charts if (this.barCtx.isHorizontal) { if (textRects.width / 1.6 > Math.abs(barWidth)) { text = ''; } } else { if (textRects.height / 1.6 > Math.abs(barHeight)) { text = ''; } } } var modifiedDataLabelsConfig = _objectSpread2({}, dataLabelsConfig); if (this.barCtx.isHorizontal) { if (val < 0) { if (dataLabelsConfig.textAnchor === 'start') { modifiedDataLabelsConfig.textAnchor = 'end'; } else if (dataLabelsConfig.textAnchor === 'end') { modifiedDataLabelsConfig.textAnchor = 'start'; } } } dataLabels.plotDataLabelsText({ x: x, y: y, text: text, i: i, j: j, parent: elDataLabelsWrap, dataLabelsConfig: modifiedDataLabelsConfig, alwaysDrawDataLabel: true, offsetCorrection: true }); } return elDataLabelsWrap; } }, { key: "drawTotalDataLabels", value: function drawTotalDataLabels(_ref3) { var x = _ref3.x, y = _ref3.y, val = _ref3.val, realIndex = _ref3.realIndex, textAnchor = _ref3.textAnchor, barTotalDataLabelsConfig = _ref3.barTotalDataLabelsConfig; var graphics = new Graphics(this.barCtx.ctx); var totalDataLabelText; if (barTotalDataLabelsConfig.enabled && typeof x !== 'undefined' && typeof y !== 'undefined' && this.barCtx.lastActiveBarSerieIndex === realIndex) { totalDataLabelText = graphics.drawText({ x: x, y: y, foreColor: barTotalDataLabelsConfig.style.color, text: val, textAnchor: textAnchor, fontFamily: barTotalDataLabelsConfig.style.fontFamily, fontSize: barTotalDataLabelsConfig.style.fontSize, fontWeight: barTotalDataLabelsConfig.style.fontWeight }); } return totalDataLabelText; } }]); return BarDataLabels; }(); var Helpers$1 = /*#__PURE__*/function () { function Helpers(barCtx) { _classCallCheck(this, Helpers); this.w = barCtx.w; this.barCtx = barCtx; } _createClass(Helpers, [{ key: "initVariables", value: function initVariables(series) { var w = this.w; this.barCtx.series = series; this.barCtx.totalItems = 0; this.barCtx.seriesLen = 0; this.barCtx.visibleI = -1; // visible Series this.barCtx.visibleItems = 1; // number of visible bars after user zoomed in/out for (var sl = 0; sl < series.length; sl++) { if (series[sl].length > 0) { this.barCtx.seriesLen = this.barCtx.seriesLen + 1; this.barCtx.totalItems += series[sl].length; } if (w.globals.isXNumeric) { // get max visible items for (var j = 0; j < series[sl].length; j++) { if (w.globals.seriesX[sl][j] > w.globals.minX && w.globals.seriesX[sl][j] < w.globals.maxX) { this.barCtx.visibleItems++; } } } else { this.barCtx.visibleItems = w.globals.dataPoints; } } if (this.barCtx.seriesLen === 0) { // A small adjustment when combo charts are used this.barCtx.seriesLen = 1; } this.barCtx.zeroSerieses = []; this.barCtx.radiusOnSeriesNumber = series.length - 1; // which series to draw ending shape on if (!w.globals.comboCharts) { this.checkZeroSeries({ series: series }); } } }, { key: "initialPositions", value: function initialPositions() { var w = this.w; var x, y, yDivision, xDivision, barHeight, barWidth, zeroH, zeroW; var dataPoints = w.globals.dataPoints; if (this.barCtx.isRangeBar) { // timeline rangebar chart dataPoints = w.globals.labels.length; } var seriesLen = this.barCtx.seriesLen; if (w.config.plotOptions.bar.rangeBarGroupRows) { seriesLen = 1; } if (this.barCtx.isHorizontal) { // height divided into equal parts yDivision = w.globals.gridHeight / dataPoints; barHeight = yDivision / seriesLen; if (w.globals.isXNumeric) { yDivision = w.globals.gridHeight / this.barCtx.totalItems; barHeight = yDivision / this.barCtx.seriesLen; } barHeight = barHeight * parseInt(this.barCtx.barOptions.barHeight, 10) / 100; zeroW = this.barCtx.baseLineInvertedY + w.globals.padHorizontal + (this.barCtx.isReversed ? w.globals.gridWidth : 0) - (this.barCtx.isReversed ? this.barCtx.baseLineInvertedY * 2 : 0); y = (yDivision - barHeight * this.barCtx.seriesLen) / 2; } else { // width divided into equal parts xDivision = w.globals.gridWidth / this.barCtx.visibleItems; if (w.config.xaxis.convertedCatToNumeric) { xDivision = w.globals.gridWidth / w.globals.dataPoints; } barWidth = xDivision / this.barCtx.seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100; if (w.globals.isXNumeric) { // max barwidth should be equal to minXDiff to avoid overlap var xRatio = this.barCtx.xRatio; if (w.config.xaxis.convertedCatToNumeric) { xRatio = this.barCtx.initialXRatio; } if (w.globals.minXDiff && w.globals.minXDiff !== 0.5 && w.globals.minXDiff / xRatio > 0) { xDivision = w.globals.minXDiff / xRatio; } barWidth = xDivision / this.barCtx.seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100; if (barWidth < 1) { barWidth = 1; } } zeroH = w.globals.gridHeight - this.barCtx.baseLineY[this.barCtx.yaxisIndex] - (this.barCtx.isReversed ? w.globals.gridHeight : 0) + (this.barCtx.isReversed ? this.barCtx.baseLineY[this.barCtx.yaxisIndex] * 2 : 0); x = w.globals.padHorizontal + (xDivision - barWidth * this.barCtx.seriesLen) / 2; } return { x: x, y: y, yDivision: yDivision, xDivision: xDivision, barHeight: barHeight, barWidth: barWidth, zeroH: zeroH, zeroW: zeroW }; } }, { key: "getPathFillColor", value: function getPathFillColor(series, i, j, realIndex) { var _w$config$series$i$da, _w$config$series$i$da2, _w$config$series$i$da3, _w$config$series$i$da4; var w = this.w; var fill = new Fill(this.barCtx.ctx); var fillColor = null; var seriesNumber = this.barCtx.barOptions.distributed ? j : i; if (this.barCtx.barOptions.colors.ranges.length > 0) { var colorRange = this.barCtx.barOptions.colors.ranges; colorRange.map(function (range) { if (series[i][j] >= range.from && series[i][j] <= range.to) { fillColor = range.color; } }); } if (w.config.series[i].data[j] && w.config.series[i].data[j].fillColor) { fillColor = w.config.series[i].data[j].fillColor; } var pathFill = fill.fillPath({ seriesNumber: this.barCtx.barOptions.distributed ? seriesNumber : realIndex, dataPointIndex: j, color: fillColor, value: series[i][j], fillConfig: (_w$config$series$i$da = w.config.series[i].data[j]) === null || _w$config$series$i$da === void 0 ? void 0 : _w$config$series$i$da.fill, fillType: (_w$config$series$i$da2 = w.config.series[i].data[j]) !== null && _w$config$series$i$da2 !== void 0 && (_w$config$series$i$da3 = _w$config$series$i$da2.fill) !== null && _w$config$series$i$da3 !== void 0 && _w$config$series$i$da3.type ? (_w$config$series$i$da4 = w.config.series[i].data[j]) === null || _w$config$series$i$da4 === void 0 ? void 0 : _w$config$series$i$da4.fill.type : w.config.fill.type }); return pathFill; } }, { key: "getStrokeWidth", value: function getStrokeWidth(i, j, realIndex) { var strokeWidth = 0; var w = this.w; if (!this.barCtx.series[i][j]) { this.barCtx.isNullValue = true; } else { this.barCtx.isNullValue = false; } if (w.config.stroke.show) { if (!this.barCtx.isNullValue) { strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth; } } return strokeWidth; } }, { key: "shouldApplyRadius", value: function shouldApplyRadius(realIndex) { var w = this.w; var applyRadius = false; if (w.config.plotOptions.bar.borderRadius > 0) { if (w.config.chart.stacked) { if (w.config.plotOptions.bar.borderRadiusWhenStacked === 'last') { if (this.barCtx.lastActiveBarSerieIndex === realIndex) { applyRadius = true; } } else { applyRadius = true; } } else { applyRadius = true; } } return applyRadius; } }, { key: "barBackground", value: function barBackground(_ref) { var j = _ref.j, i = _ref.i, x1 = _ref.x1, x2 = _ref.x2, y1 = _ref.y1, y2 = _ref.y2, elSeries = _ref.elSeries; var w = this.w; var graphics = new Graphics(this.barCtx.ctx); var sr = new Series(this.barCtx.ctx); var activeSeriesIndex = sr.getActiveConfigSeriesIndex(); if (this.barCtx.barOptions.colors.backgroundBarColors.length > 0 && activeSeriesIndex === i) { if (j >= this.barCtx.barOptions.colors.backgroundBarColors.length) { j %= this.barCtx.barOptions.colors.backgroundBarColors.length; } var bcolor = this.barCtx.barOptions.colors.backgroundBarColors[j]; var rect = graphics.drawRect(typeof x1 !== 'undefined' ? x1 : 0, typeof y1 !== 'undefined' ? y1 : 0, typeof x2 !== 'undefined' ? x2 : w.globals.gridWidth, typeof y2 !== 'undefined' ? y2 : w.globals.gridHeight, this.barCtx.barOptions.colors.backgroundBarRadius, bcolor, this.barCtx.barOptions.colors.backgroundBarOpacity); elSeries.add(rect); rect.node.classList.add('apexcharts-backgroundBar'); } } }, { key: "getColumnPaths", value: function getColumnPaths(_ref2) { var _w$config$series$real; var barWidth = _ref2.barWidth, barXPosition = _ref2.barXPosition, y1 = _ref2.y1, y2 = _ref2.y2, strokeWidth = _ref2.strokeWidth, realIndex = _ref2.realIndex, i = _ref2.i, j = _ref2.j, w = _ref2.w; var graphics = new Graphics(this.barCtx.ctx); strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth; if (!strokeWidth) strokeWidth = 0; var bW = barWidth; var bXP = barXPosition; if ((_w$config$series$real = w.config.series[realIndex].data[j]) !== null && _w$config$series$real !== void 0 && _w$config$series$real.columnWidthOffset) { bXP = barXPosition - w.config.series[realIndex].data[j].columnWidthOffset / 2; bW = barWidth + w.config.series[realIndex].data[j].columnWidthOffset; } var x1 = bXP; var x2 = bXP + bW; // append tiny pixels to avoid exponentials (which cause issues in border-radius) y1 += 0.001; y2 += 0.001; var pathTo = graphics.move(x1, y1); var pathFrom = graphics.move(x1, y1); var sl = graphics.line(x2 - strokeWidth, y1); if (w.globals.previousPaths.length > 0) { pathFrom = this.barCtx.getPreviousPath(realIndex, j, false); } pathTo = pathTo + graphics.line(x1, y2) + graphics.line(x2 - strokeWidth, y2) + graphics.line(x2 - strokeWidth, y1) + (w.config.plotOptions.bar.borderRadiusApplication === 'around' ? ' Z' : ' z'); // the lines in pathFrom are repeated to equal it to the points of pathTo // this is to avoid weird animation (bug in svg.js) pathFrom = pathFrom + graphics.line(x1, y1) + sl + sl + sl + sl + sl + graphics.line(x1, y1) + (w.config.plotOptions.bar.borderRadiusApplication === 'around' ? ' Z' : ' z'); if (this.shouldApplyRadius(realIndex)) { pathTo = graphics.roundPathCorners(pathTo, w.config.plotOptions.bar.borderRadius); } if (w.config.chart.stacked) { this.barCtx.yArrj.push(y2); this.barCtx.yArrjF.push(Math.abs(y1 - y2)); this.barCtx.yArrjVal.push(this.barCtx.series[i][j]); } return { pathTo: pathTo, pathFrom: pathFrom }; } }, { key: "getBarpaths", value: function getBarpaths(_ref3) { var _w$config$series$real2; var barYPosition = _ref3.barYPosition, barHeight = _ref3.barHeight, x1 = _ref3.x1, x2 = _ref3.x2, strokeWidth = _ref3.strokeWidth, realIndex = _ref3.realIndex, i = _ref3.i, j = _ref3.j, w = _ref3.w; var graphics = new Graphics(this.barCtx.ctx); strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth; if (!strokeWidth) strokeWidth = 0; var bYP = barYPosition; var bH = barHeight; if ((_w$config$series$real2 = w.config.series[realIndex].data[j]) !== null && _w$config$series$real2 !== void 0 && _w$config$series$real2.barHeightOffset) { bYP = barYPosition - w.config.series[realIndex].data[j].barHeightOffset / 2; bH = barHeight + w.config.series[realIndex].data[j].barHeightOffset; } var y1 = bYP; var y2 = bYP + bH; // append tiny pixels to avoid exponentials (which cause issues in border-radius) x1 += 0.001; x2 += 0.001; var pathTo = graphics.move(x1, y1); var pathFrom = graphics.move(x1, y1); if (w.globals.previousPaths.length > 0) { pathFrom = this.barCtx.getPreviousPath(realIndex, j, false); } var sl = graphics.line(x1, y2 - strokeWidth); pathTo = pathTo + graphics.line(x2, y1) + graphics.line(x2, y2 - strokeWidth) + sl + (w.config.plotOptions.bar.borderRadiusApplication === 'around' ? ' Z' : ' z'); pathFrom = pathFrom + graphics.line(x1, y1) + sl + sl + sl + sl + sl + graphics.line(x1, y1) + (w.config.plotOptions.bar.borderRadiusApplication === 'around' ? ' Z' : ' z'); if (this.shouldApplyRadius(realIndex)) { pathTo = graphics.roundPathCorners(pathTo, w.config.plotOptions.bar.borderRadius); } if (w.config.chart.stacked) { this.barCtx.xArrj.push(x2); this.barCtx.xArrjF.push(Math.abs(x1 - x2)); this.barCtx.xArrjVal.push(this.barCtx.series[i][j]); } return { pathTo: pathTo, pathFrom: pathFrom }; } }, { key: "checkZeroSeries", value: function checkZeroSeries(_ref4) { var series = _ref4.series; var w = this.w; for (var zs = 0; zs < series.length; zs++) { var total = 0; for (var zsj = 0; zsj < series[w.globals.maxValsInArrayIndex].length; zsj++) { total += series[zs][zsj]; } if (total === 0) { this.barCtx.zeroSerieses.push(zs); } } // After getting all zeroserieses, we need to ensure whether radiusOnSeriesNumber is not in that zeroseries array for (var s = series.length - 1; s >= 0; s--) { if (this.barCtx.zeroSerieses.indexOf(s) > -1 && s === this.radiusOnSeriesNumber) { this.barCtx.radiusOnSeriesNumber -= 1; } } for (var _s = series.length - 1; _s >= 0; _s--) { if (w.globals.collapsedSeriesIndices.indexOf(this.barCtx.radiusOnSeriesNumber) > -1) { this.barCtx.radiusOnSeriesNumber -= 1; } } } }, { key: "getXForValue", value: function getXForValue(value, zeroW) { var zeroPositionForNull = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var xForVal = zeroPositionForNull ? zeroW : null; if (typeof value !== 'undefined' && value !== null) { xForVal = zeroW + value / this.barCtx.invertedYRatio - (this.barCtx.isReversed ? value / this.barCtx.invertedYRatio : 0) * 2; } return xForVal; } }, { key: "getYForValue", value: function getYForValue(value, zeroH) { var zeroPositionForNull = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var yForVal = zeroPositionForNull ? zeroH : null; if (typeof value !== 'undefined' && value !== null) { yForVal = zeroH - value / this.barCtx.yRatio[this.barCtx.yaxisIndex] + (this.barCtx.isReversed ? value / this.barCtx.yRatio[this.barCtx.yaxisIndex] : 0) * 2; } return yForVal; } }, { key: "getGoalValues", value: function getGoalValues(type, zeroW, zeroH, i, j) { var _this = this; var w = this.w; var goals = []; if (w.globals.seriesGoals[i] && w.globals.seriesGoals[i][j] && Array.isArray(w.globals.seriesGoals[i][j])) { w.globals.seriesGoals[i][j].forEach(function (goal) { var _goals$push; goals.push((_goals$push = {}, _defineProperty(_goals$push, type, type === 'x' ? _this.getXForValue(goal.value, zeroW, false) : _this.getYForValue(goal.value, zeroH, false)), _defineProperty(_goals$push, "attrs", goal), _goals$push)); }); } return goals; } }, { key: "drawGoalLine", value: function drawGoalLine(_ref5) { var barXPosition = _ref5.barXPosition, barYPosition = _ref5.barYPosition, goalX = _ref5.goalX, goalY = _ref5.goalY, barWidth = _ref5.barWidth, barHeight = _ref5.barHeight; var graphics = new Graphics(this.barCtx.ctx); var lineGroup = graphics.group({ className: 'apexcharts-bar-goals-groups' }); var line = null; if (this.barCtx.isHorizontal) { if (Array.isArray(goalX)) { goalX.forEach(function (goal) { var sHeight = typeof goal.attrs.strokeHeight !== 'undefined' ? goal.attrs.strokeHeight : barHeight / 2; var y = barYPosition + sHeight + barHeight / 2; line = graphics.drawLine(goal.x, y - sHeight * 2, goal.x, y, goal.attrs.strokeColor ? goal.attrs.strokeColor : undefined, goal.attrs.strokeDashArray, goal.attrs.strokeWidth ? goal.attrs.strokeWidth : 2, goal.attrs.strokeLineCap); lineGroup.add(line); }); } } else { if (Array.isArray(goalY)) { goalY.forEach(function (goal) { var sWidth = typeof goal.attrs.strokeWidth !== 'undefined' ? goal.attrs.strokeWidth : barWidth / 2; var x = barXPosition + sWidth + barWidth / 2; line = graphics.drawLine(x - sWidth * 2, goal.y, x, goal.y, goal.attrs.strokeColor ? goal.attrs.strokeColor : undefined, goal.attrs.strokeDashArray, goal.attrs.strokeHeight ? goal.attrs.strokeHeight : 2, goal.attrs.strokeLineCap); lineGroup.add(line); }); } } return lineGroup; } }]); return Helpers; }(); /** * ApexCharts Bar Class responsible for drawing both Columns and Bars. * * @module Bar **/ var Bar = /*#__PURE__*/function () { function Bar(ctx, xyRatios) { _classCallCheck(this, Bar); this.ctx = ctx; this.w = ctx.w; var w = this.w; this.barOptions = w.config.plotOptions.bar; this.isHorizontal = this.barOptions.horizontal; this.strokeWidth = w.config.stroke.width; this.isNullValue = false; this.isRangeBar = w.globals.seriesRange.length && this.isHorizontal; this.xyRatios = xyRatios; if (this.xyRatios !== null) { this.xRatio = xyRatios.xRatio; this.initialXRatio = xyRatios.initialXRatio; this.yRatio = xyRatios.yRatio; this.invertedXRatio = xyRatios.invertedXRatio; this.invertedYRatio = xyRatios.invertedYRatio; this.baseLineY = xyRatios.baseLineY; this.baseLineInvertedY = xyRatios.baseLineInvertedY; } this.yaxisIndex = 0; this.seriesLen = 0; var ser = new Series(this.ctx); this.lastActiveBarSerieIndex = ser.getActiveConfigSeriesIndex('desc', ['bar', 'column']); var barSeriesIndices = ser.getBarSeriesIndices(); var coreUtils = new CoreUtils(this.ctx); this.stackedSeriesTotals = coreUtils.getStackedSeriesTotals(this.w.config.series.map(function (s, i) { return barSeriesIndices.indexOf(i) === -1 ? i : -1; }).filter(function (s) { return s !== -1; })); this.barHelpers = new Helpers$1(this); } /** primary draw method which is called on bar object * @memberof Bar * @param {array} series - user supplied series values * @param {int} seriesIndex - the index by which series will be drawn on the svg * @return {node} element which is supplied to parent chart draw method for appending **/ _createClass(Bar, [{ key: "draw", value: function draw(series, seriesIndex) { var w = this.w; var graphics = new Graphics(this.ctx); var coreUtils = new CoreUtils(this.ctx, w); series = coreUtils.getLogSeries(series); this.series = series; this.yRatio = coreUtils.getLogYRatios(this.yRatio); this.barHelpers.initVariables(series); var ret = graphics.group({ class: 'apexcharts-bar-series apexcharts-plot-series' }); if (w.config.dataLabels.enabled) { if (this.totalItems > this.barOptions.dataLabels.maxItems) { console.warn('WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering.'); } } for (var i = 0, bc = 0; i < series.length; i++, bc++) { var x = void 0, y = void 0, xDivision = void 0, // xDivision is the GRIDWIDTH divided by number of datapoints (columns) yDivision = void 0, // yDivision is the GRIDHEIGHT divided by number of datapoints (bars) zeroH = void 0, // zeroH is the baseline where 0 meets y axis zeroW = void 0; // zeroW is the baseline where 0 meets x axis var yArrj = []; // hold y values of current iterating series var xArrj = []; // hold x values of current iterating series var realIndex = w.globals.comboCharts ? seriesIndex[i] : i; // el to which series will be drawn var elSeries = graphics.group({ class: "apexcharts-series", rel: i + 1, seriesName: Utils$1.escapeString(w.globals.seriesNames[realIndex]), 'data:realIndex': realIndex }); this.ctx.series.addCollapsedClassToSeries(elSeries, realIndex); if (series[i].length > 0) { this.visibleI = this.visibleI + 1; } var barHeight = 0; var barWidth = 0; if (this.yRatio.length > 1) { this.yaxisIndex = realIndex; } this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed; var initPositions = this.barHelpers.initialPositions(); y = initPositions.y; barHeight = initPositions.barHeight; yDivision = initPositions.yDivision; zeroW = initPositions.zeroW; x = initPositions.x; barWidth = initPositions.barWidth; xDivision = initPositions.xDivision; zeroH = initPositions.zeroH; if (!this.horizontal) { xArrj.push(x + barWidth / 2); } // eldatalabels var elDataLabelsWrap = graphics.group({ class: 'apexcharts-datalabels', 'data:realIndex': realIndex }); var elGoalsMarkers = graphics.group({ class: 'apexcharts-bar-goals-markers', style: "pointer-events: none" }); for (var j = 0; j < w.globals.dataPoints; j++) { var strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex); var paths = null; var pathsParams = { indexes: { i: i, j: j, realIndex: realIndex, bc: bc }, x: x, y: y, strokeWidth: strokeWidth, elSeries: elSeries }; if (this.isHorizontal) { paths = this.drawBarPaths(_objectSpread2(_objectSpread2({}, pathsParams), {}, { barHeight: barHeight, zeroW: zeroW, yDivision: yDivision })); barWidth = this.series[i][j] / this.invertedYRatio; } else { paths = this.drawColumnPaths(_objectSpread2(_objectSpread2({}, pathsParams), {}, { xDivision: xDivision, barWidth: barWidth, zeroH: zeroH })); barHeight = this.series[i][j] / this.yRatio[this.yaxisIndex]; } var barGoalLine = this.barHelpers.drawGoalLine({ barXPosition: paths.barXPosition, barYPosition: paths.barYPosition, goalX: paths.goalX, goalY: paths.goalY, barHeight: barHeight, barWidth: barWidth }); if (barGoalLine) { elGoalsMarkers.add(barGoalLine); } y = paths.y; x = paths.x; // push current X if (j > 0) { xArrj.push(x + barWidth / 2); } yArrj.push(y); var pathFill = this.barHelpers.getPathFillColor(series, i, j, realIndex); this.renderSeries({ realIndex: realIndex, pathFill: pathFill, j: j, i: i, pathFrom: paths.pathFrom, pathTo: paths.pathTo, strokeWidth: strokeWidth, elSeries: elSeries, x: x, y: y, series: series, barHeight: barHeight, barWidth: barWidth, elDataLabelsWrap: elDataLabelsWrap, elGoalsMarkers: elGoalsMarkers, visibleSeries: this.visibleI, type: 'bar' }); } // push all x val arrays into main xArr w.globals.seriesXvalues[realIndex] = xArrj; w.globals.seriesYvalues[realIndex] = yArrj; ret.add(elSeries); } return ret; } }, { key: "renderSeries", value: function renderSeries(_ref) { var realIndex = _ref.realIndex, pathFill = _ref.pathFill, lineFill = _ref.lineFill, j = _ref.j, i = _ref.i, pathFrom = _ref.pathFrom, pathTo = _ref.pathTo, strokeWidth = _ref.strokeWidth, elSeries = _ref.elSeries, x = _ref.x, y = _ref.y, y1 = _ref.y1, y2 = _ref.y2, series = _ref.series, barHeight = _ref.barHeight, barWidth = _ref.barWidth, barYPosition = _ref.barYPosition, elDataLabelsWrap = _ref.elDataLabelsWrap, elGoalsMarkers = _ref.elGoalsMarkers, visibleSeries = _ref.visibleSeries, type = _ref.type; var w = this.w; var graphics = new Graphics(this.ctx); if (!lineFill) { /* fix apexcharts#341 */ lineFill = this.barOptions.distributed ? w.globals.stroke.colors[j] : w.globals.stroke.colors[realIndex]; } if (w.config.series[i].data[j] && w.config.series[i].data[j].strokeColor) { lineFill = w.config.series[i].data[j].strokeColor; } if (this.isNullValue) { pathFill = 'none'; } var delay = j / w.config.chart.animations.animateGradually.delay * (w.config.chart.animations.speed / w.globals.dataPoints) / 2.4; var renderedPath = graphics.renderPaths({ i: i, j: j, realIndex: realIndex, pathFrom: pathFrom, pathTo: pathTo, stroke: lineFill, strokeWidth: strokeWidth, strokeLineCap: w.config.stroke.lineCap, fill: pathFill, animationDelay: delay, initialSpeed: w.config.chart.animations.speed, dataChangeSpeed: w.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-".concat(type, "-area") }); renderedPath.attr('clip-path', "url(#gridRectMask".concat(w.globals.cuid, ")")); var forecast = w.config.forecastDataPoints; if (forecast.count > 0) { if (j >= w.globals.dataPoints - forecast.count) { renderedPath.node.setAttribute('stroke-dasharray', forecast.dashArray); renderedPath.node.setAttribute('stroke-width', forecast.strokeWidth); renderedPath.node.setAttribute('fill-opacity', forecast.fillOpacity); } } if (typeof y1 !== 'undefined' && typeof y2 !== 'undefined') { renderedPath.attr('data-range-y1', y1); renderedPath.attr('data-range-y2', y2); } var filters = new Filters(this.ctx); filters.setSelectionFilter(renderedPath, realIndex, j); elSeries.add(renderedPath); var barDataLabels = new BarDataLabels(this); var dataLabelsObj = barDataLabels.handleBarDataLabels({ x: x, y: y, y1: y1, y2: y2, i: i, j: j, series: series, realIndex: realIndex, barHeight: barHeight, barWidth: barWidth, barYPosition: barYPosition, renderedPath: renderedPath, visibleSeries: visibleSeries }); if (dataLabelsObj.dataLabels !== null) { elDataLabelsWrap.add(dataLabelsObj.dataLabels); } if (dataLabelsObj.totalDataLabels) { elDataLabelsWrap.add(dataLabelsObj.totalDataLabels); } elSeries.add(elDataLabelsWrap); if (elGoalsMarkers) { elSeries.add(elGoalsMarkers); } return elSeries; } }, { key: "drawBarPaths", value: function drawBarPaths(_ref2) { var indexes = _ref2.indexes, barHeight = _ref2.barHeight, strokeWidth = _ref2.strokeWidth, zeroW = _ref2.zeroW, x = _ref2.x, y = _ref2.y, yDivision = _ref2.yDivision, elSeries = _ref2.elSeries; var w = this.w; var i = indexes.i; var j = indexes.j; var barYPosition; if (w.globals.isXNumeric) { y = (w.globals.seriesX[i][j] - w.globals.minX) / this.invertedXRatio - barHeight; barYPosition = y + barHeight * this.visibleI; } else { if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) { var nonZeroColumns = 0; var zeroEncounters = 0; w.globals.seriesPercent.forEach(function (_s, _si) { if (_s[j]) { nonZeroColumns++; } if (_si < i && _s[j] === 0) { zeroEncounters++; } }); barHeight = this.seriesLen * barHeight / nonZeroColumns; barYPosition = y + barHeight * this.visibleI; barYPosition -= barHeight * zeroEncounters; } } x = this.barHelpers.getXForValue(this.series[i][j], zeroW); var paths = this.barHelpers.getBarpaths({ barYPosition: barYPosition, barHeight: barHeight, x1: zeroW, x2: x, strokeWidth: strokeWidth, series: this.series, realIndex: indexes.realIndex, i: i, j: j, w: w }); if (!w.globals.isXNumeric) { y = y + yDivision; } this.barHelpers.barBackground({ j: j, i: i, y1: barYPosition - barHeight * this.visibleI, y2: barHeight * this.seriesLen, elSeries: elSeries }); return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, x: x, y: y, goalX: this.barHelpers.getGoalValues('x', zeroW, null, i, j), barYPosition: barYPosition }; } }, { key: "drawColumnPaths", value: function drawColumnPaths(_ref3) { var indexes = _ref3.indexes, x = _ref3.x, y = _ref3.y, xDivision = _ref3.xDivision, barWidth = _ref3.barWidth, zeroH = _ref3.zeroH, strokeWidth = _ref3.strokeWidth, elSeries = _ref3.elSeries; var w = this.w; var realIndex = indexes.realIndex; var i = indexes.i; var j = indexes.j; var bc = indexes.bc; var barXPosition; if (w.globals.isXNumeric) { var sxI = realIndex; if (!w.globals.seriesX[realIndex].length) { sxI = w.globals.maxValsInArrayIndex; } if (w.globals.seriesX[sxI][j]) { x = (w.globals.seriesX[sxI][j] - w.globals.minX) / this.xRatio - barWidth * this.seriesLen / 2; } // re-calc barXPosition as x changed barXPosition = x + barWidth * this.visibleI; } else { if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) { var nonZeroColumns = 0; var zeroEncounters = 0; w.globals.seriesPercent.forEach(function (_s, _si) { if (_s[j]) { nonZeroColumns++; } if (_si < i && _s[j] === 0) { zeroEncounters++; } }); barWidth = this.seriesLen * barWidth / nonZeroColumns; barXPosition = x + barWidth * this.visibleI; barXPosition -= barWidth * zeroEncounters; } } y = this.barHelpers.getYForValue(this.series[i][j], zeroH); var paths = this.barHelpers.getColumnPaths({ barXPosition: barXPosition, barWidth: barWidth, y1: zeroH, y2: y, strokeWidth: strokeWidth, series: this.series, realIndex: indexes.realIndex, i: i, j: j, w: w }); if (!w.globals.isXNumeric) { x = x + xDivision; } this.barHelpers.barBackground({ bc: bc, j: j, i: i, x1: barXPosition - strokeWidth / 2 - barWidth * this.visibleI, x2: barWidth * this.seriesLen + strokeWidth / 2, elSeries: elSeries }); return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, x: x, y: y, goalY: this.barHelpers.getGoalValues('y', null, zeroH, i, j), barXPosition: barXPosition }; } /** getPreviousPath is a common function for bars/columns which is used to get previous paths when data changes. * @memberof Bar * @param {int} realIndex - current iterating i * @param {int} j - current iterating series's j index * @return {string} pathFrom is the string which will be appended in animations **/ }, { key: "getPreviousPath", value: function getPreviousPath(realIndex, j) { var w = this.w; var pathFrom; for (var pp = 0; pp < w.globals.previousPaths.length; pp++) { var gpp = w.globals.previousPaths[pp]; if (gpp.paths && gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(realIndex, 10)) { if (typeof w.globals.previousPaths[pp].paths[j] !== 'undefined') { pathFrom = w.globals.previousPaths[pp].paths[j].d; } } } return pathFrom; } }]); return Bar; }(); /** * ApexCharts BarStacked Class responsible for drawing both Stacked Columns and Bars. * * @module BarStacked * The whole calculation for stacked bar/column is different from normal bar/column, * hence it makes sense to derive a new class for it extending most of the props of Parent Bar **/ var BarStacked = /*#__PURE__*/function (_Bar) { _inherits(BarStacked, _Bar); var _super = _createSuper(BarStacked); function BarStacked() { _classCallCheck(this, BarStacked); return _super.apply(this, arguments); } _createClass(BarStacked, [{ key: "draw", value: function draw(series, seriesIndex) { var _this = this; var w = this.w; this.graphics = new Graphics(this.ctx); this.bar = new Bar(this.ctx, this.xyRatios); var coreUtils = new CoreUtils(this.ctx, w); series = coreUtils.getLogSeries(series); this.yRatio = coreUtils.getLogYRatios(this.yRatio); this.barHelpers.initVariables(series); if (w.config.chart.stackType === '100%') { series = w.globals.seriesPercent.slice(); } this.series = series; this.totalItems = 0; this.prevY = []; // y position on chart this.prevX = []; // x position on chart this.prevYF = []; // y position including shapes on chart this.prevXF = []; // x position including shapes on chart this.prevYVal = []; // y values (series[i][j]) in columns this.prevXVal = []; // x values (series[i][j]) in bars this.xArrj = []; // xj indicates x position on graph in bars this.xArrjF = []; // xjF indicates bar's x position + roundedShape's positions in bars this.xArrjVal = []; // x val means the actual series's y values in horizontal/bars this.yArrj = []; // yj indicates y position on graph in columns this.yArrjF = []; // yjF indicates bar's y position + roundedShape's positions in columns this.yArrjVal = []; // y val means the actual series's y values in columns for (var sl = 0; sl < series.length; sl++) { if (series[sl].length > 0) { this.totalItems += series[sl].length; } } var ret = this.graphics.group({ class: 'apexcharts-bar-series apexcharts-plot-series' }); var x = 0; var y = 0; var _loop = function _loop(i, bc) { var xDivision = void 0; // xDivision is the GRIDWIDTH divided by number of datapoints (columns) var yDivision = void 0; // yDivision is the GRIDHEIGHT divided by number of datapoints (bars) var zeroH = void 0; // zeroH is the baseline where 0 meets y axis var zeroW = void 0; // zeroW is the baseline where 0 meets x axis var xArrValues = []; var yArrValues = []; var realIndex = w.globals.comboCharts ? seriesIndex[i] : i; if (_this.yRatio.length > 1) { _this.yaxisIndex = realIndex; } _this.isReversed = w.config.yaxis[_this.yaxisIndex] && w.config.yaxis[_this.yaxisIndex].reversed; // el to which series will be drawn var elSeries = _this.graphics.group({ class: "apexcharts-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[realIndex]), rel: i + 1, 'data:realIndex': realIndex }); _this.ctx.series.addCollapsedClassToSeries(elSeries, realIndex); // eldatalabels var elDataLabelsWrap = _this.graphics.group({ class: 'apexcharts-datalabels', 'data:realIndex': realIndex }); var elGoalsMarkers = _this.graphics.group({ class: 'apexcharts-bar-goals-markers', style: "pointer-events: none" }); var barHeight = 0; var barWidth = 0; var initPositions = _this.initialPositions(x, y, xDivision, yDivision, zeroH, zeroW); y = initPositions.y; barHeight = initPositions.barHeight; yDivision = initPositions.yDivision; zeroW = initPositions.zeroW; x = initPositions.x; barWidth = initPositions.barWidth; xDivision = initPositions.xDivision; zeroH = initPositions.zeroH; _this.yArrj = []; _this.yArrjF = []; _this.yArrjVal = []; _this.xArrj = []; _this.xArrjF = []; _this.xArrjVal = []; // if (!this.horizontal) { // this.xArrj.push(x + barWidth / 2) // } // fix issue #1215; // where all stack bar disappear after collapsing the first series // sol: if only 1 arr in this.prevY(this.prevY.length === 1) and all are NaN if (_this.prevY.length === 1 && _this.prevY[0].every(function (val) { return isNaN(val); })) { // make this.prevY[0] all zeroH _this.prevY[0] = _this.prevY[0].map(function (val) { return zeroH; }); // make this.prevYF[0] all 0 _this.prevYF[0] = _this.prevYF[0].map(function (val) { return 0; }); } for (var j = 0; j < w.globals.dataPoints; j++) { var strokeWidth = _this.barHelpers.getStrokeWidth(i, j, realIndex); var commonPathOpts = { indexes: { i: i, j: j, realIndex: realIndex, bc: bc }, strokeWidth: strokeWidth, x: x, y: y, elSeries: elSeries }; var paths = null; if (_this.isHorizontal) { paths = _this.drawStackedBarPaths(_objectSpread2(_objectSpread2({}, commonPathOpts), {}, { zeroW: zeroW, barHeight: barHeight, yDivision: yDivision })); barWidth = _this.series[i][j] / _this.invertedYRatio; } else { paths = _this.drawStackedColumnPaths(_objectSpread2(_objectSpread2({}, commonPathOpts), {}, { xDivision: xDivision, barWidth: barWidth, zeroH: zeroH })); barHeight = _this.series[i][j] / _this.yRatio[_this.yaxisIndex]; } var barGoalLine = _this.barHelpers.drawGoalLine({ barXPosition: paths.barXPosition, barYPosition: paths.barYPosition, goalX: paths.goalX, goalY: paths.goalY, barHeight: barHeight, barWidth: barWidth }); if (barGoalLine) { elGoalsMarkers.add(barGoalLine); } y = paths.y; x = paths.x; xArrValues.push(x); yArrValues.push(y); var pathFill = _this.barHelpers.getPathFillColor(series, i, j, realIndex); elSeries = _this.renderSeries({ realIndex: realIndex, pathFill: pathFill, j: j, i: i, pathFrom: paths.pathFrom, pathTo: paths.pathTo, strokeWidth: strokeWidth, elSeries: elSeries, x: x, y: y, series: series, barHeight: barHeight, barWidth: barWidth, elDataLabelsWrap: elDataLabelsWrap, elGoalsMarkers: elGoalsMarkers, type: 'bar', visibleSeries: 0 }); } // push all x val arrays into main xArr w.globals.seriesXvalues[realIndex] = xArrValues; w.globals.seriesYvalues[realIndex] = yArrValues; // push all current y values array to main PrevY Array _this.prevY.push(_this.yArrj); _this.prevYF.push(_this.yArrjF); _this.prevYVal.push(_this.yArrjVal); _this.prevX.push(_this.xArrj); _this.prevXF.push(_this.xArrjF); _this.prevXVal.push(_this.xArrjVal); ret.add(elSeries); }; for (var i = 0, bc = 0; i < series.length; i++, bc++) { _loop(i, bc); } return ret; } }, { key: "initialPositions", value: function initialPositions(x, y, xDivision, yDivision, zeroH, zeroW) { var w = this.w; var barHeight, barWidth; if (this.isHorizontal) { // height divided into equal parts yDivision = w.globals.gridHeight / w.globals.dataPoints; barHeight = yDivision; barHeight = barHeight * parseInt(w.config.plotOptions.bar.barHeight, 10) / 100; zeroW = this.baseLineInvertedY + w.globals.padHorizontal + (this.isReversed ? w.globals.gridWidth : 0) - (this.isReversed ? this.baseLineInvertedY * 2 : 0); // initial y position is half of barHeight * half of number of Bars y = (yDivision - barHeight) / 2; } else { // width divided into equal parts xDivision = w.globals.gridWidth / w.globals.dataPoints; barWidth = xDivision; if (w.globals.isXNumeric && w.globals.dataPoints > 1) { // the check (w.globals.dataPoints > 1) fixes apexcharts.js #1617 xDivision = w.globals.minXDiff / this.xRatio; barWidth = xDivision * parseInt(this.barOptions.columnWidth, 10) / 100; } else { barWidth = barWidth * parseInt(w.config.plotOptions.bar.columnWidth, 10) / 100; } zeroH = w.globals.gridHeight - this.baseLineY[this.yaxisIndex] - (this.isReversed ? w.globals.gridHeight : 0) + (this.isReversed ? this.baseLineY[this.yaxisIndex] * 2 : 0); // initial x position is one third of barWidth x = w.globals.padHorizontal + (xDivision - barWidth) / 2; } return { x: x, y: y, yDivision: yDivision, xDivision: xDivision, barHeight: barHeight, barWidth: barWidth, zeroH: zeroH, zeroW: zeroW }; } }, { key: "drawStackedBarPaths", value: function drawStackedBarPaths(_ref) { var indexes = _ref.indexes, barHeight = _ref.barHeight, strokeWidth = _ref.strokeWidth, zeroW = _ref.zeroW, x = _ref.x, y = _ref.y, yDivision = _ref.yDivision, elSeries = _ref.elSeries; var w = this.w; var barYPosition = y; var barXPosition; var i = indexes.i; var j = indexes.j; var prevBarW = 0; for (var k = 0; k < this.prevXF.length; k++) { prevBarW = prevBarW + this.prevXF[k][j]; } if (i > 0) { var bXP = zeroW; if (this.prevXVal[i - 1][j] < 0) { bXP = this.series[i][j] >= 0 ? this.prevX[i - 1][j] + prevBarW - (this.isReversed ? prevBarW : 0) * 2 : this.prevX[i - 1][j]; } else if (this.prevXVal[i - 1][j] >= 0) { bXP = this.series[i][j] >= 0 ? this.prevX[i - 1][j] : this.prevX[i - 1][j] - prevBarW + (this.isReversed ? prevBarW : 0) * 2; } barXPosition = bXP; } else { // the first series will not have prevX values barXPosition = zeroW; } if (this.series[i][j] === null) { x = barXPosition; } else { x = barXPosition + this.series[i][j] / this.invertedYRatio - (this.isReversed ? this.series[i][j] / this.invertedYRatio : 0) * 2; } var paths = this.barHelpers.getBarpaths({ barYPosition: barYPosition, barHeight: barHeight, x1: barXPosition, x2: x, strokeWidth: strokeWidth, series: this.series, realIndex: indexes.realIndex, i: i, j: j, w: w }); this.barHelpers.barBackground({ j: j, i: i, y1: barYPosition, y2: barHeight, elSeries: elSeries }); y = y + yDivision; return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, goalX: this.barHelpers.getGoalValues('x', zeroW, null, i, j), barYPosition: barYPosition, x: x, y: y }; } }, { key: "drawStackedColumnPaths", value: function drawStackedColumnPaths(_ref2) { var indexes = _ref2.indexes, x = _ref2.x, y = _ref2.y, xDivision = _ref2.xDivision, barWidth = _ref2.barWidth, zeroH = _ref2.zeroH; _ref2.strokeWidth; var elSeries = _ref2.elSeries; var w = this.w; var i = indexes.i; var j = indexes.j; var bc = indexes.bc; if (w.globals.isXNumeric) { var seriesVal = w.globals.seriesX[i][j]; if (!seriesVal) seriesVal = 0; x = (seriesVal - w.globals.minX) / this.xRatio - barWidth / 2; } var barXPosition = x; var barYPosition; var prevBarH = 0; for (var k = 0; k < this.prevYF.length; k++) { // fix issue #1215 // in case where this.prevYF[k][j] is NaN, use 0 instead prevBarH = prevBarH + (!isNaN(this.prevYF[k][j]) ? this.prevYF[k][j] : 0); } if (i > 0 && !w.globals.isXNumeric || i > 0 && w.globals.isXNumeric && w.globals.seriesX[i - 1][j] === w.globals.seriesX[i][j]) { var bYP; var prevYValue; var p = Math.min(this.yRatio.length + 1, i + 1); if (this.prevY[i - 1] !== undefined) { for (var ii = 1; ii < p; ii++) { if (!isNaN(this.prevY[i - ii][j])) { // find the previous available value to give prevYValue prevYValue = this.prevY[i - ii][j]; // if found it, break the loop break; } } } for (var _ii = 1; _ii < p; _ii++) { // find the previous available value(non-NaN) to give bYP if (this.prevYVal[i - _ii][j] < 0) { bYP = this.series[i][j] >= 0 ? prevYValue - prevBarH + (this.isReversed ? prevBarH : 0) * 2 : prevYValue; // found it? break the loop break; } else if (this.prevYVal[i - _ii][j] >= 0) { bYP = this.series[i][j] >= 0 ? prevYValue : prevYValue + prevBarH - (this.isReversed ? prevBarH : 0) * 2; // found it? break the loop break; } } if (typeof bYP === 'undefined') bYP = w.globals.gridHeight; // if this.prevYF[0] is all 0 resulted from line #486 // AND every arr starting from the second only contains NaN if (this.prevYF[0].every(function (val) { return val === 0; }) && this.prevYF.slice(1, i).every(function (arr) { return arr.every(function (val) { return isNaN(val); }); })) { barYPosition = zeroH; } else { // Nothing special barYPosition = bYP; } } else { // the first series will not have prevY values, also if the prev index's series X doesn't matches the current index's series X, then start from zero barYPosition = zeroH; } if (this.series[i][j]) { y = barYPosition - this.series[i][j] / this.yRatio[this.yaxisIndex] + (this.isReversed ? this.series[i][j] / this.yRatio[this.yaxisIndex] : 0) * 2; } else { // fixes #3610 y = barYPosition; } var paths = this.barHelpers.getColumnPaths({ barXPosition: barXPosition, barWidth: barWidth, y1: barYPosition, y2: y, yRatio: this.yRatio[this.yaxisIndex], strokeWidth: this.strokeWidth, series: this.series, realIndex: indexes.realIndex, i: i, j: j, w: w }); this.barHelpers.barBackground({ bc: bc, j: j, i: i, x1: barXPosition, x2: barWidth, elSeries: elSeries }); x = x + xDivision; return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, goalY: this.barHelpers.getGoalValues('y', null, zeroH, i, j), barXPosition: barXPosition, x: w.globals.isXNumeric ? x - xDivision : x, y: y }; } }]); return BarStacked; }(Bar); /** * ApexCharts BoxCandleStick Class responsible for drawing both Stacked Columns and Bars. * * @module BoxCandleStick **/ var BoxCandleStick = /*#__PURE__*/function (_Bar) { _inherits(BoxCandleStick, _Bar); var _super = _createSuper(BoxCandleStick); function BoxCandleStick() { _classCallCheck(this, BoxCandleStick); return _super.apply(this, arguments); } _createClass(BoxCandleStick, [{ key: "draw", value: function draw(series, seriesIndex) { var _this = this; var w = this.w; var graphics = new Graphics(this.ctx); var fill = new Fill(this.ctx); this.candlestickOptions = this.w.config.plotOptions.candlestick; this.boxOptions = this.w.config.plotOptions.boxPlot; this.isHorizontal = w.config.plotOptions.bar.horizontal; var coreUtils = new CoreUtils(this.ctx, w); series = coreUtils.getLogSeries(series); this.series = series; this.yRatio = coreUtils.getLogYRatios(this.yRatio); this.barHelpers.initVariables(series); var ret = graphics.group({ class: "apexcharts-".concat(w.config.chart.type, "-series apexcharts-plot-series") }); var _loop = function _loop(i) { _this.isBoxPlot = w.config.chart.type === 'boxPlot' || w.config.series[i].type === 'boxPlot'; var x = void 0, y = void 0, xDivision = void 0, // xDivision is the GRIDWIDTH divided by number of datapoints (columns) yDivision = void 0, // yDivision is the GRIDHEIGHT divided by number of datapoints (bars) zeroH = void 0, // zeroH is the baseline where 0 meets y axis zeroW = void 0; // zeroW is the baseline where 0 meets x axis var yArrj = []; // hold y values of current iterating series var xArrj = []; // hold x values of current iterating series var realIndex = w.globals.comboCharts ? seriesIndex[i] : i; // el to which series will be drawn var elSeries = graphics.group({ class: "apexcharts-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[realIndex]), rel: i + 1, 'data:realIndex': realIndex }); _this.ctx.series.addCollapsedClassToSeries(elSeries, realIndex); if (series[i].length > 0) { _this.visibleI = _this.visibleI + 1; } var barHeight = 0; var barWidth = 0; if (_this.yRatio.length > 1) { _this.yaxisIndex = realIndex; } var initPositions = _this.barHelpers.initialPositions(); y = initPositions.y; barHeight = initPositions.barHeight; yDivision = initPositions.yDivision; zeroW = initPositions.zeroW; x = initPositions.x; barWidth = initPositions.barWidth; xDivision = initPositions.xDivision; zeroH = initPositions.zeroH; xArrj.push(x + barWidth / 2); // eldatalabels var elDataLabelsWrap = graphics.group({ class: 'apexcharts-datalabels', 'data:realIndex': realIndex }); var _loop2 = function _loop2(j) { var strokeWidth = _this.barHelpers.getStrokeWidth(i, j, realIndex); var paths = null; var pathsParams = { indexes: { i: i, j: j, realIndex: realIndex }, x: x, y: y, strokeWidth: strokeWidth, elSeries: elSeries }; if (_this.isHorizontal) { paths = _this.drawHorizontalBoxPaths(_objectSpread2(_objectSpread2({}, pathsParams), {}, { yDivision: yDivision, barHeight: barHeight, zeroW: zeroW })); } else { paths = _this.drawVerticalBoxPaths(_objectSpread2(_objectSpread2({}, pathsParams), {}, { xDivision: xDivision, barWidth: barWidth, zeroH: zeroH })); } y = paths.y; x = paths.x; // push current X if (j > 0) { xArrj.push(x + barWidth / 2); } yArrj.push(y); paths.pathTo.forEach(function (pathTo, pi) { var lineFill = !_this.isBoxPlot && _this.candlestickOptions.wick.useFillColor ? paths.color[pi] : w.globals.stroke.colors[i]; var pathFill = fill.fillPath({ seriesNumber: realIndex, dataPointIndex: j, color: paths.color[pi], value: series[i][j] }); _this.renderSeries({ realIndex: realIndex, pathFill: pathFill, lineFill: lineFill, j: j, i: i, pathFrom: paths.pathFrom, pathTo: pathTo, strokeWidth: strokeWidth, elSeries: elSeries, x: x, y: y, series: series, barHeight: barHeight, barWidth: barWidth, elDataLabelsWrap: elDataLabelsWrap, visibleSeries: _this.visibleI, type: w.config.chart.type }); }); }; for (var j = 0; j < w.globals.dataPoints; j++) { _loop2(j); } // push all x val arrays into main xArr w.globals.seriesXvalues[realIndex] = xArrj; w.globals.seriesYvalues[realIndex] = yArrj; ret.add(elSeries); }; for (var i = 0; i < series.length; i++) { _loop(i); } return ret; } }, { key: "drawVerticalBoxPaths", value: function drawVerticalBoxPaths(_ref) { var indexes = _ref.indexes, x = _ref.x; _ref.y; var xDivision = _ref.xDivision, barWidth = _ref.barWidth, zeroH = _ref.zeroH, strokeWidth = _ref.strokeWidth; var w = this.w; var graphics = new Graphics(this.ctx); var i = indexes.i; var j = indexes.j; var isPositive = true; var colorPos = w.config.plotOptions.candlestick.colors.upward; var colorNeg = w.config.plotOptions.candlestick.colors.downward; var color = ''; if (this.isBoxPlot) { color = [this.boxOptions.colors.lower, this.boxOptions.colors.upper]; } var yRatio = this.yRatio[this.yaxisIndex]; var realIndex = indexes.realIndex; var ohlc = this.getOHLCValue(realIndex, j); var l1 = zeroH; var l2 = zeroH; if (ohlc.o > ohlc.c) { isPositive = false; } var y1 = Math.min(ohlc.o, ohlc.c); var y2 = Math.max(ohlc.o, ohlc.c); var m = ohlc.m; if (w.globals.isXNumeric) { x = (w.globals.seriesX[realIndex][j] - w.globals.minX) / this.xRatio - barWidth / 2; } var barXPosition = x + barWidth * this.visibleI; if (typeof this.series[i][j] === 'undefined' || this.series[i][j] === null) { y1 = zeroH; y2 = zeroH; } else { y1 = zeroH - y1 / yRatio; y2 = zeroH - y2 / yRatio; l1 = zeroH - ohlc.h / yRatio; l2 = zeroH - ohlc.l / yRatio; m = zeroH - ohlc.m / yRatio; } var pathTo = graphics.move(barXPosition, zeroH); var pathFrom = graphics.move(barXPosition + barWidth / 2, y1); if (w.globals.previousPaths.length > 0) { pathFrom = this.getPreviousPath(realIndex, j, true); } if (this.isBoxPlot) { pathTo = [graphics.move(barXPosition, y1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 4, l1) + graphics.line(barXPosition + barWidth - barWidth / 4, l1) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth, y1) + graphics.line(barXPosition + barWidth, m) + graphics.line(barXPosition, m) + graphics.line(barXPosition, y1 + strokeWidth / 2), graphics.move(barXPosition, m) + graphics.line(barXPosition + barWidth, m) + graphics.line(barXPosition + barWidth, y2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth - barWidth / 4, l2) + graphics.line(barXPosition + barWidth / 4, l2) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition, y2) + graphics.line(barXPosition, m) + 'z']; } else { // candlestick pathTo = [graphics.move(barXPosition, y2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth, y2) + graphics.line(barXPosition + barWidth, y1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition, y1) + graphics.line(barXPosition, y2 - strokeWidth / 2)]; } pathFrom = pathFrom + graphics.move(barXPosition, y1); if (!w.globals.isXNumeric) { x = x + xDivision; } return { pathTo: pathTo, pathFrom: pathFrom, x: x, y: y2, barXPosition: barXPosition, color: this.isBoxPlot ? color : isPositive ? [colorPos] : [colorNeg] }; } }, { key: "drawHorizontalBoxPaths", value: function drawHorizontalBoxPaths(_ref2) { var indexes = _ref2.indexes; _ref2.x; var y = _ref2.y, yDivision = _ref2.yDivision, barHeight = _ref2.barHeight, zeroW = _ref2.zeroW, strokeWidth = _ref2.strokeWidth; var w = this.w; var graphics = new Graphics(this.ctx); var i = indexes.i; var j = indexes.j; var color = this.boxOptions.colors.lower; if (this.isBoxPlot) { color = [this.boxOptions.colors.lower, this.boxOptions.colors.upper]; } var yRatio = this.invertedYRatio; var realIndex = indexes.realIndex; var ohlc = this.getOHLCValue(realIndex, j); var l1 = zeroW; var l2 = zeroW; var x1 = Math.min(ohlc.o, ohlc.c); var x2 = Math.max(ohlc.o, ohlc.c); var m = ohlc.m; if (w.globals.isXNumeric) { y = (w.globals.seriesX[realIndex][j] - w.globals.minX) / this.invertedXRatio - barHeight / 2; } var barYPosition = y + barHeight * this.visibleI; if (typeof this.series[i][j] === 'undefined' || this.series[i][j] === null) { x1 = zeroW; x2 = zeroW; } else { x1 = zeroW + x1 / yRatio; x2 = zeroW + x2 / yRatio; l1 = zeroW + ohlc.h / yRatio; l2 = zeroW + ohlc.l / yRatio; m = zeroW + ohlc.m / yRatio; } var pathTo = graphics.move(zeroW, barYPosition); var pathFrom = graphics.move(x1, barYPosition + barHeight / 2); if (w.globals.previousPaths.length > 0) { pathFrom = this.getPreviousPath(realIndex, j, true); } pathTo = [graphics.move(x1, barYPosition) + graphics.line(x1, barYPosition + barHeight / 2) + graphics.line(l1, barYPosition + barHeight / 2) + graphics.line(l1, barYPosition + barHeight / 2 - barHeight / 4) + graphics.line(l1, barYPosition + barHeight / 2 + barHeight / 4) + graphics.line(l1, barYPosition + barHeight / 2) + graphics.line(x1, barYPosition + barHeight / 2) + graphics.line(x1, barYPosition + barHeight) + graphics.line(m, barYPosition + barHeight) + graphics.line(m, barYPosition) + graphics.line(x1 + strokeWidth / 2, barYPosition), graphics.move(m, barYPosition) + graphics.line(m, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight - barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition) + graphics.line(m, barYPosition) + 'z']; pathFrom = pathFrom + graphics.move(x1, barYPosition); if (!w.globals.isXNumeric) { y = y + yDivision; } return { pathTo: pathTo, pathFrom: pathFrom, x: x2, y: y, barYPosition: barYPosition, color: color }; } }, { key: "getOHLCValue", value: function getOHLCValue(i, j) { var w = this.w; return { o: this.isBoxPlot ? w.globals.seriesCandleH[i][j] : w.globals.seriesCandleO[i][j], h: this.isBoxPlot ? w.globals.seriesCandleO[i][j] : w.globals.seriesCandleH[i][j], m: w.globals.seriesCandleM[i][j], l: this.isBoxPlot ? w.globals.seriesCandleC[i][j] : w.globals.seriesCandleL[i][j], c: this.isBoxPlot ? w.globals.seriesCandleL[i][j] : w.globals.seriesCandleC[i][j] }; } }]); return BoxCandleStick; }(Bar); var TreemapHelpers = /*#__PURE__*/function () { function TreemapHelpers(ctx) { _classCallCheck(this, TreemapHelpers); this.ctx = ctx; this.w = ctx.w; } _createClass(TreemapHelpers, [{ key: "checkColorRange", value: function checkColorRange() { var w = this.w; var negRange = false; var chartOpts = w.config.plotOptions[w.config.chart.type]; if (chartOpts.colorScale.ranges.length > 0) { chartOpts.colorScale.ranges.map(function (range, index) { if (range.from <= 0) { negRange = true; } }); } return negRange; } }, { key: "getShadeColor", value: function getShadeColor(chartType, i, j, negRange) { var w = this.w; var colorShadePercent = 1; var shadeIntensity = w.config.plotOptions[chartType].shadeIntensity; var colorProps = this.determineColor(chartType, i, j); if (w.globals.hasNegs || negRange) { if (w.config.plotOptions[chartType].reverseNegativeShade) { if (colorProps.percent < 0) { colorShadePercent = colorProps.percent / 100 * (shadeIntensity * 1.25); } else { colorShadePercent = (1 - colorProps.percent / 100) * (shadeIntensity * 1.25); } } else { if (colorProps.percent <= 0) { colorShadePercent = 1 - (1 + colorProps.percent / 100) * shadeIntensity; } else { colorShadePercent = (1 - colorProps.percent / 100) * shadeIntensity; } } } else { colorShadePercent = 1 - colorProps.percent / 100; if (chartType === 'treemap') { colorShadePercent = (1 - colorProps.percent / 100) * (shadeIntensity * 1.25); } } var color = colorProps.color; var utils = new Utils$1(); if (w.config.plotOptions[chartType].enableShades) { if (this.w.config.theme.mode === 'dark') { color = Utils$1.hexToRgba(utils.shadeColor(colorShadePercent * -1, colorProps.color), w.config.fill.opacity); } else { color = Utils$1.hexToRgba(utils.shadeColor(colorShadePercent, colorProps.color), w.config.fill.opacity); } } return { color: color, colorProps: colorProps }; } }, { key: "determineColor", value: function determineColor(chartType, i, j) { var w = this.w; var val = w.globals.series[i][j]; var chartOpts = w.config.plotOptions[chartType]; var seriesNumber = chartOpts.colorScale.inverse ? j : i; if (chartOpts.distributed && w.config.chart.type === 'treemap') { seriesNumber = j; } var color = w.globals.colors[seriesNumber]; var foreColor = null; var min = Math.min.apply(Math, _toConsumableArray(w.globals.series[i])); var max = Math.max.apply(Math, _toConsumableArray(w.globals.series[i])); if (!chartOpts.distributed && chartType === 'heatmap') { min = w.globals.minY; max = w.globals.maxY; } if (typeof chartOpts.colorScale.min !== 'undefined') { min = chartOpts.colorScale.min < w.globals.minY ? chartOpts.colorScale.min : w.globals.minY; max = chartOpts.colorScale.max > w.globals.maxY ? chartOpts.colorScale.max : w.globals.maxY; } var total = Math.abs(max) + Math.abs(min); var percent = 100 * val / (total === 0 ? total - 0.000001 : total); if (chartOpts.colorScale.ranges.length > 0) { var colorRange = chartOpts.colorScale.ranges; colorRange.map(function (range, index) { if (val >= range.from && val <= range.to) { color = range.color; foreColor = range.foreColor ? range.foreColor : null; min = range.from; max = range.to; var rTotal = Math.abs(max) + Math.abs(min); percent = 100 * val / (rTotal === 0 ? rTotal - 0.000001 : rTotal); } }); } return { color: color, foreColor: foreColor, percent: percent }; } }, { key: "calculateDataLabels", value: function calculateDataLabels(_ref) { var text = _ref.text, x = _ref.x, y = _ref.y, i = _ref.i, j = _ref.j, colorProps = _ref.colorProps, fontSize = _ref.fontSize; var w = this.w; var dataLabelsConfig = w.config.dataLabels; var graphics = new Graphics(this.ctx); var dataLabels = new DataLabels(this.ctx); var elDataLabelsWrap = null; if (dataLabelsConfig.enabled) { elDataLabelsWrap = graphics.group({ class: 'apexcharts-data-labels' }); var offX = dataLabelsConfig.offsetX; var offY = dataLabelsConfig.offsetY; var dataLabelsX = x + offX; var dataLabelsY = y + parseFloat(dataLabelsConfig.style.fontSize) / 3 + offY; dataLabels.plotDataLabelsText({ x: dataLabelsX, y: dataLabelsY, text: text, i: i, j: j, color: colorProps.foreColor, parent: elDataLabelsWrap, fontSize: fontSize, dataLabelsConfig: dataLabelsConfig }); } return elDataLabelsWrap; } }, { key: "addListeners", value: function addListeners(elRect) { var graphics = new Graphics(this.ctx); elRect.node.addEventListener('mouseenter', graphics.pathMouseEnter.bind(this, elRect)); elRect.node.addEventListener('mouseleave', graphics.pathMouseLeave.bind(this, elRect)); elRect.node.addEventListener('mousedown', graphics.pathMouseDown.bind(this, elRect)); } }]); return TreemapHelpers; }(); /** * ApexCharts HeatMap Class. * @module HeatMap **/ var HeatMap = /*#__PURE__*/function () { function HeatMap(ctx, xyRatios) { _classCallCheck(this, HeatMap); this.ctx = ctx; this.w = ctx.w; this.xRatio = xyRatios.xRatio; this.yRatio = xyRatios.yRatio; this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation; this.helpers = new TreemapHelpers(ctx); this.rectRadius = this.w.config.plotOptions.heatmap.radius; this.strokeWidth = this.w.config.stroke.show ? this.w.config.stroke.width : 0; } _createClass(HeatMap, [{ key: "draw", value: function draw(series) { var w = this.w; var graphics = new Graphics(this.ctx); var ret = graphics.group({ class: 'apexcharts-heatmap' }); ret.attr('clip-path', "url(#gridRectMask".concat(w.globals.cuid, ")")); // width divided into equal parts var xDivision = w.globals.gridWidth / w.globals.dataPoints; var yDivision = w.globals.gridHeight / w.globals.series.length; var y1 = 0; var rev = false; this.negRange = this.helpers.checkColorRange(); var heatSeries = series.slice(); if (w.config.yaxis[0].reversed) { rev = true; heatSeries.reverse(); } for (var i = rev ? 0 : heatSeries.length - 1; rev ? i < heatSeries.length : i >= 0; rev ? i++ : i--) { // el to which series will be drawn var elSeries = graphics.group({ class: "apexcharts-series apexcharts-heatmap-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[i]), rel: i + 1, 'data:realIndex': i }); this.ctx.series.addCollapsedClassToSeries(elSeries, i); if (w.config.chart.dropShadow.enabled) { var shadow = w.config.chart.dropShadow; var filters = new Filters(this.ctx); filters.dropShadow(elSeries, shadow, i); } var x1 = 0; var shadeIntensity = w.config.plotOptions.heatmap.shadeIntensity; for (var j = 0; j < heatSeries[i].length; j++) { var heatColor = this.helpers.getShadeColor(w.config.chart.type, i, j, this.negRange); var color = heatColor.color; var heatColorProps = heatColor.colorProps; if (w.config.fill.type === 'image') { var fill = new Fill(this.ctx); color = fill.fillPath({ seriesNumber: i, dataPointIndex: j, opacity: w.globals.hasNegs ? heatColorProps.percent < 0 ? 1 - (1 + heatColorProps.percent / 100) : shadeIntensity + heatColorProps.percent / 100 : heatColorProps.percent / 100, patternID: Utils$1.randomId(), width: w.config.fill.image.width ? w.config.fill.image.width : xDivision, height: w.config.fill.image.height ? w.config.fill.image.height : yDivision }); } var radius = this.rectRadius; var rect = graphics.drawRect(x1, y1, xDivision, yDivision, radius); rect.attr({ cx: x1, cy: y1 }); rect.node.classList.add('apexcharts-heatmap-rect'); elSeries.add(rect); rect.attr({ fill: color, i: i, index: i, j: j, val: heatSeries[i][j], 'stroke-width': this.strokeWidth, stroke: w.config.plotOptions.heatmap.useFillColorAsStroke ? color : w.globals.stroke.colors[0], color: color }); this.helpers.addListeners(rect); if (w.config.chart.animations.enabled && !w.globals.dataChanged) { var speed = 1; if (!w.globals.resized) { speed = w.config.chart.animations.speed; } this.animateHeatMap(rect, x1, y1, xDivision, yDivision, speed); } if (w.globals.dataChanged) { var _speed = 1; if (this.dynamicAnim.enabled && w.globals.shouldAnimate) { _speed = this.dynamicAnim.speed; var colorFrom = w.globals.previousPaths[i] && w.globals.previousPaths[i][j] && w.globals.previousPaths[i][j].color; if (!colorFrom) colorFrom = 'rgba(255, 255, 255, 0)'; this.animateHeatColor(rect, Utils$1.isColorHex(colorFrom) ? colorFrom : Utils$1.rgb2hex(colorFrom), Utils$1.isColorHex(color) ? color : Utils$1.rgb2hex(color), _speed); } } var formatter = w.config.dataLabels.formatter; var formattedText = formatter(w.globals.series[i][j], { value: w.globals.series[i][j], seriesIndex: i, dataPointIndex: j, w: w }); var dataLabels = this.helpers.calculateDataLabels({ text: formattedText, x: x1 + xDivision / 2, y: y1 + yDivision / 2, i: i, j: j, colorProps: heatColorProps, series: heatSeries }); if (dataLabels !== null) { elSeries.add(dataLabels); } x1 = x1 + xDivision; } y1 = y1 + yDivision; ret.add(elSeries); } // adjust yaxis labels for heatmap var yAxisScale = w.globals.yAxisScale[0].result.slice(); if (w.config.yaxis[0].reversed) { yAxisScale.unshift(''); } else { yAxisScale.push(''); } w.globals.yAxisScale[0].result = yAxisScale; var divisor = w.globals.gridHeight / w.globals.series.length; w.config.yaxis[0].labels.offsetY = -(divisor / 2); return ret; } }, { key: "animateHeatMap", value: function animateHeatMap(el, x, y, width, height, speed) { var animations = new Animations(this.ctx); animations.animateRect(el, { x: x + width / 2, y: y + height / 2, width: 0, height: 0 }, { x: x, y: y, width: width, height: height }, speed, function () { animations.animationCompleted(el); }); } }, { key: "animateHeatColor", value: function animateHeatColor(el, colorFrom, colorTo, speed) { el.attr({ fill: colorFrom }).animate(speed).attr({ fill: colorTo }); } }]); return HeatMap; }(); var CircularChartsHelpers = /*#__PURE__*/function () { function CircularChartsHelpers(ctx) { _classCallCheck(this, CircularChartsHelpers); this.ctx = ctx; this.w = ctx.w; } _createClass(CircularChartsHelpers, [{ key: "drawYAxisTexts", value: function drawYAxisTexts(x, y, i, text) { var w = this.w; var yaxisConfig = w.config.yaxis[0]; var formatter = w.globals.yLabelFormatters[0]; var graphics = new Graphics(this.ctx); var yaxisLabel = graphics.drawText({ x: x + yaxisConfig.labels.offsetX, y: y + yaxisConfig.labels.offsetY, text: formatter(text, i), textAnchor: 'middle', fontSize: yaxisConfig.labels.style.fontSize, fontFamily: yaxisConfig.labels.style.fontFamily, foreColor: Array.isArray(yaxisConfig.labels.style.colors) ? yaxisConfig.labels.style.colors[i] : yaxisConfig.labels.style.colors }); return yaxisLabel; } }]); return CircularChartsHelpers; }(); /** * ApexCharts Pie Class for drawing Pie / Donut Charts. * @module Pie **/ var Pie = /*#__PURE__*/function () { function Pie(ctx) { _classCallCheck(this, Pie); this.ctx = ctx; this.w = ctx.w; var w = this.w; this.chartType = this.w.config.chart.type; this.initialAnim = this.w.config.chart.animations.enabled; this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled; this.animBeginArr = [0]; this.animDur = 0; this.donutDataLabels = this.w.config.plotOptions.pie.donut.labels; this.lineColorArr = w.globals.stroke.colors !== undefined ? w.globals.stroke.colors : w.globals.colors; this.defaultSize = Math.min(w.globals.gridWidth, w.globals.gridHeight); this.centerY = this.defaultSize / 2; this.centerX = w.globals.gridWidth / 2; if (w.config.chart.type === 'radialBar') { this.fullAngle = 360; } else { this.fullAngle = Math.abs(w.config.plotOptions.pie.endAngle - w.config.plotOptions.pie.startAngle); } this.initialAngle = w.config.plotOptions.pie.startAngle % this.fullAngle; w.globals.radialSize = this.defaultSize / 2.05 - w.config.stroke.width - (!w.config.chart.sparkline.enabled ? w.config.chart.dropShadow.blur : 0); this.donutSize = w.globals.radialSize * parseInt(w.config.plotOptions.pie.donut.size, 10) / 100; this.maxY = 0; this.sliceLabels = []; this.sliceSizes = []; this.prevSectorAngleArr = []; // for dynamic animations } _createClass(Pie, [{ key: "draw", value: function draw(series) { var _this = this; var self = this; var w = this.w; var graphics = new Graphics(this.ctx); this.ret = graphics.group({ class: 'apexcharts-pie' }); if (w.globals.noData) return this.ret; var total = 0; for (var k = 0; k < series.length; k++) { // CALCULATE THE TOTAL total += Utils$1.negToZero(series[k]); } var sectorAngleArr = []; // el to which series will be drawn var elSeries = graphics.group(); // prevent division by zero error if there is no data if (total === 0) { total = 0.00001; } series.forEach(function (m) { _this.maxY = Math.max(_this.maxY, m); }); // override maxY if user provided in config if (w.config.yaxis[0].max) { this.maxY = w.config.yaxis[0].max; } if (w.config.grid.position === 'back' && this.chartType === 'polarArea') { this.drawPolarElements(this.ret); } for (var i = 0; i < series.length; i++) { // CALCULATE THE ANGLES var angle = this.fullAngle * Utils$1.negToZero(series[i]) / total; sectorAngleArr.push(angle); if (this.chartType === 'polarArea') { sectorAngleArr[i] = this.fullAngle / series.length; this.sliceSizes.push(w.globals.radialSize * series[i] / this.maxY); } else { this.sliceSizes.push(w.globals.radialSize); } } if (w.globals.dataChanged) { var prevTotal = 0; for (var _k = 0; _k < w.globals.previousPaths.length; _k++) { // CALCULATE THE PREV TOTAL prevTotal += Utils$1.negToZero(w.globals.previousPaths[_k]); } var previousAngle; for (var _i = 0; _i < w.globals.previousPaths.length; _i++) { // CALCULATE THE PREVIOUS ANGLES previousAngle = this.fullAngle * Utils$1.negToZero(w.globals.previousPaths[_i]) / prevTotal; this.prevSectorAngleArr.push(previousAngle); } } // on small chart size after few count of resizes browser window donutSize can be negative if (this.donutSize < 0) { this.donutSize = 0; } var scaleSize = w.config.plotOptions.pie.customScale; var halfW = w.globals.gridWidth / 2; var halfH = w.globals.gridHeight / 2; var translateX = halfW - w.globals.gridWidth / 2 * scaleSize; var translateY = halfH - w.globals.gridHeight / 2 * scaleSize; if (this.chartType === 'donut') { // draw the inner circle and add some text to it var circle = graphics.drawCircle(this.donutSize); circle.attr({ cx: this.centerX, cy: this.centerY, fill: w.config.plotOptions.pie.donut.background ? w.config.plotOptions.pie.donut.background : 'transparent' }); elSeries.add(circle); } var elG = self.drawArcs(sectorAngleArr, series); // add slice dataLabels at the end this.sliceLabels.forEach(function (s) { elG.add(s); }); elSeries.attr({ transform: "translate(".concat(translateX, ", ").concat(translateY, ") scale(").concat(scaleSize, ")") }); elSeries.add(elG); this.ret.add(elSeries); if (this.donutDataLabels.show) { var dataLabels = this.renderInnerDataLabels(this.donutDataLabels, { hollowSize: this.donutSize, centerX: this.centerX, centerY: this.centerY, opacity: this.donutDataLabels.show, translateX: translateX, translateY: translateY }); this.ret.add(dataLabels); } if (w.config.grid.position === 'front' && this.chartType === 'polarArea') { this.drawPolarElements(this.ret); } return this.ret; } // core function for drawing pie arcs }, { key: "drawArcs", value: function drawArcs(sectorAngleArr, series) { var w = this.w; var filters = new Filters(this.ctx); var graphics = new Graphics(this.ctx); var fill = new Fill(this.ctx); var g = graphics.group({ class: 'apexcharts-slices' }); var startAngle = this.initialAngle; var prevStartAngle = this.initialAngle; var endAngle = this.initialAngle; var prevEndAngle = this.initialAngle; this.strokeWidth = w.config.stroke.show ? w.config.stroke.width : 0; for (var i = 0; i < sectorAngleArr.length; i++) { var elPieArc = graphics.group({ class: "apexcharts-series apexcharts-pie-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[i]), rel: i + 1, 'data:realIndex': i }); g.add(elPieArc); startAngle = endAngle; prevStartAngle = prevEndAngle; endAngle = startAngle + sectorAngleArr[i]; prevEndAngle = prevStartAngle + this.prevSectorAngleArr[i]; var angle = endAngle < startAngle ? this.fullAngle + endAngle - startAngle : endAngle - startAngle; var pathFill = fill.fillPath({ seriesNumber: i, size: this.sliceSizes[i], value: series[i] }); // additionally, pass size for gradient drawing in the fillPath function var path = this.getChangedPath(prevStartAngle, prevEndAngle); var elPath = graphics.drawPath({ d: path, stroke: Array.isArray(this.lineColorArr) ? this.lineColorArr[i] : this.lineColorArr, strokeWidth: 0, fill: pathFill, fillOpacity: w.config.fill.opacity, classes: "apexcharts-pie-area apexcharts-".concat(this.chartType.toLowerCase(), "-slice-").concat(i) }); elPath.attr({ index: 0, j: i }); filters.setSelectionFilter(elPath, 0, i); if (w.config.chart.dropShadow.enabled) { var shadow = w.config.chart.dropShadow; filters.dropShadow(elPath, shadow, i); } this.addListeners(elPath, this.donutDataLabels); Graphics.setAttrs(elPath.node, { 'data:angle': angle, 'data:startAngle': startAngle, 'data:strokeWidth': this.strokeWidth, 'data:value': series[i] }); var labelPosition = { x: 0, y: 0 }; if (this.chartType === 'pie' || this.chartType === 'polarArea') { labelPosition = Utils$1.polarToCartesian(this.centerX, this.centerY, w.globals.radialSize / 1.25 + w.config.plotOptions.pie.dataLabels.offset, (startAngle + angle / 2) % this.fullAngle); } else if (this.chartType === 'donut') { labelPosition = Utils$1.polarToCartesian(this.centerX, this.centerY, (w.globals.radialSize + this.donutSize) / 2 + w.config.plotOptions.pie.dataLabels.offset, (startAngle + angle / 2) % this.fullAngle); } elPieArc.add(elPath); // Animation code starts var dur = 0; if (this.initialAnim && !w.globals.resized && !w.globals.dataChanged) { dur = angle / this.fullAngle * w.config.chart.animations.speed; if (dur === 0) dur = 1; this.animDur = dur + this.animDur; this.animBeginArr.push(this.animDur); } else { this.animBeginArr.push(0); } if (this.dynamicAnim && w.globals.dataChanged) { this.animatePaths(elPath, { size: this.sliceSizes[i], endAngle: endAngle, startAngle: startAngle, prevStartAngle: prevStartAngle, prevEndAngle: prevEndAngle, animateStartingPos: true, i: i, animBeginArr: this.animBeginArr, shouldSetPrevPaths: true, dur: w.config.chart.animations.dynamicAnimation.speed }); } else { this.animatePaths(elPath, { size: this.sliceSizes[i], endAngle: endAngle, startAngle: startAngle, i: i, totalItems: sectorAngleArr.length - 1, animBeginArr: this.animBeginArr, dur: dur }); } // animation code ends if (w.config.plotOptions.pie.expandOnClick && this.chartType !== 'polarArea') { elPath.click(this.pieClicked.bind(this, i)); } if (typeof w.globals.selectedDataPoints[0] !== 'undefined' && w.globals.selectedDataPoints[0].indexOf(i) > -1) { this.pieClicked(i); } if (w.config.dataLabels.enabled) { var xPos = labelPosition.x; var yPos = labelPosition.y; var text = 100 * angle / this.fullAngle + '%'; if (angle !== 0 && w.config.plotOptions.pie.dataLabels.minAngleToShowLabel < sectorAngleArr[i]) { var formatter = w.config.dataLabels.formatter; if (formatter !== undefined) { text = formatter(w.globals.seriesPercent[i][0], { seriesIndex: i, w: w }); } var foreColor = w.globals.dataLabels.style.colors[i]; var elPieLabelWrap = graphics.group({ class: "apexcharts-datalabels" }); var elPieLabel = graphics.drawText({ x: xPos, y: yPos, text: text, textAnchor: 'middle', fontSize: w.config.dataLabels.style.fontSize, fontFamily: w.config.dataLabels.style.fontFamily, fontWeight: w.config.dataLabels.style.fontWeight, foreColor: foreColor }); elPieLabelWrap.add(elPieLabel); if (w.config.dataLabels.dropShadow.enabled) { var textShadow = w.config.dataLabels.dropShadow; filters.dropShadow(elPieLabel, textShadow); } elPieLabel.node.classList.add('apexcharts-pie-label'); if (w.config.chart.animations.animate && w.globals.resized === false) { elPieLabel.node.classList.add('apexcharts-pie-label-delay'); elPieLabel.node.style.animationDelay = w.config.chart.animations.speed / 940 + 's'; } this.sliceLabels.push(elPieLabelWrap); } } } return g; } }, { key: "addListeners", value: function addListeners(elPath, dataLabels) { var graphics = new Graphics(this.ctx); // append filters on mouseenter and mouseleave elPath.node.addEventListener('mouseenter', graphics.pathMouseEnter.bind(this, elPath)); elPath.node.addEventListener('mouseleave', graphics.pathMouseLeave.bind(this, elPath)); elPath.node.addEventListener('mouseleave', this.revertDataLabelsInner.bind(this, elPath.node, dataLabels)); elPath.node.addEventListener('mousedown', graphics.pathMouseDown.bind(this, elPath)); if (!this.donutDataLabels.total.showAlways) { elPath.node.addEventListener('mouseenter', this.printDataLabelsInner.bind(this, elPath.node, dataLabels)); elPath.node.addEventListener('mousedown', this.printDataLabelsInner.bind(this, elPath.node, dataLabels)); } } // This function can be used for other circle charts too }, { key: "animatePaths", value: function animatePaths(el, opts) { var w = this.w; var me = this; var angle = opts.endAngle < opts.startAngle ? this.fullAngle + opts.endAngle - opts.startAngle : opts.endAngle - opts.startAngle; var prevAngle = angle; var fromStartAngle = opts.startAngle; var toStartAngle = opts.startAngle; if (opts.prevStartAngle !== undefined && opts.prevEndAngle !== undefined) { fromStartAngle = opts.prevEndAngle; prevAngle = opts.prevEndAngle < opts.prevStartAngle ? this.fullAngle + opts.prevEndAngle - opts.prevStartAngle : opts.prevEndAngle - opts.prevStartAngle; } if (opts.i === w.config.series.length - 1) { // some adjustments for the last overlapping paths if (angle + toStartAngle > this.fullAngle) { opts.endAngle = opts.endAngle - (angle + toStartAngle); } else if (angle + toStartAngle < this.fullAngle) { opts.endAngle = opts.endAngle + (this.fullAngle - (angle + toStartAngle)); } } if (angle === this.fullAngle) angle = this.fullAngle - 0.01; me.animateArc(el, fromStartAngle, toStartAngle, angle, prevAngle, opts); } }, { key: "animateArc", value: function animateArc(el, fromStartAngle, toStartAngle, angle, prevAngle, opts) { var me = this; var w = this.w; var animations = new Animations(this.ctx); var size = opts.size; var path; if (isNaN(fromStartAngle) || isNaN(prevAngle)) { fromStartAngle = toStartAngle; prevAngle = angle; opts.dur = 0; } var currAngle = angle; var startAngle = toStartAngle; var fromAngle = fromStartAngle < toStartAngle ? this.fullAngle + fromStartAngle - toStartAngle : fromStartAngle - toStartAngle; if (w.globals.dataChanged && opts.shouldSetPrevPaths) { // to avoid flicker when updating, set prev path first and then animate from there if (opts.prevEndAngle) { path = me.getPiePath({ me: me, startAngle: opts.prevStartAngle, angle: opts.prevEndAngle < opts.prevStartAngle ? this.fullAngle + opts.prevEndAngle - opts.prevStartAngle : opts.prevEndAngle - opts.prevStartAngle, size: size }); el.attr({ d: path }); } } if (opts.dur !== 0) { el.animate(opts.dur, w.globals.easing, opts.animBeginArr[opts.i]).afterAll(function () { if (me.chartType === 'pie' || me.chartType === 'donut' || me.chartType === 'polarArea') { this.animate(w.config.chart.animations.dynamicAnimation.speed).attr({ 'stroke-width': me.strokeWidth }); } if (opts.i === w.config.series.length - 1) { animations.animationCompleted(el); } }).during(function (pos) { currAngle = fromAngle + (angle - fromAngle) * pos; if (opts.animateStartingPos) { currAngle = prevAngle + (angle - prevAngle) * pos; startAngle = fromStartAngle - prevAngle + (toStartAngle - (fromStartAngle - prevAngle)) * pos; } path = me.getPiePath({ me: me, startAngle: startAngle, angle: currAngle, size: size }); el.node.setAttribute('data:pathOrig', path); el.attr({ d: path }); }); } else { path = me.getPiePath({ me: me, startAngle: startAngle, angle: angle, size: size }); if (!opts.isTrack) { w.globals.animationEnded = true; } el.node.setAttribute('data:pathOrig', path); el.attr({ d: path, 'stroke-width': me.strokeWidth }); } } }, { key: "pieClicked", value: function pieClicked(i) { var w = this.w; var me = this; var path; var size = me.sliceSizes[i] + (w.config.plotOptions.pie.expandOnClick ? 4 : 0); var elPath = w.globals.dom.Paper.select(".apexcharts-".concat(me.chartType.toLowerCase(), "-slice-").concat(i)).members[0]; if (elPath.attr('data:pieClicked') === 'true') { elPath.attr({ 'data:pieClicked': 'false' }); this.revertDataLabelsInner(elPath.node, this.donutDataLabels); var origPath = elPath.attr('data:pathOrig'); elPath.attr({ d: origPath }); return; } else { // reset all elems var allEls = w.globals.dom.baseEl.getElementsByClassName('apexcharts-pie-area'); Array.prototype.forEach.call(allEls, function (pieSlice) { pieSlice.setAttribute('data:pieClicked', 'false'); var origPath = pieSlice.getAttribute('data:pathOrig'); pieSlice.setAttribute('d', origPath); }); elPath.attr('data:pieClicked', 'true'); } var startAngle = parseInt(elPath.attr('data:startAngle'), 10); var angle = parseInt(elPath.attr('data:angle'), 10); path = me.getPiePath({ me: me, startAngle: startAngle, angle: angle, size: size }); if (angle === 360) return; elPath.plot(path); } }, { key: "getChangedPath", value: function getChangedPath(prevStartAngle, prevEndAngle) { var path = ''; if (this.dynamicAnim && this.w.globals.dataChanged) { path = this.getPiePath({ me: this, startAngle: prevStartAngle, angle: prevEndAngle - prevStartAngle, size: this.size }); } return path; } }, { key: "getPiePath", value: function getPiePath(_ref) { var me = _ref.me, startAngle = _ref.startAngle, angle = _ref.angle, size = _ref.size; var path; var startDeg = startAngle; var startRadians = Math.PI * (startDeg - 90) / 180; var endDeg = angle + startAngle; // prevent overlap if (Math.ceil(endDeg) >= this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle) { endDeg = this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle - 0.01; } if (Math.ceil(endDeg) > this.fullAngle) endDeg -= this.fullAngle; var endRadians = Math.PI * (endDeg - 90) / 180; var x1 = me.centerX + size * Math.cos(startRadians); var y1 = me.centerY + size * Math.sin(startRadians); var x2 = me.centerX + size * Math.cos(endRadians); var y2 = me.centerY + size * Math.sin(endRadians); var startInner = Utils$1.polarToCartesian(me.centerX, me.centerY, me.donutSize, endDeg); var endInner = Utils$1.polarToCartesian(me.centerX, me.centerY, me.donutSize, startDeg); var largeArc = angle > 180 ? 1 : 0; var pathBeginning = ['M', x1, y1, 'A', size, size, 0, largeArc, 1, x2, y2]; if (me.chartType === 'donut') { path = [].concat(pathBeginning, ['L', startInner.x, startInner.y, 'A', me.donutSize, me.donutSize, 0, largeArc, 0, endInner.x, endInner.y, 'L', x1, y1, 'z']).join(' '); } else if (me.chartType === 'pie' || me.chartType === 'polarArea') { path = [].concat(pathBeginning, ['L', me.centerX, me.centerY, 'L', x1, y1]).join(' '); } else { path = [].concat(pathBeginning).join(' '); } return path; } }, { key: "drawPolarElements", value: function drawPolarElements(parent) { var w = this.w; var scale = new Range$1(this.ctx); var graphics = new Graphics(this.ctx); var helpers = new CircularChartsHelpers(this.ctx); var gCircles = graphics.group(); var gYAxis = graphics.group(); var yScale = scale.niceScale(0, Math.ceil(this.maxY), w.config.yaxis[0].tickAmount, 0, true); var yTexts = yScale.result.reverse(); var len = yScale.result.length; this.maxY = yScale.niceMax; var circleSize = w.globals.radialSize; var diff = circleSize / (len - 1); for (var i = 0; i < len - 1; i++) { var circle = graphics.drawCircle(circleSize); circle.attr({ cx: this.centerX, cy: this.centerY, fill: 'none', 'stroke-width': w.config.plotOptions.polarArea.rings.strokeWidth, stroke: w.config.plotOptions.polarArea.rings.strokeColor }); if (w.config.yaxis[0].show) { var yLabel = helpers.drawYAxisTexts(this.centerX, this.centerY - circleSize + parseInt(w.config.yaxis[0].labels.style.fontSize, 10) / 2, i, yTexts[i]); gYAxis.add(yLabel); } gCircles.add(circle); circleSize = circleSize - diff; } this.drawSpokes(parent); parent.add(gCircles); parent.add(gYAxis); } }, { key: "renderInnerDataLabels", value: function renderInnerDataLabels(dataLabelsConfig, opts) { var w = this.w; var graphics = new Graphics(this.ctx); var g = graphics.group({ class: 'apexcharts-datalabels-group', transform: "translate(".concat(opts.translateX ? opts.translateX : 0, ", ").concat(opts.translateY ? opts.translateY : 0, ") scale(").concat(w.config.plotOptions.pie.customScale, ")") }); var showTotal = dataLabelsConfig.total.show; g.node.style.opacity = opts.opacity; var x = opts.centerX; var y = opts.centerY; var labelColor, valueColor; if (dataLabelsConfig.name.color === undefined) { labelColor = w.globals.colors[0]; } else { labelColor = dataLabelsConfig.name.color; } var labelFontSize = dataLabelsConfig.name.fontSize; var labelFontFamily = dataLabelsConfig.name.fontFamily; var labelFontWeight = dataLabelsConfig.name.fontWeight; if (dataLabelsConfig.value.color === undefined) { valueColor = w.config.chart.foreColor; } else { valueColor = dataLabelsConfig.value.color; } var lbFormatter = dataLabelsConfig.value.formatter; var val = ''; var name = ''; if (showTotal) { labelColor = dataLabelsConfig.total.color; labelFontSize = dataLabelsConfig.total.fontSize; labelFontFamily = dataLabelsConfig.total.fontFamily; labelFontWeight = dataLabelsConfig.total.fontWeight; name = dataLabelsConfig.total.label; val = dataLabelsConfig.total.formatter(w); } else { if (w.globals.series.length === 1) { val = lbFormatter(w.globals.series[0], w); name = w.globals.seriesNames[0]; } } if (name) { name = dataLabelsConfig.name.formatter(name, dataLabelsConfig.total.show, w); } if (dataLabelsConfig.name.show) { var elLabel = graphics.drawText({ x: x, y: y + parseFloat(dataLabelsConfig.name.offsetY), text: name, textAnchor: 'middle', foreColor: labelColor, fontSize: labelFontSize, fontWeight: labelFontWeight, fontFamily: labelFontFamily }); elLabel.node.classList.add('apexcharts-datalabel-label'); g.add(elLabel); } if (dataLabelsConfig.value.show) { var valOffset = dataLabelsConfig.name.show ? parseFloat(dataLabelsConfig.value.offsetY) + 16 : dataLabelsConfig.value.offsetY; var elValue = graphics.drawText({ x: x, y: y + valOffset, text: val, textAnchor: 'middle', foreColor: valueColor, fontWeight: dataLabelsConfig.value.fontWeight, fontSize: dataLabelsConfig.value.fontSize, fontFamily: dataLabelsConfig.value.fontFamily }); elValue.node.classList.add('apexcharts-datalabel-value'); g.add(elValue); } // for a multi-series circle chart, we need to show total value instead of first series labels return g; } /** * * @param {string} name - The name of the series * @param {string} val - The value of that series * @param {object} el - Optional el (indicates which series was hovered/clicked). If this param is not present, means we need to show total */ }, { key: "printInnerLabels", value: function printInnerLabels(labelsConfig, name, val, el) { var w = this.w; var labelColor; if (el) { if (labelsConfig.name.color === undefined) { labelColor = w.globals.colors[parseInt(el.parentNode.getAttribute('rel'), 10) - 1]; } else { labelColor = labelsConfig.name.color; } } else { if (w.globals.series.length > 1 && labelsConfig.total.show) { labelColor = labelsConfig.total.color; } } var elLabel = w.globals.dom.baseEl.querySelector('.apexcharts-datalabel-label'); var elValue = w.globals.dom.baseEl.querySelector('.apexcharts-datalabel-value'); var lbFormatter = labelsConfig.value.formatter; val = lbFormatter(val, w); // we need to show Total Val - so get the formatter of it if (!el && typeof labelsConfig.total.formatter === 'function') { val = labelsConfig.total.formatter(w); } var isTotal = name === labelsConfig.total.label; name = labelsConfig.name.formatter(name, isTotal, w); if (elLabel !== null) { elLabel.textContent = name; } if (elValue !== null) { elValue.textContent = val; } if (elLabel !== null) { elLabel.style.fill = labelColor; } } }, { key: "printDataLabelsInner", value: function printDataLabelsInner(el, dataLabelsConfig) { var w = this.w; var val = el.getAttribute('data:value'); var name = w.globals.seriesNames[parseInt(el.parentNode.getAttribute('rel'), 10) - 1]; if (w.globals.series.length > 1) { this.printInnerLabels(dataLabelsConfig, name, val, el); } var dataLabelsGroup = w.globals.dom.baseEl.querySelector('.apexcharts-datalabels-group'); if (dataLabelsGroup !== null) { dataLabelsGroup.style.opacity = 1; } } }, { key: "drawSpokes", value: function drawSpokes(parent) { var _this2 = this; var w = this.w; var graphics = new Graphics(this.ctx); var spokeConfig = w.config.plotOptions.polarArea.spokes; if (spokeConfig.strokeWidth === 0) return; var spokes = []; var angleDivision = 360 / w.globals.series.length; for (var i = 0; i < w.globals.series.length; i++) { spokes.push(Utils$1.polarToCartesian(this.centerX, this.centerY, w.globals.radialSize, w.config.plotOptions.pie.startAngle + angleDivision * i)); } spokes.forEach(function (p, i) { var line = graphics.drawLine(p.x, p.y, _this2.centerX, _this2.centerY, Array.isArray(spokeConfig.connectorColors) ? spokeConfig.connectorColors[i] : spokeConfig.connectorColors); parent.add(line); }); } }, { key: "revertDataLabelsInner", value: function revertDataLabelsInner(elem, dataLabelsConfig, event) { var _this3 = this; var w = this.w; var dataLabelsGroup = w.globals.dom.baseEl.querySelector('.apexcharts-datalabels-group'); var sliceOut = false; var slices = w.globals.dom.baseEl.getElementsByClassName("apexcharts-pie-area"); var selectSlice = function selectSlice(_ref2) { var makeSliceOut = _ref2.makeSliceOut, printLabel = _ref2.printLabel; Array.prototype.forEach.call(slices, function (s) { if (s.getAttribute('data:pieClicked') === 'true') { if (makeSliceOut) { sliceOut = true; } if (printLabel) { _this3.printDataLabelsInner(s, dataLabelsConfig); } } }); }; selectSlice({ makeSliceOut: true, printLabel: false }); if (dataLabelsConfig.total.show && w.globals.series.length > 1) { if (sliceOut && !dataLabelsConfig.total.showAlways) { selectSlice({ makeSliceOut: false, printLabel: true }); } else { this.printInnerLabels(dataLabelsConfig, dataLabelsConfig.total.label, dataLabelsConfig.total.formatter(w)); } } else { selectSlice({ makeSliceOut: false, printLabel: true }); if (!sliceOut) { if (w.globals.selectedDataPoints.length && w.globals.series.length > 1) { if (w.globals.selectedDataPoints[0].length > 0) { var index = w.globals.selectedDataPoints[0]; var el = w.globals.dom.baseEl.querySelector(".apexcharts-".concat(this.chartType.toLowerCase(), "-slice-").concat(index)); this.printDataLabelsInner(el, dataLabelsConfig); } else if (dataLabelsGroup && w.globals.selectedDataPoints.length && w.globals.selectedDataPoints[0].length === 0) { dataLabelsGroup.style.opacity = 0; } } else { if (dataLabelsGroup && w.globals.series.length > 1) { dataLabelsGroup.style.opacity = 0; } } } } } }]); return Pie; }(); /** * ApexCharts Radar Class for Spider/Radar Charts. * @module Radar **/ var Radar = /*#__PURE__*/function () { function Radar(ctx) { _classCallCheck(this, Radar); this.ctx = ctx; this.w = ctx.w; this.chartType = this.w.config.chart.type; this.initialAnim = this.w.config.chart.animations.enabled; this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled; this.animDur = 0; var w = this.w; this.graphics = new Graphics(this.ctx); this.lineColorArr = w.globals.stroke.colors !== undefined ? w.globals.stroke.colors : w.globals.colors; this.defaultSize = w.globals.svgHeight < w.globals.svgWidth ? w.globals.gridHeight + w.globals.goldenPadding * 1.5 : w.globals.gridWidth; this.isLog = w.config.yaxis[0].logarithmic; this.coreUtils = new CoreUtils(this.ctx); this.maxValue = this.isLog ? this.coreUtils.getLogVal(w.globals.maxY, 0) : w.globals.maxY; this.minValue = this.isLog ? this.coreUtils.getLogVal(this.w.globals.minY, 0) : w.globals.minY; this.polygons = w.config.plotOptions.radar.polygons; this.strokeWidth = w.config.stroke.show ? w.config.stroke.width : 0; this.size = this.defaultSize / 2.1 - this.strokeWidth - w.config.chart.dropShadow.blur; if (w.config.xaxis.labels.show) { this.size = this.size - w.globals.xAxisLabelsWidth / 1.75; } if (w.config.plotOptions.radar.size !== undefined) { this.size = w.config.plotOptions.radar.size; } this.dataRadiusOfPercent = []; this.dataRadius = []; this.angleArr = []; this.yaxisLabelsTextsPos = []; } _createClass(Radar, [{ key: "draw", value: function draw(series) { var _this = this; var w = this.w; var fill = new Fill(this.ctx); var allSeries = []; var dataLabels = new DataLabels(this.ctx); if (series.length) { this.dataPointsLen = series[w.globals.maxValsInArrayIndex].length; } this.disAngle = Math.PI * 2 / this.dataPointsLen; var halfW = w.globals.gridWidth / 2; var halfH = w.globals.gridHeight / 2; var translateX = halfW + w.config.plotOptions.radar.offsetX; var translateY = halfH + w.config.plotOptions.radar.offsetY; var ret = this.graphics.group({ class: 'apexcharts-radar-series apexcharts-plot-series', transform: "translate(".concat(translateX || 0, ", ").concat(translateY || 0, ")") }); var dataPointsPos = []; var elPointsMain = null; var elDataPointsMain = null; this.yaxisLabels = this.graphics.group({ class: 'apexcharts-yaxis' }); series.forEach(function (s, i) { var longestSeries = s.length === w.globals.dataPoints; // el to which series will be drawn var elSeries = _this.graphics.group().attr({ class: "apexcharts-series", 'data:longestSeries': longestSeries, seriesName: Utils$1.escapeString(w.globals.seriesNames[i]), rel: i + 1, 'data:realIndex': i }); _this.dataRadiusOfPercent[i] = []; _this.dataRadius[i] = []; _this.angleArr[i] = []; s.forEach(function (dv, j) { var range = Math.abs(_this.maxValue - _this.minValue); dv = dv + Math.abs(_this.minValue); if (_this.isLog) { dv = _this.coreUtils.getLogVal(dv, 0); } _this.dataRadiusOfPercent[i][j] = dv / range; _this.dataRadius[i][j] = _this.dataRadiusOfPercent[i][j] * _this.size; _this.angleArr[i][j] = j * _this.disAngle; }); dataPointsPos = _this.getDataPointsPos(_this.dataRadius[i], _this.angleArr[i]); var paths = _this.createPaths(dataPointsPos, { x: 0, y: 0 }); // points elPointsMain = _this.graphics.group({ class: 'apexcharts-series-markers-wrap apexcharts-element-hidden' }); // datapoints elDataPointsMain = _this.graphics.group({ class: "apexcharts-datalabels", 'data:realIndex': i }); w.globals.delayedElements.push({ el: elPointsMain.node, index: i }); var defaultRenderedPathOptions = { i: i, realIndex: i, animationDelay: i, initialSpeed: w.config.chart.animations.speed, dataChangeSpeed: w.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-radar", shouldClipToGrid: false, bindEventsOnPaths: false, stroke: w.globals.stroke.colors[i], strokeLineCap: w.config.stroke.lineCap }; var pathFrom = null; if (w.globals.previousPaths.length > 0) { pathFrom = _this.getPreviousPath(i); } for (var p = 0; p < paths.linePathsTo.length; p++) { var renderedLinePath = _this.graphics.renderPaths(_objectSpread2(_objectSpread2({}, defaultRenderedPathOptions), {}, { pathFrom: pathFrom === null ? paths.linePathsFrom[p] : pathFrom, pathTo: paths.linePathsTo[p], strokeWidth: Array.isArray(_this.strokeWidth) ? _this.strokeWidth[i] : _this.strokeWidth, fill: 'none', drawShadow: false })); elSeries.add(renderedLinePath); var pathFill = fill.fillPath({ seriesNumber: i }); var renderedAreaPath = _this.graphics.renderPaths(_objectSpread2(_objectSpread2({}, defaultRenderedPathOptions), {}, { pathFrom: pathFrom === null ? paths.areaPathsFrom[p] : pathFrom, pathTo: paths.areaPathsTo[p], strokeWidth: 0, fill: pathFill, drawShadow: false })); if (w.config.chart.dropShadow.enabled) { var filters = new Filters(_this.ctx); var shadow = w.config.chart.dropShadow; filters.dropShadow(renderedAreaPath, Object.assign({}, shadow, { noUserSpaceOnUse: true }), i); } elSeries.add(renderedAreaPath); } s.forEach(function (sj, j) { var markers = new Markers(_this.ctx); var opts = markers.getMarkerConfig({ cssClass: 'apexcharts-marker', seriesIndex: i, dataPointIndex: j }); var point = _this.graphics.drawMarker(dataPointsPos[j].x, dataPointsPos[j].y, opts); point.attr('rel', j); point.attr('j', j); point.attr('index', i); point.node.setAttribute('default-marker-size', opts.pSize); var elPointsWrap = _this.graphics.group({ class: 'apexcharts-series-markers' }); if (elPointsWrap) { elPointsWrap.add(point); } elPointsMain.add(elPointsWrap); elSeries.add(elPointsMain); var dataLabelsConfig = w.config.dataLabels; if (dataLabelsConfig.enabled) { var text = dataLabelsConfig.formatter(w.globals.series[i][j], { seriesIndex: i, dataPointIndex: j, w: w }); dataLabels.plotDataLabelsText({ x: dataPointsPos[j].x, y: dataPointsPos[j].y, text: text, textAnchor: 'middle', i: i, j: i, parent: elDataPointsMain, offsetCorrection: false, dataLabelsConfig: _objectSpread2({}, dataLabelsConfig) }); } elSeries.add(elDataPointsMain); }); allSeries.push(elSeries); }); this.drawPolygons({ parent: ret }); if (w.config.xaxis.labels.show) { var xaxisTexts = this.drawXAxisTexts(); ret.add(xaxisTexts); } allSeries.forEach(function (elS) { ret.add(elS); }); ret.add(this.yaxisLabels); return ret; } }, { key: "drawPolygons", value: function drawPolygons(opts) { var _this2 = this; var w = this.w; var parent = opts.parent; var helpers = new CircularChartsHelpers(this.ctx); var yaxisTexts = w.globals.yAxisScale[0].result.reverse(); var layers = yaxisTexts.length; var radiusSizes = []; var layerDis = this.size / (layers - 1); for (var i = 0; i < layers; i++) { radiusSizes[i] = layerDis * i; } radiusSizes.reverse(); var polygonStrings = []; var lines = []; radiusSizes.forEach(function (radiusSize, r) { var polygon = Utils$1.getPolygonPos(radiusSize, _this2.dataPointsLen); var string = ''; polygon.forEach(function (p, i) { if (r === 0) { var line = _this2.graphics.drawLine(p.x, p.y, 0, 0, Array.isArray(_this2.polygons.connectorColors) ? _this2.polygons.connectorColors[i] : _this2.polygons.connectorColors); lines.push(line); } if (i === 0) { _this2.yaxisLabelsTextsPos.push({ x: p.x, y: p.y }); } string += p.x + ',' + p.y + ' '; }); polygonStrings.push(string); }); polygonStrings.forEach(function (p, i) { var strokeColors = _this2.polygons.strokeColors; var strokeWidth = _this2.polygons.strokeWidth; var polygon = _this2.graphics.drawPolygon(p, Array.isArray(strokeColors) ? strokeColors[i] : strokeColors, Array.isArray(strokeWidth) ? strokeWidth[i] : strokeWidth, w.globals.radarPolygons.fill.colors[i]); parent.add(polygon); }); lines.forEach(function (l) { parent.add(l); }); if (w.config.yaxis[0].show) { this.yaxisLabelsTextsPos.forEach(function (p, i) { var yText = helpers.drawYAxisTexts(p.x, p.y, i, yaxisTexts[i]); _this2.yaxisLabels.add(yText); }); } } }, { key: "drawXAxisTexts", value: function drawXAxisTexts() { var _this3 = this; var w = this.w; var xaxisLabelsConfig = w.config.xaxis.labels; var elXAxisWrap = this.graphics.group({ class: 'apexcharts-xaxis' }); var polygonPos = Utils$1.getPolygonPos(this.size, this.dataPointsLen); w.globals.labels.forEach(function (label, i) { var formatter = w.config.xaxis.labels.formatter; var dataLabels = new DataLabels(_this3.ctx); if (polygonPos[i]) { var textPos = _this3.getTextPos(polygonPos[i], _this3.size); var text = formatter(label, { seriesIndex: -1, dataPointIndex: i, w: w }); dataLabels.plotDataLabelsText({ x: textPos.newX, y: textPos.newY, text: text, textAnchor: textPos.textAnchor, i: i, j: i, parent: elXAxisWrap, color: Array.isArray(xaxisLabelsConfig.style.colors) && xaxisLabelsConfig.style.colors[i] ? xaxisLabelsConfig.style.colors[i] : '#a8a8a8', dataLabelsConfig: _objectSpread2({ textAnchor: textPos.textAnchor, dropShadow: { enabled: false } }, xaxisLabelsConfig), offsetCorrection: false }); } }); return elXAxisWrap; } }, { key: "createPaths", value: function createPaths(pos, origin) { var _this4 = this; var linePathsTo = []; var linePathsFrom = []; var areaPathsTo = []; var areaPathsFrom = []; if (pos.length) { linePathsFrom = [this.graphics.move(origin.x, origin.y)]; areaPathsFrom = [this.graphics.move(origin.x, origin.y)]; var linePathTo = this.graphics.move(pos[0].x, pos[0].y); var areaPathTo = this.graphics.move(pos[0].x, pos[0].y); pos.forEach(function (p, i) { linePathTo += _this4.graphics.line(p.x, p.y); areaPathTo += _this4.graphics.line(p.x, p.y); if (i === pos.length - 1) { linePathTo += 'Z'; areaPathTo += 'Z'; } }); linePathsTo.push(linePathTo); areaPathsTo.push(areaPathTo); } return { linePathsFrom: linePathsFrom, linePathsTo: linePathsTo, areaPathsFrom: areaPathsFrom, areaPathsTo: areaPathsTo }; } }, { key: "getTextPos", value: function getTextPos(pos, polygonSize) { var limit = 10; var textAnchor = 'middle'; var newX = pos.x; var newY = pos.y; if (Math.abs(pos.x) >= limit) { if (pos.x > 0) { textAnchor = 'start'; newX += 10; } else if (pos.x < 0) { textAnchor = 'end'; newX -= 10; } } else { textAnchor = 'middle'; } if (Math.abs(pos.y) >= polygonSize - limit) { if (pos.y < 0) { newY -= 10; } else if (pos.y > 0) { newY += 10; } } return { textAnchor: textAnchor, newX: newX, newY: newY }; } }, { key: "getPreviousPath", value: function getPreviousPath(realIndex) { var w = this.w; var pathFrom = null; for (var pp = 0; pp < w.globals.previousPaths.length; pp++) { var gpp = w.globals.previousPaths[pp]; if (gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(realIndex, 10)) { if (typeof w.globals.previousPaths[pp].paths[0] !== 'undefined') { pathFrom = w.globals.previousPaths[pp].paths[0].d; } } } return pathFrom; } }, { key: "getDataPointsPos", value: function getDataPointsPos(dataRadiusArr, angleArr) { var dataPointsLen = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.dataPointsLen; dataRadiusArr = dataRadiusArr || []; angleArr = angleArr || []; var dataPointsPosArray = []; for (var j = 0; j < dataPointsLen; j++) { var curPointPos = {}; curPointPos.x = dataRadiusArr[j] * Math.sin(angleArr[j]); curPointPos.y = -dataRadiusArr[j] * Math.cos(angleArr[j]); dataPointsPosArray.push(curPointPos); } return dataPointsPosArray; } }]); return Radar; }(); /** * ApexCharts Radial Class for drawing Circle / Semi Circle Charts. * @module Radial **/ var Radial = /*#__PURE__*/function (_Pie) { _inherits(Radial, _Pie); var _super = _createSuper(Radial); function Radial(ctx) { var _this; _classCallCheck(this, Radial); _this = _super.call(this, ctx); _this.ctx = ctx; _this.w = ctx.w; _this.animBeginArr = [0]; _this.animDur = 0; var w = _this.w; _this.startAngle = w.config.plotOptions.radialBar.startAngle; _this.endAngle = w.config.plotOptions.radialBar.endAngle; _this.totalAngle = Math.abs(w.config.plotOptions.radialBar.endAngle - w.config.plotOptions.radialBar.startAngle); _this.trackStartAngle = w.config.plotOptions.radialBar.track.startAngle; _this.trackEndAngle = w.config.plotOptions.radialBar.track.endAngle; _this.donutDataLabels = _this.w.config.plotOptions.radialBar.dataLabels; _this.radialDataLabels = _this.donutDataLabels; // make a copy for easy reference if (!_this.trackStartAngle) _this.trackStartAngle = _this.startAngle; if (!_this.trackEndAngle) _this.trackEndAngle = _this.endAngle; if (_this.endAngle === 360) _this.endAngle = 359.99; _this.margin = parseInt(w.config.plotOptions.radialBar.track.margin, 10); return _this; } _createClass(Radial, [{ key: "draw", value: function draw(series) { var w = this.w; var graphics = new Graphics(this.ctx); var ret = graphics.group({ class: 'apexcharts-radialbar' }); if (w.globals.noData) return ret; var elSeries = graphics.group(); var centerY = this.defaultSize / 2; var centerX = w.globals.gridWidth / 2; var size = this.defaultSize / 2.05; if (!w.config.chart.sparkline.enabled) { size = size - w.config.stroke.width - w.config.chart.dropShadow.blur; } var colorArr = w.globals.fill.colors; if (w.config.plotOptions.radialBar.track.show) { var elTracks = this.drawTracks({ size: size, centerX: centerX, centerY: centerY, colorArr: colorArr, series: series }); elSeries.add(elTracks); } var elG = this.drawArcs({ size: size, centerX: centerX, centerY: centerY, colorArr: colorArr, series: series }); var totalAngle = 360; if (w.config.plotOptions.radialBar.startAngle < 0) { totalAngle = this.totalAngle; } var angleRatio = (360 - totalAngle) / 360; w.globals.radialSize = size - size * angleRatio; if (this.radialDataLabels.value.show) { var offset = Math.max(this.radialDataLabels.value.offsetY, this.radialDataLabels.name.offsetY); w.globals.radialSize += offset * angleRatio; } elSeries.add(elG.g); if (w.config.plotOptions.radialBar.hollow.position === 'front') { elG.g.add(elG.elHollow); if (elG.dataLabels) { elG.g.add(elG.dataLabels); } } ret.add(elSeries); return ret; } }, { key: "drawTracks", value: function drawTracks(opts) { var w = this.w; var graphics = new Graphics(this.ctx); var g = graphics.group({ class: 'apexcharts-tracks' }); var filters = new Filters(this.ctx); var fill = new Fill(this.ctx); var strokeWidth = this.getStrokeWidth(opts); opts.size = opts.size - strokeWidth / 2; for (var i = 0; i < opts.series.length; i++) { var elRadialBarTrack = graphics.group({ class: 'apexcharts-radialbar-track apexcharts-track' }); g.add(elRadialBarTrack); elRadialBarTrack.attr({ rel: i + 1 }); opts.size = opts.size - strokeWidth - this.margin; var trackConfig = w.config.plotOptions.radialBar.track; var pathFill = fill.fillPath({ seriesNumber: 0, size: opts.size, fillColors: Array.isArray(trackConfig.background) ? trackConfig.background[i] : trackConfig.background, solid: true }); var startAngle = this.trackStartAngle; var endAngle = this.trackEndAngle; if (Math.abs(endAngle) + Math.abs(startAngle) >= 360) endAngle = 360 - Math.abs(this.startAngle) - 0.1; var elPath = graphics.drawPath({ d: '', stroke: pathFill, strokeWidth: strokeWidth * parseInt(trackConfig.strokeWidth, 10) / 100, fill: 'none', strokeOpacity: trackConfig.opacity, classes: 'apexcharts-radialbar-area' }); if (trackConfig.dropShadow.enabled) { var shadow = trackConfig.dropShadow; filters.dropShadow(elPath, shadow); } elRadialBarTrack.add(elPath); elPath.attr('id', 'apexcharts-radialbarTrack-' + i); this.animatePaths(elPath, { centerX: opts.centerX, centerY: opts.centerY, endAngle: endAngle, startAngle: startAngle, size: opts.size, i: i, totalItems: 2, animBeginArr: 0, dur: 0, isTrack: true, easing: w.globals.easing }); } return g; } }, { key: "drawArcs", value: function drawArcs(opts) { var w = this.w; // size, donutSize, centerX, centerY, colorArr, lineColorArr, sectorAngleArr, series var graphics = new Graphics(this.ctx); var fill = new Fill(this.ctx); var filters = new Filters(this.ctx); var g = graphics.group(); var strokeWidth = this.getStrokeWidth(opts); opts.size = opts.size - strokeWidth / 2; var hollowFillID = w.config.plotOptions.radialBar.hollow.background; var hollowSize = opts.size - strokeWidth * opts.series.length - this.margin * opts.series.length - strokeWidth * parseInt(w.config.plotOptions.radialBar.track.strokeWidth, 10) / 100 / 2; var hollowRadius = hollowSize - w.config.plotOptions.radialBar.hollow.margin; if (w.config.plotOptions.radialBar.hollow.image !== undefined) { hollowFillID = this.drawHollowImage(opts, g, hollowSize, hollowFillID); } var elHollow = this.drawHollow({ size: hollowRadius, centerX: opts.centerX, centerY: opts.centerY, fill: hollowFillID ? hollowFillID : 'transparent' }); if (w.config.plotOptions.radialBar.hollow.dropShadow.enabled) { var shadow = w.config.plotOptions.radialBar.hollow.dropShadow; filters.dropShadow(elHollow, shadow); } var shown = 1; if (!this.radialDataLabels.total.show && w.globals.series.length > 1) { shown = 0; } var dataLabels = null; if (this.radialDataLabels.show) { dataLabels = this.renderInnerDataLabels(this.radialDataLabels, { hollowSize: hollowSize, centerX: opts.centerX, centerY: opts.centerY, opacity: shown }); } if (w.config.plotOptions.radialBar.hollow.position === 'back') { g.add(elHollow); if (dataLabels) { g.add(dataLabels); } } var reverseLoop = false; if (w.config.plotOptions.radialBar.inverseOrder) { reverseLoop = true; } for (var i = reverseLoop ? opts.series.length - 1 : 0; reverseLoop ? i >= 0 : i < opts.series.length; reverseLoop ? i-- : i++) { var elRadialBarArc = graphics.group({ class: "apexcharts-series apexcharts-radial-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[i]) }); g.add(elRadialBarArc); elRadialBarArc.attr({ rel: i + 1, 'data:realIndex': i }); this.ctx.series.addCollapsedClassToSeries(elRadialBarArc, i); opts.size = opts.size - strokeWidth - this.margin; var pathFill = fill.fillPath({ seriesNumber: i, size: opts.size, value: opts.series[i] }); var startAngle = this.startAngle; var prevStartAngle = void 0; // if data exceeds 100, make it 100 var dataValue = Utils$1.negToZero(opts.series[i] > 100 ? 100 : opts.series[i]) / 100; var endAngle = Math.round(this.totalAngle * dataValue) + this.startAngle; var prevEndAngle = void 0; if (w.globals.dataChanged) { prevStartAngle = this.startAngle; prevEndAngle = Math.round(this.totalAngle * Utils$1.negToZero(w.globals.previousPaths[i]) / 100) + prevStartAngle; } var currFullAngle = Math.abs(endAngle) + Math.abs(startAngle); if (currFullAngle >= 360) { endAngle = endAngle - 0.01; } var prevFullAngle = Math.abs(prevEndAngle) + Math.abs(prevStartAngle); if (prevFullAngle >= 360) { prevEndAngle = prevEndAngle - 0.01; } var angle = endAngle - startAngle; var dashArray = Array.isArray(w.config.stroke.dashArray) ? w.config.stroke.dashArray[i] : w.config.stroke.dashArray; var elPath = graphics.drawPath({ d: '', stroke: pathFill, strokeWidth: strokeWidth, fill: 'none', fillOpacity: w.config.fill.opacity, classes: 'apexcharts-radialbar-area apexcharts-radialbar-slice-' + i, strokeDashArray: dashArray }); Graphics.setAttrs(elPath.node, { 'data:angle': angle, 'data:value': opts.series[i] }); if (w.config.chart.dropShadow.enabled) { var _shadow = w.config.chart.dropShadow; filters.dropShadow(elPath, _shadow, i); } filters.setSelectionFilter(elPath, 0, i); this.addListeners(elPath, this.radialDataLabels); elRadialBarArc.add(elPath); elPath.attr({ index: 0, j: i }); var dur = 0; if (this.initialAnim && !w.globals.resized && !w.globals.dataChanged) { dur = w.config.chart.animations.speed; } if (w.globals.dataChanged) { dur = w.config.chart.animations.dynamicAnimation.speed; } this.animDur = dur / (opts.series.length * 1.2) + this.animDur; this.animBeginArr.push(this.animDur); this.animatePaths(elPath, { centerX: opts.centerX, centerY: opts.centerY, endAngle: endAngle, startAngle: startAngle, prevEndAngle: prevEndAngle, prevStartAngle: prevStartAngle, size: opts.size, i: i, totalItems: 2, animBeginArr: this.animBeginArr, dur: dur, shouldSetPrevPaths: true, easing: w.globals.easing }); } return { g: g, elHollow: elHollow, dataLabels: dataLabels }; } }, { key: "drawHollow", value: function drawHollow(opts) { var graphics = new Graphics(this.ctx); var circle = graphics.drawCircle(opts.size * 2); circle.attr({ class: 'apexcharts-radialbar-hollow', cx: opts.centerX, cy: opts.centerY, r: opts.size, fill: opts.fill }); return circle; } }, { key: "drawHollowImage", value: function drawHollowImage(opts, g, hollowSize, hollowFillID) { var w = this.w; var fill = new Fill(this.ctx); var randID = Utils$1.randomId(); var hollowFillImg = w.config.plotOptions.radialBar.hollow.image; if (w.config.plotOptions.radialBar.hollow.imageClipped) { fill.clippedImgArea({ width: hollowSize, height: hollowSize, image: hollowFillImg, patternID: "pattern".concat(w.globals.cuid).concat(randID) }); hollowFillID = "url(#pattern".concat(w.globals.cuid).concat(randID, ")"); } else { var imgWidth = w.config.plotOptions.radialBar.hollow.imageWidth; var imgHeight = w.config.plotOptions.radialBar.hollow.imageHeight; if (imgWidth === undefined && imgHeight === undefined) { var image = w.globals.dom.Paper.image(hollowFillImg).loaded(function (loader) { this.move(opts.centerX - loader.width / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetX, opts.centerY - loader.height / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetY); }); g.add(image); } else { var _image = w.globals.dom.Paper.image(hollowFillImg).loaded(function (loader) { this.move(opts.centerX - imgWidth / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetX, opts.centerY - imgHeight / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetY); this.size(imgWidth, imgHeight); }); g.add(_image); } } return hollowFillID; } }, { key: "getStrokeWidth", value: function getStrokeWidth(opts) { var w = this.w; return opts.size * (100 - parseInt(w.config.plotOptions.radialBar.hollow.size, 10)) / 100 / (opts.series.length + 1) - this.margin; } }]); return Radial; }(Pie); /** * ApexCharts RangeBar Class responsible for drawing Range/Timeline Bars. * * @module RangeBar **/ var RangeBar = /*#__PURE__*/function (_Bar) { _inherits(RangeBar, _Bar); var _super = _createSuper(RangeBar); function RangeBar() { _classCallCheck(this, RangeBar); return _super.apply(this, arguments); } _createClass(RangeBar, [{ key: "draw", value: function draw(series, seriesIndex) { var w = this.w; var graphics = new Graphics(this.ctx); this.rangeBarOptions = this.w.config.plotOptions.rangeBar; this.series = series; this.seriesRangeStart = w.globals.seriesRangeStart; this.seriesRangeEnd = w.globals.seriesRangeEnd; this.barHelpers.initVariables(series); var ret = graphics.group({ class: 'apexcharts-rangebar-series apexcharts-plot-series' }); for (var i = 0; i < series.length; i++) { var x = void 0, y = void 0, xDivision = void 0, // xDivision is the GRIDWIDTH divided by number of datapoints (columns) yDivision = void 0, // yDivision is the GRIDHEIGHT divided by number of datapoints (bars) zeroH = void 0, // zeroH is the baseline where 0 meets y axis zeroW = void 0; // zeroW is the baseline where 0 meets x axis var realIndex = w.globals.comboCharts ? seriesIndex[i] : i; // el to which series will be drawn var elSeries = graphics.group({ class: "apexcharts-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[realIndex]), rel: i + 1, 'data:realIndex': realIndex }); this.ctx.series.addCollapsedClassToSeries(elSeries, realIndex); if (series[i].length > 0) { this.visibleI = this.visibleI + 1; } var barHeight = 0; var barWidth = 0; if (this.yRatio.length > 1) { this.yaxisIndex = realIndex; } var initPositions = this.barHelpers.initialPositions(); y = initPositions.y; zeroW = initPositions.zeroW; x = initPositions.x; barWidth = initPositions.barWidth; xDivision = initPositions.xDivision; zeroH = initPositions.zeroH; // eldatalabels var elDataLabelsWrap = graphics.group({ class: 'apexcharts-datalabels', 'data:realIndex': realIndex }); var elGoalsMarkers = graphics.group({ class: 'apexcharts-rangebar-goals-markers', style: "pointer-events: none" }); for (var j = 0; j < w.globals.dataPoints; j++) { var strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex); var y1 = this.seriesRangeStart[i][j]; var y2 = this.seriesRangeEnd[i][j]; var paths = null; var barYPosition = null; var params = { x: x, y: y, strokeWidth: strokeWidth, elSeries: elSeries }; yDivision = initPositions.yDivision; barHeight = initPositions.barHeight; if (this.isHorizontal) { barYPosition = y + barHeight * this.visibleI; var seriesLen = this.seriesLen; if (w.config.plotOptions.bar.rangeBarGroupRows) { seriesLen = 1; } var srty = (yDivision - barHeight * seriesLen) / 2; if (typeof w.config.series[i].data[j] === 'undefined') { // no data exists for further indexes, hence we need to get out the innr loop. // As we are iterating over total datapoints, there is a possiblity the series might not have data for j index break; } if (w.config.series[i].data[j].x) { var positions = this.detectOverlappingBars({ i: i, j: j, barYPosition: barYPosition, srty: srty, barHeight: barHeight, yDivision: yDivision, initPositions: initPositions }); barHeight = positions.barHeight; barYPosition = positions.barYPosition; } paths = this.drawRangeBarPaths(_objectSpread2({ indexes: { i: i, j: j, realIndex: realIndex }, barHeight: barHeight, barYPosition: barYPosition, zeroW: zeroW, yDivision: yDivision, y1: y1, y2: y2 }, params)); barWidth = paths.barWidth; } else { paths = this.drawRangeColumnPaths(_objectSpread2({ indexes: { i: i, j: j, realIndex: realIndex }, zeroH: zeroH, barWidth: barWidth, xDivision: xDivision }, params)); barHeight = paths.barHeight; } var barGoalLine = this.barHelpers.drawGoalLine({ barXPosition: paths.barXPosition, barYPosition: barYPosition, goalX: paths.goalX, goalY: paths.goalY, barHeight: barHeight, barWidth: barWidth }); if (barGoalLine) { elGoalsMarkers.add(barGoalLine); } y = paths.y; x = paths.x; var pathFill = this.barHelpers.getPathFillColor(series, i, j, realIndex); var lineFill = w.globals.stroke.colors[realIndex]; this.renderSeries({ realIndex: realIndex, pathFill: pathFill, lineFill: lineFill, j: j, i: i, x: x, y: y, y1: y1, y2: y2, pathFrom: paths.pathFrom, pathTo: paths.pathTo, strokeWidth: strokeWidth, elSeries: elSeries, series: series, barHeight: barHeight, barYPosition: barYPosition, barWidth: barWidth, elDataLabelsWrap: elDataLabelsWrap, elGoalsMarkers: elGoalsMarkers, visibleSeries: this.visibleI, type: 'rangebar' }); } ret.add(elSeries); } return ret; } }, { key: "detectOverlappingBars", value: function detectOverlappingBars(_ref) { var i = _ref.i, j = _ref.j, barYPosition = _ref.barYPosition, srty = _ref.srty, barHeight = _ref.barHeight, yDivision = _ref.yDivision, initPositions = _ref.initPositions; var w = this.w; var overlaps = []; var rangeName = w.config.series[i].data[j].rangeName; var labelX = w.config.series[i].data[j].x; var rowIndex = w.globals.labels.indexOf(labelX); var overlappedIndex = w.globals.seriesRange[i].findIndex(function (tx) { return tx.x === labelX && tx.overlaps.length > 0; }); if (w.config.plotOptions.bar.rangeBarGroupRows) { barYPosition = srty + yDivision * rowIndex; } else { barYPosition = srty + barHeight * this.visibleI + yDivision * rowIndex; } if (overlappedIndex > -1 && !w.config.plotOptions.bar.rangeBarOverlap) { overlaps = w.globals.seriesRange[i][overlappedIndex].overlaps; if (overlaps.indexOf(rangeName) > -1) { barHeight = initPositions.barHeight / overlaps.length; barYPosition = barHeight * this.visibleI + yDivision * (100 - parseInt(this.barOptions.barHeight, 10)) / 100 / 2 + barHeight * (this.visibleI + overlaps.indexOf(rangeName)) + yDivision * rowIndex; } } return { barYPosition: barYPosition, barHeight: barHeight }; } }, { key: "drawRangeColumnPaths", value: function drawRangeColumnPaths(_ref2) { var indexes = _ref2.indexes, x = _ref2.x; _ref2.strokeWidth; var xDivision = _ref2.xDivision, barWidth = _ref2.barWidth, zeroH = _ref2.zeroH; var w = this.w; var i = indexes.i; var j = indexes.j; var yRatio = this.yRatio[this.yaxisIndex]; var realIndex = indexes.realIndex; var range = this.getRangeValue(realIndex, j); var y1 = Math.min(range.start, range.end); var y2 = Math.max(range.start, range.end); if (w.globals.isXNumeric) { x = (w.globals.seriesX[i][j] - w.globals.minX) / this.xRatio - barWidth / 2; } var barXPosition = x + barWidth * this.visibleI; if (typeof this.series[i][j] === 'undefined' || this.series[i][j] === null) { y1 = zeroH; } else { y1 = zeroH - y1 / yRatio; y2 = zeroH - y2 / yRatio; } var barHeight = Math.abs(y2 - y1); var paths = this.barHelpers.getColumnPaths({ barXPosition: barXPosition, barWidth: barWidth, y1: y1, y2: y2, strokeWidth: this.strokeWidth, series: this.seriesRangeEnd, realIndex: indexes.realIndex, i: realIndex, j: j, w: w }); if (!w.globals.isXNumeric) { x = x + xDivision; } return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, barHeight: barHeight, x: x, y: y2, goalY: this.barHelpers.getGoalValues('y', null, zeroH, i, j), barXPosition: barXPosition }; } }, { key: "drawRangeBarPaths", value: function drawRangeBarPaths(_ref3) { var indexes = _ref3.indexes, y = _ref3.y, y1 = _ref3.y1, y2 = _ref3.y2, yDivision = _ref3.yDivision, barHeight = _ref3.barHeight, barYPosition = _ref3.barYPosition, zeroW = _ref3.zeroW; var w = this.w; var x1 = zeroW + y1 / this.invertedYRatio; var x2 = zeroW + y2 / this.invertedYRatio; var barWidth = Math.abs(x2 - x1); var paths = this.barHelpers.getBarpaths({ barYPosition: barYPosition, barHeight: barHeight, x1: x1, x2: x2, strokeWidth: this.strokeWidth, series: this.seriesRangeEnd, i: indexes.realIndex, realIndex: indexes.realIndex, j: indexes.j, w: w }); if (!w.globals.isXNumeric) { y = y + yDivision; } return { pathTo: paths.pathTo, pathFrom: paths.pathFrom, barWidth: barWidth, x: x2, goalX: this.barHelpers.getGoalValues('x', zeroW, null, indexes.realIndex, indexes.j), y: y }; } }, { key: "getRangeValue", value: function getRangeValue(i, j) { var w = this.w; return { start: w.globals.seriesRangeStart[i][j], end: w.globals.seriesRangeEnd[i][j] }; } }]); return RangeBar; }(Bar); var Helpers = /*#__PURE__*/function () { function Helpers(lineCtx) { _classCallCheck(this, Helpers); this.w = lineCtx.w; this.lineCtx = lineCtx; } _createClass(Helpers, [{ key: "sameValueSeriesFix", value: function sameValueSeriesFix(i, series) { var w = this.w; if (w.config.fill.type === 'gradient' || w.config.fill.type[i] === 'gradient') { var coreUtils = new CoreUtils(this.lineCtx.ctx, w); // applied only to LINE chart // a small adjustment to allow gradient line to draw correctly for all same values /* #fix https://github.com/apexcharts/apexcharts.js/issues/358 */ if (coreUtils.seriesHaveSameValues(i)) { var gSeries = series[i].slice(); gSeries[gSeries.length - 1] = gSeries[gSeries.length - 1] + 0.000001; series[i] = gSeries; } } return series; } }, { key: "calculatePoints", value: function calculatePoints(_ref) { var series = _ref.series, realIndex = _ref.realIndex, x = _ref.x, y = _ref.y, i = _ref.i, j = _ref.j, prevY = _ref.prevY; var w = this.w; var ptX = []; var ptY = []; if (j === 0) { var xPT1st = this.lineCtx.categoryAxisCorrection + w.config.markers.offsetX; // the first point for line series // we need to check whether it's not a time series, because a time series may // start from the middle of the x axis if (w.globals.isXNumeric) { xPT1st = (w.globals.seriesX[realIndex][0] - w.globals.minX) / this.lineCtx.xRatio + w.config.markers.offsetX; } // push 2 points for the first data values ptX.push(xPT1st); ptY.push(Utils$1.isNumber(series[i][0]) ? prevY + w.config.markers.offsetY : null); ptX.push(x + w.config.markers.offsetX); ptY.push(Utils$1.isNumber(series[i][j + 1]) ? y + w.config.markers.offsetY : null); } else { ptX.push(x + w.config.markers.offsetX); ptY.push(Utils$1.isNumber(series[i][j + 1]) ? y + w.config.markers.offsetY : null); } var pointsPos = { x: ptX, y: ptY }; return pointsPos; } }, { key: "checkPreviousPaths", value: function checkPreviousPaths(_ref2) { var pathFromLine = _ref2.pathFromLine, pathFromArea = _ref2.pathFromArea, realIndex = _ref2.realIndex; var w = this.w; for (var pp = 0; pp < w.globals.previousPaths.length; pp++) { var gpp = w.globals.previousPaths[pp]; if ((gpp.type === 'line' || gpp.type === 'area') && gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(realIndex, 10)) { if (gpp.type === 'line') { this.lineCtx.appendPathFrom = false; pathFromLine = w.globals.previousPaths[pp].paths[0].d; } else if (gpp.type === 'area') { this.lineCtx.appendPathFrom = false; pathFromArea = w.globals.previousPaths[pp].paths[0].d; if (w.config.stroke.show && w.globals.previousPaths[pp].paths[1]) { pathFromLine = w.globals.previousPaths[pp].paths[1].d; } } } } return { pathFromLine: pathFromLine, pathFromArea: pathFromArea }; } }, { key: "determineFirstPrevY", value: function determineFirstPrevY(_ref3) { var _series$i; var i = _ref3.i, series = _ref3.series, prevY = _ref3.prevY, lineYPosition = _ref3.lineYPosition; var w = this.w; if (typeof ((_series$i = series[i]) === null || _series$i === void 0 ? void 0 : _series$i[0]) !== 'undefined') { if (w.config.chart.stacked) { if (i > 0) { // 1st y value of previous series lineYPosition = this.lineCtx.prevSeriesY[i - 1][0]; } else { // the first series will not have prevY values lineYPosition = this.lineCtx.zeroY; } } else { lineYPosition = this.lineCtx.zeroY; } prevY = lineYPosition - series[i][0] / this.lineCtx.yRatio[this.lineCtx.yaxisIndex] + (this.lineCtx.isReversed ? series[i][0] / this.lineCtx.yRatio[this.lineCtx.yaxisIndex] : 0) * 2; } else { // the first value in the current series is null if (w.config.chart.stacked && i > 0 && typeof series[i][0] === 'undefined') { // check for undefined value (undefined value will occur when we clear the series while user clicks on legend to hide serieses) for (var s = i - 1; s >= 0; s--) { // for loop to get to 1st previous value until we get it if (series[s][0] !== null && typeof series[s][0] !== 'undefined') { lineYPosition = this.lineCtx.prevSeriesY[s][0]; prevY = lineYPosition; break; } } } } return { prevY: prevY, lineYPosition: lineYPosition }; } }]); return Helpers; }(); /** * ApexCharts Line Class responsible for drawing Line / Area / RangeArea Charts. * This class is also responsible for generating values for Bubble/Scatter charts, so need to rename it to Axis Charts to avoid confusions * @module Line **/ var Line = /*#__PURE__*/function () { function Line(ctx, xyRatios, isPointsChart) { _classCallCheck(this, Line); this.ctx = ctx; this.w = ctx.w; this.xyRatios = xyRatios; this.pointsChart = !(this.w.config.chart.type !== 'bubble' && this.w.config.chart.type !== 'scatter') || isPointsChart; this.scatter = new Scatter(this.ctx); this.noNegatives = this.w.globals.minX === Number.MAX_VALUE; this.lineHelpers = new Helpers(this); this.markers = new Markers(this.ctx); this.prevSeriesY = []; this.categoryAxisCorrection = 0; this.yaxisIndex = 0; } _createClass(Line, [{ key: "draw", value: function draw(series, ctype, seriesIndex, seriesRangeEnd) { var w = this.w; var graphics = new Graphics(this.ctx); var type = w.globals.comboCharts ? ctype : w.config.chart.type; var ret = graphics.group({ class: "apexcharts-".concat(type, "-series apexcharts-plot-series") }); var coreUtils = new CoreUtils(this.ctx, w); this.yRatio = this.xyRatios.yRatio; this.zRatio = this.xyRatios.zRatio; this.xRatio = this.xyRatios.xRatio; this.baseLineY = this.xyRatios.baseLineY; series = coreUtils.getLogSeries(series); this.yRatio = coreUtils.getLogYRatios(this.yRatio); // push all series in an array, so we can draw in reverse order (for stacked charts) var allSeries = []; for (var i = 0; i < series.length; i++) { series = this.lineHelpers.sameValueSeriesFix(i, series); var realIndex = w.globals.comboCharts ? seriesIndex[i] : i; this._initSerieVariables(series, i, realIndex); var yArrj = []; // hold y values of current iterating series var xArrj = []; // hold x values of current iterating series var x = w.globals.padHorizontal + this.categoryAxisCorrection; var y = 1; var linePaths = []; var areaPaths = []; this.ctx.series.addCollapsedClassToSeries(this.elSeries, realIndex); if (w.globals.isXNumeric && w.globals.seriesX.length > 0) { x = (w.globals.seriesX[realIndex][0] - w.globals.minX) / this.xRatio; } xArrj.push(x); var pX = x; var pY = void 0; var pY2 = void 0; var prevX = pX; var prevY = this.zeroY; var prevY2 = this.zeroY; var lineYPosition = 0; // the first value in the current series is not null or undefined var firstPrevY = this.lineHelpers.determineFirstPrevY({ i: i, series: series, prevY: prevY, lineYPosition: lineYPosition }); prevY = firstPrevY.prevY; yArrj.push(prevY); pY = prevY; // y2 are needed for range-area charts var firstPrevY2 = void 0; if (type === 'rangeArea') { firstPrevY2 = this.lineHelpers.determineFirstPrevY({ i: i, series: seriesRangeEnd, prevY: prevY2, lineYPosition: lineYPosition }); prevY2 = firstPrevY2.prevY; pY2 = prevY2; } var pathsFrom = this._calculatePathsFrom({ type: type, series: series, i: i, realIndex: realIndex, prevX: prevX, prevY: prevY, prevY2: prevY2 }); var iteratingOpts = { type: type, series: series, realIndex: realIndex, i: i, x: x, y: y, pX: pX, pY: pY, pathsFrom: pathsFrom, linePaths: linePaths, areaPaths: areaPaths, seriesIndex: seriesIndex, lineYPosition: lineYPosition, xArrj: xArrj, yArrj: yArrj, seriesRangeEnd: seriesRangeEnd }; var paths = this._iterateOverDataPoints(_objectSpread2(_objectSpread2({}, iteratingOpts), {}, { iterations: type === 'rangeArea' ? series[i].length - 1 : undefined, isRangeStart: true })); if (type === 'rangeArea') { var pathsFrom2 = this._calculatePathsFrom({ series: seriesRangeEnd, i: i, realIndex: realIndex, prevX: prevX, prevY: prevY2 }); var rangePaths = this._iterateOverDataPoints(_objectSpread2(_objectSpread2({}, iteratingOpts), {}, { series: seriesRangeEnd, pY: pY2, pathsFrom: pathsFrom2, iterations: seriesRangeEnd[i].length - 1, isRangeStart: false })); paths.linePaths[0] = rangePaths.linePath + paths.linePath; paths.pathFromLine = rangePaths.pathFromLine + paths.pathFromLine; } this._handlePaths({ type: type, realIndex: realIndex, i: i, paths: paths }); this.elSeries.add(this.elPointsMain); this.elSeries.add(this.elDataLabelsWrap); allSeries.push(this.elSeries); } if (w.config.chart.stacked) { for (var s = allSeries.length; s > 0; s--) { ret.add(allSeries[s - 1]); } } else { for (var _s = 0; _s < allSeries.length; _s++) { ret.add(allSeries[_s]); } } return ret; } }, { key: "_initSerieVariables", value: function _initSerieVariables(series, i, realIndex) { var w = this.w; var graphics = new Graphics(this.ctx); // width divided into equal parts this.xDivision = w.globals.gridWidth / (w.globals.dataPoints - (w.config.xaxis.tickPlacement === 'on' ? 1 : 0)); this.strokeWidth = Array.isArray(w.config.stroke.width) ? w.config.stroke.width[realIndex] : w.config.stroke.width; if (this.yRatio.length > 1) { this.yaxisIndex = realIndex; } this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed; // zeroY is the 0 value in y series which can be used in negative charts this.zeroY = w.globals.gridHeight - this.baseLineY[this.yaxisIndex] - (this.isReversed ? w.globals.gridHeight : 0) + (this.isReversed ? this.baseLineY[this.yaxisIndex] * 2 : 0); this.areaBottomY = this.zeroY; if (this.zeroY > w.globals.gridHeight || w.config.plotOptions.area.fillTo === 'end') { this.areaBottomY = w.globals.gridHeight; } this.categoryAxisCorrection = this.xDivision / 2; // el to which series will be drawn this.elSeries = graphics.group({ class: "apexcharts-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[realIndex]) }); // points this.elPointsMain = graphics.group({ class: 'apexcharts-series-markers-wrap', 'data:realIndex': realIndex }); // eldatalabels this.elDataLabelsWrap = graphics.group({ class: 'apexcharts-datalabels', 'data:realIndex': realIndex }); var longestSeries = series[i].length === w.globals.dataPoints; this.elSeries.attr({ 'data:longestSeries': longestSeries, rel: i + 1, 'data:realIndex': realIndex }); this.appendPathFrom = true; } }, { key: "_calculatePathsFrom", value: function _calculatePathsFrom(_ref) { var type = _ref.type, series = _ref.series, i = _ref.i, realIndex = _ref.realIndex, prevX = _ref.prevX, prevY = _ref.prevY, prevY2 = _ref.prevY2; var w = this.w; var graphics = new Graphics(this.ctx); var linePath, areaPath, pathFromLine, pathFromArea; if (series[i][0] === null) { // when the first value itself is null, we need to move the pointer to a location where a null value is not found for (var s = 0; s < series[i].length; s++) { if (series[i][s] !== null) { prevX = this.xDivision * s; prevY = this.zeroY - series[i][s] / this.yRatio[this.yaxisIndex]; linePath = graphics.move(prevX, prevY); areaPath = graphics.move(prevX, this.areaBottomY); break; } } } else { linePath = graphics.move(prevX, prevY); if (type === 'rangeArea') { linePath = graphics.move(prevX, prevY2) + graphics.line(prevX, prevY); } areaPath = graphics.move(prevX, this.areaBottomY) + graphics.line(prevX, prevY); } pathFromLine = graphics.move(-1, this.zeroY) + graphics.line(-1, this.zeroY); pathFromArea = graphics.move(-1, this.zeroY) + graphics.line(-1, this.zeroY); if (w.globals.previousPaths.length > 0) { var pathFrom = this.lineHelpers.checkPreviousPaths({ pathFromLine: pathFromLine, pathFromArea: pathFromArea, realIndex: realIndex }); pathFromLine = pathFrom.pathFromLine; pathFromArea = pathFrom.pathFromArea; } return { prevX: prevX, prevY: prevY, linePath: linePath, areaPath: areaPath, pathFromLine: pathFromLine, pathFromArea: pathFromArea }; } }, { key: "_handlePaths", value: function _handlePaths(_ref2) { var type = _ref2.type, realIndex = _ref2.realIndex, i = _ref2.i, paths = _ref2.paths; var w = this.w; var graphics = new Graphics(this.ctx); var fill = new Fill(this.ctx); // push all current y values array to main PrevY Array this.prevSeriesY.push(paths.yArrj); // push all x val arrays into main xArr w.globals.seriesXvalues[realIndex] = paths.xArrj; w.globals.seriesYvalues[realIndex] = paths.yArrj; var forecast = w.config.forecastDataPoints; if (forecast.count > 0 && type !== 'rangeArea') { var forecastCutoff = w.globals.seriesXvalues[realIndex][w.globals.seriesXvalues[realIndex].length - forecast.count - 1]; var elForecastMask = graphics.drawRect(forecastCutoff, 0, w.globals.gridWidth, w.globals.gridHeight, 0); w.globals.dom.elForecastMask.appendChild(elForecastMask.node); var elNonForecastMask = graphics.drawRect(0, 0, forecastCutoff, w.globals.gridHeight, 0); w.globals.dom.elNonForecastMask.appendChild(elNonForecastMask.node); } // these elements will be shown after area path animation completes if (!this.pointsChart) { w.globals.delayedElements.push({ el: this.elPointsMain.node, index: realIndex }); } var defaultRenderedPathOptions = { i: i, realIndex: realIndex, animationDelay: i, initialSpeed: w.config.chart.animations.speed, dataChangeSpeed: w.config.chart.animations.dynamicAnimation.speed, className: "apexcharts-".concat(type) }; if (type === 'area') { var pathFill = fill.fillPath({ seriesNumber: realIndex }); for (var p = 0; p < paths.areaPaths.length; p++) { var renderedPath = graphics.renderPaths(_objectSpread2(_objectSpread2({}, defaultRenderedPathOptions), {}, { pathFrom: paths.pathFromArea, pathTo: paths.areaPaths[p], stroke: 'none', strokeWidth: 0, strokeLineCap: null, fill: pathFill })); this.elSeries.add(renderedPath); } } if (w.config.stroke.show && !this.pointsChart) { var lineFill = null; if (type === 'line') { lineFill = fill.fillPath({ seriesNumber: realIndex, i: i }); } else { if (w.config.stroke.fill.type === 'solid') { lineFill = w.globals.stroke.colors[realIndex]; } else { var prevFill = w.config.fill; w.config.fill = w.config.stroke.fill; lineFill = fill.fillPath({ seriesNumber: realIndex, i: i }); w.config.fill = prevFill; } } // range-area paths are drawn using linePaths for (var _p = 0; _p < paths.linePaths.length; _p++) { var _pathFill = lineFill; if (type === 'rangeArea') { _pathFill = fill.fillPath({ seriesNumber: realIndex }); } var linePathCommonOpts = _objectSpread2(_objectSpread2({}, defaultRenderedPathOptions), {}, { pathFrom: paths.pathFromLine, pathTo: paths.linePaths[_p], stroke: lineFill, strokeWidth: this.strokeWidth, strokeLineCap: w.config.stroke.lineCap, fill: type === 'rangeArea' ? _pathFill : 'none' }); var _renderedPath = graphics.renderPaths(linePathCommonOpts); this.elSeries.add(_renderedPath); _renderedPath.attr('fill-rule', "evenodd"); if (forecast.count > 0 && type !== 'rangeArea') { var renderedForecastPath = graphics.renderPaths(linePathCommonOpts); renderedForecastPath.node.setAttribute('stroke-dasharray', forecast.dashArray); if (forecast.strokeWidth) { renderedForecastPath.node.setAttribute('stroke-width', forecast.strokeWidth); } this.elSeries.add(renderedForecastPath); renderedForecastPath.attr('clip-path', "url(#forecastMask".concat(w.globals.cuid, ")")); _renderedPath.attr('clip-path', "url(#nonForecastMask".concat(w.globals.cuid, ")")); } } } } }, { key: "_iterateOverDataPoints", value: function _iterateOverDataPoints(_ref3) { var type = _ref3.type, series = _ref3.series, iterations = _ref3.iterations, realIndex = _ref3.realIndex, i = _ref3.i, x = _ref3.x, y = _ref3.y, pX = _ref3.pX, pY = _ref3.pY, pathsFrom = _ref3.pathsFrom, linePaths = _ref3.linePaths, areaPaths = _ref3.areaPaths, seriesIndex = _ref3.seriesIndex, lineYPosition = _ref3.lineYPosition, xArrj = _ref3.xArrj, yArrj = _ref3.yArrj, isRangeStart = _ref3.isRangeStart, seriesRangeEnd = _ref3.seriesRangeEnd; var w = this.w; var graphics = new Graphics(this.ctx); var yRatio = this.yRatio; var prevY = pathsFrom.prevY, linePath = pathsFrom.linePath, areaPath = pathsFrom.areaPath, pathFromLine = pathsFrom.pathFromLine, pathFromArea = pathsFrom.pathFromArea; var minY = Utils$1.isNumber(w.globals.minYArr[realIndex]) ? w.globals.minYArr[realIndex] : w.globals.minY; if (!iterations) { iterations = w.globals.dataPoints > 1 ? w.globals.dataPoints - 1 : w.globals.dataPoints; } var y2 = y; for (var j = 0; j < iterations; j++) { var isNull = typeof series[i][j + 1] === 'undefined' || series[i][j + 1] === null; if (w.globals.isXNumeric) { var sX = w.globals.seriesX[realIndex][j + 1]; if (typeof w.globals.seriesX[realIndex][j + 1] === 'undefined') { /* fix #374 */ sX = w.globals.seriesX[realIndex][iterations - 1]; } x = (sX - w.globals.minX) / this.xRatio; } else { x = x + this.xDivision; } if (w.config.chart.stacked) { if (i > 0 && w.globals.collapsedSeries.length < w.config.series.length - 1) { // a collapsed series in a stacked bar chart may provide wrong result for the next series, hence find the prevIndex of prev series which is not collapsed - fixes apexcharts.js#1372 var prevIndex = function prevIndex(pi) { var pii = pi; for (var cpi = 0; cpi < w.globals.series.length; cpi++) { if (w.globals.collapsedSeriesIndices.indexOf(pi) > -1) { pii--; break; } } return pii >= 0 ? pii : 0; }; lineYPosition = this.prevSeriesY[prevIndex(i - 1)][j + 1]; } else { // the first series will not have prevY values lineYPosition = this.zeroY; } } else { lineYPosition = this.zeroY; } if (isNull) { y = lineYPosition - minY / yRatio[this.yaxisIndex] + (this.isReversed ? minY / yRatio[this.yaxisIndex] : 0) * 2; } else { y = lineYPosition - series[i][j + 1] / yRatio[this.yaxisIndex] + (this.isReversed ? series[i][j + 1] / yRatio[this.yaxisIndex] : 0) * 2; if (type === 'rangeArea') { y2 = lineYPosition - seriesRangeEnd[i][j + 1] / yRatio[this.yaxisIndex] + (this.isReversed ? seriesRangeEnd[i][j + 1] / yRatio[this.yaxisIndex] : 0) * 2; } } // push current X xArrj.push(x); // push current Y that will be used as next series's bottom position yArrj.push(y); var pointsPos = this.lineHelpers.calculatePoints({ series: series, x: x, y: y, realIndex: realIndex, i: i, j: j, prevY: prevY }); var calculatedPaths = this._createPaths({ type: type, series: series, i: i, realIndex: realIndex, j: j, x: x, y: y, y2: y2, pX: pX, pY: pY, linePath: linePath, areaPath: areaPath, linePaths: linePaths, areaPaths: areaPaths, seriesIndex: seriesIndex, isRangeStart: isRangeStart }); areaPaths = calculatedPaths.areaPaths; linePaths = calculatedPaths.linePaths; pX = calculatedPaths.pX; pY = calculatedPaths.pY; areaPath = calculatedPaths.areaPath; linePath = calculatedPaths.linePath; if (this.appendPathFrom) { pathFromLine = pathFromLine + graphics.line(x, this.zeroY); pathFromArea = pathFromArea + graphics.line(x, this.zeroY); } this.handleNullDataPoints(series, pointsPos, i, j, realIndex); this._handleMarkersAndLabels({ type: type, pointsPos: pointsPos, i: i, j: j, realIndex: realIndex, isRangeStart: isRangeStart }); } return { yArrj: yArrj, xArrj: xArrj, pathFromArea: pathFromArea, areaPaths: areaPaths, pathFromLine: pathFromLine, linePaths: linePaths, linePath: linePath, areaPath: areaPath }; } }, { key: "_handleMarkersAndLabels", value: function _handleMarkersAndLabels(_ref4) { var type = _ref4.type, pointsPos = _ref4.pointsPos, isRangeStart = _ref4.isRangeStart, i = _ref4.i, j = _ref4.j, realIndex = _ref4.realIndex; var w = this.w; var dataLabels = new DataLabels(this.ctx); if (!this.pointsChart) { if (w.globals.series[i].length > 1) { this.elPointsMain.node.classList.add('apexcharts-element-hidden'); } var elPointsWrap = this.markers.plotChartMarkers(pointsPos, realIndex, j + 1); if (elPointsWrap !== null) { this.elPointsMain.add(elPointsWrap); } } else { // scatter / bubble chart points creation this.scatter.draw(this.elSeries, j, { realIndex: realIndex, pointsPos: pointsPos, zRatio: this.zRatio, elParent: this.elPointsMain }); } var drawnLabels = dataLabels.drawDataLabel({ type: type, isRangeStart: isRangeStart, pos: pointsPos, i: realIndex, j: j + 1 }); if (drawnLabels !== null) { this.elDataLabelsWrap.add(drawnLabels); } } }, { key: "_createPaths", value: function _createPaths(_ref5) { var type = _ref5.type, series = _ref5.series, i = _ref5.i, realIndex = _ref5.realIndex, j = _ref5.j, x = _ref5.x, y = _ref5.y, y2 = _ref5.y2, pX = _ref5.pX, pY = _ref5.pY, linePath = _ref5.linePath, areaPath = _ref5.areaPath, linePaths = _ref5.linePaths, areaPaths = _ref5.areaPaths, seriesIndex = _ref5.seriesIndex, isRangeStart = _ref5.isRangeStart; var w = this.w; var graphics = new Graphics(this.ctx); var curve = w.config.stroke.curve; var areaBottomY = this.areaBottomY; if (Array.isArray(w.config.stroke.curve)) { if (Array.isArray(seriesIndex)) { curve = w.config.stroke.curve[seriesIndex[i]]; } else { curve = w.config.stroke.curve[i]; } } // logic of smooth curve derived from chartist // CREDITS: https://gionkunz.github.io/chartist-js/ if (curve === 'smooth') { var length = (x - pX) * 0.35; if (w.globals.hasNullValues) { if (series[i][j] !== null) { if (series[i][j + 1] !== null) { linePath = graphics.move(pX, pY) + graphics.curve(pX + length, pY, x - length, y, x + 1, y); areaPath = graphics.move(pX + 1, pY) + graphics.curve(pX + length, pY, x - length, y, x + 1, y) + graphics.line(x, areaBottomY) + graphics.line(pX, areaBottomY) + 'z'; } else { linePath = graphics.move(pX, pY); areaPath = graphics.move(pX, pY) + 'z'; } } linePaths.push(linePath); areaPaths.push(areaPath); } else { linePath = linePath + graphics.curve(pX + length, pY, x - length, y, x, y); areaPath = areaPath + graphics.curve(pX + length, pY, x - length, y, x, y); } pX = x; pY = y; if (j === series[i].length - 2) { // last loop, close path areaPath = areaPath + graphics.curve(pX, pY, x, y, x, areaBottomY) + graphics.move(x, y) + 'z'; if (type === 'rangeArea' && isRangeStart) { linePath = linePath + graphics.curve(pX, pY, x, y, x, y2) + graphics.move(x, y2) + 'z'; } else { if (!w.globals.hasNullValues) { linePaths.push(linePath); areaPaths.push(areaPath); } } } } else { if (series[i][j + 1] === null) { linePath = linePath + graphics.move(x, y); var numericOrCatX = w.globals.isXNumeric ? (w.globals.seriesX[realIndex][j] - w.globals.minX) / this.xRatio : x - this.xDivision; areaPath = areaPath + graphics.line(numericOrCatX, areaBottomY) + graphics.move(x, y) + 'z'; } if (series[i][j] === null) { linePath = linePath + graphics.move(x, y); areaPath = areaPath + graphics.move(x, areaBottomY); } if (curve === 'stepline') { linePath = linePath + graphics.line(x, null, 'H') + graphics.line(null, y, 'V'); areaPath = areaPath + graphics.line(x, null, 'H') + graphics.line(null, y, 'V'); } else if (curve === 'straight') { linePath = linePath + graphics.line(x, y); areaPath = areaPath + graphics.line(x, y); } if (j === series[i].length - 2) { // last loop, close path areaPath = areaPath + graphics.line(x, areaBottomY) + graphics.move(x, y) + 'z'; if (type === 'rangeArea' && isRangeStart) { linePath = linePath + graphics.line(x, y2) + graphics.move(x, y2) + 'z'; } else { linePaths.push(linePath); areaPaths.push(areaPath); } } } return { linePaths: linePaths, areaPaths: areaPaths, pX: pX, pY: pY, linePath: linePath, areaPath: areaPath }; } }, { key: "handleNullDataPoints", value: function handleNullDataPoints(series, pointsPos, i, j, realIndex) { var w = this.w; if (series[i][j] === null && w.config.markers.showNullDataPoints || series[i].length === 1) { // fixes apexcharts.js#1282, #1252 var elPointsWrap = this.markers.plotChartMarkers(pointsPos, realIndex, j + 1, this.strokeWidth - w.config.markers.strokeWidth / 2, true); if (elPointsWrap !== null) { this.elPointsMain.add(elPointsWrap); } } } }]); return Line; }(); /* * treemap-squarify.js - open source implementation of squarified treemaps * * Treemap Squared 0.5 - Treemap Charting library * * https://github.com/imranghory/treemap-squared/ * * Copyright (c) 2012 Imran Ghory (imranghory@gmail.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. * * * Implementation of the squarify treemap algorithm described in: * * Bruls, Mark; Huizing, Kees; van Wijk, Jarke J. (2000), "Squarified treemaps" * in de Leeuw, W.; van Liere, R., Data Visualization 2000: * Proc. Joint Eurographics and IEEE TCVG Symp. on Visualization, Springer-Verlag, pp. 33–42. * * Paper is available online at: http://www.win.tue.nl/~vanwijk/stm.pdf * * The code in this file is completeley decoupled from the drawing code so it should be trivial * to port it to any other vector drawing library. Given an array of datapoints this library returns * an array of cartesian coordinates that represent the rectangles that make up the treemap. * * The library also supports multidimensional data (nested treemaps) and performs normalization on the data. * * See the README file for more details. */ window.TreemapSquared = {}; (function () { window.TreemapSquared.generate = function () { function Container(xoffset, yoffset, width, height) { this.xoffset = xoffset; // offset from the the top left hand corner this.yoffset = yoffset; // ditto this.height = height; this.width = width; this.shortestEdge = function () { return Math.min(this.height, this.width); }; // getCoordinates - for a row of boxes which we've placed // return an array of their cartesian coordinates this.getCoordinates = function (row) { var coordinates = []; var subxoffset = this.xoffset, subyoffset = this.yoffset; //our offset within the container var areawidth = sumArray(row) / this.height; var areaheight = sumArray(row) / this.width; var i; if (this.width >= this.height) { for (i = 0; i < row.length; i++) { coordinates.push([subxoffset, subyoffset, subxoffset + areawidth, subyoffset + row[i] / areawidth]); subyoffset = subyoffset + row[i] / areawidth; } } else { for (i = 0; i < row.length; i++) { coordinates.push([subxoffset, subyoffset, subxoffset + row[i] / areaheight, subyoffset + areaheight]); subxoffset = subxoffset + row[i] / areaheight; } } return coordinates; }; // cutArea - once we've placed some boxes into an row we then need to identify the remaining area, // this function takes the area of the boxes we've placed and calculates the location and // dimensions of the remaining space and returns a container box defined by the remaining area this.cutArea = function (area) { var newcontainer; if (this.width >= this.height) { var areawidth = area / this.height; var newwidth = this.width - areawidth; newcontainer = new Container(this.xoffset + areawidth, this.yoffset, newwidth, this.height); } else { var areaheight = area / this.width; var newheight = this.height - areaheight; newcontainer = new Container(this.xoffset, this.yoffset + areaheight, this.width, newheight); } return newcontainer; }; } // normalize - the Bruls algorithm assumes we're passing in areas that nicely fit into our // container box, this method takes our raw data and normalizes the data values into // area values so that this assumption is valid. function normalize(data, area) { var normalizeddata = []; var sum = sumArray(data); var multiplier = area / sum; var i; for (i = 0; i < data.length; i++) { normalizeddata[i] = data[i] * multiplier; } return normalizeddata; } // treemapMultidimensional - takes multidimensional data (aka [[23,11],[11,32]] - nested array) // and recursively calls itself using treemapSingledimensional // to create a patchwork of treemaps and merge them function treemapMultidimensional(data, width, height, xoffset, yoffset) { xoffset = typeof xoffset === 'undefined' ? 0 : xoffset; yoffset = typeof yoffset === 'undefined' ? 0 : yoffset; var mergeddata = []; var mergedtreemap; var results = []; var i; if (isArray(data[0])) { // if we've got more dimensions of depth for (i = 0; i < data.length; i++) { mergeddata[i] = sumMultidimensionalArray(data[i]); } mergedtreemap = treemapSingledimensional(mergeddata, width, height, xoffset, yoffset); for (i = 0; i < data.length; i++) { results.push(treemapMultidimensional(data[i], mergedtreemap[i][2] - mergedtreemap[i][0], mergedtreemap[i][3] - mergedtreemap[i][1], mergedtreemap[i][0], mergedtreemap[i][1])); } } else { results = treemapSingledimensional(data, width, height, xoffset, yoffset); } return results; } // treemapSingledimensional - simple wrapper around squarify function treemapSingledimensional(data, width, height, xoffset, yoffset) { xoffset = typeof xoffset === 'undefined' ? 0 : xoffset; yoffset = typeof yoffset === 'undefined' ? 0 : yoffset; var rawtreemap = squarify(normalize(data, width * height), [], new Container(xoffset, yoffset, width, height), []); return flattenTreemap(rawtreemap); } // flattenTreemap - squarify implementation returns an array of arrays of coordinates // because we have a new array everytime we switch to building a new row // this converts it into an array of coordinates. function flattenTreemap(rawtreemap) { var flattreemap = []; var i, j; for (i = 0; i < rawtreemap.length; i++) { for (j = 0; j < rawtreemap[i].length; j++) { flattreemap.push(rawtreemap[i][j]); } } return flattreemap; } // squarify - as per the Bruls paper // plus coordinates stack and containers so we get // usable data out of it function squarify(data, currentrow, container, stack) { var length; var nextdatapoint; var newcontainer; if (data.length === 0) { stack.push(container.getCoordinates(currentrow)); return; } length = container.shortestEdge(); nextdatapoint = data[0]; if (improvesRatio(currentrow, nextdatapoint, length)) { currentrow.push(nextdatapoint); squarify(data.slice(1), currentrow, container, stack); } else { newcontainer = container.cutArea(sumArray(currentrow), stack); stack.push(container.getCoordinates(currentrow)); squarify(data, [], newcontainer, stack); } return stack; } // improveRatio - implements the worse calculation and comparision as given in Bruls // (note the error in the original paper; fixed here) function improvesRatio(currentrow, nextnode, length) { var newrow; if (currentrow.length === 0) { return true; } newrow = currentrow.slice(); newrow.push(nextnode); var currentratio = calculateRatio(currentrow, length); var newratio = calculateRatio(newrow, length); // the pseudocode in the Bruls paper has the direction of the comparison // wrong, this is the correct one. return currentratio >= newratio; } // calculateRatio - calculates the maximum width to height ratio of the // boxes in this row function calculateRatio(row, length) { var min = Math.min.apply(Math, row); var max = Math.max.apply(Math, row); var sum = sumArray(row); return Math.max(Math.pow(length, 2) * max / Math.pow(sum, 2), Math.pow(sum, 2) / (Math.pow(length, 2) * min)); } // isArray - checks if arr is an array function isArray(arr) { return arr && arr.constructor === Array; } // sumArray - sums a single dimensional array function sumArray(arr) { var sum = 0; var i; for (i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } // sumMultidimensionalArray - sums the values in a nested array (aka [[0,1],[[2,3]]]) function sumMultidimensionalArray(arr) { var i, total = 0; if (isArray(arr[0])) { for (i = 0; i < arr.length; i++) { total += sumMultidimensionalArray(arr[i]); } } else { total = sumArray(arr); } return total; } return treemapMultidimensional; }(); })(); /** * ApexCharts TreemapChart Class. * @module TreemapChart **/ var TreemapChart = /*#__PURE__*/function () { function TreemapChart(ctx, xyRatios) { _classCallCheck(this, TreemapChart); this.ctx = ctx; this.w = ctx.w; this.strokeWidth = this.w.config.stroke.width; this.helpers = new TreemapHelpers(ctx); this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation; this.labels = []; } _createClass(TreemapChart, [{ key: "draw", value: function draw(series) { var _this = this; var w = this.w; var graphics = new Graphics(this.ctx); var fill = new Fill(this.ctx); var ret = graphics.group({ class: 'apexcharts-treemap' }); if (w.globals.noData) return ret; var ser = []; series.forEach(function (s) { var d = s.map(function (v) { return Math.abs(v); }); ser.push(d); }); this.negRange = this.helpers.checkColorRange(); w.config.series.forEach(function (s, i) { s.data.forEach(function (l) { if (!Array.isArray(_this.labels[i])) _this.labels[i] = []; _this.labels[i].push(l.x); }); }); var nodes = window.TreemapSquared.generate(ser, w.globals.gridWidth, w.globals.gridHeight); nodes.forEach(function (node, i) { var elSeries = graphics.group({ class: "apexcharts-series apexcharts-treemap-series", seriesName: Utils$1.escapeString(w.globals.seriesNames[i]), rel: i + 1, 'data:realIndex': i }); if (w.config.chart.dropShadow.enabled) { var shadow = w.config.chart.dropShadow; var filters = new Filters(_this.ctx); filters.dropShadow(ret, shadow, i); } var elDataLabelWrap = graphics.group({ class: 'apexcharts-data-labels' }); node.forEach(function (r, j) { var x1 = r[0]; var y1 = r[1]; var x2 = r[2]; var y2 = r[3]; var elRect = graphics.drawRect(x1, y1, x2 - x1, y2 - y1, 0, '#fff', 1, _this.strokeWidth, w.config.plotOptions.treemap.useFillColorAsStroke ? color : w.globals.stroke.colors[i]); elRect.attr({ cx: x1, cy: y1, index: i, i: i, j: j, width: x2 - x1, height: y2 - y1 }); var colorProps = _this.helpers.getShadeColor(w.config.chart.type, i, j, _this.negRange); var color = colorProps.color; if (typeof w.config.series[i].data[j] !== 'undefined' && w.config.series[i].data[j].fillColor) { color = w.config.series[i].data[j].fillColor; } var pathFill = fill.fillPath({ color: color, seriesNumber: i, dataPointIndex: j }); elRect.node.classList.add('apexcharts-treemap-rect'); elRect.attr({ fill: pathFill }); _this.helpers.addListeners(elRect); var fromRect = { x: x1 + (x2 - x1) / 2, y: y1 + (y2 - y1) / 2, width: 0, height: 0 }; var toRect = { x: x1, y: y1, width: x2 - x1, height: y2 - y1 }; if (w.config.chart.animations.enabled && !w.globals.dataChanged) { var speed = 1; if (!w.globals.resized) { speed = w.config.chart.animations.speed; } _this.animateTreemap(elRect, fromRect, toRect, speed); } if (w.globals.dataChanged) { var _speed = 1; if (_this.dynamicAnim.enabled && w.globals.shouldAnimate) { _speed = _this.dynamicAnim.speed; if (w.globals.previousPaths[i] && w.globals.previousPaths[i][j] && w.globals.previousPaths[i][j].rect) { fromRect = w.globals.previousPaths[i][j].rect; } _this.animateTreemap(elRect, fromRect, toRect, _speed); } } var fontSize = _this.getFontSize(r); var formattedText = w.config.dataLabels.formatter(_this.labels[i][j], { value: w.globals.series[i][j], seriesIndex: i, dataPointIndex: j, w: w }); var dataLabels = _this.helpers.calculateDataLabels({ text: formattedText, x: (x1 + x2) / 2, y: (y1 + y2) / 2 + _this.strokeWidth / 2 + fontSize / 3, i: i, j: j, colorProps: colorProps, fontSize: fontSize, series: series }); if (w.config.dataLabels.enabled && dataLabels) { _this.rotateToFitLabel(dataLabels, fontSize, formattedText, x1, y1, x2, y2); } elSeries.add(elRect); if (dataLabels !== null) { elSeries.add(dataLabels); } }); elSeries.add(elDataLabelWrap); ret.add(elSeries); }); return ret; } // This calculates a font-size based upon // average label length and the size of the box the label is // going into. The maximum font size is set in chart config. }, { key: "getFontSize", value: function getFontSize(coordinates) { var w = this.w; // total length of labels (i.e [["Italy"],["Spain", "Greece"]] -> 16) function totalLabelLength(arr) { var i, total = 0; if (Array.isArray(arr[0])) { for (i = 0; i < arr.length; i++) { total += totalLabelLength(arr[i]); } } else { for (i = 0; i < arr.length; i++) { total += arr[i].length; } } return total; } // count of labels (i.e [["Italy"],["Spain", "Greece"]] -> 3) function countLabels(arr) { var i, total = 0; if (Array.isArray(arr[0])) { for (i = 0; i < arr.length; i++) { total += countLabels(arr[i]); } } else { for (i = 0; i < arr.length; i++) { total += 1; } } return total; } var averagelabelsize = totalLabelLength(this.labels) / countLabels(this.labels); function fontSize(width, height) { // the font size should be proportional to the size of the box (and the value) // otherwise you can end up creating a visual distortion where two boxes of identical // size have different sized labels, and thus make it look as if the two boxes // represent different sizes var area = width * height; var arearoot = Math.pow(area, 0.5); return Math.min(arearoot / averagelabelsize, parseInt(w.config.dataLabels.style.fontSize, 10)); } return fontSize(coordinates[2] - coordinates[0], coordinates[3] - coordinates[1]); } }, { key: "rotateToFitLabel", value: function rotateToFitLabel(elText, fontSize, text, x1, y1, x2, y2) { var graphics = new Graphics(this.ctx); var textRect = graphics.getTextRects(text, fontSize); //if the label fits better sideways then rotate it if (textRect.width + this.w.config.stroke.width + 5 > x2 - x1 && textRect.width <= y2 - y1) { var labelRotatingCenter = graphics.rotateAroundCenter(elText.node); elText.node.setAttribute('transform', "rotate(-90 ".concat(labelRotatingCenter.x, " ").concat(labelRotatingCenter.y, ")")); } } }, { key: "animateTreemap", value: function animateTreemap(el, fromRect, toRect, speed) { var animations = new Animations(this.ctx); animations.animateRect(el, { x: fromRect.x, y: fromRect.y, width: fromRect.width, height: fromRect.height }, { x: toRect.x, y: toRect.y, width: toRect.width, height: toRect.height }, speed, function () { animations.animationCompleted(el); }); } }]); return TreemapChart; }(); var MINUTES_IN_DAY = 24 * 60; var SECONDS_IN_DAY = MINUTES_IN_DAY * 60; var MIN_ZOOM_DAYS = 10 / SECONDS_IN_DAY; /** * ApexCharts TimeScale Class for generating time ticks for x-axis. * * @module TimeScale **/ var TimeScale = /*#__PURE__*/function () { function TimeScale(ctx) { _classCallCheck(this, TimeScale); this.ctx = ctx; this.w = ctx.w; this.timeScaleArray = []; this.utc = this.w.config.xaxis.labels.datetimeUTC; } _createClass(TimeScale, [{ key: "calculateTimeScaleTicks", value: function calculateTimeScaleTicks(minX, maxX) { var _this = this; var w = this.w; // null check when no series to show if (w.globals.allSeriesCollapsed) { w.globals.labels = []; w.globals.timescaleLabels = []; return []; } var dt = new DateTime(this.ctx); var daysDiff = (maxX - minX) / (1000 * SECONDS_IN_DAY); this.determineInterval(daysDiff); w.globals.disableZoomIn = false; w.globals.disableZoomOut = false; if (daysDiff < MIN_ZOOM_DAYS) { w.globals.disableZoomIn = true; } else if (daysDiff > 50000) { w.globals.disableZoomOut = true; } var timeIntervals = dt.getTimeUnitsfromTimestamp(minX, maxX, this.utc); var daysWidthOnXAxis = w.globals.gridWidth / daysDiff; var hoursWidthOnXAxis = daysWidthOnXAxis / 24; var minutesWidthOnXAxis = hoursWidthOnXAxis / 60; var secondsWidthOnXAxis = minutesWidthOnXAxis / 60; var numberOfHours = Math.floor(daysDiff * 24); var numberOfMinutes = Math.floor(daysDiff * MINUTES_IN_DAY); var numberOfSeconds = Math.floor(daysDiff * SECONDS_IN_DAY); var numberOfDays = Math.floor(daysDiff); var numberOfMonths = Math.floor(daysDiff / 30); var numberOfYears = Math.floor(daysDiff / 365); var firstVal = { minMillisecond: timeIntervals.minMillisecond, minSecond: timeIntervals.minSecond, minMinute: timeIntervals.minMinute, minHour: timeIntervals.minHour, minDate: timeIntervals.minDate, minMonth: timeIntervals.minMonth, minYear: timeIntervals.minYear }; var currentMillisecond = firstVal.minMillisecond; var currentSecond = firstVal.minSecond; var currentMinute = firstVal.minMinute; var currentHour = firstVal.minHour; var currentMonthDate = firstVal.minDate; var currentDate = firstVal.minDate; var currentMonth = firstVal.minMonth; var currentYear = firstVal.minYear; var params = { firstVal: firstVal, currentMillisecond: currentMillisecond, currentSecond: currentSecond, currentMinute: currentMinute, currentHour: currentHour, currentMonthDate: currentMonthDate, currentDate: currentDate, currentMonth: currentMonth, currentYear: currentYear, daysWidthOnXAxis: daysWidthOnXAxis, hoursWidthOnXAxis: hoursWidthOnXAxis, minutesWidthOnXAxis: minutesWidthOnXAxis, secondsWidthOnXAxis: secondsWidthOnXAxis, numberOfSeconds: numberOfSeconds, numberOfMinutes: numberOfMinutes, numberOfHours: numberOfHours, numberOfDays: numberOfDays, numberOfMonths: numberOfMonths, numberOfYears: numberOfYears }; switch (this.tickInterval) { case 'years': { this.generateYearScale(params); break; } case 'months': case 'half_year': { this.generateMonthScale(params); break; } case 'months_days': case 'months_fortnight': case 'days': case 'week_days': { this.generateDayScale(params); break; } case 'hours': { this.generateHourScale(params); break; } case 'minutes_fives': case 'minutes': this.generateMinuteScale(params); break; case 'seconds_tens': case 'seconds_fives': case 'seconds': this.generateSecondScale(params); break; } // first, we will adjust the month values index // as in the upper function, it is starting from 0 // we will start them from 1 var adjustedMonthInTimeScaleArray = this.timeScaleArray.map(function (ts) { var defaultReturn = { position: ts.position, unit: ts.unit, year: ts.year, day: ts.day ? ts.day : 1, hour: ts.hour ? ts.hour : 0, month: ts.month + 1 }; if (ts.unit === 'month') { return _objectSpread2(_objectSpread2({}, defaultReturn), {}, { day: 1, value: ts.value + 1 }); } else if (ts.unit === 'day' || ts.unit === 'hour') { return _objectSpread2(_objectSpread2({}, defaultReturn), {}, { value: ts.value }); } else if (ts.unit === 'minute') { return _objectSpread2(_objectSpread2({}, defaultReturn), {}, { value: ts.value, minute: ts.value }); } else if (ts.unit === 'second') { return _objectSpread2(_objectSpread2({}, defaultReturn), {}, { value: ts.value, minute: ts.minute, second: ts.second }); } return ts; }); var filteredTimeScale = adjustedMonthInTimeScaleArray.filter(function (ts) { var modulo = 1; var ticks = Math.ceil(w.globals.gridWidth / 120); var value = ts.value; if (w.config.xaxis.tickAmount !== undefined) { ticks = w.config.xaxis.tickAmount; } if (adjustedMonthInTimeScaleArray.length > ticks) { modulo = Math.floor(adjustedMonthInTimeScaleArray.length / ticks); } var shouldNotSkipUnit = false; // there is a big change in unit i.e days to months var shouldNotPrint = false; // should skip these values switch (_this.tickInterval) { case 'years': // make years label denser if (ts.unit === 'year') { shouldNotSkipUnit = true; } break; case 'half_year': modulo = 7; if (ts.unit === 'year') { shouldNotSkipUnit = true; } break; case 'months': modulo = 1; if (ts.unit === 'year') { shouldNotSkipUnit = true; } break; case 'months_fortnight': modulo = 15; if (ts.unit === 'year' || ts.unit === 'month') { shouldNotSkipUnit = true; } if (value === 30) { shouldNotPrint = true; } break; case 'months_days': modulo = 10; if (ts.unit === 'month') { shouldNotSkipUnit = true; } if (value === 30) { shouldNotPrint = true; } break; case 'week_days': modulo = 8; if (ts.unit === 'month') { shouldNotSkipUnit = true; } break; case 'days': modulo = 1; if (ts.unit === 'month') { shouldNotSkipUnit = true; } break; case 'hours': if (ts.unit === 'day') { shouldNotSkipUnit = true; } break; case 'minutes_fives': if (value % 5 !== 0) { shouldNotPrint = true; } break; case 'seconds_tens': if (value % 10 !== 0) { shouldNotPrint = true; } break; case 'seconds_fives': if (value % 5 !== 0) { shouldNotPrint = true; } break; } if (_this.tickInterval === 'hours' || _this.tickInterval === 'minutes_fives' || _this.tickInterval === 'seconds_tens' || _this.tickInterval === 'seconds_fives') { if (!shouldNotPrint) { return true; } } else { if ((value % modulo === 0 || shouldNotSkipUnit) && !shouldNotPrint) { return true; } } }); return filteredTimeScale; } }, { key: "recalcDimensionsBasedOnFormat", value: function recalcDimensionsBasedOnFormat(filteredTimeScale, inverted) { var w = this.w; var reformattedTimescaleArray = this.formatDates(filteredTimeScale); var removedOverlappingTS = this.removeOverlappingTS(reformattedTimescaleArray); w.globals.timescaleLabels = removedOverlappingTS.slice(); // at this stage, we need to re-calculate coords of the grid as timeline labels may have altered the xaxis labels coords // The reason we can't do this prior to this stage is because timeline labels depends on gridWidth, and as the ticks are calculated based on available gridWidth, there can be unknown number of ticks generated for different minX and maxX // Dependency on Dimensions(), need to refactor correctly // TODO - find an alternate way to avoid calling this Heavy method twice var dimensions = new Dimensions(this.ctx); dimensions.plotCoords(); } }, { key: "determineInterval", value: function determineInterval(daysDiff) { var yearsDiff = daysDiff / 365; var hoursDiff = daysDiff * 24; var minutesDiff = hoursDiff * 60; var secondsDiff = minutesDiff * 60; switch (true) { case yearsDiff > 5: this.tickInterval = 'years'; break; case daysDiff > 800: this.tickInterval = 'half_year'; break; case daysDiff > 180: this.tickInterval = 'months'; break; case daysDiff > 90: this.tickInterval = 'months_fortnight'; break; case daysDiff > 60: this.tickInterval = 'months_days'; break; case daysDiff > 30: this.tickInterval = 'week_days'; break; case daysDiff > 2: this.tickInterval = 'days'; break; case hoursDiff > 2.4: this.tickInterval = 'hours'; break; case minutesDiff > 15: this.tickInterval = 'minutes_fives'; break; case minutesDiff > 5: this.tickInterval = 'minutes'; break; case minutesDiff > 1: this.tickInterval = 'seconds_tens'; break; case secondsDiff > 20: this.tickInterval = 'seconds_fives'; break; default: this.tickInterval = 'seconds'; break; } } }, { key: "generateYearScale", value: function generateYearScale(_ref) { var firstVal = _ref.firstVal, currentMonth = _ref.currentMonth, currentYear = _ref.currentYear, daysWidthOnXAxis = _ref.daysWidthOnXAxis, numberOfYears = _ref.numberOfYears; var firstTickValue = firstVal.minYear; var firstTickPosition = 0; var dt = new DateTime(this.ctx); var unit = 'year'; if (firstVal.minDate > 1 || firstVal.minMonth > 0) { var remainingDays = dt.determineRemainingDaysOfYear(firstVal.minYear, firstVal.minMonth, firstVal.minDate); // remainingDaysofFirstMonth is used to reacht the 2nd tick position var remainingDaysOfFirstYear = dt.determineDaysOfYear(firstVal.minYear) - remainingDays + 1; // calculate the first tick position firstTickPosition = remainingDaysOfFirstYear * daysWidthOnXAxis; firstTickValue = firstVal.minYear + 1; // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: firstTickValue, unit: unit, year: firstTickValue, month: Utils$1.monthMod(currentMonth + 1) }); } else if (firstVal.minDate === 1 && firstVal.minMonth === 0) { // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: firstTickValue, unit: unit, year: currentYear, month: Utils$1.monthMod(currentMonth + 1) }); } var year = firstTickValue; var pos = firstTickPosition; // keep drawing rest of the ticks for (var i = 0; i < numberOfYears; i++) { year++; pos = dt.determineDaysOfYear(year - 1) * daysWidthOnXAxis + pos; this.timeScaleArray.push({ position: pos, value: year, unit: unit, year: year, month: 1 }); } } }, { key: "generateMonthScale", value: function generateMonthScale(_ref2) { var firstVal = _ref2.firstVal, currentMonthDate = _ref2.currentMonthDate, currentMonth = _ref2.currentMonth, currentYear = _ref2.currentYear, daysWidthOnXAxis = _ref2.daysWidthOnXAxis, numberOfMonths = _ref2.numberOfMonths; var firstTickValue = currentMonth; var firstTickPosition = 0; var dt = new DateTime(this.ctx); var unit = 'month'; var yrCounter = 0; if (firstVal.minDate > 1) { // remainingDaysofFirstMonth is used to reacht the 2nd tick position var remainingDaysOfFirstMonth = dt.determineDaysOfMonths(currentMonth + 1, firstVal.minYear) - currentMonthDate + 1; // calculate the first tick position firstTickPosition = remainingDaysOfFirstMonth * daysWidthOnXAxis; firstTickValue = Utils$1.monthMod(currentMonth + 1); var year = currentYear + yrCounter; var _month = Utils$1.monthMod(firstTickValue); var value = firstTickValue; // it's Jan, so update the year if (firstTickValue === 0) { unit = 'year'; value = year; _month = 1; yrCounter += 1; year = year + yrCounter; } // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: value, unit: unit, year: year, month: _month }); } else { // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: firstTickValue, unit: unit, year: currentYear, month: Utils$1.monthMod(currentMonth) }); } var month = firstTickValue + 1; var pos = firstTickPosition; // keep drawing rest of the ticks for (var i = 0, j = 1; i < numberOfMonths; i++, j++) { month = Utils$1.monthMod(month); if (month === 0) { unit = 'year'; yrCounter += 1; } else { unit = 'month'; } var _year = this._getYear(currentYear, month, yrCounter); pos = dt.determineDaysOfMonths(month, _year) * daysWidthOnXAxis + pos; var monthVal = month === 0 ? _year : month; this.timeScaleArray.push({ position: pos, value: monthVal, unit: unit, year: _year, month: month === 0 ? 1 : month }); month++; } } }, { key: "generateDayScale", value: function generateDayScale(_ref3) { var firstVal = _ref3.firstVal, currentMonth = _ref3.currentMonth, currentYear = _ref3.currentYear, hoursWidthOnXAxis = _ref3.hoursWidthOnXAxis, numberOfDays = _ref3.numberOfDays; var dt = new DateTime(this.ctx); var unit = 'day'; var firstTickValue = firstVal.minDate + 1; var date = firstTickValue; var changeMonth = function changeMonth(dateVal, month, year) { var monthdays = dt.determineDaysOfMonths(month + 1, year); if (dateVal > monthdays) { month = month + 1; date = 1; unit = 'month'; val = month; return month; } return month; }; var remainingHours = 24 - firstVal.minHour; var yrCounter = 0; // calculate the first tick position var firstTickPosition = remainingHours * hoursWidthOnXAxis; var val = firstTickValue; var month = changeMonth(date, currentMonth, currentYear); if (firstVal.minHour === 0 && firstVal.minDate === 1) { // the first value is the first day of month firstTickPosition = 0; val = Utils$1.monthMod(firstVal.minMonth); unit = 'month'; date = firstVal.minDate; numberOfDays++; } else if (firstVal.minDate !== 1 && firstVal.minHour === 0 && firstVal.minMinute === 0) { // fixes apexcharts/apexcharts.js/issues/1730 firstTickPosition = 0; firstTickValue = firstVal.minDate; date = firstTickValue; val = firstTickValue; // in case it's the last date of month, we need to check it month = changeMonth(date, currentMonth, currentYear); } // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: val, unit: unit, year: this._getYear(currentYear, month, yrCounter), month: Utils$1.monthMod(month), day: date }); var pos = firstTickPosition; // keep drawing rest of the ticks for (var i = 0; i < numberOfDays; i++) { date += 1; unit = 'day'; month = changeMonth(date, month, this._getYear(currentYear, month, yrCounter)); var year = this._getYear(currentYear, month, yrCounter); pos = 24 * hoursWidthOnXAxis + pos; var value = date === 1 ? Utils$1.monthMod(month) : date; this.timeScaleArray.push({ position: pos, value: value, unit: unit, year: year, month: Utils$1.monthMod(month), day: value }); } } }, { key: "generateHourScale", value: function generateHourScale(_ref4) { var firstVal = _ref4.firstVal, currentDate = _ref4.currentDate, currentMonth = _ref4.currentMonth, currentYear = _ref4.currentYear, minutesWidthOnXAxis = _ref4.minutesWidthOnXAxis, numberOfHours = _ref4.numberOfHours; var dt = new DateTime(this.ctx); var yrCounter = 0; var unit = 'hour'; var changeDate = function changeDate(dateVal, month) { var monthdays = dt.determineDaysOfMonths(month + 1, currentYear); if (dateVal > monthdays) { date = 1; month = month + 1; } return { month: month, date: date }; }; var changeMonth = function changeMonth(dateVal, month) { var monthdays = dt.determineDaysOfMonths(month + 1, currentYear); if (dateVal > monthdays) { month = month + 1; return month; } return month; }; // factor in minSeconds as well var remainingMins = 60 - (firstVal.minMinute + firstVal.minSecond / 60.0); var firstTickPosition = remainingMins * minutesWidthOnXAxis; var firstTickValue = firstVal.minHour + 1; var hour = firstTickValue + 1; if (remainingMins === 60) { firstTickPosition = 0; firstTickValue = firstVal.minHour; hour = firstTickValue + 1; } var date = currentDate; var month = changeMonth(date, currentMonth); // push the first tick in the array this.timeScaleArray.push({ position: firstTickPosition, value: firstTickValue, unit: unit, day: date, hour: hour, year: currentYear, month: Utils$1.monthMod(month) }); var pos = firstTickPosition; // keep drawing rest of the ticks for (var i = 0; i < numberOfHours; i++) { unit = 'hour'; if (hour >= 24) { hour = 0; date += 1; unit = 'day'; var checkNextMonth = changeDate(date, month); month = checkNextMonth.month; month = changeMonth(date, month); } var year = this._getYear(currentYear, month, yrCounter); pos = 60 * minutesWidthOnXAxis + pos; var val = hour === 0 ? date : hour; this.timeScaleArray.push({ position: pos, value: val, unit: unit, hour: hour, day: date, year: year, month: Utils$1.monthMod(month) }); hour++; } } }, { key: "generateMinuteScale", value: function generateMinuteScale(_ref5) { var currentMillisecond = _ref5.currentMillisecond, currentSecond = _ref5.currentSecond, currentMinute = _ref5.currentMinute, currentHour = _ref5.currentHour, currentDate = _ref5.currentDate, currentMonth = _ref5.currentMonth, currentYear = _ref5.currentYear, minutesWidthOnXAxis = _ref5.minutesWidthOnXAxis, secondsWidthOnXAxis = _ref5.secondsWidthOnXAxis, numberOfMinutes = _ref5.numberOfMinutes; var yrCounter = 0; var unit = 'minute'; var remainingSecs = 60 - currentSecond; var firstTickPosition = (remainingSecs - currentMillisecond / 1000) * secondsWidthOnXAxis; var minute = currentMinute + 1; var date = currentDate; var month = currentMonth; var year = currentYear; var hour = currentHour; var pos = firstTickPosition; for (var i = 0; i < numberOfMinutes; i++) { if (minute >= 60) { minute = 0; hour += 1; if (hour === 24) { hour = 0; } } this.timeScaleArray.push({ position: pos, value: minute, unit: unit, hour: hour, minute: minute, day: date, year: this._getYear(year, month, yrCounter), month: Utils$1.monthMod(month) }); pos += minutesWidthOnXAxis; minute++; } } }, { key: "generateSecondScale", value: function generateSecondScale(_ref6) { var currentMillisecond = _ref6.currentMillisecond, currentSecond = _ref6.currentSecond, currentMinute = _ref6.currentMinute, currentHour = _ref6.currentHour, currentDate = _ref6.currentDate, currentMonth = _ref6.currentMonth, currentYear = _ref6.currentYear, secondsWidthOnXAxis = _ref6.secondsWidthOnXAxis, numberOfSeconds = _ref6.numberOfSeconds; var yrCounter = 0; var unit = 'second'; var remainingMillisecs = 1000 - currentMillisecond; var firstTickPosition = remainingMillisecs / 1000 * secondsWidthOnXAxis; var second = currentSecond + 1; var minute = currentMinute; var date = currentDate; var month = currentMonth; var year = currentYear; var hour = currentHour; var pos = firstTickPosition; for (var i = 0; i < numberOfSeconds; i++) { if (second >= 60) { minute++; second = 0; if (minute >= 60) { hour++; minute = 0; if (hour === 24) { hour = 0; } } } this.timeScaleArray.push({ position: pos, value: second, unit: unit, hour: hour, minute: minute, second: second, day: date, year: this._getYear(year, month, yrCounter), month: Utils$1.monthMod(month) }); pos += secondsWidthOnXAxis; second++; } } }, { key: "createRawDateString", value: function createRawDateString(ts, value) { var raw = ts.year; if (ts.month === 0) { // invalid month, correct it ts.month = 1; } raw += '-' + ('0' + ts.month.toString()).slice(-2); // unit is day if (ts.unit === 'day') { raw += ts.unit === 'day' ? '-' + ('0' + value).slice(-2) : '-01'; } else { raw += '-' + ('0' + (ts.day ? ts.day : '1')).slice(-2); } // unit is hour if (ts.unit === 'hour') { raw += ts.unit === 'hour' ? 'T' + ('0' + value).slice(-2) : 'T00'; } else { raw += 'T' + ('0' + (ts.hour ? ts.hour : '0')).slice(-2); } if (ts.unit === 'minute') { raw += ':' + ('0' + value).slice(-2); } else { raw += ':' + (ts.minute ? ('0' + ts.minute).slice(-2) : '00'); } if (ts.unit === 'second') { raw += ':' + ('0' + value).slice(-2); } else { raw += ':00'; } if (this.utc) { raw += '.000Z'; } return raw; } }, { key: "formatDates", value: function formatDates(filteredTimeScale) { var _this2 = this; var w = this.w; var reformattedTimescaleArray = filteredTimeScale.map(function (ts) { var value = ts.value.toString(); var dt = new DateTime(_this2.ctx); var raw = _this2.createRawDateString(ts, value); var dateToFormat = dt.getDate(dt.parseDate(raw)); if (!_this2.utc) { // Fixes #1726, #1544, #1485, #1255 dateToFormat = dt.getDate(dt.parseDateWithTimezone(raw)); } if (w.config.xaxis.labels.format === undefined) { var customFormat = 'dd MMM'; var dtFormatter = w.config.xaxis.labels.datetimeFormatter; if (ts.unit === 'year') customFormat = dtFormatter.year; if (ts.unit === 'month') customFormat = dtFormatter.month; if (ts.unit === 'day') customFormat = dtFormatter.day; if (ts.unit === 'hour') customFormat = dtFormatter.hour; if (ts.unit === 'minute') customFormat = dtFormatter.minute; if (ts.unit === 'second') customFormat = dtFormatter.second; value = dt.formatDate(dateToFormat, customFormat); } else { value = dt.formatDate(dateToFormat, w.config.xaxis.labels.format); } return { dateString: raw, position: ts.position, value: value, unit: ts.unit, year: ts.year, month: ts.month }; }); return reformattedTimescaleArray; } }, { key: "removeOverlappingTS", value: function removeOverlappingTS(arr) { var _this3 = this; var graphics = new Graphics(this.ctx); var equalLabelLengthFlag = false; // These labels got same length? var constantLabelWidth; // If true, what is the constant length to use if (arr.length > 0 && // check arr length arr[0].value && // check arr[0] contains value arr.every(function (lb) { return lb.value.length === arr[0].value.length; }) // check every arr label value is the same as the first one ) { equalLabelLengthFlag = true; // These labels got same length constantLabelWidth = graphics.getTextRects(arr[0].value).width; // The constant label width to use } var lastDrawnIndex = 0; var filteredArray = arr.map(function (item, index) { if (index > 0 && _this3.w.config.xaxis.labels.hideOverlappingLabels) { var prevLabelWidth = !equalLabelLengthFlag // if vary in label length ? graphics.getTextRects(arr[lastDrawnIndex].value).width // get individual length : constantLabelWidth; // else: use constant length var prevPos = arr[lastDrawnIndex].position; var pos = item.position; if (pos > prevPos + prevLabelWidth + 10) { lastDrawnIndex = index; return item; } else { return null; } } else { return item; } }); filteredArray = filteredArray.filter(function (f) { return f !== null; }); return filteredArray; } }, { key: "_getYear", value: function _getYear(currentYear, month, yrCounter) { return currentYear + Math.floor(month / 12) + yrCounter; } }]); return TimeScale; }(); /** * ApexCharts Core Class responsible for major calculations and creating elements. * * @module Core **/ var Core = /*#__PURE__*/function () { function Core(el, ctx) { _classCallCheck(this, Core); this.ctx = ctx; this.w = ctx.w; this.el = el; } // get data and store into appropriate vars _createClass(Core, [{ key: "setupElements", value: function setupElements() { var gl = this.w.globals; var cnf = this.w.config; // const graphics = new Graphics(this.ctx) var ct = cnf.chart.type; var axisChartsArrTypes = ['line', 'area', 'bar', 'rangeBar', 'rangeArea', 'candlestick', 'boxPlot', 'scatter', 'bubble', 'radar', 'heatmap', 'treemap']; var xyChartsArrTypes = ['line', 'area', 'bar', 'rangeBar', 'rangeArea', 'candlestick', 'boxPlot', 'scatter', 'bubble']; gl.axisCharts = axisChartsArrTypes.indexOf(ct) > -1; gl.xyCharts = xyChartsArrTypes.indexOf(ct) > -1; gl.isBarHorizontal = (cnf.chart.type === 'bar' || cnf.chart.type === 'rangeBar' || cnf.chart.type === 'boxPlot') && cnf.plotOptions.bar.horizontal; gl.chartClass = '.apexcharts' + gl.chartID; gl.dom.baseEl = this.el; gl.dom.elWrap = document.createElement('div'); Graphics.setAttrs(gl.dom.elWrap, { id: gl.chartClass.substring(1), class: 'apexcharts-canvas ' + gl.chartClass.substring(1) }); this.el.appendChild(gl.dom.elWrap); gl.dom.Paper = new window.SVG.Doc(gl.dom.elWrap); gl.dom.Paper.attr({ class: 'apexcharts-svg', 'xmlns:data': 'ApexChartsNS', transform: "translate(".concat(cnf.chart.offsetX, ", ").concat(cnf.chart.offsetY, ")") }); gl.dom.Paper.node.style.background = cnf.chart.background; this.setSVGDimensions(); gl.dom.elGraphical = gl.dom.Paper.group().attr({ class: 'apexcharts-inner apexcharts-graphical' }); gl.dom.elAnnotations = gl.dom.Paper.group().attr({ class: 'apexcharts-annotations' }); gl.dom.elDefs = gl.dom.Paper.defs(); gl.dom.elLegendWrap = document.createElement('div'); gl.dom.elLegendWrap.classList.add('apexcharts-legend'); gl.dom.elWrap.appendChild(gl.dom.elLegendWrap); gl.dom.Paper.add(gl.dom.elGraphical); gl.dom.elGraphical.add(gl.dom.elDefs); } }, { key: "plotChartType", value: function plotChartType(ser, xyRatios) { var w = this.w; var cnf = w.config; var gl = w.globals; var lineSeries = { series: [], i: [] }; var areaSeries = { series: [], i: [] }; var scatterSeries = { series: [], i: [] }; var bubbleSeries = { series: [], i: [] }; var columnSeries = { series: [], i: [] }; var candlestickSeries = { series: [], i: [] }; var boxplotSeries = { series: [], i: [] }; var rangeBarSeries = { series: [], i: [] }; var rangeAreaSeries = { series: [], seriesRangeEnd: [], i: [] }; gl.series.map(function (serie, st) { var comboCount = 0; // if user has specified a particular type for particular series if (typeof ser[st].type !== 'undefined') { if (ser[st].type === 'column' || ser[st].type === 'bar') { if (gl.series.length > 1 && cnf.plotOptions.bar.horizontal) { // horizontal bars not supported in mixed charts, hence show a warning console.warn('Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`'); } columnSeries.series.push(serie); columnSeries.i.push(st); comboCount++; w.globals.columnSeries = columnSeries.series; } else if (ser[st].type === 'area') { areaSeries.series.push(serie); areaSeries.i.push(st); comboCount++; } else if (ser[st].type === 'line') { lineSeries.series.push(serie); lineSeries.i.push(st); comboCount++; } else if (ser[st].type === 'scatter') { scatterSeries.series.push(serie); scatterSeries.i.push(st); } else if (ser[st].type === 'bubble') { bubbleSeries.series.push(serie); bubbleSeries.i.push(st); comboCount++; } else if (ser[st].type === 'candlestick') { candlestickSeries.series.push(serie); candlestickSeries.i.push(st); comboCount++; } else if (ser[st].type === 'boxPlot') { boxplotSeries.series.push(serie); boxplotSeries.i.push(st); comboCount++; } else if (ser[st].type === 'rangeBar') { rangeBarSeries.series.push(serie); rangeBarSeries.i.push(st); comboCount++; } else if (ser[st].type === 'rangeArea') { rangeAreaSeries.series.push(gl.seriesRangeStart[st]); rangeAreaSeries.seriesRangeEnd.push(gl.seriesRangeEnd[st]); rangeAreaSeries.i.push(st); comboCount++; } else { // user has specified type, but it is not valid (other than line/area/column) console.warn('You have specified an unrecognized chart type. Available types for this property are line/area/column/bar/scatter/bubble'); } if (comboCount > 1) { gl.comboCharts = true; } } else { lineSeries.series.push(serie); lineSeries.i.push(st); } }); var line = new Line(this.ctx, xyRatios); var boxCandlestick = new BoxCandleStick(this.ctx, xyRatios); this.ctx.pie = new Pie(this.ctx); var radialBar = new Radial(this.ctx); this.ctx.rangeBar = new RangeBar(this.ctx, xyRatios); var radar = new Radar(this.ctx); var elGraph = []; if (gl.comboCharts) { if (areaSeries.series.length > 0) { elGraph.push(line.draw(areaSeries.series, 'area', areaSeries.i)); } if (columnSeries.series.length > 0) { if (w.config.chart.stacked) { var barStacked = new BarStacked(this.ctx, xyRatios); elGraph.push(barStacked.draw(columnSeries.series, columnSeries.i)); } else { this.ctx.bar = new Bar(this.ctx, xyRatios); elGraph.push(this.ctx.bar.draw(columnSeries.series, columnSeries.i)); } } if (rangeAreaSeries.series.length > 0) { elGraph.push(line.draw(rangeAreaSeries.series, 'rangeArea', rangeAreaSeries.i, rangeAreaSeries.seriesRangeEnd)); } if (lineSeries.series.length > 0) { elGraph.push(line.draw(lineSeries.series, 'line', lineSeries.i)); } if (candlestickSeries.series.length > 0) { elGraph.push(boxCandlestick.draw(candlestickSeries.series, candlestickSeries.i)); } if (boxplotSeries.series.length > 0) { elGraph.push(boxCandlestick.draw(boxplotSeries.series, boxplotSeries.i)); } if (rangeBarSeries.series.length > 0) { elGraph.push(this.ctx.rangeBar.draw(rangeBarSeries.series, rangeBarSeries.i)); } if (scatterSeries.series.length > 0) { var scatterLine = new Line(this.ctx, xyRatios, true); elGraph.push(scatterLine.draw(scatterSeries.series, 'scatter', scatterSeries.i)); } if (bubbleSeries.series.length > 0) { var bubbleLine = new Line(this.ctx, xyRatios, true); elGraph.push(bubbleLine.draw(bubbleSeries.series, 'bubble', bubbleSeries.i)); } } else { switch (cnf.chart.type) { case 'line': elGraph = line.draw(gl.series, 'line'); break; case 'area': elGraph = line.draw(gl.series, 'area'); break; case 'bar': if (cnf.chart.stacked) { var _barStacked = new BarStacked(this.ctx, xyRatios); elGraph = _barStacked.draw(gl.series); } else { this.ctx.bar = new Bar(this.ctx, xyRatios); elGraph = this.ctx.bar.draw(gl.series); } break; case 'candlestick': var candleStick = new BoxCandleStick(this.ctx, xyRatios); elGraph = candleStick.draw(gl.series); break; case 'boxPlot': var boxPlot = new BoxCandleStick(this.ctx, xyRatios); elGraph = boxPlot.draw(gl.series); break; case 'rangeBar': elGraph = this.ctx.rangeBar.draw(gl.series); break; case 'rangeArea': elGraph = line.draw(gl.seriesRangeStart, 'rangeArea', undefined, gl.seriesRangeEnd); break; case 'heatmap': var heatmap = new HeatMap(this.ctx, xyRatios); elGraph = heatmap.draw(gl.series); break; case 'treemap': var treemap = new TreemapChart(this.ctx, xyRatios); elGraph = treemap.draw(gl.series); break; case 'pie': case 'donut': case 'polarArea': elGraph = this.ctx.pie.draw(gl.series); break; case 'radialBar': elGraph = radialBar.draw(gl.series); break; case 'radar': elGraph = radar.draw(gl.series); break; default: elGraph = line.draw(gl.series); } } return elGraph; } }, { key: "setSVGDimensions", value: function setSVGDimensions() { var gl = this.w.globals; var cnf = this.w.config; gl.svgWidth = cnf.chart.width; gl.svgHeight = cnf.chart.height; var elDim = Utils$1.getDimensions(this.el); var widthUnit = cnf.chart.width.toString().split(/[0-9]+/g).pop(); if (widthUnit === '%') { if (Utils$1.isNumber(elDim[0])) { if (elDim[0].width === 0) { elDim = Utils$1.getDimensions(this.el.parentNode); } gl.svgWidth = elDim[0] * parseInt(cnf.chart.width, 10) / 100; } } else if (widthUnit === 'px' || widthUnit === '') { gl.svgWidth = parseInt(cnf.chart.width, 10); } var heightUnit = cnf.chart.height.toString().split(/[0-9]+/g).pop(); if (gl.svgHeight !== 'auto' && gl.svgHeight !== '') { if (heightUnit === '%') { var elParentDim = Utils$1.getDimensions(this.el.parentNode); gl.svgHeight = elParentDim[1] * parseInt(cnf.chart.height, 10) / 100; } else { gl.svgHeight = parseInt(cnf.chart.height, 10); } } else { if (gl.axisCharts) { gl.svgHeight = gl.svgWidth / 1.61; } else { gl.svgHeight = gl.svgWidth / 1.2; } } if (gl.svgWidth < 0) gl.svgWidth = 0; if (gl.svgHeight < 0) gl.svgHeight = 0; Graphics.setAttrs(gl.dom.Paper.node, { width: gl.svgWidth, height: gl.svgHeight }); if (heightUnit !== '%') { // fixes https://github.com/apexcharts/apexcharts.js/issues/2059 var offsetY = cnf.chart.sparkline.enabled ? 0 : gl.axisCharts ? cnf.chart.parentHeightOffset : 0; gl.dom.Paper.node.parentNode.parentNode.style.minHeight = gl.svgHeight + offsetY + 'px'; } gl.dom.elWrap.style.width = gl.svgWidth + 'px'; gl.dom.elWrap.style.height = gl.svgHeight + 'px'; } }, { key: "shiftGraphPosition", value: function shiftGraphPosition() { var gl = this.w.globals; var tY = gl.translateY; var tX = gl.translateX; var scalingAttrs = { transform: 'translate(' + tX + ', ' + tY + ')' }; Graphics.setAttrs(gl.dom.elGraphical.node, scalingAttrs); } // To prevent extra spacings in the bottom of the chart, we need to recalculate the height for pie/donut/radialbar charts }, { key: "resizeNonAxisCharts", value: function resizeNonAxisCharts() { var w = this.w; var gl = w.globals; var legendHeight = 0; var offY = w.config.chart.sparkline.enabled ? 1 : 15; offY = offY + w.config.grid.padding.bottom; if ((w.config.legend.position === 'top' || w.config.legend.position === 'bottom') && w.config.legend.show && !w.config.legend.floating) { legendHeight = new Legend(this.ctx).legendHelpers.getLegendBBox().clwh + 10; } var el = w.globals.dom.baseEl.querySelector('.apexcharts-radialbar, .apexcharts-pie'); var chartInnerDimensions = w.globals.radialSize * 2.05; if (el && !w.config.chart.sparkline.enabled && w.config.plotOptions.radialBar.startAngle !== 0) { var elRadialRect = Utils$1.getBoundingClientRect(el); chartInnerDimensions = elRadialRect.bottom; var maxHeight = elRadialRect.bottom - elRadialRect.top; chartInnerDimensions = Math.max(w.globals.radialSize * 2.05, maxHeight); } var newHeight = chartInnerDimensions + gl.translateY + legendHeight + offY; if (gl.dom.elLegendForeign) { gl.dom.elLegendForeign.setAttribute('height', newHeight); } // fix apexcharts/apexcharts.js/issues/3105 (when % is provided in height, it keeps increasing) if (w.config.chart.height && String(w.config.chart.height).indexOf('%') > 0) return; gl.dom.elWrap.style.height = newHeight + 'px'; Graphics.setAttrs(gl.dom.Paper.node, { height: newHeight }); gl.dom.Paper.node.parentNode.parentNode.style.minHeight = newHeight + 'px'; } /* ** All the calculations for setting range in charts will be done here */ }, { key: "coreCalculations", value: function coreCalculations() { var range = new Range(this.ctx); range.init(); } }, { key: "resetGlobals", value: function resetGlobals() { var _this = this; var resetxyValues = function resetxyValues() { return _this.w.config.series.map(function (s) { return []; }); }; var globalObj = new Globals(); var gl = this.w.globals; globalObj.initGlobalVars(gl); gl.seriesXvalues = resetxyValues(); gl.seriesYvalues = resetxyValues(); } }, { key: "isMultipleY", value: function isMultipleY() { // user has supplied an array in yaxis property. So, turn on multipleYAxis flag if (this.w.config.yaxis.constructor === Array && this.w.config.yaxis.length > 1) { this.w.globals.isMultipleYAxis = true; return true; } } }, { key: "xySettings", value: function xySettings() { var xyRatios = null; var w = this.w; if (w.globals.axisCharts) { if (w.config.xaxis.crosshairs.position === 'back') { var crosshairs = new Crosshairs(this.ctx); crosshairs.drawXCrosshairs(); } if (w.config.yaxis[0].crosshairs.position === 'back') { var _crosshairs = new Crosshairs(this.ctx); _crosshairs.drawYCrosshairs(); } if (w.config.xaxis.type === 'datetime' && w.config.xaxis.labels.formatter === undefined) { this.ctx.timeScale = new TimeScale(this.ctx); var formattedTimeScale = []; if (isFinite(w.globals.minX) && isFinite(w.globals.maxX) && !w.globals.isBarHorizontal) { formattedTimeScale = this.ctx.timeScale.calculateTimeScaleTicks(w.globals.minX, w.globals.maxX); } else if (w.globals.isBarHorizontal) { formattedTimeScale = this.ctx.timeScale.calculateTimeScaleTicks(w.globals.minY, w.globals.maxY); } this.ctx.timeScale.recalcDimensionsBasedOnFormat(formattedTimeScale); } var coreUtils = new CoreUtils(this.ctx); xyRatios = coreUtils.getCalculatedRatios(); } return xyRatios; } }, { key: "updateSourceChart", value: function updateSourceChart(targetChart) { this.ctx.w.globals.selection = undefined; this.ctx.updateHelpers._updateOptions({ chart: { selection: { xaxis: { min: targetChart.w.globals.minX, max: targetChart.w.globals.maxX } } } }, false, false); } }, { key: "setupBrushHandler", value: function setupBrushHandler() { var _this2 = this; var w = this.w; // only for brush charts if (!w.config.chart.brush.enabled) { return; } // if user has not defined a custom function for selection - we handle the brush chart // otherwise we leave it to the user to define the functionality for selection if (typeof w.config.chart.events.selection !== 'function') { var targets = w.config.chart.brush.targets || [w.config.chart.brush.target]; // retro compatibility with single target option targets.forEach(function (target) { var targetChart = ApexCharts.getChartByID(target); targetChart.w.globals.brushSource = _this2.ctx; if (typeof targetChart.w.config.chart.events.zoomed !== 'function') { targetChart.w.config.chart.events.zoomed = function () { _this2.updateSourceChart(targetChart); }; } if (typeof targetChart.w.config.chart.events.scrolled !== 'function') { targetChart.w.config.chart.events.scrolled = function () { _this2.updateSourceChart(targetChart); }; } }); w.config.chart.events.selection = function (chart, e) { targets.forEach(function (target) { var targetChart = ApexCharts.getChartByID(target); var yaxis = Utils$1.clone(w.config.yaxis); if (w.config.chart.brush.autoScaleYaxis && targetChart.w.globals.series.length === 1) { var scale = new Range$1(targetChart); yaxis = scale.autoScaleY(targetChart, yaxis, e); } var multipleYaxis = targetChart.w.config.yaxis.reduce(function (acc, curr, index) { return [].concat(_toConsumableArray(acc), [_objectSpread2(_objectSpread2({}, targetChart.w.config.yaxis[index]), {}, { min: yaxis[0].min, max: yaxis[0].max })]); }, []); targetChart.ctx.updateHelpers._updateOptions({ xaxis: { min: e.xaxis.min, max: e.xaxis.max }, yaxis: multipleYaxis }, false, false, false, false); }); }; } } }]); return Core; }(); var UpdateHelpers = /*#__PURE__*/function () { function UpdateHelpers(ctx) { _classCallCheck(this, UpdateHelpers); this.ctx = ctx; this.w = ctx.w; } /** * private method to update Options. * * @param {object} options - A new config object can be passed which will be merged with the existing config object * @param {boolean} redraw - should redraw from beginning or should use existing paths and redraw from there * @param {boolean} animate - should animate or not on updating Options * @param {boolean} overwriteInitialConfig - should update the initial config or not */ _createClass(UpdateHelpers, [{ key: "_updateOptions", value: function _updateOptions(options) { var _this = this; var redraw = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var animate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var updateSyncedCharts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var overwriteInitialConfig = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; return new Promise(function (resolve) { var charts = [_this.ctx]; if (updateSyncedCharts) { charts = _this.ctx.getSyncedCharts(); } if (_this.ctx.w.globals.isExecCalled) { // If the user called exec method, we don't want to get grouped charts as user specifically provided a chartID to update charts = [_this.ctx]; _this.ctx.w.globals.isExecCalled = false; } charts.forEach(function (ch, chartIndex) { var w = ch.w; w.globals.shouldAnimate = animate; if (!redraw) { w.globals.resized = true; w.globals.dataChanged = true; if (animate) { ch.series.getPreviousPaths(); } } if (options && _typeof(options) === 'object') { ch.config = new Config(options); options = CoreUtils.extendArrayProps(ch.config, options, w); // fixes #914, #623 if (ch.w.globals.chartID !== _this.ctx.w.globals.chartID) { // don't overwrite series of synchronized charts delete options.series; } w.config = Utils$1.extend(w.config, options); if (overwriteInitialConfig) { // we need to forget the lastXAxis and lastYAxis as user forcefully overwriteInitialConfig. If we do not do this, and next time when user zooms the chart after setting yaxis.min/max or xaxis.min/max - the stored lastXAxis will never allow the chart to use the updated min/max by user. w.globals.lastXAxis = options.xaxis ? Utils$1.clone(options.xaxis) : []; w.globals.lastYAxis = options.yaxis ? Utils$1.clone(options.yaxis) : []; // After forgetting lastAxes, we need to restore the new config in initialConfig/initialSeries w.globals.initialConfig = Utils$1.extend({}, w.config); w.globals.initialSeries = Utils$1.clone(w.config.series); if (options.series) { // Replace the collapsed series data for (var i = 0; i < w.globals.collapsedSeriesIndices.length; i++) { var series = w.config.series[w.globals.collapsedSeriesIndices[i]]; w.globals.collapsedSeries[i].data = w.globals.axisCharts ? series.data.slice() : series; } for (var _i = 0; _i < w.globals.ancillaryCollapsedSeriesIndices.length; _i++) { var _series = w.config.series[w.globals.ancillaryCollapsedSeriesIndices[_i]]; w.globals.ancillaryCollapsedSeries[_i].data = w.globals.axisCharts ? _series.data.slice() : _series; } // Ensure that auto-generated axes are scaled to the visible data ch.series.emptyCollapsedSeries(w.config.series); } } } return ch.update(options).then(function () { if (chartIndex === charts.length - 1) { resolve(ch); } }); }); }); } /** * Private method to update Series. * * @param {array} series - New series which will override the existing */ }, { key: "_updateSeries", value: function _updateSeries(newSeries, animate) { var _this2 = this; var overwriteInitialSeries = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; return new Promise(function (resolve) { var w = _this2.w; w.globals.shouldAnimate = animate; w.globals.dataChanged = true; if (animate) { _this2.ctx.series.getPreviousPaths(); } var existingSeries; // axis charts if (w.globals.axisCharts) { existingSeries = newSeries.map(function (s, i) { return _this2._extendSeries(s, i); }); if (existingSeries.length === 0) { existingSeries = [{ data: [] }]; } w.config.series = existingSeries; } else { // non-axis chart (pie/radialbar) w.config.series = newSeries.slice(); } if (overwriteInitialSeries) { w.globals.initialConfig.series = Utils$1.clone(w.config.series); w.globals.initialSeries = Utils$1.clone(w.config.series); } return _this2.ctx.update().then(function () { resolve(_this2.ctx); }); }); } }, { key: "_extendSeries", value: function _extendSeries(s, i) { var w = this.w; var ser = w.config.series[i]; return _objectSpread2(_objectSpread2({}, w.config.series[i]), {}, { name: s.name ? s.name : ser && ser.name, color: s.color ? s.color : ser && ser.color, type: s.type ? s.type : ser && ser.type, data: s.data ? s.data : ser && ser.data }); } }, { key: "toggleDataPointSelection", value: function toggleDataPointSelection(seriesIndex, dataPointIndex) { var w = this.w; var elPath = null; var parent = ".apexcharts-series[data\\:realIndex='".concat(seriesIndex, "']"); if (w.globals.axisCharts) { elPath = w.globals.dom.Paper.select("".concat(parent, " path[j='").concat(dataPointIndex, "'], ").concat(parent, " circle[j='").concat(dataPointIndex, "'], ").concat(parent, " rect[j='").concat(dataPointIndex, "']")).members[0]; } else { // dataPointIndex will be undefined here, hence using seriesIndex if (typeof dataPointIndex === 'undefined') { elPath = w.globals.dom.Paper.select("".concat(parent, " path[j='").concat(seriesIndex, "']")).members[0]; if (w.config.chart.type === 'pie' || w.config.chart.type === 'polarArea' || w.config.chart.type === 'donut') { this.ctx.pie.pieClicked(seriesIndex); } } } if (elPath) { var graphics = new Graphics(this.ctx); graphics.pathMouseDown(elPath, null); } else { console.warn('toggleDataPointSelection: Element not found'); return null; } return elPath.node ? elPath.node : null; } }, { key: "forceXAxisUpdate", value: function forceXAxisUpdate(options) { var w = this.w; var minmax = ['min', 'max']; minmax.forEach(function (a) { if (typeof options.xaxis[a] !== 'undefined') { w.config.xaxis[a] = options.xaxis[a]; w.globals.lastXAxis[a] = options.xaxis[a]; } }); if (options.xaxis.categories && options.xaxis.categories.length) { w.config.xaxis.categories = options.xaxis.categories; } if (w.config.xaxis.convertedCatToNumeric) { var defaults = new Defaults(options); options = defaults.convertCatToNumericXaxis(options, this.ctx); } return options; } }, { key: "forceYAxisUpdate", value: function forceYAxisUpdate(options) { if (options.chart && options.chart.stacked && options.chart.stackType === '100%') { if (Array.isArray(options.yaxis)) { options.yaxis.forEach(function (yaxe, index) { options.yaxis[index].min = 0; options.yaxis[index].max = 100; }); } else { options.yaxis.min = 0; options.yaxis.max = 100; } } return options; } /** * This function reverts the yaxis and xaxis min/max values to what it was when the chart was defined. * This function fixes an important bug where a user might load a new series after zooming in/out of previous series which resulted in wrong min/max * Also, this should never be called internally on zoom/pan - the reset should only happen when user calls the updateSeries() function externally * The function also accepts an object {xaxis, yaxis} which when present is set as the new xaxis/yaxis */ }, { key: "revertDefaultAxisMinMax", value: function revertDefaultAxisMinMax(opts) { var _this3 = this; var w = this.w; var xaxis = w.globals.lastXAxis; var yaxis = w.globals.lastYAxis; if (opts && opts.xaxis) { xaxis = opts.xaxis; } if (opts && opts.yaxis) { yaxis = opts.yaxis; } w.config.xaxis.min = xaxis.min; w.config.xaxis.max = xaxis.max; var getLastYAxis = function getLastYAxis(index) { if (typeof yaxis[index] !== 'undefined') { w.config.yaxis[index].min = yaxis[index].min; w.config.yaxis[index].max = yaxis[index].max; } }; w.config.yaxis.map(function (yaxe, index) { if (w.globals.zoomed) { // user has zoomed, check the last yaxis getLastYAxis(index); } else { // user hasn't zoomed, check the last yaxis first if (typeof yaxis[index] !== 'undefined') { getLastYAxis(index); } else { // if last y-axis don't exist, check the original yaxis if (typeof _this3.ctx.opts.yaxis[index] !== 'undefined') { yaxe.min = _this3.ctx.opts.yaxis[index].min; yaxe.max = _this3.ctx.opts.yaxis[index].max; } } } }); } }]); return UpdateHelpers; }(); (function (root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define(function () { return factory(root, root.document); }); /* below check fixes #412 */ } else if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined') { module.exports = root.document ? factory(root, root.document) : function (w) { return factory(w, w.document); }; } else { root.SVG = factory(root, root.document); } })(typeof window !== 'undefined' ? window : undefined, function (window, document) { // Find global reference - uses 'this' by default when available, // falls back to 'window' otherwise (for bundlers like Webpack) var globalRef = typeof this !== 'undefined' ? this : window; // The main wrapping element var SVG = globalRef.SVG = function (element) { if (SVG.supported) { element = new SVG.Doc(element); if (!SVG.parser.draw) { SVG.prepare(); } return element; } }; // Default namespaces SVG.ns = 'http://www.w3.org/2000/svg'; SVG.xmlns = 'http://www.w3.org/2000/xmlns/'; SVG.xlink = 'http://www.w3.org/1999/xlink'; SVG.svgjs = 'http://svgjs.dev'; // Svg support test SVG.supported = function () { return true; // !!document.createElementNS && // !! document.createElementNS(SVG.ns,'svg').createSVGRect }(); // Don't bother to continue if SVG is not supported if (!SVG.supported) return false; // Element id sequence SVG.did = 1000; // Get next named element id SVG.eid = function (name) { return 'Svgjs' + capitalize(name) + SVG.did++; }; // Method for element creation SVG.create = function (name) { // create element var element = document.createElementNS(this.ns, name); // apply unique id element.setAttribute('id', this.eid(name)); return element; }; // Method for extending objects SVG.extend = function () { var modules, methods; // Get list of modules modules = [].slice.call(arguments); // Get object with extensions methods = modules.pop(); for (var i = modules.length - 1; i >= 0; i--) { if (modules[i]) { for (var key in methods) { modules[i].prototype[key] = methods[key]; } } } // Make sure SVG.Set inherits any newly added methods if (SVG.Set && SVG.Set.inherit) { SVG.Set.inherit(); } }; // Invent new element SVG.invent = function (config) { // Create element initializer var initializer = typeof config.create === 'function' ? config.create : function () { this.constructor.call(this, SVG.create(config.create)); }; // Inherit prototype if (config.inherit) { initializer.prototype = new config.inherit(); } // Extend with methods if (config.extend) { SVG.extend(initializer, config.extend); } // Attach construct method to parent if (config.construct) { SVG.extend(config.parent || SVG.Container, config.construct); } return initializer; }; // Adopt existing svg elements SVG.adopt = function (node) { // check for presence of node if (!node) return null; // make sure a node isn't already adopted if (node.instance) return node.instance; // initialize variables var element; // adopt with element-specific settings if (node.nodeName == 'svg') { element = node.parentNode instanceof window.SVGElement ? new SVG.Nested() : new SVG.Doc(); } else if (node.nodeName == 'linearGradient') { element = new SVG.Gradient('linear'); } else if (node.nodeName == 'radialGradient') { element = new SVG.Gradient('radial'); } else if (SVG[capitalize(node.nodeName)]) { element = new SVG[capitalize(node.nodeName)](); } else { element = new SVG.Element(node); } // ensure references element.type = node.nodeName; element.node = node; node.instance = element; // SVG.Class specific preparations if (element instanceof SVG.Doc) { element.namespace().defs(); } // pull svgjs data from the dom (getAttributeNS doesn't work in html5) element.setData(JSON.parse(node.getAttribute('svgjs:data')) || {}); return element; }; // Initialize parsing element SVG.prepare = function () { // Select document body and create invisible svg element var body = document.getElementsByTagName('body')[0], draw = (body ? new SVG.Doc(body) : SVG.adopt(document.documentElement).nested()).size(2, 0); // Create parser object SVG.parser = { body: body || document.documentElement, draw: draw.style('opacity:0;position:absolute;left:-100%;top:-100%;overflow:hidden').node, poly: draw.polyline().node, path: draw.path().node, native: SVG.create('svg') }; }; SVG.parser = { native: SVG.create('svg') }; document.addEventListener('DOMContentLoaded', function () { if (!SVG.parser.draw) { SVG.prepare(); } }, false); // Storage for regular expressions SVG.regex = { // Parse unit value numberAndUnit: /^([+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?)([a-z%]*)$/i, // Parse hex value hex: /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i, // Parse rgb value rgb: /rgb\((\d+),(\d+),(\d+)\)/, // Parse reference id reference: /#([a-z0-9\-_]+)/i, // splits a transformation chain transforms: /\)\s*,?\s*/, // Whitespace whitespace: /\s/g, // Test hex value isHex: /^#[a-f0-9]{3,6}$/i, // Test rgb value isRgb: /^rgb\(/, // Test css declaration isCss: /[^:]+:[^;]+;?/, // Test for blank string isBlank: /^(\s+)?$/, // Test for numeric string isNumber: /^[+-]?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, // Test for percent value isPercent: /^-?[\d\.]+%$/, // Test for image url isImage: /\.(jpg|jpeg|png|gif|svg)(\?[^=]+.*)?/i, // split at whitespace and comma delimiter: /[\s,]+/, // The following regex are used to parse the d attribute of a path // Matches all hyphens which are not after an exponent hyphen: /([^e])\-/gi, // Replaces and tests for all path letters pathLetters: /[MLHVCSQTAZ]/gi, // yes we need this one, too isPathLetter: /[MLHVCSQTAZ]/i, // matches 0.154.23.45 numbersWithDots: /((\d?\.\d+(?:e[+-]?\d+)?)((?:\.\d+(?:e[+-]?\d+)?)+))+/gi, // matches . dots: /\./g }; SVG.utils = { // Map function map: function map(array, block) { var il = array.length, result = []; for (var i = 0; i < il; i++) { result.push(block(array[i])); } return result; }, // Filter function filter: function filter(array, block) { var il = array.length, result = []; for (var i = 0; i < il; i++) { if (block(array[i])) { result.push(array[i]); } } return result; }, filterSVGElements: function filterSVGElements(nodes) { return this.filter(nodes, function (el) { return el instanceof window.SVGElement; }); } }; SVG.defaults = { // Default attribute values attrs: { // fill and stroke 'fill-opacity': 1, 'stroke-opacity': 1, 'stroke-width': 0, 'stroke-linejoin': 'miter', 'stroke-linecap': 'butt', fill: '#000000', stroke: '#000000', opacity: 1, // position x: 0, y: 0, cx: 0, cy: 0, // size width: 0, height: 0, // radius r: 0, rx: 0, ry: 0, // gradient offset: 0, 'stop-opacity': 1, 'stop-color': '#000000', // text 'font-size': 16, 'font-family': 'Helvetica, Arial, sans-serif', 'text-anchor': 'start' } }; // Module for color convertions SVG.Color = function (color) { var match; // initialize defaults this.r = 0; this.g = 0; this.b = 0; if (!color) return; // parse color if (typeof color === 'string') { if (SVG.regex.isRgb.test(color)) { // get rgb values match = SVG.regex.rgb.exec(color.replace(SVG.regex.whitespace, '')); // parse numeric values this.r = parseInt(match[1]); this.g = parseInt(match[2]); this.b = parseInt(match[3]); } else if (SVG.regex.isHex.test(color)) { // get hex values match = SVG.regex.hex.exec(fullHex(color)); // parse numeric values this.r = parseInt(match[1], 16); this.g = parseInt(match[2], 16); this.b = parseInt(match[3], 16); } } else if (_typeof(color) === 'object') { this.r = color.r; this.g = color.g; this.b = color.b; } }; SVG.extend(SVG.Color, { // Default to hex conversion toString: function toString() { return this.toHex(); }, // Build hex value toHex: function toHex() { return '#' + compToHex(this.r) + compToHex(this.g) + compToHex(this.b); }, // Build rgb value toRgb: function toRgb() { return 'rgb(' + [this.r, this.g, this.b].join() + ')'; }, // Calculate true brightness brightness: function brightness() { return this.r / 255 * 0.30 + this.g / 255 * 0.59 + this.b / 255 * 0.11; }, // Make color morphable morph: function morph(color) { this.destination = new SVG.Color(color); return this; }, // Get morphed color at given position at: function at(pos) { // make sure a destination is defined if (!this.destination) return this; // normalise pos pos = pos < 0 ? 0 : pos > 1 ? 1 : pos; // generate morphed color return new SVG.Color({ r: ~~(this.r + (this.destination.r - this.r) * pos), g: ~~(this.g + (this.destination.g - this.g) * pos), b: ~~(this.b + (this.destination.b - this.b) * pos) }); } }); // Testers // Test if given value is a color string SVG.Color.test = function (color) { color += ''; return SVG.regex.isHex.test(color) || SVG.regex.isRgb.test(color); }; // Test if given value is a rgb object SVG.Color.isRgb = function (color) { return color && typeof color.r === 'number' && typeof color.g === 'number' && typeof color.b === 'number'; }; // Test if given value is a color SVG.Color.isColor = function (color) { return SVG.Color.isRgb(color) || SVG.Color.test(color); }; // Module for array conversion SVG.Array = function (array, fallback) { array = (array || []).valueOf(); // if array is empty and fallback is provided, use fallback if (array.length == 0 && fallback) { array = fallback.valueOf(); } // parse array this.value = this.parse(array); }; SVG.extend(SVG.Array, { // Convert array to string toString: function toString() { return this.value.join(' '); }, // Real value valueOf: function valueOf() { return this.value; }, // Parse whitespace separated string parse: function parse(array) { array = array.valueOf(); // if already is an array, no need to parse it if (Array.isArray(array)) return array; return this.split(array); } }); // Poly points array SVG.PointArray = function (array, fallback) { SVG.Array.call(this, array, fallback || [[0, 0]]); }; // Inherit from SVG.Array SVG.PointArray.prototype = new SVG.Array(); SVG.PointArray.prototype.constructor = SVG.PointArray; var pathHandlers = { M: function M(c, p, p0) { p.x = p0.x = c[0]; p.y = p0.y = c[1]; return ['M', p.x, p.y]; }, L: function L(c, p) { p.x = c[0]; p.y = c[1]; return ['L', c[0], c[1]]; }, H: function H(c, p) { p.x = c[0]; return ['H', c[0]]; }, V: function V(c, p) { p.y = c[0]; return ['V', c[0]]; }, C: function C(c, p) { p.x = c[4]; p.y = c[5]; return ['C', c[0], c[1], c[2], c[3], c[4], c[5]]; }, Q: function Q(c, p) { p.x = c[2]; p.y = c[3]; return ['Q', c[0], c[1], c[2], c[3]]; }, Z: function Z(c, p, p0) { p.x = p0.x; p.y = p0.y; return ['Z']; } }; var mlhvqtcsa = 'mlhvqtcsaz'.split(''); for (var i = 0, il = mlhvqtcsa.length; i < il; ++i) { pathHandlers[mlhvqtcsa[i]] = function (i) { return function (c, p, p0) { if (i == 'H') c[0] = c[0] + p.x;else if (i == 'V') c[0] = c[0] + p.y;else if (i == 'A') { c[5] = c[5] + p.x, c[6] = c[6] + p.y; } else { for (var j = 0, jl = c.length; j < jl; ++j) { c[j] = c[j] + (j % 2 ? p.y : p.x); } } if (pathHandlers && typeof pathHandlers[i] === 'function') { // this check fixes jest unit tests return pathHandlers[i](c, p, p0); } }; }(mlhvqtcsa[i].toUpperCase()); } // Path points array SVG.PathArray = function (array, fallback) { SVG.Array.call(this, array, fallback || [['M', 0, 0]]); }; // Inherit from SVG.Array SVG.PathArray.prototype = new SVG.Array(); SVG.PathArray.prototype.constructor = SVG.PathArray; SVG.extend(SVG.PathArray, { // Convert array to string toString: function toString() { return arrayToString(this.value); }, // Move path string move: function move(x, y) { // get bounding box of current situation var box = this.bbox(); // get relative offset x -= box.x; y -= box.y; return this; }, // Get morphed path array at given position at: function at(pos) { // make sure a destination is defined if (!this.destination) return this; var sourceArray = this.value, destinationArray = this.destination.value, array = [], pathArray = new SVG.PathArray(), il, jl; // Animate has specified in the SVG spec // See: https://www.w3.org/TR/SVG11/paths.html#PathElement for (var i = 0, il = sourceArray.length; i < il; i++) { array[i] = [sourceArray[i][0]]; for (var j = 1, jl = sourceArray[i].length; j < jl; j++) { array[i][j] = sourceArray[i][j] + (destinationArray[i][j] - sourceArray[i][j]) * pos; } // For the two flags of the elliptical arc command, the SVG spec say: // Flags and booleans are interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true // Elliptical arc command as an array followed by corresponding indexes: // ['A', rx, ry, x-axis-rotation, large-arc-flag, sweep-flag, x, y] // 0 1 2 3 4 5 6 7 if (array[i][0] === 'A') { array[i][4] = +(array[i][4] != 0); array[i][5] = +(array[i][5] != 0); } } // Directly modify the value of a path array, this is done this way for performance pathArray.value = array; return pathArray; }, // Absolutize and parse path to array parse: function parse(array) { // if it's already a patharray, no need to parse it if (array instanceof SVG.PathArray) return array.valueOf(); // prepare for parsing var s, arr, paramCnt = { 'M': 2, 'L': 2, 'H': 1, 'V': 1, 'C': 6, 'S': 4, 'Q': 4, 'T': 2, 'A': 7, 'Z': 0 }; if (typeof array === 'string') { array = array.replace(SVG.regex.numbersWithDots, pathRegReplace) // convert 45.123.123 to 45.123 .123 .replace(SVG.regex.pathLetters, ' $& ') // put some room between letters and numbers .replace(SVG.regex.hyphen, '$1 -') // add space before hyphen .trim() // trim .split(SVG.regex.delimiter); // split into array } else { array = array.reduce(function (prev, curr) { return [].concat.call(prev, curr); }, []); } // array now is an array containing all parts of a path e.g. ['M', '0', '0', 'L', '30', '30' ...] var arr = [], p = new SVG.Point(), p0 = new SVG.Point(), index = 0, len = array.length; do { // Test if we have a path letter if (SVG.regex.isPathLetter.test(array[index])) { s = array[index]; ++index; // If last letter was a move command and we got no new, it defaults to [L]ine } else if (s == 'M') { s = 'L'; } else if (s == 'm') { s = 'l'; } arr.push(pathHandlers[s].call(null, array.slice(index, index = index + paramCnt[s.toUpperCase()]).map(parseFloat), p, p0)); } while (len > index); return arr; }, // Get bounding box of path bbox: function bbox() { if (!SVG.parser.draw) { SVG.prepare(); } SVG.parser.path.setAttribute('d', this.toString()); return SVG.parser.path.getBBox(); } }); // Module for unit convertions SVG.Number = SVG.invent({ // Initialize create: function create(value, unit) { // initialize defaults this.value = 0; this.unit = unit || ''; // parse value if (typeof value === 'number') { // ensure a valid numeric value this.value = isNaN(value) ? 0 : !isFinite(value) ? value < 0 ? -3.4e+38 : +3.4e+38 : value; } else if (typeof value === 'string') { unit = value.match(SVG.regex.numberAndUnit); if (unit) { // make value numeric this.value = parseFloat(unit[1]); // normalize if (unit[5] == '%') { this.value /= 100; } else if (unit[5] == 's') { this.value *= 1000; } // store unit this.unit = unit[5]; } } else { if (value instanceof SVG.Number) { this.value = value.valueOf(); this.unit = value.unit; } } }, // Add methods extend: { // Stringalize toString: function toString() { return (this.unit == '%' ? ~~(this.value * 1e8) / 1e6 : this.unit == 's' ? this.value / 1e3 : this.value) + this.unit; }, toJSON: function toJSON() { return this.toString(); }, // Convert to primitive valueOf: function valueOf() { return this.value; }, // Add number plus: function plus(number) { number = new SVG.Number(number); return new SVG.Number(this + number, this.unit || number.unit); }, // Subtract number minus: function minus(number) { number = new SVG.Number(number); return new SVG.Number(this - number, this.unit || number.unit); }, // Multiply number times: function times(number) { number = new SVG.Number(number); return new SVG.Number(this * number, this.unit || number.unit); }, // Divide number divide: function divide(number) { number = new SVG.Number(number); return new SVG.Number(this / number, this.unit || number.unit); }, // Convert to different unit to: function to(unit) { var number = new SVG.Number(this); if (typeof unit === 'string') { number.unit = unit; } return number; }, // Make number morphable morph: function morph(number) { this.destination = new SVG.Number(number); if (number.relative) { this.destination.value += this.value; } return this; }, // Get morphed number at given position at: function at(pos) { // Make sure a destination is defined if (!this.destination) return this; // Generate new morphed number return new SVG.Number(this.destination).minus(this).times(pos).plus(this); } } }); SVG.Element = SVG.invent({ // Initialize node create: function create(node) { // make stroke value accessible dynamically this._stroke = SVG.defaults.attrs.stroke; this._event = null; // initialize data object this.dom = {}; // create circular reference if (this.node = node) { this.type = node.nodeName; this.node.instance = this; // store current attribute value this._stroke = node.getAttribute('stroke') || this._stroke; } }, // Add class methods extend: { // Move over x-axis x: function x(_x) { return this.attr('x', _x); }, // Move over y-axis y: function y(_y) { return this.attr('y', _y); }, // Move by center over x-axis cx: function cx(x) { return x == null ? this.x() + this.width() / 2 : this.x(x - this.width() / 2); }, // Move by center over y-axis cy: function cy(y) { return y == null ? this.y() + this.height() / 2 : this.y(y - this.height() / 2); }, // Move element to given x and y values move: function move(x, y) { return this.x(x).y(y); }, // Move element by its center center: function center(x, y) { return this.cx(x).cy(y); }, // Set width of element width: function width(_width) { return this.attr('width', _width); }, // Set height of element height: function height(_height) { return this.attr('height', _height); }, // Set element size to given width and height size: function size(width, height) { var p = proportionalSize(this, width, height); return this.width(new SVG.Number(p.width)).height(new SVG.Number(p.height)); }, // Clone element clone: function clone(parent) { // write dom data to the dom so the clone can pickup the data this.writeDataToDom(); // clone element and assign new id var clone = assignNewId(this.node.cloneNode(true)); // insert the clone in the given parent or after myself if (parent) parent.add(clone);else this.after(clone); return clone; }, // Remove element remove: function remove() { if (this.parent()) { this.parent().removeElement(this); } return this; }, // Replace element replace: function replace(element) { this.after(element).remove(); return element; }, // Add element to given container and return self addTo: function addTo(parent) { return parent.put(this); }, // Add element to given container and return container putIn: function putIn(parent) { return parent.add(this); }, // Get / set id id: function id(_id) { return this.attr('id', _id); }, // Show element show: function show() { return this.style('display', ''); }, // Hide element hide: function hide() { return this.style('display', 'none'); }, // Is element visible? visible: function visible() { return this.style('display') != 'none'; }, // Return id on string conversion toString: function toString() { return this.attr('id'); }, // Return array of classes on the node classes: function classes() { var attr = this.attr('class'); return attr == null ? [] : attr.trim().split(SVG.regex.delimiter); }, // Return true if class exists on the node, false otherwise hasClass: function hasClass(name) { return this.classes().indexOf(name) != -1; }, // Add class to the node addClass: function addClass(name) { if (!this.hasClass(name)) { var array = this.classes(); array.push(name); this.attr('class', array.join(' ')); } return this; }, // Remove class from the node removeClass: function removeClass(name) { if (this.hasClass(name)) { this.attr('class', this.classes().filter(function (c) { return c != name; }).join(' ')); } return this; }, // Toggle the presence of a class on the node toggleClass: function toggleClass(name) { return this.hasClass(name) ? this.removeClass(name) : this.addClass(name); }, // Get referenced element form attribute value reference: function reference(attr) { return SVG.get(this.attr(attr)); }, // Returns the parent element instance parent: function parent(type) { var parent = this; // check for parent if (!parent.node.parentNode) return null; // get parent element parent = SVG.adopt(parent.node.parentNode); if (!type) return parent; // loop trough ancestors if type is given while (parent && parent.node instanceof window.SVGElement) { if (typeof type === 'string' ? parent.matches(type) : parent instanceof type) return parent; if (!parent.node.parentNode || parent.node.parentNode.nodeName == '#document') return null; // #759, #720 parent = SVG.adopt(parent.node.parentNode); } }, // Get parent document doc: function doc() { return this instanceof SVG.Doc ? this : this.parent(SVG.Doc); }, // return array of all ancestors of given type up to the root svg parents: function parents(type) { var parents = [], parent = this; do { parent = parent.parent(type); if (!parent || !parent.node) break; parents.push(parent); } while (parent.parent); return parents; }, // matches the element vs a css selector matches: function matches(selector) { return _matches(this.node, selector); }, // Returns the svg node to call native svg methods on it native: function native() { return this.node; }, // Import raw svg svg: function svg(_svg) { // create temporary holder var well = document.createElement('svg'); // act as a setter if svg is given if (_svg && this instanceof SVG.Parent) { // dump raw svg well.innerHTML = '' + _svg.replace(/\n/, '').replace(/<([\w:-]+)([^<]+?)\/>/g, '<$1$2>') + ''; // transplant nodes for (var i = 0, il = well.firstChild.childNodes.length; i < il; i++) { this.node.appendChild(well.firstChild.firstChild); } // otherwise act as a getter } else { // create a wrapping svg element in case of partial content well.appendChild(_svg = document.createElement('svg')); // write svgjs data to the dom this.writeDataToDom(); // insert a copy of this node _svg.appendChild(this.node.cloneNode(true)); // return target element return well.innerHTML.replace(/^/, '').replace(/<\/svg>$/, ''); } return this; }, // write svgjs data to the dom writeDataToDom: function writeDataToDom() { // dump variables recursively if (this.each || this.lines) { var fn = this.each ? this : this.lines(); fn.each(function () { this.writeDataToDom(); }); } // remove previously set data this.node.removeAttribute('svgjs:data'); if (Object.keys(this.dom).length) { this.node.setAttribute('svgjs:data', JSON.stringify(this.dom)); } // see #428 return this; }, // set given data to the elements data property setData: function setData(o) { this.dom = o; return this; }, is: function is(obj) { return _is(this, obj); } } }); SVG.easing = { '-': function _(pos) { return pos; }, '<>': function _(pos) { return -Math.cos(pos * Math.PI) / 2 + 0.5; }, '>': function _(pos) { return Math.sin(pos * Math.PI / 2); }, '<': function _(pos) { return -Math.cos(pos * Math.PI / 2) + 1; } }; SVG.morph = function (pos) { return function (from, to) { return new SVG.MorphObj(from, to).at(pos); }; }; SVG.Situation = SVG.invent({ create: function create(o) { this.init = false; this.reversed = false; this.reversing = false; this.duration = new SVG.Number(o.duration).valueOf(); this.delay = new SVG.Number(o.delay).valueOf(); this.start = +new Date() + this.delay; this.finish = this.start + this.duration; this.ease = o.ease; // this.loop is incremented from 0 to this.loops // it is also incremented when in an infinite loop (when this.loops is true) this.loop = 0; this.loops = false; this.animations = {// functionToCall: [list of morphable objects] // e.g. move: [SVG.Number, SVG.Number] }; this.attrs = {// holds all attributes which are not represented from a function svg.js provides // e.g. someAttr: SVG.Number }; this.styles = {// holds all styles which should be animated // e.g. fill-color: SVG.Color }; this.transforms = [// holds all transformations as transformation objects // e.g. [SVG.Rotate, SVG.Translate, SVG.Matrix] ]; this.once = {// functions to fire at a specific position // e.g. "0.5": function foo(){} }; } }); SVG.FX = SVG.invent({ create: function create(element) { this._target = element; this.situations = []; this.active = false; this.situation = null; this.paused = false; this.lastPos = 0; this.pos = 0; // The absolute position of an animation is its position in the context of its complete duration (including delay and loops) // When performing a delay, absPos is below 0 and when performing a loop, its value is above 1 this.absPos = 0; this._speed = 1; }, extend: { /** * sets or returns the target of this animation * @param o object || number In case of Object it holds all parameters. In case of number its the duration of the animation * @param ease function || string Function which should be used for easing or easing keyword * @param delay Number indicating the delay before the animation starts * @return target || this */ animate: function animate(o, ease, delay) { if (_typeof(o) === 'object') { ease = o.ease; delay = o.delay; o = o.duration; } var situation = new SVG.Situation({ duration: o || 1000, delay: delay || 0, ease: SVG.easing[ease || '-'] || ease }); this.queue(situation); return this; }, /** * sets a delay before the next element of the queue is called * @param delay Duration of delay in milliseconds * @return this.target() */ /** * sets or returns the target of this animation * @param null || target SVG.Element which should be set as new target * @return target || this */ target: function target(_target) { if (_target && _target instanceof SVG.Element) { this._target = _target; return this; } return this._target; }, // returns the absolute position at a given time timeToAbsPos: function timeToAbsPos(timestamp) { return (timestamp - this.situation.start) / (this.situation.duration / this._speed); }, // returns the timestamp from a given absolute positon absPosToTime: function absPosToTime(absPos) { return this.situation.duration / this._speed * absPos + this.situation.start; }, // starts the animationloop startAnimFrame: function startAnimFrame() { this.stopAnimFrame(); this.animationFrame = window.requestAnimationFrame(function () { this.step(); }.bind(this)); }, // cancels the animationframe stopAnimFrame: function stopAnimFrame() { window.cancelAnimationFrame(this.animationFrame); }, // kicks off the animation - only does something when the queue is currently not active and at least one situation is set start: function start() { // dont start if already started if (!this.active && this.situation) { this.active = true; this.startCurrent(); } return this; }, // start the current situation startCurrent: function startCurrent() { this.situation.start = +new Date() + this.situation.delay / this._speed; this.situation.finish = this.situation.start + this.situation.duration / this._speed; return this.initAnimations().step(); }, /** * adds a function / Situation to the animation queue * @param fn function / situation to add * @return this */ queue: function queue(fn) { if (typeof fn === 'function' || fn instanceof SVG.Situation) { this.situations.push(fn); } if (!this.situation) this.situation = this.situations.shift(); return this; }, /** * pulls next element from the queue and execute it * @return this */ dequeue: function dequeue() { // stop current animation this.stop(); // get next animation from queue this.situation = this.situations.shift(); if (this.situation) { if (this.situation instanceof SVG.Situation) { this.start(); } else { // If it is not a SVG.Situation, then it is a function, we execute it this.situation.call(this); } } return this; }, // updates all animations to the current state of the element // this is important when one property could be changed from another property initAnimations: function initAnimations() { var source; var s = this.situation; if (s.init) return this; for (var i in s.animations) { source = this.target()[i](); if (!Array.isArray(source)) { source = [source]; } if (!Array.isArray(s.animations[i])) { s.animations[i] = [s.animations[i]]; } // if(s.animations[i].length > source.length) { // source.concat = source.concat(s.animations[i].slice(source.length, s.animations[i].length)) // } for (var j = source.length; j--;) { // The condition is because some methods return a normal number instead // of a SVG.Number if (s.animations[i][j] instanceof SVG.Number) { source[j] = new SVG.Number(source[j]); } s.animations[i][j] = source[j].morph(s.animations[i][j]); } } for (var i in s.attrs) { s.attrs[i] = new SVG.MorphObj(this.target().attr(i), s.attrs[i]); } for (var i in s.styles) { s.styles[i] = new SVG.MorphObj(this.target().style(i), s.styles[i]); } s.initialTransformation = this.target().matrixify(); s.init = true; return this; }, clearQueue: function clearQueue() { this.situations = []; return this; }, clearCurrent: function clearCurrent() { this.situation = null; return this; }, /** stops the animation immediately * @param jumpToEnd A Boolean indicating whether to complete the current animation immediately. * @param clearQueue A Boolean indicating whether to remove queued animation as well. * @return this */ stop: function stop(jumpToEnd, clearQueue) { var active = this.active; this.active = false; if (clearQueue) { this.clearQueue(); } if (jumpToEnd && this.situation) { // initialize the situation if it was not !active && this.startCurrent(); this.atEnd(); } this.stopAnimFrame(); return this.clearCurrent(); }, after: function after(fn) { var c = this.last(), wrapper = function wrapper(e) { if (e.detail.situation == c) { fn.call(this, c); this.off('finished.fx', wrapper); // prevent memory leak } }; this.target().on('finished.fx', wrapper); return this._callStart(); }, // adds a callback which is called whenever one animation step is performed during: function during(fn) { var c = this.last(), wrapper = function wrapper(e) { if (e.detail.situation == c) { fn.call(this, e.detail.pos, SVG.morph(e.detail.pos), e.detail.eased, c); } }; // see above this.target().off('during.fx', wrapper).on('during.fx', wrapper); this.after(function () { this.off('during.fx', wrapper); }); return this._callStart(); }, // calls after ALL animations in the queue are finished afterAll: function afterAll(fn) { var wrapper = function wrapper(e) { fn.call(this); this.off('allfinished.fx', wrapper); }; // see above this.target().off('allfinished.fx', wrapper).on('allfinished.fx', wrapper); return this._callStart(); }, last: function last() { return this.situations.length ? this.situations[this.situations.length - 1] : this.situation; }, // adds one property to the animations add: function add(method, args, type) { this.last()[type || 'animations'][method] = args; return this._callStart(); }, /** perform one step of the animation * @param ignoreTime Boolean indicating whether to ignore time and use position directly or recalculate position based on time * @return this */ step: function step(ignoreTime) { // convert current time to an absolute position if (!ignoreTime) this.absPos = this.timeToAbsPos(+new Date()); // This part convert an absolute position to a position if (this.situation.loops !== false) { var absPos, absPosInt, lastLoop; // If the absolute position is below 0, we just treat it as if it was 0 absPos = Math.max(this.absPos, 0); absPosInt = Math.floor(absPos); if (this.situation.loops === true || absPosInt < this.situation.loops) { this.pos = absPos - absPosInt; lastLoop = this.situation.loop; this.situation.loop = absPosInt; } else { this.absPos = this.situation.loops; this.pos = 1; // The -1 here is because we don't want to toggle reversed when all the loops have been completed lastLoop = this.situation.loop - 1; this.situation.loop = this.situation.loops; } if (this.situation.reversing) { // Toggle reversed if an odd number of loops as occured since the last call of step this.situation.reversed = this.situation.reversed != Boolean((this.situation.loop - lastLoop) % 2); } } else { // If there are no loop, the absolute position must not be above 1 this.absPos = Math.min(this.absPos, 1); this.pos = this.absPos; } // while the absolute position can be below 0, the position must not be below 0 if (this.pos < 0) this.pos = 0; if (this.situation.reversed) this.pos = 1 - this.pos; // apply easing var eased = this.situation.ease(this.pos); // call once-callbacks for (var i in this.situation.once) { if (i > this.lastPos && i <= eased) { this.situation.once[i].call(this.target(), this.pos, eased); delete this.situation.once[i]; } } // fire during callback with position, eased position and current situation as parameter if (this.active) this.target().fire('during', { pos: this.pos, eased: eased, fx: this, situation: this.situation }); // the user may call stop or finish in the during callback // so make sure that we still have a valid situation if (!this.situation) { return this; } // apply the actual animation to every property this.eachAt(); // do final code when situation is finished if (this.pos == 1 && !this.situation.reversed || this.situation.reversed && this.pos == 0) { // stop animation callback this.stopAnimFrame(); // fire finished callback with current situation as parameter this.target().fire('finished', { fx: this, situation: this.situation }); if (!this.situations.length) { this.target().fire('allfinished'); // Recheck the length since the user may call animate in the afterAll callback if (!this.situations.length) { this.target().off('.fx'); // there shouldnt be any binding left, but to make sure... this.active = false; } } // start next animation if (this.active) this.dequeue();else this.clearCurrent(); } else if (!this.paused && this.active) { // we continue animating when we are not at the end this.startAnimFrame(); } // save last eased position for once callback triggering this.lastPos = eased; return this; }, // calculates the step for every property and calls block with it eachAt: function eachAt() { var len, at, self = this, target = this.target(), s = this.situation; // apply animations which can be called trough a method for (var i in s.animations) { at = [].concat(s.animations[i]).map(function (el) { return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el; }); target[i].apply(target, at); } // apply animation which has to be applied with attr() for (var i in s.attrs) { at = [i].concat(s.attrs[i]).map(function (el) { return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el; }); target.attr.apply(target, at); } // apply animation which has to be applied with style() for (var i in s.styles) { at = [i].concat(s.styles[i]).map(function (el) { return typeof el !== 'string' && el.at ? el.at(s.ease(self.pos), self.pos) : el; }); target.style.apply(target, at); } // animate initialTransformation which has to be chained if (s.transforms.length) { // get initial initialTransformation at = s.initialTransformation; for (var i = 0, len = s.transforms.length; i < len; i++) { // get next transformation in chain var a = s.transforms[i]; // multiply matrix directly if (a instanceof SVG.Matrix) { if (a.relative) { at = at.multiply(new SVG.Matrix().morph(a).at(s.ease(this.pos))); } else { at = at.morph(a).at(s.ease(this.pos)); } continue; } // when transformation is absolute we have to reset the needed transformation first if (!a.relative) { a.undo(at.extract()); } // and reapply it after at = at.multiply(a.at(s.ease(this.pos))); } // set new matrix on element target.matrix(at); } return this; }, // adds an once-callback which is called at a specific position and never again once: function once(pos, fn, isEased) { var c = this.last(); if (!isEased) pos = c.ease(pos); c.once[pos] = fn; return this; }, _callStart: function _callStart() { setTimeout(function () { this.start(); }.bind(this), 0); return this; } }, parent: SVG.Element, // Add method to parent elements construct: { // Get fx module or create a new one, then animate with given duration and ease animate: function animate(o, ease, delay) { return (this.fx || (this.fx = new SVG.FX(this))).animate(o, ease, delay); }, delay: function delay(_delay) { return (this.fx || (this.fx = new SVG.FX(this))).delay(_delay); }, stop: function stop(jumpToEnd, clearQueue) { if (this.fx) { this.fx.stop(jumpToEnd, clearQueue); } return this; }, finish: function finish() { if (this.fx) { this.fx.finish(); } return this; } } }); // MorphObj is used whenever no morphable object is given SVG.MorphObj = SVG.invent({ create: function create(from, to) { // prepare color for morphing if (SVG.Color.isColor(to)) return new SVG.Color(from).morph(to); // check if we have a list of values if (SVG.regex.delimiter.test(from)) { // prepare path for morphing if (SVG.regex.pathLetters.test(from)) return new SVG.PathArray(from).morph(to); // prepare value list for morphing else return new SVG.Array(from).morph(to); } // prepare number for morphing if (SVG.regex.numberAndUnit.test(to)) return new SVG.Number(from).morph(to); // prepare for plain morphing this.value = from; this.destination = to; }, extend: { at: function at(pos, real) { return real < 1 ? this.value : this.destination; }, valueOf: function valueOf() { return this.value; } } }); SVG.extend(SVG.FX, { // Add animatable attributes attr: function attr(a, v, relative) { // apply attributes individually if (_typeof(a) === 'object') { for (var key in a) { this.attr(key, a[key]); } } else { this.add(a, v, 'attrs'); } return this; }, // Add animatable plot plot: function plot(a, b, c, d) { // Lines can be plotted with 4 arguments if (arguments.length == 4) { return this.plot([a, b, c, d]); } return this.add('plot', new (this.target().morphArray)(a)); } }); SVG.Box = SVG.invent({ create: function create(x, y, width, height) { if (_typeof(x) === 'object' && !(x instanceof SVG.Element)) { // chromes getBoundingClientRect has no x and y property return SVG.Box.call(this, x.left != null ? x.left : x.x, x.top != null ? x.top : x.y, x.width, x.height); } else if (arguments.length == 4) { this.x = x; this.y = y; this.width = width; this.height = height; } // add center, right, bottom... fullBox(this); } }); SVG.BBox = SVG.invent({ // Initialize create: function create(element) { SVG.Box.apply(this, [].slice.call(arguments)); // get values if element is given if (element instanceof SVG.Element) { var box; // yes this is ugly, but Firefox can be a pain when it comes to elements that are not yet rendered try { if (!document.documentElement.contains) { // This is IE - it does not support contains() for top-level SVGs var topParent = element.node; while (topParent.parentNode) { topParent = topParent.parentNode; } if (topParent != document) throw new Error('Element not in the dom'); } else {// the element is NOT in the dom, throw error // disabling the check below which fixes issue #76 // if (!document.documentElement.contains(element.node)) throw new Exception('Element not in the dom') } // find native bbox box = element.node.getBBox(); } catch (e) { if (element instanceof SVG.Shape) { if (!SVG.parser.draw) { // fixes apexcharts/vue-apexcharts #14 SVG.prepare(); } var clone = element.clone(SVG.parser.draw.instance).show(); if (clone && clone.node && typeof clone.node.getBBox === 'function') { // this check fixes jest unit tests box = clone.node.getBBox(); } if (clone && typeof clone.remove === 'function') { clone.remove(); } } else { box = { x: element.node.clientLeft, y: element.node.clientTop, width: element.node.clientWidth, height: element.node.clientHeight }; } } SVG.Box.call(this, box); } }, // Define ancestor inherit: SVG.Box, // Define Parent parent: SVG.Element, // Constructor construct: { // Get bounding box bbox: function bbox() { return new SVG.BBox(this); } } }); SVG.BBox.prototype.constructor = SVG.BBox; SVG.Matrix = SVG.invent({ // Initialize create: function create(source) { var base = arrayToMatrix([1, 0, 0, 1, 0, 0]); // ensure source as object source = source === null ? base : source instanceof SVG.Element ? source.matrixify() : typeof source === 'string' ? arrayToMatrix(source.split(SVG.regex.delimiter).map(parseFloat)) : arguments.length == 6 ? arrayToMatrix([].slice.call(arguments)) : Array.isArray(source) ? arrayToMatrix(source) : source && _typeof(source) === 'object' ? source : base; // merge source for (var i = abcdef.length - 1; i >= 0; --i) { this[abcdef[i]] = source[abcdef[i]] != null ? source[abcdef[i]] : base[abcdef[i]]; } }, // Add methods extend: { // Extract individual transformations extract: function extract() { // find delta transform points var px = deltaTransformPoint(this, 0, 1); deltaTransformPoint(this, 1, 0); var skewX = 180 / Math.PI * Math.atan2(px.y, px.x) - 90; return { // translation x: this.e, y: this.f, transformedX: (this.e * Math.cos(skewX * Math.PI / 180) + this.f * Math.sin(skewX * Math.PI / 180)) / Math.sqrt(this.a * this.a + this.b * this.b), transformedY: (this.f * Math.cos(skewX * Math.PI / 180) + this.e * Math.sin(-skewX * Math.PI / 180)) / Math.sqrt(this.c * this.c + this.d * this.d), // rotation rotation: skewX, a: this.a, b: this.b, c: this.c, d: this.d, e: this.e, f: this.f, matrix: new SVG.Matrix(this) }; }, // Clone matrix clone: function clone() { return new SVG.Matrix(this); }, // Morph one matrix into another morph: function morph(matrix) { // store new destination this.destination = new SVG.Matrix(matrix); return this; }, // Multiplies by given matrix multiply: function multiply(matrix) { return new SVG.Matrix(this.native().multiply(parseMatrix(matrix).native())); }, // Inverses matrix inverse: function inverse() { return new SVG.Matrix(this.native().inverse()); }, // Translate matrix translate: function translate(x, y) { return new SVG.Matrix(this.native().translate(x || 0, y || 0)); }, // Convert to native SVGMatrix native: function native() { // create new matrix var matrix = SVG.parser.native.createSVGMatrix(); // update with current values for (var i = abcdef.length - 1; i >= 0; i--) { matrix[abcdef[i]] = this[abcdef[i]]; } return matrix; }, // Convert matrix to string toString: function toString() { // Construct the matrix directly, avoid values that are too small return 'matrix(' + float32String(this.a) + ',' + float32String(this.b) + ',' + float32String(this.c) + ',' + float32String(this.d) + ',' + float32String(this.e) + ',' + float32String(this.f) + ')'; } }, // Define parent parent: SVG.Element, // Add parent method construct: { // Get current matrix ctm: function ctm() { return new SVG.Matrix(this.node.getCTM()); }, // Get current screen matrix screenCTM: function screenCTM() { /* https://bugzilla.mozilla.org/show_bug.cgi?id=1344537 This is needed because FF does not return the transformation matrix for the inner coordinate system when getScreenCTM() is called on nested svgs. However all other Browsers do that */ if (this instanceof SVG.Nested) { var rect = this.rect(1, 1); var m = rect.node.getScreenCTM(); rect.remove(); return new SVG.Matrix(m); } return new SVG.Matrix(this.node.getScreenCTM()); } } }); SVG.Point = SVG.invent({ // Initialize create: function create(x, y) { var source, base = { x: 0, y: 0 }; // ensure source as object source = Array.isArray(x) ? { x: x[0], y: x[1] } : _typeof(x) === 'object' ? { x: x.x, y: x.y } : x != null ? { x: x, y: y != null ? y : x } : base; // If y has no value, then x is used has its value // merge source this.x = source.x; this.y = source.y; }, // Add methods extend: { // Clone point clone: function clone() { return new SVG.Point(this); }, // Morph one point into another morph: function morph(x, y) { // store new destination this.destination = new SVG.Point(x, y); return this; } } }); SVG.extend(SVG.Element, { // Get point point: function point(x, y) { return new SVG.Point(x, y).transform(this.screenCTM().inverse()); } }); SVG.extend(SVG.Element, { // Set svg element attribute attr: function attr(a, v, n) { // act as full getter if (a == null) { // get an object of attributes a = {}; v = this.node.attributes; for (var n = v.length - 1; n >= 0; n--) { a[v[n].nodeName] = SVG.regex.isNumber.test(v[n].nodeValue) ? parseFloat(v[n].nodeValue) : v[n].nodeValue; } return a; } else if (_typeof(a) === 'object') { // apply every attribute individually if an object is passed for (var v_ in a) { this.attr(v_, a[v_]); } } else if (v === null) { // remove value this.node.removeAttribute(a); } else if (v == null) { // act as a getter if the first and only argument is not an object v = this.node.getAttribute(a); return v == null ? SVG.defaults.attrs[a] : SVG.regex.isNumber.test(v) ? parseFloat(v) : v; } else { // BUG FIX: some browsers will render a stroke if a color is given even though stroke width is 0 if (a == 'stroke-width') { this.attr('stroke', parseFloat(v) > 0 ? this._stroke : null); } else if (a == 'stroke') { this._stroke = v; } // convert image fill and stroke to patterns if (a == 'fill' || a == 'stroke') { if (SVG.regex.isImage.test(v)) { v = this.doc().defs().image(v, 0, 0); } if (v instanceof SVG.Image) { v = this.doc().defs().pattern(0, 0, function () { this.add(v); }); } } // ensure correct numeric values (also accepts NaN and Infinity) if (typeof v === 'number') { v = new SVG.Number(v); } // ensure full hex color else if (SVG.Color.isColor(v)) { v = new SVG.Color(v); } // parse array values else if (Array.isArray(v)) { v = new SVG.Array(v); } // if the passed attribute is leading... if (a == 'leading') { // ... call the leading method instead if (this.leading) { this.leading(v); } } else { // set given attribute on node typeof n === 'string' ? this.node.setAttributeNS(n, a, v.toString()) : this.node.setAttribute(a, v.toString()); } // rebuild if required if (this.rebuild && (a == 'font-size' || a == 'x')) { this.rebuild(a, v); } } return this; } }); SVG.extend(SVG.Element, { // Add transformations transform: function transform(o, relative) { // get target in case of the fx module, otherwise reference this var target = this, matrix; // act as a getter if (_typeof(o) !== 'object') { // get current matrix matrix = new SVG.Matrix(target).extract(); return typeof o === 'string' ? matrix[o] : matrix; } // get current matrix matrix = new SVG.Matrix(target); // ensure relative flag relative = !!relative || !!o.relative; // act on matrix if (o.a != null) { matrix = relative // relative ? matrix.multiply(new SVG.Matrix(o)) // absolute : new SVG.Matrix(o); } return this.attr('transform', matrix); } }); SVG.extend(SVG.Element, { // Reset all transformations untransform: function untransform() { return this.attr('transform', null); }, // merge the whole transformation chain into one matrix and returns it matrixify: function matrixify() { var matrix = (this.attr('transform') || '').split(SVG.regex.transforms).slice(0, -1).map(function (str) { // generate key => value pairs var kv = str.trim().split('('); return [kv[0], kv[1].split(SVG.regex.delimiter).map(function (str) { return parseFloat(str); })]; }) // merge every transformation into one matrix .reduce(function (matrix, transform) { if (transform[0] == 'matrix') return matrix.multiply(arrayToMatrix(transform[1])); return matrix[transform[0]].apply(matrix, transform[1]); }, new SVG.Matrix()); return matrix; }, // add an element to another parent without changing the visual representation on the screen toParent: function toParent(parent) { if (this == parent) return this; var ctm = this.screenCTM(); var pCtm = parent.screenCTM().inverse(); this.addTo(parent).untransform().transform(pCtm.multiply(ctm)); return this; }, // same as above with parent equals root-svg toDoc: function toDoc() { return this.toParent(this.doc()); } }); SVG.Transformation = SVG.invent({ create: function create(source, inversed) { if (arguments.length > 1 && typeof inversed !== 'boolean') { return this.constructor.call(this, [].slice.call(arguments)); } if (Array.isArray(source)) { for (var i = 0, len = this.arguments.length; i < len; ++i) { this[this.arguments[i]] = source[i]; } } else if (source && _typeof(source) === 'object') { for (var i = 0, len = this.arguments.length; i < len; ++i) { this[this.arguments[i]] = source[this.arguments[i]]; } } this.inversed = false; if (inversed === true) { this.inversed = true; } } }); SVG.Translate = SVG.invent({ parent: SVG.Matrix, inherit: SVG.Transformation, create: function create(source, inversed) { this.constructor.apply(this, [].slice.call(arguments)); }, extend: { arguments: ['transformedX', 'transformedY'], method: 'translate' } }); SVG.extend(SVG.Element, { // Dynamic style generator style: function style(s, v) { if (arguments.length == 0) { // get full style return this.node.style.cssText || ''; } else if (arguments.length < 2) { // apply every style individually if an object is passed if (_typeof(s) === 'object') { for (var v_ in s) { this.style(v_, s[v_]); } } else if (SVG.regex.isCss.test(s)) { // parse css string s = s.split(/\s*;\s*/) // filter out suffix ; and stuff like ;; .filter(function (e) { return !!e; }).map(function (e) { return e.split(/\s*:\s*/); }); // apply every definition individually while (v = s.pop()) { this.style(v[0], v[1]); } } else { // act as a getter if the first and only argument is not an object return this.node.style[camelCase(s)]; } } else { this.node.style[camelCase(s)] = v === null || SVG.regex.isBlank.test(v) ? '' : v; } return this; } }); SVG.Parent = SVG.invent({ // Initialize node create: function create(element) { this.constructor.call(this, element); }, // Inherit from inherit: SVG.Element, // Add class methods extend: { // Returns all child elements children: function children() { return SVG.utils.map(SVG.utils.filterSVGElements(this.node.childNodes), function (node) { return SVG.adopt(node); }); }, // Add given element at a position add: function add(element, i) { if (i == null) { this.node.appendChild(element.node); } else if (element.node != this.node.childNodes[i]) { this.node.insertBefore(element.node, this.node.childNodes[i]); } return this; }, // Basically does the same as `add()` but returns the added element instead put: function put(element, i) { this.add(element, i); return element; }, // Checks if the given element is a child has: function has(element) { return this.index(element) >= 0; }, // Gets index of given element index: function index(element) { return [].slice.call(this.node.childNodes).indexOf(element.node); }, // Get a element at the given index get: function get(i) { return SVG.adopt(this.node.childNodes[i]); }, // Get first child first: function first() { return this.get(0); }, // Get the last child last: function last() { return this.get(this.node.childNodes.length - 1); }, // Iterates over all children and invokes a given block each: function each(block, deep) { var il, children = this.children(); for (var i = 0, il = children.length; i < il; i++) { if (children[i] instanceof SVG.Element) { block.apply(children[i], [i, children]); } if (deep && children[i] instanceof SVG.Container) { children[i].each(block, deep); } } return this; }, // Remove a given child removeElement: function removeElement(element) { this.node.removeChild(element.node); return this; }, // Remove all elements in this container clear: function clear() { // remove children while (this.node.hasChildNodes()) { this.node.removeChild(this.node.lastChild); } // remove defs reference delete this._defs; return this; }, // Get defs defs: function defs() { return this.doc().defs(); } } }); SVG.extend(SVG.Parent, { ungroup: function ungroup(parent, depth) { if (depth === 0 || this instanceof SVG.Defs || this.node == SVG.parser.draw) return this; parent = parent || (this instanceof SVG.Doc ? this : this.parent(SVG.Parent)); depth = depth || Infinity; this.each(function () { if (this instanceof SVG.Defs) return this; if (this instanceof SVG.Parent) return this.ungroup(parent, depth - 1); return this.toParent(parent); }); this.node.firstChild || this.remove(); return this; }, flatten: function flatten(parent, depth) { return this.ungroup(parent, depth); } }); SVG.Container = SVG.invent({ // Initialize node create: function create(element) { this.constructor.call(this, element); }, // Inherit from inherit: SVG.Parent }); SVG.ViewBox = SVG.invent({ // Define parent parent: SVG.Container, // Add parent method construct: {} }) // Add events to elements ; ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', // , 'mouseenter' -> not supported by IE // , 'mouseleave' -> not supported by IE 'touchstart', 'touchmove', 'touchleave', 'touchend', 'touchcancel'].forEach(function (event) { // add event to SVG.Element SVG.Element.prototype[event] = function (f) { // bind event to element rather than element node SVG.on(this.node, event, f); return this; }; }); // Initialize listeners stack SVG.listeners = []; SVG.handlerMap = []; SVG.listenerId = 0; // Add event binder in the SVG namespace SVG.on = function (node, event, listener, binding, options) { // create listener, get object-index var l = listener.bind(binding || node.instance || node), index = (SVG.handlerMap.indexOf(node) + 1 || SVG.handlerMap.push(node)) - 1, ev = event.split('.')[0], ns = event.split('.')[1] || '*'; // ensure valid object SVG.listeners[index] = SVG.listeners[index] || {}; SVG.listeners[index][ev] = SVG.listeners[index][ev] || {}; SVG.listeners[index][ev][ns] = SVG.listeners[index][ev][ns] || {}; if (!listener._svgjsListenerId) { listener._svgjsListenerId = ++SVG.listenerId; } // reference listener SVG.listeners[index][ev][ns][listener._svgjsListenerId] = l; // add listener node.addEventListener(ev, l, options || { passive: true }); }; // Add event unbinder in the SVG namespace SVG.off = function (node, event, listener) { var index = SVG.handlerMap.indexOf(node), ev = event && event.split('.')[0], ns = event && event.split('.')[1], namespace = ''; if (index == -1) return; if (listener) { if (typeof listener === 'function') listener = listener._svgjsListenerId; if (!listener) return; // remove listener reference if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns || '*']) { // remove listener node.removeEventListener(ev, SVG.listeners[index][ev][ns || '*'][listener], false); delete SVG.listeners[index][ev][ns || '*'][listener]; } } else if (ns && ev) { // remove all listeners for a namespaced event if (SVG.listeners[index][ev] && SVG.listeners[index][ev][ns]) { for (var listener_ in SVG.listeners[index][ev][ns]) { SVG.off(node, [ev, ns].join('.'), listener_); } delete SVG.listeners[index][ev][ns]; } } else if (ns) { // remove all listeners for a specific namespace for (var event_ in SVG.listeners[index]) { for (var namespace in SVG.listeners[index][event_]) { if (ns === namespace) { SVG.off(node, [event_, ns].join('.')); } } } } else if (ev) { // remove all listeners for the event if (SVG.listeners[index][ev]) { for (var namespace in SVG.listeners[index][ev]) { SVG.off(node, [ev, namespace].join('.')); } delete SVG.listeners[index][ev]; } } else { // remove all listeners on a given node for (var event_ in SVG.listeners[index]) { SVG.off(node, event_); } delete SVG.listeners[index]; delete SVG.handlerMap[index]; } }; // SVG.extend(SVG.Element, { // Bind given event to listener on: function on(event, listener, binding, options) { SVG.on(this.node, event, listener, binding, options); return this; }, // Unbind event from listener off: function off(event, listener) { SVG.off(this.node, event, listener); return this; }, // Fire given event fire: function fire(event, data) { // Dispatch event if (event instanceof window.Event) { this.node.dispatchEvent(event); } else { this.node.dispatchEvent(event = new SVG.CustomEvent(event, { detail: data, cancelable: true })); } this._event = event; return this; }, event: function event() { return this._event; } }); SVG.Defs = SVG.invent({ // Initialize node create: 'defs', // Inherit from inherit: SVG.Container }); SVG.G = SVG.invent({ // Initialize node create: 'g', // Inherit from inherit: SVG.Container, // Add class methods extend: { // Move over x-axis x: function x(_x2) { return _x2 == null ? this.transform('x') : this.transform({ x: _x2 - this.x() }, true); } }, // Add parent method construct: { // Create a group element group: function group() { return this.put(new SVG.G()); } } }); SVG.Doc = SVG.invent({ // Initialize node create: function create(element) { if (element) { // ensure the presence of a dom element element = typeof element === 'string' ? document.getElementById(element) : element; // If the target is an svg element, use that element as the main wrapper. // This allows svg.js to work with svg documents as well. if (element.nodeName == 'svg') { this.constructor.call(this, element); } else { this.constructor.call(this, SVG.create('svg')); element.appendChild(this.node); this.size('100%', '100%'); } // set svg element attributes and ensure defs node this.namespace().defs(); } }, // Inherit from inherit: SVG.Container, // Add class methods extend: { // Add namespaces namespace: function namespace() { return this.attr({ xmlns: SVG.ns, version: '1.1' }).attr('xmlns:xlink', SVG.xlink, SVG.xmlns).attr('xmlns:svgjs', SVG.svgjs, SVG.xmlns); }, // Creates and returns defs element defs: function defs() { if (!this._defs) { var defs; // Find or create a defs element in this instance if (defs = this.node.getElementsByTagName('defs')[0]) { this._defs = SVG.adopt(defs); } else { this._defs = new SVG.Defs(); } // Make sure the defs node is at the end of the stack this.node.appendChild(this._defs.node); } return this._defs; }, // custom parent method parent: function parent() { if (!this.node.parentNode || this.node.parentNode.nodeName == '#document') return null; return this.node.parentNode; }, // Removes the doc from the DOM remove: function remove() { if (this.parent()) { this.parent().removeChild(this.node); } return this; }, clear: function clear() { // remove children while (this.node.hasChildNodes()) { this.node.removeChild(this.node.lastChild); } // remove defs reference delete this._defs; // add back parser if (SVG.parser.draw && !SVG.parser.draw.parentNode) { this.node.appendChild(SVG.parser.draw); } return this; }, clone: function clone(parent) { // write dom data to the dom so the clone can pickup the data this.writeDataToDom(); // get reference to node var node = this.node; // clone element and assign new id var clone = assignNewId(node.cloneNode(true)); // insert the clone in the given parent or after myself if (parent) { (parent.node || parent).appendChild(clone.node); } else { node.parentNode.insertBefore(clone.node, node.nextSibling); } return clone; } } }); // ### This module adds backward / forward functionality to elements. // SVG.extend(SVG.Element, {// Get all siblings, including myself }); SVG.Gradient = SVG.invent({ // Initialize node create: function create(type) { this.constructor.call(this, SVG.create(type + 'Gradient')); // store type this.type = type; }, // Inherit from inherit: SVG.Container, // Add class methods extend: { // Add a color stop at: function at(offset, color, opacity) { return this.put(new SVG.Stop()).update(offset, color, opacity); }, // Update gradient update: function update(block) { // remove all stops this.clear(); // invoke passed block if (typeof block === 'function') { block.call(this, this); } return this; }, // Return the fill id fill: function fill() { return 'url(#' + this.id() + ')'; }, // Alias string convertion to fill toString: function toString() { return this.fill(); }, // custom attr to handle transform attr: function attr(a, b, c) { if (a == 'transform') a = 'gradientTransform'; return SVG.Container.prototype.attr.call(this, a, b, c); } }, // Add parent method construct: { // Create gradient element in defs gradient: function gradient(type, block) { return this.defs().gradient(type, block); } } }); // Add animatable methods to both gradient and fx module SVG.extend(SVG.Gradient, SVG.FX, { // From position from: function from(x, y) { return (this._target || this).type == 'radial' ? this.attr({ fx: new SVG.Number(x), fy: new SVG.Number(y) }) : this.attr({ x1: new SVG.Number(x), y1: new SVG.Number(y) }); }, // To position to: function to(x, y) { return (this._target || this).type == 'radial' ? this.attr({ cx: new SVG.Number(x), cy: new SVG.Number(y) }) : this.attr({ x2: new SVG.Number(x), y2: new SVG.Number(y) }); } }); // Base gradient generation SVG.extend(SVG.Defs, { // define gradient gradient: function gradient(type, block) { return this.put(new SVG.Gradient(type)).update(block); } }); SVG.Stop = SVG.invent({ // Initialize node create: 'stop', // Inherit from inherit: SVG.Element, // Add class methods extend: { // add color stops update: function update(o) { if (typeof o === 'number' || o instanceof SVG.Number) { o = { offset: arguments[0], color: arguments[1], opacity: arguments[2] }; } // set attributes if (o.opacity != null) this.attr('stop-opacity', o.opacity); if (o.color != null) this.attr('stop-color', o.color); if (o.offset != null) this.attr('offset', new SVG.Number(o.offset)); return this; } } }); SVG.Pattern = SVG.invent({ // Initialize node create: 'pattern', // Inherit from inherit: SVG.Container, // Add class methods extend: { // Return the fill id fill: function fill() { return 'url(#' + this.id() + ')'; }, // Update pattern by rebuilding update: function update(block) { // remove content this.clear(); // invoke passed block if (typeof block === 'function') { block.call(this, this); } return this; }, // Alias string convertion to fill toString: function toString() { return this.fill(); }, // custom attr to handle transform attr: function attr(a, b, c) { if (a == 'transform') a = 'patternTransform'; return SVG.Container.prototype.attr.call(this, a, b, c); } }, // Add parent method construct: { // Create pattern element in defs pattern: function pattern(width, height, block) { return this.defs().pattern(width, height, block); } } }); SVG.extend(SVG.Defs, { // Define gradient pattern: function pattern(width, height, block) { return this.put(new SVG.Pattern()).update(block).attr({ x: 0, y: 0, width: width, height: height, patternUnits: 'userSpaceOnUse' }); } }); SVG.Shape = SVG.invent({ // Initialize node create: function create(element) { this.constructor.call(this, element); }, // Inherit from inherit: SVG.Element }); SVG.Symbol = SVG.invent({ // Initialize node create: 'symbol', // Inherit from inherit: SVG.Container, construct: { // create symbol symbol: function symbol() { return this.put(new SVG.Symbol()); } } }); SVG.Use = SVG.invent({ // Initialize node create: 'use', // Inherit from inherit: SVG.Shape, // Add class methods extend: { // Use element as a reference element: function element(_element, file) { // Set lined element return this.attr('href', (file || '') + '#' + _element, SVG.xlink); } }, // Add parent method construct: { // Create a use element use: function use(element, file) { return this.put(new SVG.Use()).element(element, file); } } }); SVG.Rect = SVG.invent({ // Initialize node create: 'rect', // Inherit from inherit: SVG.Shape, // Add parent method construct: { // Create a rect element rect: function rect(width, height) { return this.put(new SVG.Rect()).size(width, height); } } }); SVG.Circle = SVG.invent({ // Initialize node create: 'circle', // Inherit from inherit: SVG.Shape, // Add parent method construct: { // Create circle element, based on ellipse circle: function circle(size) { return this.put(new SVG.Circle()).rx(new SVG.Number(size).divide(2)).move(0, 0); } } }); SVG.extend(SVG.Circle, SVG.FX, { // Radius x value rx: function rx(_rx) { return this.attr('r', _rx); }, // Alias radius x value ry: function ry(_ry) { return this.rx(_ry); } }); SVG.Ellipse = SVG.invent({ // Initialize node create: 'ellipse', // Inherit from inherit: SVG.Shape, // Add parent method construct: { // Create an ellipse ellipse: function ellipse(width, height) { return this.put(new SVG.Ellipse()).size(width, height).move(0, 0); } } }); SVG.extend(SVG.Ellipse, SVG.Rect, SVG.FX, { // Radius x value rx: function rx(_rx2) { return this.attr('rx', _rx2); }, // Radius y value ry: function ry(_ry2) { return this.attr('ry', _ry2); } }); // Add common method SVG.extend(SVG.Circle, SVG.Ellipse, { // Move over x-axis x: function x(_x3) { return _x3 == null ? this.cx() - this.rx() : this.cx(_x3 + this.rx()); }, // Move over y-axis y: function y(_y2) { return _y2 == null ? this.cy() - this.ry() : this.cy(_y2 + this.ry()); }, // Move by center over x-axis cx: function cx(x) { return x == null ? this.attr('cx') : this.attr('cx', x); }, // Move by center over y-axis cy: function cy(y) { return y == null ? this.attr('cy') : this.attr('cy', y); }, // Set width of element width: function width(_width2) { return _width2 == null ? this.rx() * 2 : this.rx(new SVG.Number(_width2).divide(2)); }, // Set height of element height: function height(_height2) { return _height2 == null ? this.ry() * 2 : this.ry(new SVG.Number(_height2).divide(2)); }, // Custom size function size: function size(width, height) { var p = proportionalSize(this, width, height); return this.rx(new SVG.Number(p.width).divide(2)).ry(new SVG.Number(p.height).divide(2)); } }); SVG.Line = SVG.invent({ // Initialize node create: 'line', // Inherit from inherit: SVG.Shape, // Add class methods extend: { // Get array array: function array() { return new SVG.PointArray([[this.attr('x1'), this.attr('y1')], [this.attr('x2'), this.attr('y2')]]); }, // Overwrite native plot() method plot: function plot(x1, y1, x2, y2) { if (x1 == null) { return this.array(); } else if (typeof y1 !== 'undefined') { x1 = { x1: x1, y1: y1, x2: x2, y2: y2 }; } else { x1 = new SVG.PointArray(x1).toLine(); } return this.attr(x1); }, // Move by left top corner move: function move(x, y) { return this.attr(this.array().move(x, y).toLine()); }, // Set element size to given width and height size: function size(width, height) { var p = proportionalSize(this, width, height); return this.attr(this.array().size(p.width, p.height).toLine()); } }, // Add parent method construct: { // Create a line element line: function line(x1, y1, x2, y2) { // make sure plot is called as a setter // x1 is not necessarily a number, it can also be an array, a string and a SVG.PointArray return SVG.Line.prototype.plot.apply(this.put(new SVG.Line()), x1 != null ? [x1, y1, x2, y2] : [0, 0, 0, 0]); } } }); SVG.Polyline = SVG.invent({ // Initialize node create: 'polyline', // Inherit from inherit: SVG.Shape, // Add parent method construct: { // Create a wrapped polyline element polyline: function polyline(p) { // make sure plot is called as a setter return this.put(new SVG.Polyline()).plot(p || new SVG.PointArray()); } } }); SVG.Polygon = SVG.invent({ // Initialize node create: 'polygon', // Inherit from inherit: SVG.Shape, // Add parent method construct: { // Create a wrapped polygon element polygon: function polygon(p) { // make sure plot is called as a setter return this.put(new SVG.Polygon()).plot(p || new SVG.PointArray()); } } }); // Add polygon-specific functions SVG.extend(SVG.Polyline, SVG.Polygon, { // Get array array: function array() { return this._array || (this._array = new SVG.PointArray(this.attr('points'))); }, // Plot new path plot: function plot(p) { return p == null ? this.array() : this.clear().attr('points', typeof p === 'string' ? p : this._array = new SVG.PointArray(p)); }, // Clear array cache clear: function clear() { delete this._array; return this; }, // Move by left top corner move: function move(x, y) { return this.attr('points', this.array().move(x, y)); }, // Set element size to given width and height size: function size(width, height) { var p = proportionalSize(this, width, height); return this.attr('points', this.array().size(p.width, p.height)); } }); // unify all point to point elements SVG.extend(SVG.Line, SVG.Polyline, SVG.Polygon, { // Define morphable array morphArray: SVG.PointArray, // Move by left top corner over x-axis x: function x(_x4) { return _x4 == null ? this.bbox().x : this.move(_x4, this.bbox().y); }, // Move by left top corner over y-axis y: function y(_y3) { return _y3 == null ? this.bbox().y : this.move(this.bbox().x, _y3); }, // Set width of element width: function width(_width3) { var b = this.bbox(); return _width3 == null ? b.width : this.size(_width3, b.height); }, // Set height of element height: function height(_height3) { var b = this.bbox(); return _height3 == null ? b.height : this.size(b.width, _height3); } }); SVG.Path = SVG.invent({ // Initialize node create: 'path', // Inherit from inherit: SVG.Shape, // Add class methods extend: { // Define morphable array morphArray: SVG.PathArray, // Get array array: function array() { return this._array || (this._array = new SVG.PathArray(this.attr('d'))); }, // Plot new path plot: function plot(d) { return d == null ? this.array() : this.clear().attr('d', typeof d === 'string' ? d : this._array = new SVG.PathArray(d)); }, // Clear array cache clear: function clear() { delete this._array; return this; } }, // Add parent method construct: { // Create a wrapped path element path: function path(d) { // make sure plot is called as a setter return this.put(new SVG.Path()).plot(d || new SVG.PathArray()); } } }); SVG.Image = SVG.invent({ // Initialize node create: 'image', // Inherit from inherit: SVG.Shape, // Add class methods extend: { // (re)load image load: function load(url) { if (!url) return this; var self = this, img = new window.Image(); // preload image SVG.on(img, 'load', function () { SVG.off(img); var p = self.parent(SVG.Pattern); if (p === null) return; // ensure image size if (self.width() == 0 && self.height() == 0) { self.size(img.width, img.height); } // ensure pattern size if not set if (p && p.width() == 0 && p.height() == 0) { p.size(self.width(), self.height()); } // callback if (typeof self._loaded === 'function') { self._loaded.call(self, { width: img.width, height: img.height, ratio: img.width / img.height, url: url }); } }); SVG.on(img, 'error', function (e) { SVG.off(img); if (typeof self._error === 'function') { self._error.call(self, e); } }); return this.attr('href', img.src = this.src = url, SVG.xlink); }, // Add loaded callback loaded: function loaded(_loaded) { this._loaded = _loaded; return this; }, error: function error(_error) { this._error = _error; return this; } }, // Add parent method construct: { // create image element, load image and set its size image: function image(source, width, height) { return this.put(new SVG.Image()).load(source).size(width || 0, height || width || 0); } } }); SVG.Text = SVG.invent({ // Initialize node create: function create() { this.constructor.call(this, SVG.create('text')); this.dom.leading = new SVG.Number(1.3); // store leading value for rebuilding this._rebuild = true; // enable automatic updating of dy values this._build = false; // disable build mode for adding multiple lines // set default font this.attr('font-family', SVG.defaults.attrs['font-family']); }, // Inherit from inherit: SVG.Shape, // Add class methods extend: { // Move over x-axis x: function x(_x5) { // act as getter if (_x5 == null) { return this.attr('x'); } return this.attr('x', _x5); }, // Set the text content text: function text(_text) { // act as getter if (typeof _text === 'undefined') { var _text = ''; var children = this.node.childNodes; for (var i = 0, len = children.length; i < len; ++i) { // add newline if its not the first child and newLined is set to true if (i != 0 && children[i].nodeType != 3 && SVG.adopt(children[i]).dom.newLined == true) { _text += '\n'; } // add content of this node _text += children[i].textContent; } return _text; } // remove existing content this.clear().build(true); if (typeof _text === 'function') { // call block _text.call(this, this); } else { // store text and make sure text is not blank _text = _text.split('\n'); // build new lines for (var i = 0, il = _text.length; i < il; i++) { this.tspan(_text[i]).newLine(); } } // disable build mode and rebuild lines return this.build(false).rebuild(); }, // Set font size size: function size(_size) { return this.attr('font-size', _size).rebuild(); }, // Set / get leading leading: function leading(value) { // act as getter if (value == null) { return this.dom.leading; } // act as setter this.dom.leading = new SVG.Number(value); return this.rebuild(); }, // Get all the first level lines lines: function lines() { var node = (this.textPath && this.textPath() || this).node; // filter tspans and map them to SVG.js instances var lines = SVG.utils.map(SVG.utils.filterSVGElements(node.childNodes), function (el) { return SVG.adopt(el); }); // return an instance of SVG.set return new SVG.Set(lines); }, // Rebuild appearance type rebuild: function rebuild(_rebuild) { // store new rebuild flag if given if (typeof _rebuild === 'boolean') { this._rebuild = _rebuild; } // define position of all lines if (this._rebuild) { var self = this, blankLineOffset = 0, dy = this.dom.leading * new SVG.Number(this.attr('font-size')); this.lines().each(function () { if (this.dom.newLined) { if (!self.textPath()) { this.attr('x', self.attr('x')); } if (this.text() == '\n') { blankLineOffset += dy; } else { this.attr('dy', dy + blankLineOffset); blankLineOffset = 0; } } }); this.fire('rebuild'); } return this; }, // Enable / disable build mode build: function build(_build) { this._build = !!_build; return this; }, // overwrite method from parent to set data properly setData: function setData(o) { this.dom = o; this.dom.leading = new SVG.Number(o.leading || 1.3); return this; } }, // Add parent method construct: { // Create text element text: function text(_text2) { return this.put(new SVG.Text()).text(_text2); }, // Create plain text element plain: function plain(text) { return this.put(new SVG.Text()).plain(text); } } }); SVG.Tspan = SVG.invent({ // Initialize node create: 'tspan', // Inherit from inherit: SVG.Shape, // Add class methods extend: { // Set text content text: function text(_text3) { if (_text3 == null) return this.node.textContent + (this.dom.newLined ? '\n' : ''); typeof _text3 === 'function' ? _text3.call(this, this) : this.plain(_text3); return this; }, // Shortcut dx dx: function dx(_dx) { return this.attr('dx', _dx); }, // Shortcut dy dy: function dy(_dy) { return this.attr('dy', _dy); }, // Create new line newLine: function newLine() { // fetch text parent var t = this.parent(SVG.Text); // mark new line this.dom.newLined = true; // apply new hy¡n return this.dy(t.dom.leading * t.attr('font-size')).attr('x', t.x()); } } }); SVG.extend(SVG.Text, SVG.Tspan, { // Create plain text node plain: function plain(text) { // clear if build mode is disabled if (this._build === false) { this.clear(); } // create text node this.node.appendChild(document.createTextNode(text)); return this; }, // Create a tspan tspan: function tspan(text) { var node = (this.textPath && this.textPath() || this).node, tspan = new SVG.Tspan(); // clear if build mode is disabled if (this._build === false) { this.clear(); } // add new tspan node.appendChild(tspan.node); return tspan.text(text); }, // Clear all lines clear: function clear() { var node = (this.textPath && this.textPath() || this).node; // remove existing child nodes while (node.hasChildNodes()) { node.removeChild(node.lastChild); } return this; }, // Get length of text element length: function length() { return this.node.getComputedTextLength(); } }); SVG.TextPath = SVG.invent({ // Initialize node create: 'textPath', // Inherit from inherit: SVG.Parent, // Define parent class parent: SVG.Text, // Add parent method construct: { morphArray: SVG.PathArray, // return the array of the path track element array: function array() { var track = this.track(); return track ? track.array() : null; }, // Plot path if any plot: function plot(d) { var track = this.track(), pathArray = null; if (track) { pathArray = track.plot(d); } return d == null ? pathArray : this; }, // Get the path track element track: function track() { var path = this.textPath(); if (path) { return path.reference('href'); } }, // Get the textPath child textPath: function textPath() { if (this.node.firstChild && this.node.firstChild.nodeName == 'textPath') { return SVG.adopt(this.node.firstChild); } } } }); SVG.Nested = SVG.invent({ // Initialize node create: function create() { this.constructor.call(this, SVG.create('svg')); this.style('overflow', 'visible'); }, // Inherit from inherit: SVG.Container, // Add parent method construct: { // Create nested svg document nested: function nested() { return this.put(new SVG.Nested()); } } }); // Define list of available attributes for stroke and fill var sugar = { stroke: ['color', 'width', 'opacity', 'linecap', 'linejoin', 'miterlimit', 'dasharray', 'dashoffset'], fill: ['color', 'opacity', 'rule'], prefix: function prefix(t, a) { return a == 'color' ? t : t + '-' + a; } } // Add sugar for fill and stroke ; ['fill', 'stroke'].forEach(function (m) { var extension = {}; extension[m] = function (o) { if (typeof o === 'undefined') { return this; } if (typeof o === 'string' || SVG.Color.isRgb(o) || o && typeof o.fill === 'function') { this.attr(m, o); } else // set all attributes from sugar.fill and sugar.stroke list { for (var i = sugar[m].length - 1; i >= 0; i--) { if (o[sugar[m][i]] != null) { this.attr(sugar.prefix(m, sugar[m][i]), o[sugar[m][i]]); } } } return this; }; SVG.extend(SVG.Element, SVG.FX, extension); }); SVG.extend(SVG.Element, SVG.FX, { // Map translate to transform translate: function translate(x, y) { return this.transform({ x: x, y: y }); }, // Map matrix to transform matrix: function matrix(m) { return this.attr('transform', new SVG.Matrix(arguments.length == 6 ? [].slice.call(arguments) : m)); }, // Opacity opacity: function opacity(value) { return this.attr('opacity', value); }, // Relative move over x axis dx: function dx(x) { return this.x(new SVG.Number(x).plus(this instanceof SVG.FX ? 0 : this.x()), true); }, // Relative move over y axis dy: function dy(y) { return this.y(new SVG.Number(y).plus(this instanceof SVG.FX ? 0 : this.y()), true); } }); SVG.extend(SVG.Path, { // Get path length length: function length() { return this.node.getTotalLength(); }, // Get point at length pointAt: function pointAt(length) { return this.node.getPointAtLength(length); } }); SVG.Set = SVG.invent({ // Initialize create: function create(members) { // Set initial state Array.isArray(members) ? this.members = members : this.clear(); }, // Add class methods extend: { // Add element to set add: function add() { var il, elements = [].slice.call(arguments); for (var i = 0, il = elements.length; i < il; i++) { this.members.push(elements[i]); } return this; }, // Remove element from set remove: function remove(element) { var i = this.index(element); // remove given child if (i > -1) { this.members.splice(i, 1); } return this; }, // Iterate over all members each: function each(block) { for (var i = 0, il = this.members.length; i < il; i++) { block.apply(this.members[i], [i, this.members]); } return this; }, // Restore to defaults clear: function clear() { // initialize store this.members = []; return this; }, // Get the length of a set length: function length() { return this.members.length; }, // Checks if a given element is present in set has: function has(element) { return this.index(element) >= 0; }, // retuns index of given element in set index: function index(element) { return this.members.indexOf(element); }, // Get member at given index get: function get(i) { return this.members[i]; }, // Get first member first: function first() { return this.get(0); }, // Get last member last: function last() { return this.get(this.members.length - 1); }, // Default value valueOf: function valueOf() { return this.members; } }, // Add parent method construct: { // Create a new set set: function set(members) { return new SVG.Set(members); } } }); SVG.FX.Set = SVG.invent({ // Initialize node create: function create(set) { // store reference to set this.set = set; } }); // Alias methods SVG.Set.inherit = function () { var methods = []; // gather shape methods for (var m in SVG.Shape.prototype) { if (typeof SVG.Shape.prototype[m] === 'function' && typeof SVG.Set.prototype[m] !== 'function') { methods.push(m); } } // apply shape aliasses methods.forEach(function (method) { SVG.Set.prototype[method] = function () { for (var i = 0, il = this.members.length; i < il; i++) { if (this.members[i] && typeof this.members[i][method] === 'function') { this.members[i][method].apply(this.members[i], arguments); } } return method == 'animate' ? this.fx || (this.fx = new SVG.FX.Set(this)) : this; }; }); // clear methods for the next round methods = []; // gather fx methods for (var m in SVG.FX.prototype) { if (typeof SVG.FX.prototype[m] === 'function' && typeof SVG.FX.Set.prototype[m] !== 'function') { methods.push(m); } } // apply fx aliasses methods.forEach(function (method) { SVG.FX.Set.prototype[method] = function () { for (var i = 0, il = this.set.members.length; i < il; i++) { this.set.members[i].fx[method].apply(this.set.members[i].fx, arguments); } return this; }; }); }; SVG.extend(SVG.Element, {}); SVG.extend(SVG.Element, { // Remember arbitrary data remember: function remember(k, v) { // remember every item in an object individually if (_typeof(arguments[0]) === 'object') { for (var v_ in k) { this.remember(v_, k[v_]); } } // retrieve memory else if (arguments.length == 1) { return this.memory()[k]; } // store memory else { this.memory()[k] = v; } return this; }, // Erase a given memory forget: function forget() { if (arguments.length == 0) { this._memory = {}; } else { for (var i = arguments.length - 1; i >= 0; i--) { delete this.memory()[arguments[i]]; } } return this; }, // Initialize or return local memory object memory: function memory() { return this._memory || (this._memory = {}); } }); // Method for getting an element by id SVG.get = function (id) { var node = document.getElementById(idFromReference(id) || id); return SVG.adopt(node); }; // Select elements by query string SVG.select = function (query, parent) { return new SVG.Set(SVG.utils.map((parent || document).querySelectorAll(query), function (node) { return SVG.adopt(node); })); }; SVG.extend(SVG.Parent, { // Scoped select method select: function select(query) { return SVG.select(query, this.node); } }); function pathRegReplace(a, b, c, d) { return c + d.replace(SVG.regex.dots, ' .'); } // creates deep clone of array function _is(el, obj) { return el instanceof obj; } // tests if a given selector matches an element function _matches(el, selector) { return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); } // Convert dash-separated-string to camelCase function camelCase(s) { return s.toLowerCase().replace(/-(.)/g, function (m, g) { return g.toUpperCase(); }); } // Capitalize first letter of a string function capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1); } // Ensure to six-based hex function fullHex(hex) { return hex.length == 4 ? ['#', hex.substring(1, 2), hex.substring(1, 2), hex.substring(2, 3), hex.substring(2, 3), hex.substring(3, 4), hex.substring(3, 4)].join('') : hex; } // Component to hex value function compToHex(comp) { var hex = comp.toString(16); return hex.length == 1 ? '0' + hex : hex; } // Calculate proportional width and height values when necessary function proportionalSize(element, width, height) { if (width == null || height == null) { var box = element.bbox(); if (width == null) { width = box.width / box.height * height; } else if (height == null) { height = box.height / box.width * width; } } return { width: width, height: height }; } // Delta transform point function deltaTransformPoint(matrix, x, y) { return { x: x * matrix.a + y * matrix.c + 0, y: x * matrix.b + y * matrix.d + 0 }; } // Map matrix array to object function arrayToMatrix(a) { return { a: a[0], b: a[1], c: a[2], d: a[3], e: a[4], f: a[5] }; } // Parse matrix if required function parseMatrix(matrix) { if (!(matrix instanceof SVG.Matrix)) { matrix = new SVG.Matrix(matrix); } return matrix; } // Add centre point to transform object function arrayToString(a) { for (var i = 0, il = a.length, s = ''; i < il; i++) { s += a[i][0]; if (a[i][1] != null) { s += a[i][1]; if (a[i][2] != null) { s += ' '; s += a[i][2]; if (a[i][3] != null) { s += ' '; s += a[i][3]; s += ' '; s += a[i][4]; if (a[i][5] != null) { s += ' '; s += a[i][5]; s += ' '; s += a[i][6]; if (a[i][7] != null) { s += ' '; s += a[i][7]; } } } } } } return s + ' '; } // Deep new id assignment function assignNewId(node) { // do the same for SVG child nodes as well for (var i = node.childNodes.length - 1; i >= 0; i--) { if (node.childNodes[i] instanceof window.SVGElement) { assignNewId(node.childNodes[i]); } } return SVG.adopt(node).id(SVG.eid(node.nodeName)); } // Add more bounding box properties function fullBox(b) { if (b.x == null) { b.x = 0; b.y = 0; b.width = 0; b.height = 0; } b.w = b.width; b.h = b.height; b.x2 = b.x + b.width; b.y2 = b.y + b.height; b.cx = b.x + b.width / 2; b.cy = b.y + b.height / 2; return b; } // Get id from reference string function idFromReference(url) { var m = (url || '').toString().match(SVG.regex.reference); if (m) return m[1]; } // If values like 1e-88 are passed, this is not a valid 32 bit float, // but in those cases, we are so close to 0 that 0 works well! function float32String(v) { return Math.abs(v) > 1e-37 ? v : 0; } // Create matrix array for looping var abcdef = 'abcdef'.split(''); // Add CustomEvent to IE9 and IE10 if (typeof window.CustomEvent !== 'function') { // Code from: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent var CustomEventPoly = function CustomEventPoly(event, options) { options = options || { bubbles: false, cancelable: false, detail: undefined }; var e = document.createEvent('CustomEvent'); e.initCustomEvent(event, options.bubbles, options.cancelable, options.detail); return e; }; CustomEventPoly.prototype = window.Event.prototype; SVG.CustomEvent = CustomEventPoly; } else { SVG.CustomEvent = window.CustomEvent; } return SVG; }); /*! svg.filter.js - v2.0.2 - 2016-02-24 * https://github.com/wout/svg.filter.js * Copyright (c) 2016 Wout Fierens; Licensed MIT */ (function() { // Main filter class SVG.Filter = SVG.invent({ create: 'filter', inherit: SVG.Parent, extend: { // Static strings source: 'SourceGraphic', sourceAlpha: 'SourceAlpha', background: 'BackgroundImage', backgroundAlpha: 'BackgroundAlpha', fill: 'FillPaint', stroke: 'StrokePaint', autoSetIn: true, // Custom put method for leaner code put: function(element, i) { this.add(element, i); if(!element.attr('in') && this.autoSetIn){ element.attr('in',this.source); } if(!element.attr('result')){ element.attr('result',element); } return element }, // Blend effect blend: function(in1, in2, mode) { return this.put(new SVG.BlendEffect(in1, in2, mode)) }, // ColorMatrix effect colorMatrix: function(type, values) { return this.put(new SVG.ColorMatrixEffect(type, values)) }, // ConvolveMatrix effect convolveMatrix: function(matrix) { return this.put(new SVG.ConvolveMatrixEffect(matrix)) }, // ComponentTransfer effect componentTransfer: function(components) { return this.put(new SVG.ComponentTransferEffect(components)) }, // Composite effect composite: function(in1, in2, operator) { return this.put(new SVG.CompositeEffect(in1, in2, operator)) }, // Flood effect flood: function(color, opacity) { return this.put(new SVG.FloodEffect(color, opacity)) }, // Offset effect offset: function(x, y) { return this.put(new SVG.OffsetEffect(x,y)) }, // Image effect image: function(src) { return this.put(new SVG.ImageEffect(src)) }, // Merge effect merge: function() { //pass the array of arguments to the constructor because we dont know if the user gave us an array as the first arguemnt or wether they listed the effects in the arguments var args = [undefined]; for(var i in arguments) args.push(arguments[i]); return this.put(new (SVG.MergeEffect.bind.apply(SVG.MergeEffect,args))) }, // Gaussian Blur effect gaussianBlur: function(x,y) { return this.put(new SVG.GaussianBlurEffect(x,y)) }, // Morphology effect morphology: function(operator,radius){ return this.put(new SVG.MorphologyEffect(operator,radius)) }, // DiffuseLighting effect diffuseLighting: function(surfaceScale,diffuseConstant,kernelUnitLength){ return this.put(new SVG.DiffuseLightingEffect(surfaceScale,diffuseConstant,kernelUnitLength)) }, // DisplacementMap effect displacementMap: function(in1,in2,scale,xChannelSelector,yChannelSelector){ return this.put(new SVG.DisplacementMapEffect(in1,in2,scale,xChannelSelector,yChannelSelector)) }, // SpecularLighting effect specularLighting: function(surfaceScale,diffuseConstant,specularExponent,kernelUnitLength){ return this.put(new SVG.SpecularLightingEffect(surfaceScale,diffuseConstant,specularExponent,kernelUnitLength)) }, // Tile effect tile: function(){ return this.put(new SVG.TileEffect()); }, // Turbulence effect turbulence: function(baseFrequency,numOctaves,seed,stitchTiles,type){ return this.put(new SVG.TurbulenceEffect(baseFrequency,numOctaves,seed,stitchTiles,type)) }, // Default string value toString: function() { return 'url(#' + this.attr('id') + ')' } } }); //add .filter function SVG.extend(SVG.Defs, { // Define filter filter: function(block) { var filter = this.put(new SVG.Filter); /* invoke passed block */ if (typeof block === 'function') block.call(filter, filter); return filter } }); SVG.extend(SVG.Container, { // Define filter on defs filter: function(block) { return this.defs().filter(block) } }); SVG.extend(SVG.Element, SVG.G, SVG.Nested, { // Create filter element in defs and store reference filter: function(block) { this.filterer = block instanceof SVG.Element ? block : this.doc().filter(block); if(this.doc() && this.filterer.doc() !== this.doc()){ this.doc().defs().add(this.filterer); } this.attr('filter', this.filterer); return this.filterer }, // Remove filter unfilter: function(remove) { /* also remove the filter node */ if (this.filterer && remove === true) this.filterer.remove(); /* delete reference to filterer */ delete this.filterer; /* remove filter attribute */ return this.attr('filter', null) } }); // Create SVG.Effect class SVG.Effect = SVG.invent({ create: function(){ this.constructor.call(this); }, inherit: SVG.Element, extend: { // Set in attribute in: function(effect) { return effect == null? this.parent() && this.parent().select('[result="'+this.attr('in')+'"]').get(0) || this.attr('in') : this.attr('in', effect) }, // Named result result: function(result) { return result == null? this.attr('result') : this.attr('result',result) }, // Stringification toString: function() { return this.result() } } }); // create class for parent effects like merge // Inherit from SVG.Parent SVG.ParentEffect = SVG.invent({ create: function(){ this.constructor.call(this); }, inherit: SVG.Parent, extend: { // Set in attribute in: function(effect) { return effect == null? this.parent() && this.parent().select('[result="'+this.attr('in')+'"]').get(0) || this.attr('in') : this.attr('in', effect) }, // Named result result: function(result) { return result == null? this.attr('result') : this.attr('result',result) }, // Stringification toString: function() { return this.result() } } }); //chaining var chainingEffects = { // Blend effect blend: function(in2, mode) { return this.parent() && this.parent().blend(this, in2, mode) //pass this as the first input }, // ColorMatrix effect colorMatrix: function(type, values) { return this.parent() && this.parent().colorMatrix(type, values).in(this) }, // ConvolveMatrix effect convolveMatrix: function(matrix) { return this.parent() && this.parent().convolveMatrix(matrix).in(this) }, // ComponentTransfer effect componentTransfer: function(components) { return this.parent() && this.parent().componentTransfer(components).in(this) }, // Composite effect composite: function(in2, operator) { return this.parent() && this.parent().composite(this, in2, operator) //pass this as the first input }, // Flood effect flood: function(color, opacity) { return this.parent() && this.parent().flood(color, opacity) //this effect dont have inputs }, // Offset effect offset: function(x, y) { return this.parent() && this.parent().offset(x,y).in(this) }, // Image effect image: function(src) { return this.parent() && this.parent().image(src) //this effect dont have inputs }, // Merge effect merge: function() { return this.parent() && this.parent().merge.apply(this.parent(),[this].concat(arguments)) //pass this as the first argument }, // Gaussian Blur effect gaussianBlur: function(x,y) { return this.parent() && this.parent().gaussianBlur(x,y).in(this) }, // Morphology effect morphology: function(operator,radius){ return this.parent() && this.parent().morphology(operator,radius).in(this) }, // DiffuseLighting effect diffuseLighting: function(surfaceScale,diffuseConstant,kernelUnitLength){ return this.parent() && this.parent().diffuseLighting(surfaceScale,diffuseConstant,kernelUnitLength).in(this) }, // DisplacementMap effect displacementMap: function(in2,scale,xChannelSelector,yChannelSelector){ return this.parent() && this.parent().displacementMap(this,in2,scale,xChannelSelector,yChannelSelector) //pass this as the first input }, // SpecularLighting effect specularLighting: function(surfaceScale,diffuseConstant,specularExponent,kernelUnitLength){ return this.parent() && this.parent().specularLighting(surfaceScale,diffuseConstant,specularExponent,kernelUnitLength).in(this) }, // Tile effect tile: function(){ return this.parent() && this.parent().tile().in(this) }, // Turbulence effect turbulence: function(baseFrequency,numOctaves,seed,stitchTiles,type){ return this.parent() && this.parent().turbulence(baseFrequency,numOctaves,seed,stitchTiles,type).in(this) } }; SVG.extend(SVG.Effect,chainingEffects); SVG.extend(SVG.ParentEffect,chainingEffects); //crea class for child effects, like MergeNode, FuncR and lights SVG.ChildEffect = SVG.invent({ create: function(){ this.constructor.call(this); }, inherit: SVG.Element, extend: { in: function(effect){ this.attr('in',effect); } //dont include any "result" functions because these types of nodes dont have them } }); // Create all different effects var effects = { blend: function(in1,in2,mode){ this.attr({ in: in1, in2: in2, mode: mode || 'normal' }); }, colorMatrix: function(type,values){ if (type == 'matrix') values = normaliseMatrix(values); this.attr({ type: type , values: typeof values == 'undefined' ? null : values }); }, convolveMatrix: function(matrix){ matrix = normaliseMatrix(matrix); this.attr({ order: Math.sqrt(matrix.split(' ').length) , kernelMatrix: matrix }); }, composite: function(in1, in2, operator){ this.attr({ in: in1, in2: in2, operator: operator }); }, flood: function(color,opacity){ this.attr('flood-color',color); if(opacity != null) this.attr('flood-opacity',opacity); }, offset: function(x,y){ this.attr({ dx: x, dy: y }); }, image: function(src){ this.attr('href', src, SVG.xlink); }, displacementMap: function(in1,in2,scale,xChannelSelector,yChannelSelector){ this.attr({ in: in1, in2: in2, scale: scale, xChannelSelector: xChannelSelector, yChannelSelector: yChannelSelector }); }, gaussianBlur: function(x,y){ if(x != null || y != null) this.attr('stdDeviation', listString(Array.prototype.slice.call(arguments))); else this.attr('stdDeviation', '0 0'); }, morphology: function(operator,radius){ this.attr({ operator: operator, radius: radius }); }, tile: function(){ }, turbulence: function(baseFrequency,numOctaves,seed,stitchTiles,type){ this.attr({ numOctaves: numOctaves, seed: seed, stitchTiles: stitchTiles, baseFrequency: baseFrequency, type: type }); } }; // Create all parent effects var parentEffects = { merge: function(){ var children; //test to see if we have a set if(arguments[0] instanceof SVG.Set){ var that = this; arguments[0].each(function(i){ if(this instanceof SVG.MergeNode) that.put(this); else if(this instanceof SVG.Effect || this instanceof SVG.ParentEffect) that.put(new SVG.MergeNode(this)); }); } else { //if the first argument is an array use it if(Array.isArray(arguments[0])) children = arguments[0]; else children = arguments; for(var i = 0; i < children.length; i++){ if(children[i] instanceof SVG.MergeNode){ this.put(children[i]); } else this.put(new SVG.MergeNode(children[i])); } } }, componentTransfer: function(compontents){ /* create rgb set */ this.rgb = new SVG.Set /* create components */ ;(['r', 'g', 'b', 'a']).forEach(function(c) { /* create component */ this[c] = new SVG['Func' + c.toUpperCase()]('identity'); /* store component in set */ this.rgb.add(this[c]); /* add component node */ this.node.appendChild(this[c].node); }.bind(this)); //lost context in foreach /* set components */ if (compontents) { if (compontents.rgb) { (['r', 'g', 'b']).forEach(function(c) { this[c].attr(compontents.rgb); }.bind(this)); delete compontents.rgb; } /* set individual components */ for (var c in compontents) this[c].attr(compontents[c]); } }, diffuseLighting: function(surfaceScale,diffuseConstant,kernelUnitLength){ this.attr({ surfaceScale: surfaceScale, diffuseConstant: diffuseConstant, kernelUnitLength: kernelUnitLength }); }, specularLighting: function(surfaceScale,diffuseConstant,specularExponent,kernelUnitLength){ this.attr({ surfaceScale: surfaceScale, diffuseConstant: diffuseConstant, specularExponent: specularExponent, kernelUnitLength: kernelUnitLength }); }, }; // Create child effects like PointLight and MergeNode var childEffects = { distantLight: function(azimuth, elevation){ this.attr({ azimuth: azimuth, elevation: elevation }); }, pointLight: function(x,y,z){ this.attr({ x: x, y: y, z: z }); }, spotLight: function(x,y,z,pointsAtX,pointsAtY,pointsAtZ){ this.attr({ x: x, y: y, z: z, pointsAtX: pointsAtX, pointsAtY: pointsAtY, pointsAtZ: pointsAtZ }); }, mergeNode: function(in1){ this.attr('in',in1); } } // Create compontent functions ;(['r', 'g', 'b', 'a']).forEach(function(c) { /* create class */ childEffects['Func' + c.toUpperCase()] = function(type) { this.attr('type',type); // take diffent arguments based on the type switch(type){ case 'table': this.attr('tableValues',arguments[1]); break case 'linear': this.attr('slope',arguments[1]); this.attr('intercept',arguments[2]); break case 'gamma': this.attr('amplitude',arguments[1]); this.attr('exponent',arguments[2]); this.attr('offset',arguments[2]); break } }; }); //create effects foreach(effects,function(effect,i){ /* capitalize name */ var name = i.charAt(0).toUpperCase() + i.slice(1); var proto = {}; /* create class */ SVG[name + 'Effect'] = SVG.invent({ create: function() { //call super this.constructor.call(this, SVG.create('fe' + name)); //call constructor for this effect effect.apply(this,arguments); //set the result this.result(this.attr('id') + 'Out'); }, inherit: SVG.Effect, extend: proto }); }); //create parent effects foreach(parentEffects,function(effect,i){ /* capitalize name */ var name = i.charAt(0).toUpperCase() + i.slice(1); var proto = {}; /* create class */ SVG[name + 'Effect'] = SVG.invent({ create: function() { //call super this.constructor.call(this, SVG.create('fe' + name)); //call constructor for this effect effect.apply(this,arguments); //set the result this.result(this.attr('id') + 'Out'); }, inherit: SVG.ParentEffect, extend: proto }); }); //create child effects foreach(childEffects,function(effect,i){ /* capitalize name */ var name = i.charAt(0).toUpperCase() + i.slice(1); var proto = {}; /* create class */ SVG[name] = SVG.invent({ create: function() { //call super this.constructor.call(this, SVG.create('fe' + name)); //call constructor for this effect effect.apply(this,arguments); }, inherit: SVG.ChildEffect, extend: proto }); }); // Effect-specific extensions SVG.extend(SVG.MergeEffect,{ in: function(effect){ if(effect instanceof SVG.MergeNode) this.add(effect,0); else this.add(new SVG.MergeNode(effect),0); return this } }); SVG.extend(SVG.CompositeEffect,SVG.BlendEffect,SVG.DisplacementMapEffect,{ in2: function(effect){ return effect == null? this.parent() && this.parent().select('[result="'+this.attr('in2')+'"]').get(0) || this.attr('in2') : this.attr('in2', effect) } }); // Presets SVG.filter = { sepiatone: [ .343, .669, .119, 0, 0 , .249, .626, .130, 0, 0 , .172, .334, .111, 0, 0 , .000, .000, .000, 1, 0 ] }; // Helpers function normaliseMatrix(matrix) { /* convert possible array value to string */ if (Array.isArray(matrix)) matrix = new SVG.Array(matrix); /* ensure there are no leading, tailing or double spaces */ return matrix.toString().replace(/^\s+/, '').replace(/\s+$/, '').replace(/\s+/g, ' ') } function listString(list) { if (!Array.isArray(list)) return list for (var i = 0, l = list.length, s = []; i < l; i++) s.push(list[i]); return s.join(' ') } function foreach(){ //loops through mutiple objects var fn = function(){}; if(typeof arguments[arguments.length-1] == 'function'){ fn = arguments[arguments.length-1]; Array.prototype.splice.call(arguments,arguments.length-1,1); } for(var k in arguments){ for(var i in arguments[k]){ fn(arguments[k][i],i,arguments[k]); } } } }).call(undefined); (function() { SVG.extend(SVG.PathArray, { morph: function(array) { var startArr = this.value , destArr = this.parse(array); var startOffsetM = 0 , destOffsetM = 0; var startOffsetNextM = false , destOffsetNextM = false; while(true){ // stop if there is no M anymore if(startOffsetM === false && destOffsetM === false) break // find the next M in path array startOffsetNextM = findNextM(startArr, startOffsetM === false ? false : startOffsetM+1); destOffsetNextM = findNextM( destArr, destOffsetM === false ? false : destOffsetM+1); // We have to add one M to the startArray if(startOffsetM === false){ var bbox = new SVG.PathArray(result.start).bbox(); // when the last block had no bounding box we simply take the first M we got if(bbox.height == 0 || bbox.width == 0){ startOffsetM = startArr.push(startArr[0]) - 1; }else { // we take the middle of the bbox instead when we got one startOffsetM = startArr.push( ['M', bbox.x + bbox.width/2, bbox.y + bbox.height/2 ] ) - 1; } } // We have to add one M to the destArray if( destOffsetM === false){ var bbox = new SVG.PathArray(result.dest).bbox(); if(bbox.height == 0 || bbox.width == 0){ destOffsetM = destArr.push(destArr[0]) - 1; }else { destOffsetM = destArr.push( ['M', bbox.x + bbox.width/2, bbox.y + bbox.height/2 ] ) - 1; } } // handle block from M to next M var result = handleBlock(startArr, startOffsetM, startOffsetNextM, destArr, destOffsetM, destOffsetNextM); // update the arrays to their new values startArr = startArr.slice(0, startOffsetM).concat(result.start, startOffsetNextM === false ? [] : startArr.slice(startOffsetNextM)); destArr = destArr.slice(0, destOffsetM).concat(result.dest , destOffsetNextM === false ? [] : destArr.slice( destOffsetNextM)); // update offsets startOffsetM = startOffsetNextM === false ? false : startOffsetM + result.start.length; destOffsetM = destOffsetNextM === false ? false : destOffsetM + result.dest.length; } // copy back arrays this.value = startArr; this.destination = new SVG.PathArray(); this.destination.value = destArr; return this } }); // sorry for the long declaration // slices out one block (from M to M) and syncronize it so the types and length match function handleBlock(startArr, startOffsetM, startOffsetNextM, destArr, destOffsetM, destOffsetNextM, undefined$1){ // slice out the block we need var startArrTemp = startArr.slice(startOffsetM, startOffsetNextM || undefined$1) , destArrTemp = destArr.slice( destOffsetM, destOffsetNextM || undefined$1); var i = 0 , posStart = {pos:[0,0], start:[0,0]} , posDest = {pos:[0,0], start:[0,0]}; do{ // convert shorthand types to long form startArrTemp[i] = simplyfy.call(posStart, startArrTemp[i]); destArrTemp[i] = simplyfy.call(posDest , destArrTemp[i]); // check if both shape types match // 2 elliptical arc curve commands ('A'), are considered different if the // flags (large-arc-flag, sweep-flag) don't match if(startArrTemp[i][0] != destArrTemp[i][0] || startArrTemp[i][0] == 'M' || (startArrTemp[i][0] == 'A' && (startArrTemp[i][4] != destArrTemp[i][4] || startArrTemp[i][5] != destArrTemp[i][5]) ) ) { // if not, convert shapes to beziere Array.prototype.splice.apply(startArrTemp, [i, 1].concat(toBeziere.call(posStart, startArrTemp[i]))); Array.prototype.splice.apply(destArrTemp, [i, 1].concat(toBeziere.call(posDest, destArrTemp[i]))); } else { // only update positions otherwise startArrTemp[i] = setPosAndReflection.call(posStart, startArrTemp[i]); destArrTemp[i] = setPosAndReflection.call(posDest , destArrTemp[i]); } // we are at the end at both arrays. stop here if(++i == startArrTemp.length && i == destArrTemp.length) break // destArray is longer. Add one element if(i == startArrTemp.length){ startArrTemp.push([ 'C', posStart.pos[0], posStart.pos[1], posStart.pos[0], posStart.pos[1], posStart.pos[0], posStart.pos[1], ]); } // startArr is longer. Add one element if(i == destArrTemp.length){ destArrTemp.push([ 'C', posDest.pos[0], posDest.pos[1], posDest.pos[0], posDest.pos[1], posDest.pos[0], posDest.pos[1] ]); } }while(true) // return the updated block return {start:startArrTemp, dest:destArrTemp} } // converts shorthand types to long form function simplyfy(val){ switch(val[0]){ case 'z': // shorthand line to start case 'Z': val[0] = 'L'; val[1] = this.start[0]; val[2] = this.start[1]; break case 'H': // shorthand horizontal line val[0] = 'L'; val[2] = this.pos[1]; break case 'V': // shorthand vertical line val[0] = 'L'; val[2] = val[1]; val[1] = this.pos[0]; break case 'T': // shorthand quadratic beziere val[0] = 'Q'; val[3] = val[1]; val[4] = val[2]; val[1] = this.reflection[1]; val[2] = this.reflection[0]; break case 'S': // shorthand cubic beziere val[0] = 'C'; val[6] = val[4]; val[5] = val[3]; val[4] = val[2]; val[3] = val[1]; val[2] = this.reflection[1]; val[1] = this.reflection[0]; break } return val } // updates reflection point and current position function setPosAndReflection(val){ var len = val.length; this.pos = [ val[len-2], val[len-1] ]; if('SCQT'.indexOf(val[0]) != -1) this.reflection = [ 2 * this.pos[0] - val[len-4], 2 * this.pos[1] - val[len-3] ]; return val } // converts all types to cubic beziere function toBeziere(val){ var retVal = [val]; switch(val[0]){ case 'M': // special handling for M this.pos = this.start = [val[1], val[2]]; return retVal case 'L': val[5] = val[3] = val[1]; val[6] = val[4] = val[2]; val[1] = this.pos[0]; val[2] = this.pos[1]; break case 'Q': val[6] = val[4]; val[5] = val[3]; val[4] = val[4] * 1/3 + val[2] * 2/3; val[3] = val[3] * 1/3 + val[1] * 2/3; val[2] = this.pos[1] * 1/3 + val[2] * 2/3; val[1] = this.pos[0] * 1/3 + val[1] * 2/3; break case 'A': retVal = arcToBeziere(this.pos, val); val = retVal[0]; break } val[0] = 'C'; this.pos = [val[5], val[6]]; this.reflection = [2 * val[5] - val[3], 2 * val[6] - val[4]]; return retVal } // finds the next position of type M function findNextM(arr, offset){ if(offset === false) return false for(var i = offset, len = arr.length;i < len;++i){ if(arr[i][0] == 'M') return i } return false } // Convert an arc segment into equivalent cubic Bezier curves // Depending on the arc, up to 4 curves might be used to represent it since a // curve gives a good approximation for only a quarter of an ellipse // The curves are returned as an array of SVG curve commands: // [ ['C', x1, y1, x2, y2, x, y] ... ] function arcToBeziere(pos, val) { // Parameters extraction, handle out-of-range parameters as specified in the SVG spec // See: https://www.w3.org/TR/SVG11/implnote.html#ArcOutOfRangeParameters var rx = Math.abs(val[1]), ry = Math.abs(val[2]), xAxisRotation = val[3] % 360 , largeArcFlag = val[4], sweepFlag = val[5], x = val[6], y = val[7] , A = new SVG.Point(pos), B = new SVG.Point(x, y) , primedCoord, lambda, mat, k, c, cSquare, t, O, OA, OB, tetaStart, tetaEnd , deltaTeta, nbSectors, f, arcSegPoints, angle, sinAngle, cosAngle, pt, i, il , retVal = [], x1, y1, x2, y2; // Ensure radii are non-zero if(rx === 0 || ry === 0 || (A.x === B.x && A.y === B.y)) { // treat this arc as a straight line segment return [['C', A.x, A.y, B.x, B.y, B.x, B.y]] } // Ensure radii are large enough using the algorithm provided in the SVG spec // See: https://www.w3.org/TR/SVG11/implnote.html#ArcCorrectionOutOfRangeRadii primedCoord = new SVG.Point((A.x-B.x)/2, (A.y-B.y)/2).transform(new SVG.Matrix().rotate(xAxisRotation)); lambda = (primedCoord.x * primedCoord.x) / (rx * rx) + (primedCoord.y * primedCoord.y) / (ry * ry); if(lambda > 1) { lambda = Math.sqrt(lambda); rx = lambda*rx; ry = lambda*ry; } // To simplify calculations, we make the arc part of a unit circle (rayon is 1) instead of an ellipse mat = new SVG.Matrix().rotate(xAxisRotation).scale(1/rx, 1/ry).rotate(-xAxisRotation); A = A.transform(mat); B = B.transform(mat); // Calculate the horizontal and vertical distance between the initial and final point of the arc k = [B.x-A.x, B.y-A.y]; // Find the length of the chord formed by A and B cSquare = k[0]*k[0] + k[1]*k[1]; c = Math.sqrt(cSquare); // Calculate the ratios of the horizontal and vertical distance on the length of the chord k[0] /= c; k[1] /= c; // Calculate the distance between the circle center and the chord midpoint // using this formula: t = sqrt(r^2 - c^2 / 4) // where t is the distance between the cirle center and the chord midpoint, // r is the rayon of the circle and c is the chord length // From: http://www.ajdesigner.com/phpcircle/circle_segment_chord_t.php // Because of the imprecision of floating point numbers, cSquare might end // up being slightly above 4 which would result in a negative radicand // To prevent that, a test is made before computing the square root t = (cSquare < 4) ? Math.sqrt(1 - cSquare/4) : 0; // For most situations, there are actually two different ellipses that // satisfy the constraints imposed by the points A and B, the radii rx and ry, // and the xAxisRotation // When the flags largeArcFlag and sweepFlag are equal, it means that the // second ellipse is used as a solution // See: https://www.w3.org/TR/SVG/paths.html#PathDataEllipticalArcCommands if(largeArcFlag === sweepFlag) { t *= -1; } // Calculate the coordinates of the center of the circle from the midpoint of the chord // This is done by multiplying the ratios calculated previously by the distance between // the circle center and the chord midpoint and using these values to go from the midpoint // to the center of the circle // The negative of the vertical distance ratio is used to modify the x coordinate while // the horizontal distance ratio is used to modify the y coordinate // That is because the center of the circle is perpendicular to the chord and perpendicular // lines are negative reciprocals O = new SVG.Point((B.x+A.x)/2 + t*-k[1], (B.y+A.y)/2 + t*k[0]); // Move the center of the circle at the origin OA = new SVG.Point(A.x-O.x, A.y-O.y); OB = new SVG.Point(B.x-O.x, B.y-O.y); // Calculate the start and end angle tetaStart = Math.acos(OA.x/Math.sqrt(OA.x*OA.x + OA.y*OA.y)); if (OA.y < 0) { tetaStart *= -1; } tetaEnd = Math.acos(OB.x/Math.sqrt(OB.x*OB.x + OB.y*OB.y)); if (OB.y < 0) { tetaEnd *= -1; } // If sweep-flag is '1', then the arc will be drawn in a "positive-angle" direction, // make sure that the end angle is above the start angle if (sweepFlag && tetaStart > tetaEnd) { tetaEnd += 2*Math.PI; } // If sweep-flag is '0', then the arc will be drawn in a "negative-angle" direction, // make sure that the end angle is below the start angle if (!sweepFlag && tetaStart < tetaEnd) { tetaEnd -= 2*Math.PI; } // Find the number of Bezier curves that are required to represent the arc // A cubic Bezier curve gives a good enough approximation when representing at most a quarter of a circle nbSectors = Math.ceil(Math.abs(tetaStart-tetaEnd) * 2/Math.PI); // Calculate the coordinates of the points of all the Bezier curves required to represent the arc // For an in-depth explanation of this part see: http://pomax.github.io/bezierinfo/#circles_cubic arcSegPoints = []; angle = tetaStart; deltaTeta = (tetaEnd-tetaStart)/nbSectors; f = 4*Math.tan(deltaTeta/4)/3; for (i = 0; i <= nbSectors; i++) { // The <= is because a Bezier curve have a start and a endpoint cosAngle = Math.cos(angle); sinAngle = Math.sin(angle); pt = new SVG.Point(O.x+cosAngle, O.y+sinAngle); arcSegPoints[i] = [new SVG.Point(pt.x+f*sinAngle, pt.y-f*cosAngle), pt, new SVG.Point(pt.x-f*sinAngle, pt.y+f*cosAngle)]; angle += deltaTeta; } // Remove the first control point of the first segment point and remove the second control point of the last segment point // These two control points are not used in the approximation of the arc, that is why they are removed arcSegPoints[0][0] = arcSegPoints[0][1].clone(); arcSegPoints[arcSegPoints.length-1][2] = arcSegPoints[arcSegPoints.length-1][1].clone(); // Revert the transformation that was applied to make the arc part of a unit circle instead of an ellipse mat = new SVG.Matrix().rotate(xAxisRotation).scale(rx, ry).rotate(-xAxisRotation); for (i = 0, il = arcSegPoints.length; i < il; i++) { arcSegPoints[i][0] = arcSegPoints[i][0].transform(mat); arcSegPoints[i][1] = arcSegPoints[i][1].transform(mat); arcSegPoints[i][2] = arcSegPoints[i][2].transform(mat); } // Convert the segments points to SVG curve commands for (i = 1, il = arcSegPoints.length; i < il; i++) { pt = arcSegPoints[i-1][2]; x1 = pt.x; y1 = pt.y; pt = arcSegPoints[i][0]; x2 = pt.x; y2 = pt.y; pt = arcSegPoints[i][1]; x = pt.x; y = pt.y; retVal.push(['C', x1, y1, x2, y2, x, y]); } return retVal } }()); /*! svg.draggable.js - v2.2.2 - 2019-01-08 * https://github.com/svgdotjs/svg.draggable.js * Copyright (c) 2019 Wout Fierens; Licensed MIT */ (function() { // creates handler, saves it function DragHandler(el){ el.remember('_draggable', this); this.el = el; } // Sets new parameter, starts dragging DragHandler.prototype.init = function(constraint, val){ var _this = this; this.constraint = constraint; this.value = val; this.el.on('mousedown.drag', function(e){ _this.start(e); }); this.el.on('touchstart.drag', function(e){ _this.start(e); }); }; // transforms one point from screen to user coords DragHandler.prototype.transformPoint = function(event, offset){ event = event || window.event; var touches = event.changedTouches && event.changedTouches[0] || event; this.p.x = touches.clientX - (offset || 0); this.p.y = touches.clientY; return this.p.matrixTransform(this.m) }; // gets elements bounding box with special handling of groups, nested and use DragHandler.prototype.getBBox = function(){ var box = this.el.bbox(); if(this.el instanceof SVG.Nested) box = this.el.rbox(); if (this.el instanceof SVG.G || this.el instanceof SVG.Use || this.el instanceof SVG.Nested) { box.x = this.el.x(); box.y = this.el.y(); } return box }; // start dragging DragHandler.prototype.start = function(e){ // check for left button if(e.type == 'click'|| e.type == 'mousedown' || e.type == 'mousemove'){ if((e.which || e.buttons) != 1){ return } } var _this = this; // fire beforedrag event this.el.fire('beforedrag', { event: e, handler: this }); if(this.el.event().defaultPrevented) return; // prevent browser drag behavior as soon as possible e.preventDefault(); // prevent propagation to a parent that might also have dragging enabled e.stopPropagation(); // search for parent on the fly to make sure we can call // draggable() even when element is not in the dom currently this.parent = this.parent || this.el.parent(SVG.Nested) || this.el.parent(SVG.Doc); this.p = this.parent.node.createSVGPoint(); // save current transformation matrix this.m = this.el.node.getScreenCTM().inverse(); var box = this.getBBox(); var anchorOffset; // fix text-anchor in text-element (#37) if(this.el instanceof SVG.Text){ anchorOffset = this.el.node.getComputedTextLength(); switch(this.el.attr('text-anchor')){ case 'middle': anchorOffset /= 2; break case 'start': anchorOffset = 0; break; } } this.startPoints = { // We take absolute coordinates since we are just using a delta here point: this.transformPoint(e, anchorOffset), box: box, transform: this.el.transform() }; // add drag and end events to window SVG.on(window, 'mousemove.drag', function(e){ _this.drag(e); }); SVG.on(window, 'touchmove.drag', function(e){ _this.drag(e); }); SVG.on(window, 'mouseup.drag', function(e){ _this.end(e); }); SVG.on(window, 'touchend.drag', function(e){ _this.end(e); }); // fire dragstart event this.el.fire('dragstart', {event: e, p: this.startPoints.point, m: this.m, handler: this}); }; // while dragging DragHandler.prototype.drag = function(e){ var box = this.getBBox() , p = this.transformPoint(e) , x = this.startPoints.box.x + p.x - this.startPoints.point.x , y = this.startPoints.box.y + p.y - this.startPoints.point.y , c = this.constraint , gx = p.x - this.startPoints.point.x , gy = p.y - this.startPoints.point.y; this.el.fire('dragmove', { event: e , p: p , m: this.m , handler: this }); if(this.el.event().defaultPrevented) return p // move the element to its new position, if possible by constraint if (typeof c == 'function') { var coord = c.call(this.el, x, y, this.m); // bool, just show us if movement is allowed or not if (typeof coord == 'boolean') { coord = { x: coord, y: coord }; } // if true, we just move. If !false its a number and we move it there if (coord.x === true) { this.el.x(x); } else if (coord.x !== false) { this.el.x(coord.x); } if (coord.y === true) { this.el.y(y); } else if (coord.y !== false) { this.el.y(coord.y); } } else if (typeof c == 'object') { // keep element within constrained box if (c.minX != null && x < c.minX) { x = c.minX; gx = x - this.startPoints.box.x; } else if (c.maxX != null && x > c.maxX - box.width) { x = c.maxX - box.width; gx = x - this.startPoints.box.x; } if (c.minY != null && y < c.minY) { y = c.minY; gy = y - this.startPoints.box.y; } else if (c.maxY != null && y > c.maxY - box.height) { y = c.maxY - box.height; gy = y - this.startPoints.box.y; } if (c.snapToGrid != null) { x = x - (x % c.snapToGrid); y = y - (y % c.snapToGrid); gx = gx - (gx % c.snapToGrid); gy = gy - (gy % c.snapToGrid); } if(this.el instanceof SVG.G) this.el.matrix(this.startPoints.transform).transform({x:gx, y: gy}, true); else this.el.move(x, y); } // so we can use it in the end-method, too return p }; DragHandler.prototype.end = function(e){ // final drag var p = this.drag(e); // fire dragend event this.el.fire('dragend', { event: e, p: p, m: this.m, handler: this }); // unbind events SVG.off(window, 'mousemove.drag'); SVG.off(window, 'touchmove.drag'); SVG.off(window, 'mouseup.drag'); SVG.off(window, 'touchend.drag'); }; SVG.extend(SVG.Element, { // Make element draggable // Constraint might be an object (as described in readme.md) or a function in the form "function (x, y)" that gets called before every move. // The function can return a boolean or an object of the form {x, y}, to which the element will be moved. "False" skips moving, true moves to raw x, y. draggable: function(value, constraint) { // Check the parameters and reassign if needed if (typeof value == 'function' || typeof value == 'object') { constraint = value; value = true; } var dragHandler = this.remember('_draggable') || new DragHandler(this); // When no parameter is given, value is true value = typeof value === 'undefined' ? true : value; if(value) dragHandler.init(constraint || {}, value); else { this.off('mousedown.drag'); this.off('touchstart.drag'); } return this } }); }).call(undefined); (function() { function SelectHandler(el) { this.el = el; el.remember('_selectHandler', this); this.pointSelection = {isSelected: false}; this.rectSelection = {isSelected: false}; // helper list with position settings of each type of point this.pointsList = { lt: [ 0, 0 ], rt: [ 'width', 0 ], rb: [ 'width', 'height' ], lb: [ 0, 'height' ], t: [ 'width', 0 ], r: [ 'width', 'height' ], b: [ 'width', 'height' ], l: [ 0, 'height' ] }; // helper function to get point coordinates based on settings above and an object (bbox in our case) this.pointCoord = function (setting, object, isPointCentered) { var coord = typeof setting !== 'string' ? setting : object[setting]; // Top, bottom, right and left points are placed in the center of element width/height return isPointCentered ? coord / 2 : coord }; this.pointCoords = function (point, object) { var settings = this.pointsList[point]; return { x: this.pointCoord(settings[0], object, (point === 't' || point === 'b')), y: this.pointCoord(settings[1], object, (point === 'r' || point === 'l')) } }; } SelectHandler.prototype.init = function (value, options) { var bbox = this.el.bbox(); this.options = {}; // store defaults list of points in order to verify users config var points = this.el.selectize.defaults.points; // Merging the defaults and the options-object together for (var i in this.el.selectize.defaults) { this.options[i] = this.el.selectize.defaults[i]; if (options[i] !== undefined) { this.options[i] = options[i]; } } // prepare & validate list of points to be added (or excluded) var pointsLists = ['points', 'pointsExclude']; for (var i in pointsLists) { var option = this.options[pointsLists[i]]; if (typeof option === 'string') { if (option.length > 0) { // if set as comma separated string list => convert it into an array option = option.split(/\s*,\s*/i); } else { option = []; } } else if (typeof option === 'boolean' && pointsLists[i] === 'points') { // this is not needed, but let's have it for legacy support option = option ? points : []; } this.options[pointsLists[i]] = option; } // intersect correct all points options with users config (exclude unwanted points) // ES5 -> NO arrow functions nor Array.includes() this.options.points = [ points, this.options.points ].reduce( function (a, b) { return a.filter( function (c) { return b.indexOf(c) > -1; } ) } ); // exclude pointsExclude, if wanted this.options.points = [ this.options.points, this.options.pointsExclude ].reduce( function (a, b) { return a.filter( function (c) { return b.indexOf(c) < 0; } ) } ); this.parent = this.el.parent(); this.nested = (this.nested || this.parent.group()); this.nested.matrix(new SVG.Matrix(this.el).translate(bbox.x, bbox.y)); // When deepSelect is enabled and the element is a line/polyline/polygon, draw only points for moving if (this.options.deepSelect && ['line', 'polyline', 'polygon'].indexOf(this.el.type) !== -1) { this.selectPoints(value); } else { this.selectRect(value); } this.observe(); this.cleanup(); }; SelectHandler.prototype.selectPoints = function (value) { this.pointSelection.isSelected = value; // When set is already there we dont have to create one if (this.pointSelection.set) { return this; } // Create our set of elements this.pointSelection.set = this.parent.set(); // draw the points and mark the element as selected this.drawPoints(); return this; }; // create the point-array which contains the 2 points of a line or simply the points-array of polyline/polygon SelectHandler.prototype.getPointArray = function () { var bbox = this.el.bbox(); return this.el.array().valueOf().map(function (el) { return [el[0] - bbox.x, el[1] - bbox.y]; }); }; // Draws a points SelectHandler.prototype.drawPoints = function () { var _this = this, array = this.getPointArray(); // go through the array of points for (var i = 0, len = array.length; i < len; ++i) { var curriedEvent = (function (k) { return function (ev) { ev = ev || window.event; ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; ev.stopPropagation(); var x = ev.pageX || ev.touches[0].pageX; var y = ev.pageY || ev.touches[0].pageY; _this.el.fire('point', {x: x, y: y, i: k, event: ev}); }; })(i); // add every point to the set // add css-classes and a touchstart-event which fires our event for moving points var point = this.drawPoint(array[i][0], array[i][1]) .addClass(this.options.classPoints) .addClass(this.options.classPoints + '_point') .on('touchstart', curriedEvent) .on('mousedown', curriedEvent); this.pointSelection.set.add(point); } }; // The function to draw single point SelectHandler.prototype.drawPoint = function (cx, cy) { var pointType = this.options.pointType; switch (pointType) { case 'circle': return this.drawCircle(cx, cy); case 'rect': return this.drawRect(cx, cy); default: if (typeof pointType === 'function') { return pointType.call(this, cx, cy); } throw new Error('Unknown ' + pointType + ' point type!'); } }; // The function to draw the circle point SelectHandler.prototype.drawCircle = function (cx, cy) { return this.nested.circle(this.options.pointSize) .center(cx, cy); }; // The function to draw the rect point SelectHandler.prototype.drawRect = function (cx, cy) { return this.nested.rect(this.options.pointSize, this.options.pointSize) .center(cx, cy); }; // every time a point is moved, we have to update the positions of our point SelectHandler.prototype.updatePointSelection = function () { var array = this.getPointArray(); this.pointSelection.set.each(function (i) { if (this.cx() === array[i][0] && this.cy() === array[i][1]) { return; } this.center(array[i][0], array[i][1]); }); }; SelectHandler.prototype.updateRectSelection = function () { var _this = this, bbox = this.el.bbox(); this.rectSelection.set.get(0).attr({ width: bbox.width, height: bbox.height }); // set.get(1) is always in the upper left corner. no need to move it if (this.options.points.length) { this.options.points.map(function (point, index) { var coords = _this.pointCoords(point, bbox); _this.rectSelection.set.get(index + 1).center(coords.x, coords.y); }); } if (this.options.rotationPoint) { var length = this.rectSelection.set.length(); this.rectSelection.set.get(length - 1).center(bbox.width / 2, 20); } }; SelectHandler.prototype.selectRect = function (value) { var _this = this, bbox = this.el.bbox(); this.rectSelection.isSelected = value; // when set is already p this.rectSelection.set = this.rectSelection.set || this.parent.set(); // helperFunction to create a mouse-down function which triggers the event specified in `eventName` function getMoseDownFunc(eventName) { return function (ev) { ev = ev || window.event; ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; ev.stopPropagation(); var x = ev.pageX || ev.touches[0].pageX; var y = ev.pageY || ev.touches[0].pageY; _this.el.fire(eventName, {x: x, y: y, event: ev}); }; } // create the selection-rectangle and add the css-class if (!this.rectSelection.set.get(0)) { this.rectSelection.set.add(this.nested.rect(bbox.width, bbox.height).addClass(this.options.classRect)); } // Draw Points at the edges, if enabled if (this.options.points.length && this.rectSelection.set.length() < 2) { var ename ="touchstart", mname = "mousedown"; this.options.points.map(function (point, index) { var coords = _this.pointCoords(point, bbox); var pointElement = _this.drawPoint(coords.x, coords.y) .attr('class', _this.options.classPoints + '_' + point) .on(mname, getMoseDownFunc(point)) .on(ename, getMoseDownFunc(point)); _this.rectSelection.set.add(pointElement); }); this.rectSelection.set.each(function () { this.addClass(_this.options.classPoints); }); } // draw rotationPint, if enabled if (this.options.rotationPoint && ((this.options.points && !this.rectSelection.set.get(9)) || (!this.options.points && !this.rectSelection.set.get(1)))) { var curriedEvent = function (ev) { ev = ev || window.event; ev.preventDefault ? ev.preventDefault() : ev.returnValue = false; ev.stopPropagation(); var x = ev.pageX || ev.touches[0].pageX; var y = ev.pageY || ev.touches[0].pageY; _this.el.fire('rot', {x: x, y: y, event: ev}); }; var pointElement = this.drawPoint(bbox.width / 2, 20) .attr('class', this.options.classPoints + '_rot') .on("touchstart", curriedEvent) .on("mousedown", curriedEvent); this.rectSelection.set.add(pointElement); } }; SelectHandler.prototype.handler = function () { var bbox = this.el.bbox(); this.nested.matrix(new SVG.Matrix(this.el).translate(bbox.x, bbox.y)); if (this.rectSelection.isSelected) { this.updateRectSelection(); } if (this.pointSelection.isSelected) { this.updatePointSelection(); } }; SelectHandler.prototype.observe = function () { var _this = this; if (MutationObserver) { if (this.rectSelection.isSelected || this.pointSelection.isSelected) { this.observerInst = this.observerInst || new MutationObserver(function () { _this.handler(); }); this.observerInst.observe(this.el.node, {attributes: true}); } else { try { this.observerInst.disconnect(); delete this.observerInst; } catch (e) { } } } else { this.el.off('DOMAttrModified.select'); if (this.rectSelection.isSelected || this.pointSelection.isSelected) { this.el.on('DOMAttrModified.select', function () { _this.handler(); }); } } }; SelectHandler.prototype.cleanup = function () { //var _this = this; if (!this.rectSelection.isSelected && this.rectSelection.set) { // stop watching the element, remove the selection this.rectSelection.set.each(function () { this.remove(); }); this.rectSelection.set.clear(); delete this.rectSelection.set; } if (!this.pointSelection.isSelected && this.pointSelection.set) { // Remove all points, clear the set, stop watching the element this.pointSelection.set.each(function () { this.remove(); }); this.pointSelection.set.clear(); delete this.pointSelection.set; } if (!this.pointSelection.isSelected && !this.rectSelection.isSelected) { this.nested.remove(); delete this.nested; } }; SVG.extend(SVG.Element, { // Select element with mouse selectize: function (value, options) { // Check the parameters and reassign if needed if (typeof value === 'object') { options = value; value = true; } var selectHandler = this.remember('_selectHandler') || new SelectHandler(this); selectHandler.init(value === undefined ? true : value, options || {}); return this; } }); SVG.Element.prototype.selectize.defaults = { points: ['lt', 'rt', 'rb', 'lb', 't', 'r', 'b', 'l'], // which points to draw, default all pointsExclude: [], // easier option if to exclude few than rewrite all classRect: 'svg_select_boundingRect', // Css-class added to the rect classPoints: 'svg_select_points', // Css-class added to the points pointSize: 7, // size of point rotationPoint: true, // If true, rotation point is drawn. Needed for rotation! deepSelect: false, // If true, moving of single points is possible (only line, polyline, polyon) pointType: 'circle' // Point type: circle or rect, default circle }; }()); (function() { (function () { function ResizeHandler(el) { el.remember('_resizeHandler', this); this.el = el; this.parameters = {}; this.lastUpdateCall = null; this.p = el.doc().node.createSVGPoint(); } ResizeHandler.prototype.transformPoint = function(x, y, m){ this.p.x = x - (this.offset.x - window.pageXOffset); this.p.y = y - (this.offset.y - window.pageYOffset); return this.p.matrixTransform(m || this.m); }; ResizeHandler.prototype._extractPosition = function(event) { // Extract a position from a mouse/touch event. // Returns { x: .., y: .. } return { x: event.clientX != null ? event.clientX : event.touches[0].clientX, y: event.clientY != null ? event.clientY : event.touches[0].clientY } }; ResizeHandler.prototype.init = function (options) { var _this = this; this.stop(); if (options === 'stop') { return; } this.options = {}; // Merge options and defaults for (var i in this.el.resize.defaults) { this.options[i] = this.el.resize.defaults[i]; if (typeof options[i] !== 'undefined') { this.options[i] = options[i]; } } // We listen to all these events which are specifying different edges this.el.on('lt.resize', function(e){ _this.resize(e || window.event); }); // Left-Top this.el.on('rt.resize', function(e){ _this.resize(e || window.event); }); // Right-Top this.el.on('rb.resize', function(e){ _this.resize(e || window.event); }); // Right-Bottom this.el.on('lb.resize', function(e){ _this.resize(e || window.event); }); // Left-Bottom this.el.on('t.resize', function(e){ _this.resize(e || window.event); }); // Top this.el.on('r.resize', function(e){ _this.resize(e || window.event); }); // Right this.el.on('b.resize', function(e){ _this.resize(e || window.event); }); // Bottom this.el.on('l.resize', function(e){ _this.resize(e || window.event); }); // Left this.el.on('rot.resize', function(e){ _this.resize(e || window.event); }); // Rotation this.el.on('point.resize', function(e){ _this.resize(e || window.event); }); // Point-Moving // This call ensures, that the plugin reacts to a change of snapToGrid immediately this.update(); }; ResizeHandler.prototype.stop = function(){ this.el.off('lt.resize'); this.el.off('rt.resize'); this.el.off('rb.resize'); this.el.off('lb.resize'); this.el.off('t.resize'); this.el.off('r.resize'); this.el.off('b.resize'); this.el.off('l.resize'); this.el.off('rot.resize'); this.el.off('point.resize'); return this; }; ResizeHandler.prototype.resize = function (event) { var _this = this; this.m = this.el.node.getScreenCTM().inverse(); this.offset = { x: window.pageXOffset, y: window.pageYOffset }; var txPt = this._extractPosition(event.detail.event); this.parameters = { type: this.el.type, // the type of element p: this.transformPoint(txPt.x, txPt.y), x: event.detail.x, // x-position of the mouse when resizing started y: event.detail.y, // y-position of the mouse when resizing started box: this.el.bbox(), // The bounding-box of the element rotation: this.el.transform().rotation // The current rotation of the element }; // Add font-size parameter if the element type is text if (this.el.type === "text") { this.parameters.fontSize = this.el.attr()["font-size"]; } // the i-param in the event holds the index of the point which is moved, when using `deepSelect` if (event.detail.i !== undefined) { // get the point array var array = this.el.array().valueOf(); // Save the index and the point which is moved this.parameters.i = event.detail.i; this.parameters.pointCoords = [array[event.detail.i][0], array[event.detail.i][1]]; } // Lets check which edge of the bounding-box was clicked and resize the this.el according to this switch (event.type) { // Left-Top-Edge case 'lt': // We build a calculating function for every case which gives us the new position of the this.el this.calc = function (diffX, diffY) { // The procedure is always the same // First we snap the edge to the given grid (snapping to 1px grid is normal resizing) var snap = this.snapToGrid(diffX, diffY); // Now we check if the new height and width still valid (> 0) if (this.parameters.box.width - snap[0] > 0 && this.parameters.box.height - snap[1] > 0) { // ...if valid, we resize the this.el (which can include moving because the coord-system starts at the left-top and this edge is moving sometimes when resized) /* * but first check if the element is text box, so we can change the font size instead of * the width and height */ if (this.parameters.type === "text") { this.el.move(this.parameters.box.x + snap[0], this.parameters.box.y); this.el.attr("font-size", this.parameters.fontSize - snap[0]); return; } snap = this.checkAspectRatio(snap); this.el.move(this.parameters.box.x + snap[0], this.parameters.box.y + snap[1]).size(this.parameters.box.width - snap[0], this.parameters.box.height - snap[1]); } }; break; // Right-Top case 'rt': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 1 << 1); if (this.parameters.box.width + snap[0] > 0 && this.parameters.box.height - snap[1] > 0) { if (this.parameters.type === "text") { this.el.move(this.parameters.box.x - snap[0], this.parameters.box.y); this.el.attr("font-size", this.parameters.fontSize + snap[0]); return; } snap = this.checkAspectRatio(snap, true); this.el.move(this.parameters.box.x, this.parameters.box.y + snap[1]).size(this.parameters.box.width + snap[0], this.parameters.box.height - snap[1]); } }; break; // Right-Bottom case 'rb': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 0); if (this.parameters.box.width + snap[0] > 0 && this.parameters.box.height + snap[1] > 0) { if (this.parameters.type === "text") { this.el.move(this.parameters.box.x - snap[0], this.parameters.box.y); this.el.attr("font-size", this.parameters.fontSize + snap[0]); return; } snap = this.checkAspectRatio(snap); this.el.move(this.parameters.box.x, this.parameters.box.y).size(this.parameters.box.width + snap[0], this.parameters.box.height + snap[1]); } }; break; // Left-Bottom case 'lb': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 1); if (this.parameters.box.width - snap[0] > 0 && this.parameters.box.height + snap[1] > 0) { if (this.parameters.type === "text") { this.el.move(this.parameters.box.x + snap[0], this.parameters.box.y); this.el.attr("font-size", this.parameters.fontSize - snap[0]); return; } snap = this.checkAspectRatio(snap, true); this.el.move(this.parameters.box.x + snap[0], this.parameters.box.y).size(this.parameters.box.width - snap[0], this.parameters.box.height + snap[1]); } }; break; // Top case 't': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 1 << 1); if (this.parameters.box.height - snap[1] > 0) { // Disable the font-resizing if it is not from the corner of bounding-box if (this.parameters.type === "text") { return; } this.el.move(this.parameters.box.x, this.parameters.box.y + snap[1]).height(this.parameters.box.height - snap[1]); } }; break; // Right case 'r': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 0); if (this.parameters.box.width + snap[0] > 0) { if (this.parameters.type === "text") { return; } this.el.move(this.parameters.box.x, this.parameters.box.y).width(this.parameters.box.width + snap[0]); } }; break; // Bottom case 'b': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 0); if (this.parameters.box.height + snap[1] > 0) { if (this.parameters.type === "text") { return; } this.el.move(this.parameters.box.x, this.parameters.box.y).height(this.parameters.box.height + snap[1]); } }; break; // Left case 'l': // s.a. this.calc = function (diffX, diffY) { var snap = this.snapToGrid(diffX, diffY, 1); if (this.parameters.box.width - snap[0] > 0) { if (this.parameters.type === "text") { return; } this.el.move(this.parameters.box.x + snap[0], this.parameters.box.y).width(this.parameters.box.width - snap[0]); } }; break; // Rotation case 'rot': // s.a. this.calc = function (diffX, diffY) { // yes this is kinda stupid but we need the mouse coords back... var current = {x: diffX + this.parameters.p.x, y: diffY + this.parameters.p.y}; // start minus middle var sAngle = Math.atan2((this.parameters.p.y - this.parameters.box.y - this.parameters.box.height / 2), (this.parameters.p.x - this.parameters.box.x - this.parameters.box.width / 2)); // end minus middle var pAngle = Math.atan2((current.y - this.parameters.box.y - this.parameters.box.height / 2), (current.x - this.parameters.box.x - this.parameters.box.width / 2)); var angle = this.parameters.rotation + (pAngle - sAngle) * 180 / Math.PI + this.options.snapToAngle / 2; // We have to move the element to the center of the box first and change the rotation afterwards // because rotation always works around a rotation-center, which is changed when moving the element // We also set the new rotation center to the center of the box. this.el.center(this.parameters.box.cx, this.parameters.box.cy).rotate(angle - (angle % this.options.snapToAngle), this.parameters.box.cx, this.parameters.box.cy); }; break; // Moving one single Point (needed when an element is deepSelected which means you can move every single point of the object) case 'point': this.calc = function (diffX, diffY) { // Snapping the point to the grid var snap = this.snapToGrid(diffX, diffY, this.parameters.pointCoords[0], this.parameters.pointCoords[1]); // Get the point array var array = this.el.array().valueOf(); // Changing the moved point in the array array[this.parameters.i][0] = this.parameters.pointCoords[0] + snap[0]; array[this.parameters.i][1] = this.parameters.pointCoords[1] + snap[1]; // And plot the new this.el this.el.plot(array); }; } this.el.fire('resizestart', {dx: this.parameters.x, dy: this.parameters.y, event: event}); // When resizing started, we have to register events for... // Touches. SVG.on(window, 'touchmove.resize', function(e) { _this.update(e || window.event); }); SVG.on(window, 'touchend.resize', function() { _this.done(); }); // Mouse. SVG.on(window, 'mousemove.resize', function (e) { _this.update(e || window.event); }); SVG.on(window, 'mouseup.resize', function () { _this.done(); }); }; // The update-function redraws the element every time the mouse is moving ResizeHandler.prototype.update = function (event) { if (!event) { if (this.lastUpdateCall) { this.calc(this.lastUpdateCall[0], this.lastUpdateCall[1]); } return; } // Calculate the difference between the mouseposition at start and now var txPt = this._extractPosition(event); var p = this.transformPoint(txPt.x, txPt.y); var diffX = p.x - this.parameters.p.x, diffY = p.y - this.parameters.p.y; this.lastUpdateCall = [diffX, diffY]; // Calculate the new position and height / width of the element this.calc(diffX, diffY); // Emit an event to say we have changed. this.el.fire('resizing', {dx: diffX, dy: diffY, event: event}); }; // Is called on mouseup. // Removes the update-function from the mousemove event ResizeHandler.prototype.done = function () { this.lastUpdateCall = null; SVG.off(window, 'mousemove.resize'); SVG.off(window, 'mouseup.resize'); SVG.off(window, 'touchmove.resize'); SVG.off(window, 'touchend.resize'); this.el.fire('resizedone'); }; // The flag is used to determine whether the resizing is used with a left-Point (first bit) and top-point (second bit) // In this cases the temp-values are calculated differently ResizeHandler.prototype.snapToGrid = function (diffX, diffY, flag, pointCoordsY) { var temp; // If `pointCoordsY` is given, a single Point has to be snapped (deepSelect). That's why we need a different temp-value if (typeof pointCoordsY !== 'undefined') { // Note that flag = pointCoordsX in this case temp = [(flag + diffX) % this.options.snapToGrid, (pointCoordsY + diffY) % this.options.snapToGrid]; } else { // We check if the flag is set and if not we set a default-value (both bits set - which means upper-left-edge) flag = flag == null ? 1 | 1 << 1 : flag; temp = [(this.parameters.box.x + diffX + (flag & 1 ? 0 : this.parameters.box.width)) % this.options.snapToGrid, (this.parameters.box.y + diffY + (flag & (1 << 1) ? 0 : this.parameters.box.height)) % this.options.snapToGrid]; } if(diffX < 0) { temp[0] -= this.options.snapToGrid; } if(diffY < 0) { temp[1] -= this.options.snapToGrid; } diffX -= (Math.abs(temp[0]) < this.options.snapToGrid / 2 ? temp[0] : temp[0] - (diffX < 0 ? -this.options.snapToGrid : this.options.snapToGrid)); diffY -= (Math.abs(temp[1]) < this.options.snapToGrid / 2 ? temp[1] : temp[1] - (diffY < 0 ? -this.options.snapToGrid : this.options.snapToGrid)); return this.constraintToBox(diffX, diffY, flag, pointCoordsY); }; // keep element within constrained box ResizeHandler.prototype.constraintToBox = function (diffX, diffY, flag, pointCoordsY) { //return [diffX, diffY] var c = this.options.constraint || {}; var orgX, orgY; if (typeof pointCoordsY !== 'undefined') { orgX = flag; orgY = pointCoordsY; } else { orgX = this.parameters.box.x + (flag & 1 ? 0 : this.parameters.box.width); orgY = this.parameters.box.y + (flag & (1<<1) ? 0 : this.parameters.box.height); } if (typeof c.minX !== 'undefined' && orgX + diffX < c.minX) { diffX = c.minX - orgX; } if (typeof c.maxX !== 'undefined' && orgX + diffX > c.maxX) { diffX = c.maxX - orgX; } if (typeof c.minY !== 'undefined' && orgY + diffY < c.minY) { diffY = c.minY - orgY; } if (typeof c.maxY !== 'undefined' && orgY + diffY > c.maxY) { diffY = c.maxY - orgY; } return [diffX, diffY]; }; ResizeHandler.prototype.checkAspectRatio = function (snap, isReverse) { if (!this.options.saveAspectRatio) { return snap; } var updatedSnap = snap.slice(); var aspectRatio = this.parameters.box.width / this.parameters.box.height; var newW = this.parameters.box.width + snap[0]; var newH = this.parameters.box.height - snap[1]; var newAspectRatio = newW / newH; if (newAspectRatio < aspectRatio) { // Height is too big. Adapt it updatedSnap[1] = newW / aspectRatio - this.parameters.box.height; isReverse && (updatedSnap[1] = -updatedSnap[1]); } else if (newAspectRatio > aspectRatio) { // Width is too big. Adapt it updatedSnap[0] = this.parameters.box.width - newH * aspectRatio; isReverse && (updatedSnap[0] = -updatedSnap[0]); } return updatedSnap; }; SVG.extend(SVG.Element, { // Resize element with mouse resize: function (options) { (this.remember('_resizeHandler') || new ResizeHandler(this)).init(options || {}); return this; } }); SVG.Element.prototype.resize.defaults = { snapToAngle: 0.1, // Specifies the speed the rotation is happening when moving the mouse snapToGrid: 1, // Snaps to a grid of `snapToGrid` Pixels constraint: {}, // keep element within constrained box saveAspectRatio: false // Save aspect ratio when resizing using lt, rt, rb or lb points }; }).call(this); }()); if (typeof window.Apex === 'undefined') { window.Apex = {}; } var InitCtxVariables = /*#__PURE__*/function () { function InitCtxVariables(ctx) { _classCallCheck(this, InitCtxVariables); this.ctx = ctx; this.w = ctx.w; } _createClass(InitCtxVariables, [{ key: "initModules", value: function initModules() { this.ctx.publicMethods = ['updateOptions', 'updateSeries', 'appendData', 'appendSeries', 'toggleSeries', 'showSeries', 'hideSeries', 'setLocale', 'resetSeries', 'zoomX', 'toggleDataPointSelection', 'dataURI', 'exportToCSV', 'addXaxisAnnotation', 'addYaxisAnnotation', 'addPointAnnotation', 'clearAnnotations', 'removeAnnotation', 'paper', 'destroy']; this.ctx.eventList = ['click', 'mousedown', 'mousemove', 'mouseleave', 'touchstart', 'touchmove', 'touchleave', 'mouseup', 'touchend']; this.ctx.animations = new Animations(this.ctx); this.ctx.axes = new Axes(this.ctx); this.ctx.core = new Core(this.ctx.el, this.ctx); this.ctx.config = new Config({}); this.ctx.data = new Data(this.ctx); this.ctx.grid = new Grid(this.ctx); this.ctx.graphics = new Graphics(this.ctx); this.ctx.coreUtils = new CoreUtils(this.ctx); this.ctx.crosshairs = new Crosshairs(this.ctx); this.ctx.events = new Events(this.ctx); this.ctx.exports = new Exports(this.ctx); this.ctx.localization = new Localization(this.ctx); this.ctx.options = new Options(); this.ctx.responsive = new Responsive(this.ctx); this.ctx.series = new Series(this.ctx); this.ctx.theme = new Theme(this.ctx); this.ctx.formatters = new Formatters(this.ctx); this.ctx.titleSubtitle = new TitleSubtitle(this.ctx); this.ctx.legend = new Legend(this.ctx); this.ctx.toolbar = new Toolbar(this.ctx); this.ctx.tooltip = new Tooltip(this.ctx); this.ctx.dimensions = new Dimensions(this.ctx); this.ctx.updateHelpers = new UpdateHelpers(this.ctx); this.ctx.zoomPanSelection = new ZoomPanSelection(this.ctx); this.ctx.w.globals.tooltip = new Tooltip(this.ctx); } }]); return InitCtxVariables; }(); var Destroy = /*#__PURE__*/function () { function Destroy(ctx) { _classCallCheck(this, Destroy); this.ctx = ctx; this.w = ctx.w; } _createClass(Destroy, [{ key: "clear", value: function clear(_ref) { var isUpdating = _ref.isUpdating; if (this.ctx.zoomPanSelection) { this.ctx.zoomPanSelection.destroy(); } if (this.ctx.toolbar) { this.ctx.toolbar.destroy(); } this.ctx.animations = null; this.ctx.axes = null; this.ctx.annotations = null; this.ctx.core = null; this.ctx.data = null; this.ctx.grid = null; this.ctx.series = null; this.ctx.responsive = null; this.ctx.theme = null; this.ctx.formatters = null; this.ctx.titleSubtitle = null; this.ctx.legend = null; this.ctx.dimensions = null; this.ctx.options = null; this.ctx.crosshairs = null; this.ctx.zoomPanSelection = null; this.ctx.updateHelpers = null; this.ctx.toolbar = null; this.ctx.localization = null; this.ctx.w.globals.tooltip = null; this.clearDomElements({ isUpdating: isUpdating }); } }, { key: "killSVG", value: function killSVG(draw) { draw.each(function (i, children) { this.removeClass('*'); this.off(); this.stop(); }, true); draw.ungroup(); draw.clear(); } }, { key: "clearDomElements", value: function clearDomElements(_ref2) { var _this = this; var isUpdating = _ref2.isUpdating; var elSVG = this.w.globals.dom.Paper.node; // fixes apexcharts.js#1654 & vue-apexcharts#256 if (elSVG.parentNode && elSVG.parentNode.parentNode && !isUpdating) { elSVG.parentNode.parentNode.style.minHeight = 'unset'; } // detach root event var baseEl = this.w.globals.dom.baseEl; if (baseEl) { // see https://github.com/apexcharts/vue-apexcharts/issues/275 this.ctx.eventList.forEach(function (event) { baseEl.removeEventListener(event, _this.ctx.events.documentEvent); }); } var domEls = this.w.globals.dom; if (this.ctx.el !== null) { // remove all child elements - resetting the whole chart while (this.ctx.el.firstChild) { this.ctx.el.removeChild(this.ctx.el.firstChild); } } this.killSVG(domEls.Paper); domEls.Paper.remove(); domEls.elWrap = null; domEls.elGraphical = null; domEls.elAnnotations = null; domEls.elLegendWrap = null; domEls.baseEl = null; domEls.elGridRect = null; domEls.elGridRectMask = null; domEls.elGridRectMarkerMask = null; domEls.elForecastMask = null; domEls.elNonForecastMask = null; domEls.elDefs = null; } }]); return Destroy; }(); // Helpers to react to element resizes, regardless of what caused them // TODO Currently this creates a new ResizeObserver every time we want to observe an element for resizes // Ideally, we should be able to use a single observer for all elements var ros = new WeakMap(); // Map callbacks to ResizeObserver instances for easy removal function addResizeListener(el, fn) { var called = false; if (el.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) { var elRect = el.getBoundingClientRect(); if (el.style.display === 'none' || elRect.width === 0) { // if elRect.width=0, the chart is not rendered at all // (it has either display none or hidden in a different tab) // fixes https://github.com/apexcharts/apexcharts.js/issues/2825 // fixes https://github.com/apexcharts/apexcharts.js/issues/2991 // fixes https://github.com/apexcharts/apexcharts.js/issues/2992 called = true; } } var ro = new ResizeObserver(function (r) { // ROs fire immediately after being created, // per spec: https://drafts.csswg.org/resize-observer/#ref-for-element%E2%91%A3 // we don't want that so we just discard the first run if (called) { fn.call(el, r); } called = true; }); if (el.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { // Document fragment, observe children instead (needed for Shadow DOM, see #1332) Array.from(el.children).forEach(function (c) { return ro.observe(c); }); } else { ro.observe(el); } ros.set(fn, ro); } function removeResizeListener(el, fn) { var ro = ros.get(fn); if (ro) { ro.disconnect(); ros.delete(fn); } } var css_248z = "@keyframes opaque {\n 0% {\n opacity: 0\n }\n\n to {\n opacity: 1\n }\n}\n\n@keyframes resizeanim {\n 0%,to {\n opacity: 0\n }\n}\n\n.apexcharts-canvas {\n position: relative;\n user-select: none\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n -webkit-appearance: none;\n width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n border-radius: 4px;\n background-color: rgba(0,0,0,.5);\n box-shadow: 0 0 1px rgba(255,255,255,.5);\n -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5)\n}\n\n.apexcharts-inner {\n position: relative\n}\n\n.apexcharts-text tspan {\n font-family: inherit\n}\n\n.legend-mouseover-inactive {\n transition: .15s ease all;\n opacity: .2\n}\n\n.apexcharts-legend-text {\n padding-left: 15px;\n margin-left: -15px;\n}\n\n.apexcharts-series-collapsed {\n opacity: 0\n}\n\n.apexcharts-tooltip {\n border-radius: 5px;\n box-shadow: 2px 2px 6px -4px #999;\n cursor: default;\n font-size: 14px;\n left: 62px;\n opacity: 0;\n pointer-events: none;\n position: absolute;\n top: 20px;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n white-space: nowrap;\n z-index: 12;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n border: 1px solid #e3e3e3;\n background: rgba(255,255,255,.96)\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n color: #fff;\n background: rgba(30,30,30,.8)\n}\n\n.apexcharts-tooltip * {\n font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n padding: 6px;\n font-size: 15px;\n margin-bottom: 4px\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title {\n background: #eceff1;\n border-bottom: 1px solid #ddd\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n background: rgba(0,0,0,.7);\n border-bottom: 1px solid #333\n}\n\n.apexcharts-tooltip-text-goals-value,.apexcharts-tooltip-text-y-value,.apexcharts-tooltip-text-z-value {\n display: inline-block;\n margin-left: 5px;\n font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,.apexcharts-tooltip-text-goals-value:empty,.apexcharts-tooltip-text-y-label:empty,.apexcharts-tooltip-text-y-value:empty,.apexcharts-tooltip-text-z-value:empty,.apexcharts-tooltip-title:empty {\n display: none\n}\n\n.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,.apexcharts-tooltip-text-goals-label,.apexcharts-tooltip-text-goals-value {\n display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),.apexcharts-tooltip-text-goals-value:not(:empty) {\n margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n width: 12px;\n height: 12px;\n position: relative;\n top: 0;\n margin-right: 10px;\n border-radius: 50%\n}\n\n.apexcharts-tooltip-series-group {\n padding: 0 10px;\n display: none;\n text-align: left;\n justify-content: left;\n align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active,.apexcharts-tooltip-series-group:last-child {\n padding-bottom: 4px\n}\n\n.apexcharts-tooltip-series-group-hidden {\n opacity: 0;\n height: 0;\n line-height: 0;\n padding: 0!important\n}\n\n.apexcharts-tooltip-y-group {\n padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,.apexcharts-tooltip-box {\n padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n display: flex;\n flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n font-weight: 600;\n color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n font-weight: 700;\n display: block;\n margin-bottom: 5px\n}\n\n.apexcharts-xaxistooltip,.apexcharts-yaxistooltip {\n opacity: 0;\n pointer-events: none;\n color: #373d3f;\n font-size: 13px;\n text-align: center;\n border-radius: 2px;\n position: absolute;\n z-index: 10;\n background: #eceff1;\n border: 1px solid #90a4ae\n}\n\n.apexcharts-xaxistooltip {\n padding: 9px 10px;\n transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-xaxistooltip:after,.apexcharts-xaxistooltip:before {\n left: 50%;\n border: solid transparent;\n content: \" \";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-xaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-left: -6px\n}\n\n.apexcharts-xaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-left: -7px\n}\n\n.apexcharts-xaxistooltip-bottom:after,.apexcharts-xaxistooltip-bottom:before {\n bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,.apexcharts-xaxistooltip-top:before {\n top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n border-bottom-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n border-bottom-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-bottom.apexcharts-theme-dark:before {\n border-bottom-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip-top:after {\n border-top-color: #eceff1\n}\n\n.apexcharts-xaxistooltip-top:before {\n border-top-color: #90a4ae\n}\n\n.apexcharts-xaxistooltip-top.apexcharts-theme-dark:after,.apexcharts-xaxistooltip-top.apexcharts-theme-dark:before {\n border-top-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n padding: 4px 10px\n}\n\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n background: rgba(0,0,0,.7);\n border: 1px solid rgba(0,0,0,.5);\n color: #fff\n}\n\n.apexcharts-yaxistooltip:after,.apexcharts-yaxistooltip:before {\n top: 50%;\n border: solid transparent;\n content: \" \";\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n border-color: transparent;\n border-width: 6px;\n margin-top: -6px\n}\n\n.apexcharts-yaxistooltip:before {\n border-color: transparent;\n border-width: 7px;\n margin-top: -7px\n}\n\n.apexcharts-yaxistooltip-left:after,.apexcharts-yaxistooltip-left:before {\n left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,.apexcharts-yaxistooltip-right:before {\n right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n border-left-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-left:before {\n border-left-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-left.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-left.apexcharts-theme-dark:before {\n border-left-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip-right:after {\n border-right-color: #eceff1\n}\n\n.apexcharts-yaxistooltip-right:before {\n border-right-color: #90a4ae\n}\n\n.apexcharts-yaxistooltip-right.apexcharts-theme-dark:after,.apexcharts-yaxistooltip-right.apexcharts-theme-dark:before {\n border-right-color: rgba(0,0,0,.5)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n display: none\n}\n\n.apexcharts-xcrosshairs,.apexcharts-ycrosshairs {\n pointer-events: none;\n opacity: 0;\n transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,.apexcharts-ycrosshairs.apexcharts-active {\n opacity: 1;\n transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n opacity: 0\n}\n\n.apexcharts-selection-rect {\n cursor: move\n}\n\n.svg_select_boundingRect,.svg_select_points_rot {\n pointer-events: none;\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_boundingRect,.apexcharts-selection-rect+g .svg_select_points_rot {\n opacity: 0;\n visibility: hidden\n}\n\n.apexcharts-selection-rect+g .svg_select_points_l,.apexcharts-selection-rect+g .svg_select_points_r {\n cursor: ew-resize;\n opacity: 1;\n visibility: visible\n}\n\n.svg_select_points {\n fill: #efefef;\n stroke: #333;\n rx: 2\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n cursor: move\n}\n\n.apexcharts-menu-icon,.apexcharts-pan-icon,.apexcharts-reset-icon,.apexcharts-selection-icon,.apexcharts-toolbar-custom-icon,.apexcharts-zoom-icon,.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n cursor: pointer;\n width: 20px;\n height: 20px;\n line-height: 24px;\n color: #6e8192;\n text-align: center\n}\n\n.apexcharts-menu-icon svg,.apexcharts-reset-icon svg,.apexcharts-zoom-icon svg,.apexcharts-zoomin-icon svg,.apexcharts-zoomout-icon svg {\n fill: #6e8192\n}\n\n.apexcharts-selection-icon svg {\n fill: #444;\n transform: scale(.76)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon svg,.apexcharts-theme-dark .apexcharts-pan-icon svg,.apexcharts-theme-dark .apexcharts-reset-icon svg,.apexcharts-theme-dark .apexcharts-selection-icon svg,.apexcharts-theme-dark .apexcharts-toolbar-custom-icon svg,.apexcharts-theme-dark .apexcharts-zoom-icon svg,.apexcharts-theme-dark .apexcharts-zoomin-icon svg,.apexcharts-theme-dark .apexcharts-zoomout-icon svg {\n fill: #f3f4f5\n}\n\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected svg,.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected svg {\n fill: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover svg,.apexcharts-theme-light .apexcharts-reset-icon:hover svg,.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover svg,.apexcharts-theme-light .apexcharts-zoomin-icon:hover svg,.apexcharts-theme-light .apexcharts-zoomout-icon:hover svg {\n fill: #333\n}\n\n.apexcharts-menu-icon,.apexcharts-selection-icon {\n position: relative\n}\n\n.apexcharts-reset-icon {\n margin-left: 5px\n}\n\n.apexcharts-menu-icon,.apexcharts-reset-icon,.apexcharts-zoom-icon {\n transform: scale(.85)\n}\n\n.apexcharts-zoomin-icon,.apexcharts-zoomout-icon {\n transform: scale(.7)\n}\n\n.apexcharts-zoomout-icon {\n margin-right: 3px\n}\n\n.apexcharts-pan-icon {\n transform: scale(.62);\n position: relative;\n left: 1px;\n top: 0\n}\n\n.apexcharts-pan-icon svg {\n fill: #fff;\n stroke: #6e8192;\n stroke-width: 2\n}\n\n.apexcharts-pan-icon.apexcharts-selected svg {\n stroke: #008ffb\n}\n\n.apexcharts-pan-icon:not(.apexcharts-selected):hover svg {\n stroke: #333\n}\n\n.apexcharts-toolbar {\n position: absolute;\n z-index: 11;\n max-width: 176px;\n text-align: right;\n border-radius: 3px;\n padding: 0 6px 2px;\n display: flex;\n justify-content: space-between;\n align-items: center\n}\n\n.apexcharts-menu {\n background: #fff;\n position: absolute;\n top: 100%;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 3px;\n right: 10px;\n opacity: 0;\n min-width: 110px;\n transition: .15s ease all;\n pointer-events: none\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n opacity: 1;\n pointer-events: all;\n transition: .15s ease all\n}\n\n.apexcharts-menu-item {\n padding: 6px 7px;\n font-size: 12px;\n cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n background: #eee\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n background: rgba(0,0,0,.7);\n color: #fff\n}\n\n@media screen and (min-width:768px) {\n .apexcharts-canvas:hover .apexcharts-toolbar {\n opacity: 1\n }\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,.apexcharts-datalabel.apexcharts-element-hidden,.apexcharts-hide .apexcharts-series-points {\n opacity: 0\n}\n\n.apexcharts-datalabel,.apexcharts-datalabel-label,.apexcharts-datalabel-value,.apexcharts-datalabels,.apexcharts-pie-label {\n cursor: default;\n pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n opacity: 0;\n animation-name: opaque;\n animation-duration: .3s;\n animation-fill-mode: forwards;\n animation-timing-function: ease\n}\n\n.apexcharts-legend {\t\n display: flex;\t\n overflow: auto;\t\n padding: 0 10px;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\t\n flex-wrap: wrap\t\n}\t\n.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n flex-direction: column;\t\n bottom: 0;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\t\n justify-content: flex-start;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\t\n justify-content: center; \t\n}\t\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\t\n justify-content: flex-end;\t\n}\t\n.apexcharts-legend-series {\t\n cursor: pointer;\t\n line-height: normal;\t\n}\t\n.apexcharts-legend.apx-legend-position-bottom .apexcharts-legend-series, .apexcharts-legend.apx-legend-position-top .apexcharts-legend-series{\t\n display: flex;\t\n align-items: center;\t\n}\t\n.apexcharts-legend-text {\t\n position: relative;\t\n font-size: 14px;\t\n}\t\n.apexcharts-legend-text *, .apexcharts-legend-marker * {\t\n pointer-events: none;\t\n}\t\n.apexcharts-legend-marker {\t\n position: relative;\t\n display: inline-block;\t\n cursor: pointer;\t\n margin-right: 3px;\t\n border-style: solid;\n}\t\n \n.apexcharts-legend.apexcharts-align-right .apexcharts-legend-series, .apexcharts-legend.apexcharts-align-left .apexcharts-legend-series{\t\n display: inline-block;\t\n}\t\n.apexcharts-legend-series.apexcharts-no-click {\t\n cursor: auto;\t\n}\t\n.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\t\n display: none !important;\t\n}\t\n.apexcharts-inactive-legend {\t\n opacity: 0.45;\t\n}\n\n.apexcharts-annotation-rect,.apexcharts-area-series .apexcharts-area,.apexcharts-area-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-gridline,.apexcharts-line,.apexcharts-line-series .apexcharts-series-markers .apexcharts-marker.no-pointer-events,.apexcharts-point-annotation-label,.apexcharts-radar-series path,.apexcharts-radar-series polygon,.apexcharts-toolbar svg,.apexcharts-tooltip .apexcharts-marker,.apexcharts-xaxis-annotation-label,.apexcharts-yaxis-annotation-label,.apexcharts-zoom-rect {\n pointer-events: none\n}\n\n.apexcharts-marker {\n transition: .15s ease all\n}\n\n.resize-triggers {\n animation: 1ms resizeanim;\n visibility: hidden;\n opacity: 0;\n height: 100%;\n width: 100%;\n overflow: hidden\n}\n\n.contract-trigger:before,.resize-triggers,.resize-triggers>div {\n content: \" \";\n display: block;\n position: absolute;\n top: 0;\n left: 0\n}\n\n.resize-triggers>div {\n height: 100%;\n width: 100%;\n background: #eee;\n overflow: auto\n}\n\n.contract-trigger:before {\n overflow: hidden;\n width: 200%;\n height: 200%\n}\n"; /** * * @module ApexCharts **/ var ApexCharts$1 = /*#__PURE__*/function () { function ApexCharts(el, opts) { _classCallCheck(this, ApexCharts); this.opts = opts; this.ctx = this; // Pass the user supplied options to the Base Class where these options will be extended with defaults. The returned object from Base Class will become the config object in the entire codebase. this.w = new Base(opts).init(); this.el = el; this.w.globals.cuid = Utils$1.randomId(); this.w.globals.chartID = this.w.config.chart.id ? Utils$1.escapeString(this.w.config.chart.id) : this.w.globals.cuid; var initCtx = new InitCtxVariables(this); initCtx.initModules(); this.create = Utils$1.bind(this.create, this); this.windowResizeHandler = this._windowResizeHandler.bind(this); this.parentResizeHandler = this._parentResizeCallback.bind(this); } /** * The primary method user will call to render the chart. */ _createClass(ApexCharts, [{ key: "render", value: function render() { var _this = this; // main method return new Promise(function (resolve, reject) { // only draw chart, if element found if (_this.el !== null) { if (typeof Apex._chartInstances === 'undefined') { Apex._chartInstances = []; } if (_this.w.config.chart.id) { Apex._chartInstances.push({ id: _this.w.globals.chartID, group: _this.w.config.chart.group, chart: _this }); } // set the locale here _this.setLocale(_this.w.config.chart.defaultLocale); var beforeMount = _this.w.config.chart.events.beforeMount; if (typeof beforeMount === 'function') { beforeMount(_this, _this.w); } _this.events.fireEvent('beforeMount', [_this, _this.w]); window.addEventListener('resize', _this.windowResizeHandler); addResizeListener(_this.el.parentNode, _this.parentResizeHandler); // Add CSS if not already added if (!_this.css) { var rootNode = _this.el.getRootNode && _this.el.getRootNode(); var inShadowRoot = Utils$1.is('ShadowRoot', rootNode); var doc = _this.el.ownerDocument; var globalCSS = doc.getElementById('apexcharts-css'); if (inShadowRoot || !globalCSS) { _this.css = document.createElement('style'); _this.css.id = 'apexcharts-css'; _this.css.textContent = css_248z; if (inShadowRoot) { // We are in Shadow DOM, add to shadow root rootNode.prepend(_this.css); } else { // Add to of element's document doc.head.appendChild(_this.css); } } } var graphData = _this.create(_this.w.config.series, {}); if (!graphData) return resolve(_this); _this.mount(graphData).then(function () { if (typeof _this.w.config.chart.events.mounted === 'function') { _this.w.config.chart.events.mounted(_this, _this.w); } _this.events.fireEvent('mounted', [_this, _this.w]); resolve(graphData); }).catch(function (e) { reject(e); // handle error in case no data or element not found }); } else { reject(new Error('Element not found')); } }); } }, { key: "create", value: function create(ser, opts) { var w = this.w; var initCtx = new InitCtxVariables(this); initCtx.initModules(); var gl = this.w.globals; gl.noData = false; gl.animationEnded = false; this.responsive.checkResponsiveConfig(opts); if (w.config.xaxis.convertedCatToNumeric) { var defaults = new Defaults(w.config); defaults.convertCatToNumericXaxis(w.config, this.ctx); } if (this.el === null) { gl.animationEnded = true; return null; } this.core.setupElements(); if (w.config.chart.type === 'treemap') { w.config.grid.show = false; w.config.yaxis[0].show = false; } if (gl.svgWidth === 0) { // if the element is hidden, skip drawing gl.animationEnded = true; return null; } var combo = CoreUtils.checkComboSeries(ser); gl.comboCharts = combo.comboCharts; gl.comboBarCount = combo.comboBarCount; var allSeriesAreEmpty = ser.every(function (s) { return s.data && s.data.length === 0; }); if (ser.length === 0 || allSeriesAreEmpty) { this.series.handleNoData(); } this.events.setupEventHandlers(); // Handle the data inputted by user and set some of the global variables (for eg, if data is datetime / numeric / category). Don't calculate the range / min / max at this time this.data.parseData(ser); // this is a good time to set theme colors first this.theme.init(); // as markers accepts array, we need to setup global markers for easier access var markers = new Markers(this); markers.setGlobalMarkerSize(); // labelFormatters should be called before dimensions as in dimensions we need text labels width this.formatters.setLabelFormatters(); this.titleSubtitle.draw(); // legend is calculated here before coreCalculations because it affects the plottable area // if there is some data to show or user collapsed all series, then proceed drawing legend if (!gl.noData || gl.collapsedSeries.length === gl.series.length || w.config.legend.showForSingleSeries) { this.legend.init(); } // check whether in multiple series, all series share the same X this.series.hasAllSeriesEqualX(); // coreCalculations will give the min/max range and yaxis/axis values. It should be called here to set series variable from config to globals if (gl.axisCharts) { this.core.coreCalculations(); if (w.config.xaxis.type !== 'category') { // as we have minX and maxX values, determine the default DateTimeFormat for time series this.formatters.setLabelFormatters(); } this.ctx.toolbar.minX = w.globals.minX; this.ctx.toolbar.maxX = w.globals.maxX; } // we need to generate yaxis for heatmap separately as we are not showing numerics there, but seriesNames. There are some tweaks which are required for heatmap to align labels correctly which are done in below function // Also we need to do this before calculating Dimensions plotCoords() method of Dimensions this.formatters.heatmapLabelFormatters(); // get the largest marker size which will be needed in dimensions calc var coreUtils = new CoreUtils(this); coreUtils.getLargestMarkerSize(); // We got plottable area here, next task would be to calculate axis areas this.dimensions.plotCoords(); var xyRatios = this.core.xySettings(); this.grid.createGridMask(); var elGraph = this.core.plotChartType(ser, xyRatios); var dataLabels = new DataLabels(this); dataLabels.bringForward(); if (w.config.dataLabels.background.enabled) { dataLabels.dataLabelsBackground(); } // after all the drawing calculations, shift the graphical area (actual charts/bars) excluding legends this.core.shiftGraphPosition(); var dim = { plot: { left: w.globals.translateX, top: w.globals.translateY, width: w.globals.gridWidth, height: w.globals.gridHeight } }; return { elGraph: elGraph, xyRatios: xyRatios, elInner: w.globals.dom.elGraphical, dimensions: dim }; } }, { key: "mount", value: function mount() { var _this2 = this; var graphData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; var me = this; var w = me.w; return new Promise(function (resolve, reject) { // no data to display if (me.el === null) { return reject(new Error('Not enough data to display or target element not found')); } else if (graphData === null || w.globals.allSeriesCollapsed) { me.series.handleNoData(); } me.grid = new Grid(me); var elgrid = me.grid.drawGrid(); me.annotations = new Annotations(me); me.annotations.drawImageAnnos(); me.annotations.drawTextAnnos(); if (w.config.grid.position === 'back' && elgrid) { w.globals.dom.elGraphical.add(elgrid.el); if (elgrid && elgrid.elGridBorders && elgrid.elGridBorders.node) { w.globals.dom.elGraphical.add(elgrid.elGridBorders); } } if (Array.isArray(graphData.elGraph)) { for (var g = 0; g < graphData.elGraph.length; g++) { w.globals.dom.elGraphical.add(graphData.elGraph[g]); } } else { w.globals.dom.elGraphical.add(graphData.elGraph); } if (w.config.grid.position === 'front' && elgrid) { w.globals.dom.elGraphical.add(elgrid.el); if (elgrid && elgrid.elGridBorders && elgrid.elGridBorders.node) { w.globals.dom.elGraphical.add(elgrid.elGridBorders); } } if (w.config.xaxis.crosshairs.position === 'front') { me.crosshairs.drawXCrosshairs(); } if (w.config.yaxis[0].crosshairs.position === 'front') { me.crosshairs.drawYCrosshairs(); } if (w.config.chart.type !== 'treemap') { me.axes.drawAxis(w.config.chart.type, elgrid); } var xAxis = new XAxis(_this2.ctx, elgrid); var yaxis = new YAxis(_this2.ctx, elgrid); if (elgrid !== null) { xAxis.xAxisLabelCorrections(elgrid.xAxisTickWidth); yaxis.setYAxisTextAlignments(); w.config.yaxis.map(function (yaxe, index) { if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1) { yaxis.yAxisTitleRotate(index, yaxe.opposite); } }); } w.globals.dom.Paper.add(w.globals.dom.elAnnotations); me.annotations.drawAxesAnnotations(); if (!w.globals.noData) { // draw tooltips at the end if (w.config.tooltip.enabled && !w.globals.noData) { me.w.globals.tooltip.drawTooltip(graphData.xyRatios); } if (w.globals.axisCharts && (w.globals.isXNumeric || w.config.xaxis.convertedCatToNumeric || w.globals.isRangeBar)) { if (w.config.chart.zoom.enabled || w.config.chart.selection && w.config.chart.selection.enabled || w.config.chart.pan && w.config.chart.pan.enabled) { me.zoomPanSelection.init({ xyRatios: graphData.xyRatios }); } } else { var tools = w.config.chart.toolbar.tools; var toolsArr = ['zoom', 'zoomin', 'zoomout', 'selection', 'pan', 'reset']; toolsArr.forEach(function (t) { tools[t] = false; }); } if (w.config.chart.toolbar.show && !w.globals.allSeriesCollapsed) { me.toolbar.createToolbar(); } } if (w.globals.memory.methodsToExec.length > 0) { w.globals.memory.methodsToExec.forEach(function (fn) { fn.method(fn.params, false, fn.context); }); } if (!w.globals.axisCharts && !w.globals.noData) { me.core.resizeNonAxisCharts(); } resolve(me); }); } /** * Destroy the chart instance by removing all elements which also clean up event listeners on those elements. */ }, { key: "destroy", value: function destroy() { window.removeEventListener('resize', this.windowResizeHandler); removeResizeListener(this.el.parentNode, this.parentResizeHandler); // remove the chart's instance from the global Apex._chartInstances var chartID = this.w.config.chart.id; if (chartID) { Apex._chartInstances.forEach(function (c, i) { if (c.id === Utils$1.escapeString(chartID)) { Apex._chartInstances.splice(i, 1); } }); } new Destroy(this.ctx).clear({ isUpdating: false }); } /** * Allows users to update Options after the chart has rendered. * * @param {object} options - A new config object can be passed which will be merged with the existing config object * @param {boolean} redraw - should redraw from beginning or should use existing paths and redraw from there * @param {boolean} animate - should animate or not on updating Options */ }, { key: "updateOptions", value: function updateOptions(options) { var _this3 = this; var redraw = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; var animate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var updateSyncedCharts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var overwriteInitialConfig = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; var w = this.w; // when called externally, clear some global variables // fixes apexcharts.js#1488 w.globals.selection = undefined; if (options.series) { this.series.resetSeries(false, true, false); if (options.series.length && options.series[0].data) { options.series = options.series.map(function (s, i) { return _this3.updateHelpers._extendSeries(s, i); }); } // user updated the series via updateOptions() function. // Hence, we need to reset axis min/max to avoid zooming issues this.updateHelpers.revertDefaultAxisMinMax(); } // user has set x-axis min/max externally - hence we need to forcefully set the xaxis min/max if (options.xaxis) { options = this.updateHelpers.forceXAxisUpdate(options); } if (options.yaxis) { options = this.updateHelpers.forceYAxisUpdate(options); } if (w.globals.collapsedSeriesIndices.length > 0) { this.series.clearPreviousPaths(); } /* update theme mode#459 */ if (options.theme) { options = this.theme.updateThemeOptions(options); } return this.updateHelpers._updateOptions(options, redraw, animate, updateSyncedCharts, overwriteInitialConfig); } /** * Allows users to update Series after the chart has rendered. * * @param {array} series - New series which will override the existing */ }, { key: "updateSeries", value: function updateSeries() { var newSeries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var overwriteInitialSeries = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; this.series.resetSeries(false); this.updateHelpers.revertDefaultAxisMinMax(); return this.updateHelpers._updateSeries(newSeries, animate, overwriteInitialSeries); } /** * Allows users to append a new series after the chart has rendered. * * @param {array} newSerie - New serie which will be appended to the existing series */ }, { key: "appendSeries", value: function appendSeries(newSerie) { var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var overwriteInitialSeries = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var newSeries = this.w.config.series.slice(); newSeries.push(newSerie); this.series.resetSeries(false); this.updateHelpers.revertDefaultAxisMinMax(); return this.updateHelpers._updateSeries(newSeries, animate, overwriteInitialSeries); } /** * Allows users to append Data to series. * * @param {array} newData - New data in the same format as series */ }, { key: "appendData", value: function appendData(newData) { var overwriteInitialSeries = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var me = this; me.w.globals.dataChanged = true; me.series.getPreviousPaths(); var newSeries = me.w.config.series.slice(); for (var i = 0; i < newSeries.length; i++) { if (newData[i] !== null && typeof newData[i] !== 'undefined') { for (var j = 0; j < newData[i].data.length; j++) { newSeries[i].data.push(newData[i].data[j]); } } } me.w.config.series = newSeries; if (overwriteInitialSeries) { me.w.globals.initialSeries = Utils$1.clone(me.w.config.series); } return this.update(); } }, { key: "update", value: function update(options) { var _this4 = this; return new Promise(function (resolve, reject) { new Destroy(_this4.ctx).clear({ isUpdating: true }); var graphData = _this4.create(_this4.w.config.series, options); if (!graphData) return resolve(_this4); _this4.mount(graphData).then(function () { if (typeof _this4.w.config.chart.events.updated === 'function') { _this4.w.config.chart.events.updated(_this4, _this4.w); } _this4.events.fireEvent('updated', [_this4, _this4.w]); _this4.w.globals.isDirty = true; resolve(_this4); }).catch(function (e) { reject(e); }); }); } /** * Get all charts in the same "group" (including the instance which is called upon) to sync them when user zooms in/out or pan. */ }, { key: "getSyncedCharts", value: function getSyncedCharts() { var chartGroups = this.getGroupedCharts(); var allCharts = [this]; if (chartGroups.length) { allCharts = []; chartGroups.forEach(function (ch) { allCharts.push(ch); }); } return allCharts; } /** * Get charts in the same "group" (excluding the instance which is called upon) to perform operations on the other charts of the same group (eg., tooltip hovering) */ }, { key: "getGroupedCharts", value: function getGroupedCharts() { var _this5 = this; return Apex._chartInstances.filter(function (ch) { if (ch.group) { return true; } }).map(function (ch) { return _this5.w.config.chart.group === ch.group ? ch.chart : _this5; }); } }, { key: "toggleSeries", value: function toggleSeries(seriesName) { return this.series.toggleSeries(seriesName); } }, { key: "highlightSeriesOnLegendHover", value: function highlightSeriesOnLegendHover(e, targetElement) { return this.series.toggleSeriesOnHover(e, targetElement); } }, { key: "showSeries", value: function showSeries(seriesName) { this.series.showSeries(seriesName); } }, { key: "hideSeries", value: function hideSeries(seriesName) { this.series.hideSeries(seriesName); } }, { key: "resetSeries", value: function resetSeries() { var shouldUpdateChart = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var shouldResetZoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; this.series.resetSeries(shouldUpdateChart, shouldResetZoom); } // Public method to add event listener on chart context }, { key: "addEventListener", value: function addEventListener(name, handler) { this.events.addEventListener(name, handler); } // Public method to remove event listener on chart context }, { key: "removeEventListener", value: function removeEventListener(name, handler) { this.events.removeEventListener(name, handler); } }, { key: "addXaxisAnnotation", value: function addXaxisAnnotation(opts) { var pushToMemory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var me = this; if (context) { me = context; } me.annotations.addXaxisAnnotationExternal(opts, pushToMemory, me); } }, { key: "addYaxisAnnotation", value: function addYaxisAnnotation(opts) { var pushToMemory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var me = this; if (context) { me = context; } me.annotations.addYaxisAnnotationExternal(opts, pushToMemory, me); } }, { key: "addPointAnnotation", value: function addPointAnnotation(opts) { var pushToMemory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined; var me = this; if (context) { me = context; } me.annotations.addPointAnnotationExternal(opts, pushToMemory, me); } }, { key: "clearAnnotations", value: function clearAnnotations() { var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : undefined; var me = this; if (context) { me = context; } me.annotations.clearAnnotations(me); } }, { key: "removeAnnotation", value: function removeAnnotation(id) { var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; var me = this; if (context) { me = context; } me.annotations.removeAnnotation(me, id); } }, { key: "getChartArea", value: function getChartArea() { var el = this.w.globals.dom.baseEl.querySelector('.apexcharts-inner'); return el; } }, { key: "getSeriesTotalXRange", value: function getSeriesTotalXRange(minX, maxX) { return this.coreUtils.getSeriesTotalsXRange(minX, maxX); } }, { key: "getHighestValueInSeries", value: function getHighestValueInSeries() { var seriesIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var range = new Range(this.ctx); return range.getMinYMaxY(seriesIndex).highestY; } }, { key: "getLowestValueInSeries", value: function getLowestValueInSeries() { var seriesIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var range = new Range(this.ctx); return range.getMinYMaxY(seriesIndex).lowestY; } }, { key: "getSeriesTotal", value: function getSeriesTotal() { return this.w.globals.seriesTotals; } }, { key: "toggleDataPointSelection", value: function toggleDataPointSelection(seriesIndex, dataPointIndex) { return this.updateHelpers.toggleDataPointSelection(seriesIndex, dataPointIndex); } }, { key: "zoomX", value: function zoomX(min, max) { this.ctx.toolbar.zoomUpdateOptions(min, max); } }, { key: "setLocale", value: function setLocale(localeName) { this.localization.setCurrentLocaleValues(localeName); } }, { key: "dataURI", value: function dataURI(options) { var exp = new Exports(this.ctx); return exp.dataURI(options); } }, { key: "exportToCSV", value: function exportToCSV() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var exp = new Exports(this.ctx); return exp.exportToCSV(options); } }, { key: "paper", value: function paper() { return this.w.globals.dom.Paper; } }, { key: "_parentResizeCallback", value: function _parentResizeCallback() { if (this.w.globals.animationEnded && this.w.config.chart.redrawOnParentResize) { this._windowResize(); } } /** * Handle window resize and re-draw the whole chart. */ }, { key: "_windowResize", value: function _windowResize() { var _this6 = this; clearTimeout(this.w.globals.resizeTimer); this.w.globals.resizeTimer = window.setTimeout(function () { _this6.w.globals.resized = true; _this6.w.globals.dataChanged = false; // we need to redraw the whole chart on window resize (with a small delay). _this6.ctx.update(); }, 150); } }, { key: "_windowResizeHandler", value: function _windowResizeHandler() { var redraw = this.w.config.chart.redrawOnWindowResize; if (typeof redraw === 'function') { redraw = redraw(); } redraw && this._windowResize(); } }], [{ key: "getChartByID", value: function getChartByID(id) { var chartId = Utils$1.escapeString(id); var c = Apex._chartInstances.filter(function (ch) { return ch.id === chartId; })[0]; return c && c.chart; } /** * Allows the user to provide data attrs in the element and the chart will render automatically when this method is called by searching for the elements containing 'data-apexcharts' attribute */ }, { key: "initOnLoad", value: function initOnLoad() { var els = document.querySelectorAll('[data-apexcharts]'); for (var i = 0; i < els.length; i++) { var el = els[i]; var options = JSON.parse(els[i].getAttribute('data-options')); var apexChart = new ApexCharts(el, options); apexChart.render(); } } /** * This static method allows users to call chart methods without necessarily from the * instance of the chart in case user has assigned chartID to the targeted chart. * The chartID is used for mapping the instance stored in Apex._chartInstances global variable * * This is helpful in cases when you don't have reference of the chart instance * easily and need to call the method from anywhere. * For eg, in React/Vue applications when you have many parent/child components, * and need easy reference to other charts for performing dynamic operations * * @param {string} chartID - The unique identifier which will be used to call methods * on that chart instance * @param {function} fn - The method name to call * @param {object} opts - The parameters which are accepted in the original method will be passed here in the same order. */ }, { key: "exec", value: function exec(chartID, fn) { var chart = this.getChartByID(chartID); if (!chart) return; // turn on the global exec flag to indicate this method was called chart.w.globals.isExecCalled = true; var ret = null; if (chart.publicMethods.indexOf(fn) !== -1) { for (var _len = arguments.length, opts = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { opts[_key - 2] = arguments[_key]; } ret = chart[fn].apply(chart, opts); } return ret; } }, { key: "merge", value: function merge(target, source) { return Utils$1.extend(target, source); } }]); return ApexCharts; }(); return ApexCharts$1; }))); ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ar.json ================================================ { "name": "ar", "options": { "months": [ "يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر" ], "shortMonths": [ "يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر" ], "days": [ "الأحد", "الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت" ], "shortDays": [ "أحد", "إثنين", "ثلاثاء", "أربعاء", "خميس", "جمعة", "سبت" ], "toolbar": { "exportToSVG": "تحميل بصيغة SVG", "exportToPNG": "تحميل بصيغة PNG", "exportToCSV": "تحميل بصيغة CSV", "menu": "القائمة", "selection": "تحديد", "selectionZoom": "تكبير التحديد", "zoomIn": "تكبير", "zoomOut": "تصغير", "pan": "تحريك", "reset": "إعادة التعيين" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ca.json ================================================ { "name": "ca", "options": { "months": [ "Gener", "Febrer", "Març", "Abril", "Maig", "Juny", "Juliol", "Agost", "Setembre", "Octubre", "Novembre", "Desembre" ], "shortMonths": [ "Gen.", "Febr.", "Març", "Abr.", "Maig", "Juny", "Jul.", "Ag.", "Set.", "Oct.", "Nov.", "Des." ], "days": [ "Diumenge", "Dilluns", "Dimarts", "Dimecres", "Dijous", "Divendres", "Dissabte" ], "shortDays": ["Dg", "Dl", "Dt", "Dc", "Dj", "Dv", "Ds"], "toolbar": { "exportToSVG": "Descarregar SVG", "exportToPNG": "Descarregar PNG", "exportToCSV": "Descarregar CSV", "menu": "Menú", "selection": "Seleccionar", "selectionZoom": "Seleccionar Zoom", "zoomIn": "Augmentar", "zoomOut": "Disminuir", "pan": "Navegació", "reset": "Reiniciar Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/cs.json ================================================ { "name": "cs", "options": { "months": [ "Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec" ], "shortMonths": [ "Led", "Úno", "Bře", "Dub", "Kvě", "Čvn", "Čvc", "Srp", "Zář", "Říj", "Lis", "Pro" ], "days": [ "Neděle", "Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota" ], "shortDays": ["Ne", "Po", "Út", "St", "Čt", "Pá", "So"], "toolbar": { "exportToSVG": "Stáhnout SVG", "exportToPNG": "Stáhnout PNG", "exportToCSV": "Stáhnout CSV", "menu": "Menu", "selection": "Vybrat", "selectionZoom": "Zoom: Vybrat", "zoomIn": "Zoom: Přiblížit", "zoomOut": "Zoom: Oddálit", "pan": "Přesouvat", "reset": "Resetovat" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/de.json ================================================ { "name": "de", "options": { "months": [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" ], "shortMonths": [ "Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez" ], "days": [ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" ], "shortDays": ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], "toolbar": { "exportToSVG": "SVG speichern", "exportToPNG": "PNG speichern", "exportToCSV": "CSV speichern", "menu": "Menü", "selection": "Auswahl", "selectionZoom": "Auswahl vergrößern", "zoomIn": "Vergrößern", "zoomOut": "Verkleinern", "pan": "Verschieben", "reset": "Zoom zurücksetzen" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/el.json ================================================ { "name": "el", "options": { "months": [ "Ιανουάριος", "Φεβρουάριος", "Μάρτιος", "Απρίλιος", "Μάιος", "Ιούνιος", "Ιούλιος", "Αύγουστος", "Σεπτέμβριος", "Οκτώβριος", "Νοέμβριος", "Δεκέμβριος" ], "shortMonths": [ "Ιαν", "Φευ", "Μαρ", "Απρ", "Μάι", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ" ], "days": [ "Κυριακή", "Δευτέρα", "Τρίτη", "Τετάρτη", "Πέμπτη", "Παρασκευή", "Σάββατο" ], "shortDays": ["Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"], "toolbar": { "exportToSVG": "Λήψη SVG", "exportToPNG": "Λήψη PNG", "exportToCSV": "Λήψη CSV", "menu": "Menu", "selection": "Επιλογή", "selectionZoom": "Μεγένθυση βάση επιλογής", "zoomIn": "Μεγένθυνση", "zoomOut": "Σμίκρυνση", "pan": "Μετατόπιση", "reset": "Επαναφορά μεγένθυνσης" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/en.json ================================================ { "name": "en", "options": { "months": [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], "days": [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], "shortDays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], "toolbar": { "exportToSVG": "Download SVG", "exportToPNG": "Download PNG", "exportToCSV": "Download CSV", "menu": "Menu", "selection": "Selection", "selectionZoom": "Selection Zoom", "zoomIn": "Zoom In", "zoomOut": "Zoom Out", "pan": "Panning", "reset": "Reset Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/es.json ================================================ { "name": "es", "options": { "months": [ "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre" ], "shortMonths": [ "Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic" ], "days": [ "Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado" ], "shortDays": ["Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"], "toolbar": { "exportToSVG": "Descargar SVG", "exportToPNG": "Descargar PNG", "exportToCSV": "Descargar CSV", "menu": "Menu", "selection": "Seleccionar", "selectionZoom": "Seleccionar Zoom", "zoomIn": "Aumentar", "zoomOut": "Disminuir", "pan": "Navegación", "reset": "Reiniciar Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/et.json ================================================ { "name": "et", "options": { "months": [ "jaanuar", "veebruar", "märts", "aprill", "mai", "juuni", "juuli", "august", "september", "oktoober", "november", "detsember" ], "shortMonths": [ "jaan", "veebr", "märts", "apr", "mai", "juuni", "juuli", "aug", "sept", "okt", "nov", "dets" ], "days": [ "pühapäev", "esmaspäev", "teisipäev", "kolmapäev", "neljapäev", "reede", "laupäev" ], "shortDays": [ "P", "E", "T", "K", "N", "R", "L" ], "toolbar": { "exportToSVG": "Lae alla SVG", "exportToPNG": "Lae alla PNG", "exportToCSV": "Lae alla CSV", "menu": "Menüü", "selection": "Valik", "selectionZoom": "Valiku suum", "zoomIn": "Suurenda", "zoomOut": "Vähenda", "pan": "Panoraamimine", "reset": "Lähtesta suum" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/fa.json ================================================ { "name": "fa", "options": { "months": [ "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند" ], "shortMonths": [ "فرو", "ارد", "خرد", "تیر", "مرد", "شهر", "مهر", "آبا", "آذر", "دی", "بهمـ", "اسفـ" ], "days": [ "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" ], "shortDays": ["ی", "د", "س", "چ", "پ", "ج", "ش"], "toolbar": { "exportToSVG": "دانلود SVG", "exportToPNG": "دانلود PNG", "exportToCSV": "دانلود CSV", "menu": "منو", "selection": "انتخاب", "selectionZoom": "بزرگنمایی انتخابی", "zoomIn": "بزرگنمایی", "zoomOut": "کوچکنمایی", "pan": "پیمایش", "reset": "بازنشانی بزرگنمایی" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/fi.json ================================================ { "name": "fi", "options": { "months": [ "Tammikuu", "Helmikuu", "Maaliskuu", "Huhtikuu", "Toukokuu", "Kesäkuu", "Heinäkuu", "Elokuu", "Syyskuu", "Lokakuu", "Marraskuu", "Joulukuu" ], "shortMonths": [ "Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu" ], "days": [ "Sunnuntai", "Maanantai", "Tiistai", "Keskiviikko", "Torstai", "Perjantai", "Lauantai" ], "shortDays": ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"], "toolbar": { "exportToSVG": "Lataa SVG", "exportToPNG": "Lataa PNG", "exportToCSV": "Lataa CSV", "menu": "Valikko", "selection": "Valinta", "selectionZoom": "Valinnan zoomaus", "zoomIn": "Lähennä", "zoomOut": "Loitonna", "pan": "Panoroi", "reset": "Nollaa zoomaus" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/fr.json ================================================ { "name": "fr", "options": { "months": [ "janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre" ], "shortMonths": [ "janv.", "févr.", "mars", "avr.", "mai", "juin", "juill.", "août", "sept.", "oct.", "nov.", "déc." ], "days": [ "dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi" ], "shortDays": ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."], "toolbar": { "exportToSVG": "Télécharger au format SVG", "exportToPNG": "Télécharger au format PNG", "exportToCSV": "Télécharger au format CSV", "menu": "Menu", "selection": "Sélection", "selectionZoom": "Sélection et zoom", "zoomIn": "Zoomer", "zoomOut": "Dézoomer", "pan": "Navigation", "reset": "Réinitialiser le zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/he.json ================================================ { "name": "he", "options": { "months": [ "ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר" ], "shortMonths": [ "ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳" ], "days": [ "ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת" ], "shortDays": ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"], "toolbar": { "exportToSVG": "הורד SVG", "exportToPNG": "הורד PNG", "exportToCSV": "הורד CSV", "menu": "תפריט", "selection": "בחירה", "selectionZoom": "זום בחירה", "zoomIn": "הגדלה", "zoomOut": "הקטנה", "pan": "הזזה", "reset": "איפוס תצוגה" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/hi.json ================================================ { "name": "hi", "options": { "months": [ "जनवरी", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितंबर", "अक्टूबर", "नवंबर", "दिसंबर" ], "shortMonths": [ "जनवरी", "फ़रवरी", "मार्च", "अप्रैल", "मई", "जून", "जुलाई", "अगस्त", "सितंबर", "अक्टूबर", "नवंबर", "दिसंबर" ], "days": [ "रविवार", "सोमवार", "मंगलवार", "बुधवार", "गुरुवार", "शुक्रवार", "शनिवार" ], "shortDays": ["रवि", "सोम", "मंगल", "बुध", "गुरु", "शुक्र", "शनि"], "toolbar": { "exportToSVG": "निर्यात SVG", "exportToPNG": "निर्यात PNG", "exportToCSV": "निर्यात CSV", "menu": "सूची", "selection": "चयन", "selectionZoom": "ज़ूम करना", "zoomIn": "ज़ूम इन", "zoomOut": "ज़ूम आउट", "pan": "पैनिंग", "reset": "फिर से कायम करना" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/hr.json ================================================ { "name": "hr", "options": { "months": [ "Siječanj", "Veljača", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac" ], "shortMonths": [ "Sij", "Velj", "Ožu", "Tra", "Svi", "Lip", "Srp", "Kol", "Ruj", "Lis", "Stu", "Pro" ], "days": [ "Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota" ], "shortDays": ["Ned", "Pon", "Uto", "Sri", "Čet", "Pet", "Sub"], "toolbar": { "exportToSVG": "Preuzmi SVG", "exportToPNG": "Preuzmi PNG", "exportToCSV": "Preuzmi CSV", "menu": "Izbornik", "selection": "Odabir", "selectionZoom": "Odabirno povećanje", "zoomIn": "Uvećajte prikaz", "zoomOut": "Umanjite prikaz", "pan": "Pomicanje", "reset": "Povratak na zadani prikaz" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/hu.json ================================================ { "name": "hu", "options": { "months": [ "január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december" ], "shortMonths": [ "jan", "feb", "mar", "ápr", "máj", "jún", "júl", "aug", "szept", "okt", "nov", "dec" ], "days": [ "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat", "vasárnap" ], "shortDays": [ "H", "K", "Sze", "Cs", "P", "Szo", "V" ], "toolbar": { "exportToSVG": "Exportálás SVG-be", "exportToPNG": "Exportálás PNG-be", "exportToCSV": "Exportálás CSV-be", "menu": "Fő ajánlat", "download": "SVG letöltése", "selection": "Kiválasztás", "selectionZoom": "Nagyító kiválasztása", "zoomIn": "Nagyítás", "zoomOut": "Kicsinyítés", "pan": "Képcsúsztatás", "reset": "Nagyító visszaállítása" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/hy.json ================================================ { "name": "hy", "options": { "months": [ "Հունվար", "Փետրվար", "Մարտ", "Ապրիլ", "Մայիս", "Հունիս", "Հուլիս", "Օգոստոս", "Սեպտեմբեր", "Հոկտեմբեր", "Նոյեմբեր", "Դեկտեմբեր" ], "shortMonths": [ "Հնվ", "Փտվ", "Մրտ", "Ապր", "Մյս", "Հնս", "Հլիս", "Օգս", "Սեպ", "Հոկ", "Նոյ", "Դեկ" ], "days": [ "Կիրակի", "Երկուշաբթի", "Երեքշաբթի", "Չորեքշաբթի", "Հինգշաբթի", "Ուրբաթ", "Շաբաթ" ], "shortDays": ["Կիր", "Երկ", "Երք", "Չրք", "Հնգ", "Ուրբ", "Շբթ"], "toolbar": { "exportToSVG": "Բեռնել SVG", "exportToPNG": "Բեռնել PNG", "exportToCSV": "Բեռնել CSV", "menu": "Մենյու", "selection": "Ընտրված", "selectionZoom": "Ընտրված հատվածի խոշորացում", "zoomIn": "Խոշորացնել", "zoomOut": "Մանրացնել", "pan": "Տեղափոխում", "reset": "Բերել սկզբնական վիճակի" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/id.json ================================================ { "name": "id", "options": { "months": [ "Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Agu", "Sep", "Okt", "Nov", "Des" ], "days": ["Minggu", "Senin", "Selasa", "Rabu", "kamis", "Jumat", "Sabtu"], "shortDays": ["Min", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab"], "toolbar": { "exportToSVG": "Unduh SVG", "exportToPNG": "Unduh PNG", "exportToCSV": "Unduh CSV", "menu": "Menu", "selection": "Pilihan", "selectionZoom": "Perbesar Pilihan", "zoomIn": "Perbesar", "zoomOut": "Perkecil", "pan": "Geser", "reset": "Atur Ulang Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/it.json ================================================ { "name": "it", "options": { "months": [ "Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ], "shortMonths": [ "Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic" ], "days": [ "Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato" ], "shortDays": ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], "toolbar": { "exportToSVG": "Scarica SVG", "exportToPNG": "Scarica PNG", "exportToCSV": "Scarica CSV", "menu": "Menu", "selection": "Selezione", "selectionZoom": "Seleziona Zoom", "zoomIn": "Zoom In", "zoomOut": "Zoom Out", "pan": "Sposta", "reset": "Reimposta Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ja.json ================================================ { "name": "ja", "options": { "months": [ "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月" ], "shortMonths": [ "1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月" ], "days": [ "日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日" ], "shortDays": ["日", "月", "火", "水", "木", "金", "土"], "toolbar": { "exportToSVG": "SVGダウンロード", "exportToPNG": "PNGダウンロード", "exportToCSV": "CSVダウンロード", "menu": "メニュー", "selection": "選択", "selectionZoom": "選択ズーム", "zoomIn": "拡大", "zoomOut": "縮小", "pan": "パン", "reset": "ズームリセット" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ka.json ================================================ { "name": "ka", "options": { "months": [ "იანვარი", "თებერვალი", "მარტი", "აპრილი", "მაისი", "ივნისი", "ივლისი", "აგვისტო", "სექტემბერი", "ოქტომბერი", "ნოემბერი", "დეკემბერი" ], "shortMonths": [ "იან", "თებ", "მარ", "აპრ", "მაი", "ივნ", "ივლ", "აგვ", "სექ", "ოქტ", "ნოე", "დეკ" ], "days": [ "კვირა", "ორშაბათი", "სამშაბათი", "ოთხშაბათი", "ხუთშაბათი", "პარასკევი", "შაბათი" ], "shortDays": ["კვი", "ორშ", "სამ", "ოთხ", "ხუთ", "პარ", "შაბ"], "toolbar": { "exportToSVG": "გადმოქაჩე SVG", "exportToPNG": "გადმოქაჩე PNG", "exportToCSV": "გადმოქაჩე CSV", "menu": "მენიუ", "selection": "არჩევა", "selectionZoom": "არჩეულის გადიდება", "zoomIn": "გადიდება", "zoomOut": "დაპატარაება", "pan": "გადაჩოჩება", "reset": "გადიდების გაუქმება" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ko.json ================================================ { "name": "ko", "options": { "months": [ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" ], "shortMonths": [ "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월" ], "days": [ "일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일" ], "shortDays": ["일", "월", "화", "수", "목", "금", "토"], "toolbar": { "exportToSVG": "SVG 다운로드", "exportToPNG": "PNG 다운로드", "exportToCSV": "CSV 다운로드", "menu": "메뉴", "selection": "선택", "selectionZoom": "선택영역 확대", "zoomIn": "확대", "zoomOut": "축소", "pan": "패닝", "reset": "원래대로" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/lt.json ================================================ { "name": "lt", "options": { "months": [ "Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "Rugpjūtis", "Rugsėjis", "Spalis", "Lapkritis", "Gruodis" ], "shortMonths": [ "Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rgp", "Rgs", "Spl", "Lap", "Grd" ], "days": [ "Sekmadienis", "Pirmadienis", "Antradienis", "Trečiadienis", "Ketvirtadienis", "Penktadienis", "Šeštadienis" ], "shortDays": ["Sk", "Per", "An", "Tr", "Kt", "Pn", "Št"], "toolbar": { "exportToSVG": "Atsisiųsti SVG", "exportToPNG": "Atsisiųsti PNG", "exportToCSV": "Atsisiųsti CSV", "menu": "Menu", "selection": "Pasirinkimas", "selectionZoom": "Zoom: Pasirinkimas", "zoomIn": "Zoom: Priartinti", "zoomOut": "Zoom: Atitolinti", "pan": "Perkėlimas", "reset": "Atstatyti" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/lv.json ================================================ { "name": "lv", "options": { "months": [ "janvāris", "februāris", "marts", "aprīlis", "maijs", "jūnijs", "jūlijs", "augusts", "septembris", "oktobris", "novembris", "decembris" ], "shortMonths": [ "janv", "febr", "marts", "apr", "maijs", "jūn", "jūl", "aug", "sept", "okt", "nov", "dec" ], "days": [ "svētdiena", "pirmdiena", "otrdiena", "trešdiena", "ceturtdiena", "piektdiena", "sestdiena" ], "shortDays": [ "Sv", "P", "O", "T", "C", "P", "S" ], "toolbar": { "exportToSVG": "Lejuplādēt SVG", "exportToPNG": "Lejuplādēt PNG", "exportToCSV": "Lejuplādēt CSV", "menu": "Izvēlne", "selection": "Atlase", "selectionZoom": "Pietuvināt atlasi", "zoomIn": "Pietuvināt", "zoomOut": "Attālināt", "pan": "Pārvietoties diagrammā", "reset": "Atiestatīt pietuvinājumu" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/nb.json ================================================ { "name": "nb", "options": { "months": [ "Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des" ], "days": [ "Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag" ], "shortDays": ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø"], "toolbar": { "exportToSVG": "Last ned SVG", "exportToPNG": "Last ned PNG", "exportToCSV": "Last ned CSV", "menu": "Menu", "selection": "Velg", "selectionZoom": "Zoom: Velg", "zoomIn": "Zoome inn", "zoomOut": "Zoome ut", "pan": "Skyving", "reset": "Start på nytt" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/nl.json ================================================ { "name": "nl", "options": { "months": [ "Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December" ], "shortMonths": [ "Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" ], "days": [ "Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag" ], "shortDays": ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"], "toolbar": { "exportToSVG": "Download SVG", "exportToPNG": "Download PNG", "exportToCSV": "Download CSV", "menu": "Menu", "selection": "Selectie", "selectionZoom": "Zoom selectie", "zoomIn": "Zoom in", "zoomOut": "Zoom out", "pan": "Verplaatsen", "reset": "Standaardwaarden" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/pl.json ================================================ { "name": "pl", "options": { "months": [ "Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień" ], "shortMonths": [ "Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru" ], "days": [ "Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota" ], "shortDays": ["Nd", "Pn", "Wt", "Śr", "Cz", "Pt", "Sb"], "toolbar": { "exportToSVG": "Pobierz SVG", "exportToPNG": "Pobierz PNG", "exportToCSV": "Pobierz CSV", "menu": "Menu", "selection": "Wybieranie", "selectionZoom": "Zoom: Wybieranie", "zoomIn": "Zoom: Przybliż", "zoomOut": "Zoom: Oddal", "pan": "Przesuwanie", "reset": "Resetuj" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/pt-br.json ================================================ { "name": "pt-br", "options": { "months": [ "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" ], "shortMonths": [ "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez" ], "days": [ "Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado" ], "shortDays": ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sab"], "toolbar": { "exportToSVG": "Baixar SVG", "exportToPNG": "Baixar PNG", "exportToCSV": "Baixar CSV", "menu": "Menu", "selection": "Selecionar", "selectionZoom": "Selecionar Zoom", "zoomIn": "Aumentar", "zoomOut": "Diminuir", "pan": "Navegação", "reset": "Reiniciar Zoom" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/pt.json ================================================ { "name": "pt", "options": { "months": [ "Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro" ], "shortMonths": [ "Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ag", "Set", "Out", "Nov", "Dez" ], "days": [ "Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado" ], "shortDays": ["Do", "Se", "Te", "Qa", "Qi", "Sx", "Sa"], "toolbar": { "exportToSVG": "Baixar SVG", "exportToPNG": "Baixar PNG", "exportToCSV": "Baixar CSV", "menu": "Menu", "selection": "Selecionar", "selectionZoom": "Zoom: Selecionar", "zoomIn": "Zoom: Aumentar", "zoomOut": "Zoom: Diminuir", "pan": "Deslocamento", "reset": "Redefinir" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/rs.json ================================================ { "name": "rs", "options": { "months": [ "Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec" ], "days": [ "Nedelja", "Ponedeljak", "Utorak", "Sreda", "Četvrtak", "Petak", "Subota" ], "shortDays": ["Ned", "Pon", "Uto", "Sre", "Čet", "Pet", "Sub"], "toolbar": { "exportToSVG": "Preuzmi SVG", "exportToPNG": "Preuzmi PNG", "exportToCSV": "Preuzmi CSV", "menu": "Meni", "selection": "Odabir", "selectionZoom": "Odabirno povećanje", "zoomIn": "Uvećajte prikaz", "zoomOut": "Umanjite prikaz", "pan": "Pomeranje", "reset": "Resetuj prikaz" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ru.json ================================================ { "name": "ru", "options": { "months": [ "Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь" ], "shortMonths": [ "Янв", "Фев", "Мар", "Апр", "Май", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек" ], "days": [ "Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота" ], "shortDays": ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"], "toolbar": { "exportToSVG": "Сохранить SVG", "exportToPNG": "Сохранить PNG", "exportToCSV": "Сохранить CSV", "menu": "Меню", "selection": "Выбор", "selectionZoom": "Выбор с увеличением", "zoomIn": "Увеличить", "zoomOut": "Уменьшить", "pan": "Перемещение", "reset": "Сбросить увеличение" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/se.json ================================================ { "name": "se", "options": { "months": [ "Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Maj", "Juni", "Juli", "Aug", "Sep", "Okt", "Nov", "Dec" ], "days": [ "Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag" ], "shortDays": ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"], "toolbar": { "exportToSVG": "Ladda SVG", "exportToPNG": "Ladda PNG", "exportToCSV": "Ladda CSV", "menu": "Meny", "selection": "Selektion", "selectionZoom": "Val av zoom", "zoomIn": "Zooma in", "zoomOut": "Zooma ut", "pan": "Panorering", "reset": "Återställ zoomning" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/sk.json ================================================ { "name": "sk", "options": { "months": [ "Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec" ], "days": [ "Nedeľa", "Pondelok", "Utorok", "Streda", "Štvrtok", "Piatok", "Sobota" ], "shortDays": ["Ne", "Po", "Ut", "St", "Št", "Pi", "So"], "toolbar": { "exportToSVG": "Stiahnuť SVG", "exportToPNG": "Stiahnuť PNG", "exportToCSV": "Stiahnuť CSV", "menu": "Menu", "selection": "Vyberanie", "selectionZoom": "Zoom: Vyberanie", "zoomIn": "Zoom: Priblížiť", "zoomOut": "Zoom: Vzdialiť", "pan": "Presúvanie", "reset": "Resetovať" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/sl.json ================================================ { "name": "sl", "options": { "months": [ "Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "Septemer", "Oktober", "November", "December" ], "shortMonths": [ "Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec" ], "days": [ "Nedelja", "Ponedeljek", "Torek", "Sreda", "Četrtek", "Petek", "Sobota" ], "shortDays": ["Ne", "Po", "To", "Sr", "Če", "Pe", "So"], "toolbar": { "exportToSVG": "Prenesi SVG", "exportToPNG": "Prenesi PNG", "exportToCSV": "Prenesi CSV", "menu": "Menu", "selection": "Izbiranje", "selectionZoom": "Zoom: Izbira", "zoomIn": "Zoom: Približaj", "zoomOut": "Zoom: Oddalji", "pan": "Pomikanje", "reset": "Resetiraj" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/sq.json ================================================ { "name": "sq", "options": { "months": [ "Janar", "Shkurt", "Mars", "Prill", "Maj", "Qershor", "Korrik", "Gusht", "Shtator", "Tetor", "Nëntor", "Dhjetor" ], "shortMonths": [ "Jan", "Shk", "Mar", "Pr", "Maj", "Qer", "Korr", "Gush", "Sht", "Tet", "Nën", "Dhj" ], "days": [ "e Dielë", "e Hënë", "e Martë", "e Mërkurë", "e Enjte", "e Premte", "e Shtunë" ], "shortDays": ["Die", "Hën", "Mar", "Mër", "Enj", "Pre", "Sht"], "toolbar": { "exportToSVG": "Shkarko SVG", "exportToPNG": "Shkarko PNG", "exportToCSV": "Shkarko CSV", "menu": "Menu", "selection": "Seleksiono", "selectionZoom": "Seleksiono Zmadhim", "zoomIn": "Zmadho", "zoomOut": "Zvogëlo", "pan": "Spostoje", "reset": "Rikthe dimensionin" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/th.json ================================================ { "name": "th", "options": { "months": [ "มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม" ], "shortMonths": [ "ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค." ], "days": [ "อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัสบดี", "ศุกร์", "เสาร์" ], "shortDays": ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส"], "toolbar": { "exportToSVG": "ดาวน์โหลด SVG", "exportToPNG": "ดาวน์โหลด PNG", "exportToCSV": "ดาวน์โหลด CSV", "menu": "เมนู", "selection": "เลือก", "selectionZoom": "เลือกจุดที่จะซูม", "zoomIn": "ซูมเข้า", "zoomOut": "ซูมออก", "pan": "ปรากฎว่า", "reset": "รีเซ็ตการซูม" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/tr.json ================================================ { "name": "tr", "options": { "months": [ "Ocak", "Şubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "Ağustos", "Eylül", "Ekim", "Kasım", "Aralık" ], "shortMonths": [ "Oca", "Şub", "Mar", "Nis", "May", "Haz", "Tem", "Ağu", "Eyl", "Eki", "Kas", "Ara" ], "days": [ "Pazar", "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma", "Cumartesi" ], "shortDays": ["Paz", "Pzt", "Sal", "Çar", "Per", "Cum", "Cmt"], "toolbar": { "exportToSVG": "SVG İndir", "exportToPNG": "PNG İndir", "exportToCSV": "CSV İndir", "menu": "Menü", "selection": "Seçim", "selectionZoom": "Seçim Yakınlaştır", "zoomIn": "Yakınlaştır", "zoomOut": "Uzaklaştır", "pan": "Kaydır", "reset": "Yakınlaştırmayı Sıfırla" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/ua.json ================================================ { "name": "ua", "options": { "months": [ "Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "Вересень", "Жовтень", "Листопад", "Грудень" ], "shortMonths": [ "Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "Лис", "Гру" ], "days": [ "Неділя", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ятниця", "Субота" ], "shortDays": ["Нд", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"], "toolbar": { "exportToSVG": "Зберегти SVG", "exportToPNG": "Зберегти PNG", "exportToCSV": "Зберегти CSV", "menu": "Меню", "selection": "Вибір", "selectionZoom": "Вибір із збільшенням", "zoomIn": "Збільшити", "zoomOut": "Зменшити", "pan": "Переміщення", "reset": "Скинути збільшення" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/zh-cn.json ================================================ { "name": "zh-cn", "options": { "months": [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], "shortMonths": [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], "days": [ "星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" ], "shortDays": ["周日", "周一", "周二", "周三", "周四", "周五", "周六"], "toolbar": { "exportToSVG": "下载 SVG", "exportToPNG": "下载 PNG", "exportToCSV": "下载 CSV", "menu": "菜单", "selection": "选择", "selectionZoom": "选择缩放", "zoomIn": "放大", "zoomOut": "缩小", "pan": "平移", "reset": "重置缩放" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/apexcharts/locales/zh-tw.json ================================================ { "name": "zh-tw", "options": { "months": [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], "shortMonths": [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月" ], "days": [ "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" ], "shortDays": ["週日", "週一", "週二", "週三", "週四", "週五", "週六"], "toolbar": { "exportToSVG": "下載 SVG", "exportToPNG": "下載 PNG", "exportToCSV": "下載 CSV", "menu": "菜單", "selection": "選擇", "selectionZoom": "選擇縮放", "zoomIn": "放大", "zoomOut": "縮小", "pan": "平移", "reset": "重置縮放" } } } ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-grid.css ================================================ /*! * Bootstrap Grid v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } .container, .container-fluid, .container-xxl, .container-xl, .container-lg, .container-md, .container-sm { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; width: 100%; padding-right: calc(var(--bs-gutter-x) * 0.5); padding-left: calc(var(--bs-gutter-x) * 0.5); margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container-sm, .container { max-width: 540px; } } @media (min-width: 768px) { .container-md, .container-sm, .container { max-width: 720px; } } @media (min-width: 992px) { .container-lg, .container-md, .container-sm, .container { max-width: 960px; } } @media (min-width: 1200px) { .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1140px; } } @media (min-width: 1400px) { .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1320px; } } .row { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; display: flex; flex-wrap: wrap; margin-top: calc(-1 * var(--bs-gutter-y)); margin-right: calc(-0.5 * var(--bs-gutter-x)); margin-left: calc(-0.5 * var(--bs-gutter-x)); } .row > * { box-sizing: border-box; flex-shrink: 0; width: 100%; max-width: 100%; padding-right: calc(var(--bs-gutter-x) * 0.5); padding-left: calc(var(--bs-gutter-x) * 0.5); margin-top: var(--bs-gutter-y); } .col { flex: 1 0 0%; } .row-cols-auto > * { flex: 0 0 auto; width: auto; } .row-cols-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-auto { flex: 0 0 auto; width: auto; } .col-1 { flex: 0 0 auto; width: 8.33333333%; } .col-2 { flex: 0 0 auto; width: 16.66666667%; } .col-3 { flex: 0 0 auto; width: 25%; } .col-4 { flex: 0 0 auto; width: 33.33333333%; } .col-5 { flex: 0 0 auto; width: 41.66666667%; } .col-6 { flex: 0 0 auto; width: 50%; } .col-7 { flex: 0 0 auto; width: 58.33333333%; } .col-8 { flex: 0 0 auto; width: 66.66666667%; } .col-9 { flex: 0 0 auto; width: 75%; } .col-10 { flex: 0 0 auto; width: 83.33333333%; } .col-11 { flex: 0 0 auto; width: 91.66666667%; } .col-12 { flex: 0 0 auto; width: 100%; } .offset-1 { margin-left: 8.33333333%; } .offset-2 { margin-left: 16.66666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.33333333%; } .offset-5 { margin-left: 41.66666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.33333333%; } .offset-8 { margin-left: 66.66666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.33333333%; } .offset-11 { margin-left: 91.66666667%; } .g-0, .gx-0 { --bs-gutter-x: 0; } .g-0, .gy-0 { --bs-gutter-y: 0; } .g-1, .gx-1 { --bs-gutter-x: 0.25rem; } .g-1, .gy-1 { --bs-gutter-y: 0.25rem; } .g-2, .gx-2 { --bs-gutter-x: 0.5rem; } .g-2, .gy-2 { --bs-gutter-y: 0.5rem; } .g-3, .gx-3 { --bs-gutter-x: 1rem; } .g-3, .gy-3 { --bs-gutter-y: 1rem; } .g-4, .gx-4 { --bs-gutter-x: 1.5rem; } .g-4, .gy-4 { --bs-gutter-y: 1.5rem; } .g-5, .gx-5 { --bs-gutter-x: 3rem; } .g-5, .gy-5 { --bs-gutter-y: 3rem; } @media (min-width: 576px) { .col-sm { flex: 1 0 0%; } .row-cols-sm-auto > * { flex: 0 0 auto; width: auto; } .row-cols-sm-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-sm-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-sm-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-sm-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-sm-auto { flex: 0 0 auto; width: auto; } .col-sm-1 { flex: 0 0 auto; width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; width: 25%; } .col-sm-4 { flex: 0 0 auto; width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; width: 50%; } .col-sm-7 { flex: 0 0 auto; width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; width: 75%; } .col-sm-10 { flex: 0 0 auto; width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; width: 100%; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.33333333%; } .offset-sm-2 { margin-left: 16.66666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.33333333%; } .offset-sm-5 { margin-left: 41.66666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.33333333%; } .offset-sm-8 { margin-left: 66.66666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.33333333%; } .offset-sm-11 { margin-left: 91.66666667%; } .g-sm-0, .gx-sm-0 { --bs-gutter-x: 0; } .g-sm-0, .gy-sm-0 { --bs-gutter-y: 0; } .g-sm-1, .gx-sm-1 { --bs-gutter-x: 0.25rem; } .g-sm-1, .gy-sm-1 { --bs-gutter-y: 0.25rem; } .g-sm-2, .gx-sm-2 { --bs-gutter-x: 0.5rem; } .g-sm-2, .gy-sm-2 { --bs-gutter-y: 0.5rem; } .g-sm-3, .gx-sm-3 { --bs-gutter-x: 1rem; } .g-sm-3, .gy-sm-3 { --bs-gutter-y: 1rem; } .g-sm-4, .gx-sm-4 { --bs-gutter-x: 1.5rem; } .g-sm-4, .gy-sm-4 { --bs-gutter-y: 1.5rem; } .g-sm-5, .gx-sm-5 { --bs-gutter-x: 3rem; } .g-sm-5, .gy-sm-5 { --bs-gutter-y: 3rem; } } @media (min-width: 768px) { .col-md { flex: 1 0 0%; } .row-cols-md-auto > * { flex: 0 0 auto; width: auto; } .row-cols-md-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-md-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-md-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-md-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-md-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-md-auto { flex: 0 0 auto; width: auto; } .col-md-1 { flex: 0 0 auto; width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; width: 25%; } .col-md-4 { flex: 0 0 auto; width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; width: 50%; } .col-md-7 { flex: 0 0 auto; width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; width: 75%; } .col-md-10 { flex: 0 0 auto; width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; width: 100%; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.33333333%; } .offset-md-2 { margin-left: 16.66666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.33333333%; } .offset-md-5 { margin-left: 41.66666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.33333333%; } .offset-md-8 { margin-left: 66.66666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.33333333%; } .offset-md-11 { margin-left: 91.66666667%; } .g-md-0, .gx-md-0 { --bs-gutter-x: 0; } .g-md-0, .gy-md-0 { --bs-gutter-y: 0; } .g-md-1, .gx-md-1 { --bs-gutter-x: 0.25rem; } .g-md-1, .gy-md-1 { --bs-gutter-y: 0.25rem; } .g-md-2, .gx-md-2 { --bs-gutter-x: 0.5rem; } .g-md-2, .gy-md-2 { --bs-gutter-y: 0.5rem; } .g-md-3, .gx-md-3 { --bs-gutter-x: 1rem; } .g-md-3, .gy-md-3 { --bs-gutter-y: 1rem; } .g-md-4, .gx-md-4 { --bs-gutter-x: 1.5rem; } .g-md-4, .gy-md-4 { --bs-gutter-y: 1.5rem; } .g-md-5, .gx-md-5 { --bs-gutter-x: 3rem; } .g-md-5, .gy-md-5 { --bs-gutter-y: 3rem; } } @media (min-width: 992px) { .col-lg { flex: 1 0 0%; } .row-cols-lg-auto > * { flex: 0 0 auto; width: auto; } .row-cols-lg-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-lg-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-lg-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-lg-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-lg-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-lg-auto { flex: 0 0 auto; width: auto; } .col-lg-1 { flex: 0 0 auto; width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; width: 25%; } .col-lg-4 { flex: 0 0 auto; width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; width: 50%; } .col-lg-7 { flex: 0 0 auto; width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; width: 75%; } .col-lg-10 { flex: 0 0 auto; width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; width: 100%; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.33333333%; } .offset-lg-2 { margin-left: 16.66666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.33333333%; } .offset-lg-5 { margin-left: 41.66666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.33333333%; } .offset-lg-8 { margin-left: 66.66666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.33333333%; } .offset-lg-11 { margin-left: 91.66666667%; } .g-lg-0, .gx-lg-0 { --bs-gutter-x: 0; } .g-lg-0, .gy-lg-0 { --bs-gutter-y: 0; } .g-lg-1, .gx-lg-1 { --bs-gutter-x: 0.25rem; } .g-lg-1, .gy-lg-1 { --bs-gutter-y: 0.25rem; } .g-lg-2, .gx-lg-2 { --bs-gutter-x: 0.5rem; } .g-lg-2, .gy-lg-2 { --bs-gutter-y: 0.5rem; } .g-lg-3, .gx-lg-3 { --bs-gutter-x: 1rem; } .g-lg-3, .gy-lg-3 { --bs-gutter-y: 1rem; } .g-lg-4, .gx-lg-4 { --bs-gutter-x: 1.5rem; } .g-lg-4, .gy-lg-4 { --bs-gutter-y: 1.5rem; } .g-lg-5, .gx-lg-5 { --bs-gutter-x: 3rem; } .g-lg-5, .gy-lg-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; } .row-cols-xl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xl-auto { flex: 0 0 auto; width: auto; } .col-xl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; width: 25%; } .col-xl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; width: 50%; } .col-xl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; width: 75%; } .col-xl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; width: 100%; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.33333333%; } .offset-xl-2 { margin-left: 16.66666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.33333333%; } .offset-xl-5 { margin-left: 41.66666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.33333333%; } .offset-xl-8 { margin-left: 66.66666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.33333333%; } .offset-xl-11 { margin-left: 91.66666667%; } .g-xl-0, .gx-xl-0 { --bs-gutter-x: 0; } .g-xl-0, .gy-xl-0 { --bs-gutter-y: 0; } .g-xl-1, .gx-xl-1 { --bs-gutter-x: 0.25rem; } .g-xl-1, .gy-xl-1 { --bs-gutter-y: 0.25rem; } .g-xl-2, .gx-xl-2 { --bs-gutter-x: 0.5rem; } .g-xl-2, .gy-xl-2 { --bs-gutter-y: 0.5rem; } .g-xl-3, .gx-xl-3 { --bs-gutter-x: 1rem; } .g-xl-3, .gy-xl-3 { --bs-gutter-y: 1rem; } .g-xl-4, .gx-xl-4 { --bs-gutter-x: 1.5rem; } .g-xl-4, .gy-xl-4 { --bs-gutter-y: 1.5rem; } .g-xl-5, .gx-xl-5 { --bs-gutter-x: 3rem; } .g-xl-5, .gy-xl-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; } .row-cols-xxl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xxl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xxl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xxl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xxl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xxl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xxl-auto { flex: 0 0 auto; width: auto; } .col-xxl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; width: 25%; } .col-xxl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; width: 50%; } .col-xxl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; width: 75%; } .col-xxl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; width: 100%; } .offset-xxl-0 { margin-left: 0; } .offset-xxl-1 { margin-left: 8.33333333%; } .offset-xxl-2 { margin-left: 16.66666667%; } .offset-xxl-3 { margin-left: 25%; } .offset-xxl-4 { margin-left: 33.33333333%; } .offset-xxl-5 { margin-left: 41.66666667%; } .offset-xxl-6 { margin-left: 50%; } .offset-xxl-7 { margin-left: 58.33333333%; } .offset-xxl-8 { margin-left: 66.66666667%; } .offset-xxl-9 { margin-left: 75%; } .offset-xxl-10 { margin-left: 83.33333333%; } .offset-xxl-11 { margin-left: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { --bs-gutter-x: 0; } .g-xxl-0, .gy-xxl-0 { --bs-gutter-y: 0; } .g-xxl-1, .gx-xxl-1 { --bs-gutter-x: 0.25rem; } .g-xxl-1, .gy-xxl-1 { --bs-gutter-y: 0.25rem; } .g-xxl-2, .gx-xxl-2 { --bs-gutter-x: 0.5rem; } .g-xxl-2, .gy-xxl-2 { --bs-gutter-y: 0.5rem; } .g-xxl-3, .gx-xxl-3 { --bs-gutter-x: 1rem; } .g-xxl-3, .gy-xxl-3 { --bs-gutter-y: 1rem; } .g-xxl-4, .gx-xxl-4 { --bs-gutter-x: 1.5rem; } .g-xxl-4, .gy-xxl-4 { --bs-gutter-y: 1.5rem; } .g-xxl-5, .gx-xxl-5 { --bs-gutter-x: 3rem; } .g-xxl-5, .gy-xxl-5 { --bs-gutter-y: 3rem; } } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-auto { margin-right: auto !important; margin-left: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-right: 0 !important; } .me-1 { margin-right: 0.25rem !important; } .me-2 { margin-right: 0.5rem !important; } .me-3 { margin-right: 1rem !important; } .me-4 { margin-right: 1.5rem !important; } .me-5 { margin-right: 3rem !important; } .me-auto { margin-right: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-left: 0 !important; } .ms-1 { margin-left: 0.25rem !important; } .ms-2 { margin-left: 0.5rem !important; } .ms-3 { margin-left: 1rem !important; } .ms-4 { margin-left: 1.5rem !important; } .ms-5 { margin-left: 3rem !important; } .ms-auto { margin-left: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-right: 0 !important; } .pe-1 { padding-right: 0.25rem !important; } .pe-2 { padding-right: 0.5rem !important; } .pe-3 { padding-right: 1rem !important; } .pe-4 { padding-right: 1.5rem !important; } .pe-5 { padding-right: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-left: 0 !important; } .ps-1 { padding-left: 0.25rem !important; } .ps-2 { padding-left: 0.5rem !important; } .ps-3 { padding-left: 1rem !important; } .ps-4 { padding-left: 1.5rem !important; } .ps-5 { padding-left: 3rem !important; } @media (min-width: 576px) { .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-sm-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-sm-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-sm-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-sm-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-sm-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-sm-auto { margin-right: auto !important; margin-left: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-right: 0 !important; } .me-sm-1 { margin-right: 0.25rem !important; } .me-sm-2 { margin-right: 0.5rem !important; } .me-sm-3 { margin-right: 1rem !important; } .me-sm-4 { margin-right: 1.5rem !important; } .me-sm-5 { margin-right: 3rem !important; } .me-sm-auto { margin-right: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-left: 0 !important; } .ms-sm-1 { margin-left: 0.25rem !important; } .ms-sm-2 { margin-left: 0.5rem !important; } .ms-sm-3 { margin-left: 1rem !important; } .ms-sm-4 { margin-left: 1.5rem !important; } .ms-sm-5 { margin-left: 3rem !important; } .ms-sm-auto { margin-left: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-sm-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-sm-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-sm-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-sm-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-sm-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-right: 0 !important; } .pe-sm-1 { padding-right: 0.25rem !important; } .pe-sm-2 { padding-right: 0.5rem !important; } .pe-sm-3 { padding-right: 1rem !important; } .pe-sm-4 { padding-right: 1.5rem !important; } .pe-sm-5 { padding-right: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-left: 0 !important; } .ps-sm-1 { padding-left: 0.25rem !important; } .ps-sm-2 { padding-left: 0.5rem !important; } .ps-sm-3 { padding-left: 1rem !important; } .ps-sm-4 { padding-left: 1.5rem !important; } .ps-sm-5 { padding-left: 3rem !important; } } @media (min-width: 768px) { .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-md-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-md-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-md-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-md-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-md-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-md-auto { margin-right: auto !important; margin-left: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-right: 0 !important; } .me-md-1 { margin-right: 0.25rem !important; } .me-md-2 { margin-right: 0.5rem !important; } .me-md-3 { margin-right: 1rem !important; } .me-md-4 { margin-right: 1.5rem !important; } .me-md-5 { margin-right: 3rem !important; } .me-md-auto { margin-right: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-left: 0 !important; } .ms-md-1 { margin-left: 0.25rem !important; } .ms-md-2 { margin-left: 0.5rem !important; } .ms-md-3 { margin-left: 1rem !important; } .ms-md-4 { margin-left: 1.5rem !important; } .ms-md-5 { margin-left: 3rem !important; } .ms-md-auto { margin-left: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-md-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-md-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-md-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-md-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-md-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-right: 0 !important; } .pe-md-1 { padding-right: 0.25rem !important; } .pe-md-2 { padding-right: 0.5rem !important; } .pe-md-3 { padding-right: 1rem !important; } .pe-md-4 { padding-right: 1.5rem !important; } .pe-md-5 { padding-right: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-left: 0 !important; } .ps-md-1 { padding-left: 0.25rem !important; } .ps-md-2 { padding-left: 0.5rem !important; } .ps-md-3 { padding-left: 1rem !important; } .ps-md-4 { padding-left: 1.5rem !important; } .ps-md-5 { padding-left: 3rem !important; } } @media (min-width: 992px) { .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-lg-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-lg-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-lg-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-lg-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-lg-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-lg-auto { margin-right: auto !important; margin-left: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-right: 0 !important; } .me-lg-1 { margin-right: 0.25rem !important; } .me-lg-2 { margin-right: 0.5rem !important; } .me-lg-3 { margin-right: 1rem !important; } .me-lg-4 { margin-right: 1.5rem !important; } .me-lg-5 { margin-right: 3rem !important; } .me-lg-auto { margin-right: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-left: 0 !important; } .ms-lg-1 { margin-left: 0.25rem !important; } .ms-lg-2 { margin-left: 0.5rem !important; } .ms-lg-3 { margin-left: 1rem !important; } .ms-lg-4 { margin-left: 1.5rem !important; } .ms-lg-5 { margin-left: 3rem !important; } .ms-lg-auto { margin-left: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-lg-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-lg-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-lg-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-lg-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-lg-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-right: 0 !important; } .pe-lg-1 { padding-right: 0.25rem !important; } .pe-lg-2 { padding-right: 0.5rem !important; } .pe-lg-3 { padding-right: 1rem !important; } .pe-lg-4 { padding-right: 1.5rem !important; } .pe-lg-5 { padding-right: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-left: 0 !important; } .ps-lg-1 { padding-left: 0.25rem !important; } .ps-lg-2 { padding-left: 0.5rem !important; } .ps-lg-3 { padding-left: 1rem !important; } .ps-lg-4 { padding-left: 1.5rem !important; } .ps-lg-5 { padding-left: 3rem !important; } } @media (min-width: 1200px) { .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-right: 0 !important; } .me-xl-1 { margin-right: 0.25rem !important; } .me-xl-2 { margin-right: 0.5rem !important; } .me-xl-3 { margin-right: 1rem !important; } .me-xl-4 { margin-right: 1.5rem !important; } .me-xl-5 { margin-right: 3rem !important; } .me-xl-auto { margin-right: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-left: 0 !important; } .ms-xl-1 { margin-left: 0.25rem !important; } .ms-xl-2 { margin-left: 0.5rem !important; } .ms-xl-3 { margin-left: 1rem !important; } .ms-xl-4 { margin-left: 1.5rem !important; } .ms-xl-5 { margin-left: 3rem !important; } .ms-xl-auto { margin-left: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-right: 0 !important; } .pe-xl-1 { padding-right: 0.25rem !important; } .pe-xl-2 { padding-right: 0.5rem !important; } .pe-xl-3 { padding-right: 1rem !important; } .pe-xl-4 { padding-right: 1.5rem !important; } .pe-xl-5 { padding-right: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-left: 0 !important; } .ps-xl-1 { padding-left: 0.25rem !important; } .ps-xl-2 { padding-left: 0.5rem !important; } .ps-xl-3 { padding-left: 1rem !important; } .ps-xl-4 { padding-left: 1.5rem !important; } .ps-xl-5 { padding-left: 3rem !important; } } @media (min-width: 1400px) { .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xxl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xxl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xxl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xxl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xxl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xxl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-right: 0 !important; } .me-xxl-1 { margin-right: 0.25rem !important; } .me-xxl-2 { margin-right: 0.5rem !important; } .me-xxl-3 { margin-right: 1rem !important; } .me-xxl-4 { margin-right: 1.5rem !important; } .me-xxl-5 { margin-right: 3rem !important; } .me-xxl-auto { margin-right: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-left: 0 !important; } .ms-xxl-1 { margin-left: 0.25rem !important; } .ms-xxl-2 { margin-left: 0.5rem !important; } .ms-xxl-3 { margin-left: 1rem !important; } .ms-xxl-4 { margin-left: 1.5rem !important; } .ms-xxl-5 { margin-left: 3rem !important; } .ms-xxl-auto { margin-left: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xxl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xxl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xxl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xxl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xxl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-right: 0 !important; } .pe-xxl-1 { padding-right: 0.25rem !important; } .pe-xxl-2 { padding-right: 0.5rem !important; } .pe-xxl-3 { padding-right: 1rem !important; } .pe-xxl-4 { padding-right: 1.5rem !important; } .pe-xxl-5 { padding-right: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-left: 0 !important; } .ps-xxl-1 { padding-left: 0.25rem !important; } .ps-xxl-2 { padding-left: 0.5rem !important; } .ps-xxl-3 { padding-left: 1rem !important; } .ps-xxl-4 { padding-left: 1.5rem !important; } .ps-xxl-5 { padding-left: 3rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap-grid.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-grid.rtl.css ================================================ /*! * Bootstrap Grid v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } .container, .container-fluid, .container-xxl, .container-xl, .container-lg, .container-md, .container-sm { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; width: 100%; padding-left: calc(var(--bs-gutter-x) * 0.5); padding-right: calc(var(--bs-gutter-x) * 0.5); margin-left: auto; margin-right: auto; } @media (min-width: 576px) { .container-sm, .container { max-width: 540px; } } @media (min-width: 768px) { .container-md, .container-sm, .container { max-width: 720px; } } @media (min-width: 992px) { .container-lg, .container-md, .container-sm, .container { max-width: 960px; } } @media (min-width: 1200px) { .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1140px; } } @media (min-width: 1400px) { .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1320px; } } .row { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; display: flex; flex-wrap: wrap; margin-top: calc(-1 * var(--bs-gutter-y)); margin-left: calc(-0.5 * var(--bs-gutter-x)); margin-right: calc(-0.5 * var(--bs-gutter-x)); } .row > * { box-sizing: border-box; flex-shrink: 0; width: 100%; max-width: 100%; padding-left: calc(var(--bs-gutter-x) * 0.5); padding-right: calc(var(--bs-gutter-x) * 0.5); margin-top: var(--bs-gutter-y); } .col { flex: 1 0 0%; } .row-cols-auto > * { flex: 0 0 auto; width: auto; } .row-cols-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-auto { flex: 0 0 auto; width: auto; } .col-1 { flex: 0 0 auto; width: 8.33333333%; } .col-2 { flex: 0 0 auto; width: 16.66666667%; } .col-3 { flex: 0 0 auto; width: 25%; } .col-4 { flex: 0 0 auto; width: 33.33333333%; } .col-5 { flex: 0 0 auto; width: 41.66666667%; } .col-6 { flex: 0 0 auto; width: 50%; } .col-7 { flex: 0 0 auto; width: 58.33333333%; } .col-8 { flex: 0 0 auto; width: 66.66666667%; } .col-9 { flex: 0 0 auto; width: 75%; } .col-10 { flex: 0 0 auto; width: 83.33333333%; } .col-11 { flex: 0 0 auto; width: 91.66666667%; } .col-12 { flex: 0 0 auto; width: 100%; } .offset-1 { margin-right: 8.33333333%; } .offset-2 { margin-right: 16.66666667%; } .offset-3 { margin-right: 25%; } .offset-4 { margin-right: 33.33333333%; } .offset-5 { margin-right: 41.66666667%; } .offset-6 { margin-right: 50%; } .offset-7 { margin-right: 58.33333333%; } .offset-8 { margin-right: 66.66666667%; } .offset-9 { margin-right: 75%; } .offset-10 { margin-right: 83.33333333%; } .offset-11 { margin-right: 91.66666667%; } .g-0, .gx-0 { --bs-gutter-x: 0; } .g-0, .gy-0 { --bs-gutter-y: 0; } .g-1, .gx-1 { --bs-gutter-x: 0.25rem; } .g-1, .gy-1 { --bs-gutter-y: 0.25rem; } .g-2, .gx-2 { --bs-gutter-x: 0.5rem; } .g-2, .gy-2 { --bs-gutter-y: 0.5rem; } .g-3, .gx-3 { --bs-gutter-x: 1rem; } .g-3, .gy-3 { --bs-gutter-y: 1rem; } .g-4, .gx-4 { --bs-gutter-x: 1.5rem; } .g-4, .gy-4 { --bs-gutter-y: 1.5rem; } .g-5, .gx-5 { --bs-gutter-x: 3rem; } .g-5, .gy-5 { --bs-gutter-y: 3rem; } @media (min-width: 576px) { .col-sm { flex: 1 0 0%; } .row-cols-sm-auto > * { flex: 0 0 auto; width: auto; } .row-cols-sm-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-sm-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-sm-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-sm-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-sm-auto { flex: 0 0 auto; width: auto; } .col-sm-1 { flex: 0 0 auto; width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; width: 25%; } .col-sm-4 { flex: 0 0 auto; width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; width: 50%; } .col-sm-7 { flex: 0 0 auto; width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; width: 75%; } .col-sm-10 { flex: 0 0 auto; width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; width: 100%; } .offset-sm-0 { margin-right: 0; } .offset-sm-1 { margin-right: 8.33333333%; } .offset-sm-2 { margin-right: 16.66666667%; } .offset-sm-3 { margin-right: 25%; } .offset-sm-4 { margin-right: 33.33333333%; } .offset-sm-5 { margin-right: 41.66666667%; } .offset-sm-6 { margin-right: 50%; } .offset-sm-7 { margin-right: 58.33333333%; } .offset-sm-8 { margin-right: 66.66666667%; } .offset-sm-9 { margin-right: 75%; } .offset-sm-10 { margin-right: 83.33333333%; } .offset-sm-11 { margin-right: 91.66666667%; } .g-sm-0, .gx-sm-0 { --bs-gutter-x: 0; } .g-sm-0, .gy-sm-0 { --bs-gutter-y: 0; } .g-sm-1, .gx-sm-1 { --bs-gutter-x: 0.25rem; } .g-sm-1, .gy-sm-1 { --bs-gutter-y: 0.25rem; } .g-sm-2, .gx-sm-2 { --bs-gutter-x: 0.5rem; } .g-sm-2, .gy-sm-2 { --bs-gutter-y: 0.5rem; } .g-sm-3, .gx-sm-3 { --bs-gutter-x: 1rem; } .g-sm-3, .gy-sm-3 { --bs-gutter-y: 1rem; } .g-sm-4, .gx-sm-4 { --bs-gutter-x: 1.5rem; } .g-sm-4, .gy-sm-4 { --bs-gutter-y: 1.5rem; } .g-sm-5, .gx-sm-5 { --bs-gutter-x: 3rem; } .g-sm-5, .gy-sm-5 { --bs-gutter-y: 3rem; } } @media (min-width: 768px) { .col-md { flex: 1 0 0%; } .row-cols-md-auto > * { flex: 0 0 auto; width: auto; } .row-cols-md-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-md-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-md-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-md-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-md-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-md-auto { flex: 0 0 auto; width: auto; } .col-md-1 { flex: 0 0 auto; width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; width: 25%; } .col-md-4 { flex: 0 0 auto; width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; width: 50%; } .col-md-7 { flex: 0 0 auto; width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; width: 75%; } .col-md-10 { flex: 0 0 auto; width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; width: 100%; } .offset-md-0 { margin-right: 0; } .offset-md-1 { margin-right: 8.33333333%; } .offset-md-2 { margin-right: 16.66666667%; } .offset-md-3 { margin-right: 25%; } .offset-md-4 { margin-right: 33.33333333%; } .offset-md-5 { margin-right: 41.66666667%; } .offset-md-6 { margin-right: 50%; } .offset-md-7 { margin-right: 58.33333333%; } .offset-md-8 { margin-right: 66.66666667%; } .offset-md-9 { margin-right: 75%; } .offset-md-10 { margin-right: 83.33333333%; } .offset-md-11 { margin-right: 91.66666667%; } .g-md-0, .gx-md-0 { --bs-gutter-x: 0; } .g-md-0, .gy-md-0 { --bs-gutter-y: 0; } .g-md-1, .gx-md-1 { --bs-gutter-x: 0.25rem; } .g-md-1, .gy-md-1 { --bs-gutter-y: 0.25rem; } .g-md-2, .gx-md-2 { --bs-gutter-x: 0.5rem; } .g-md-2, .gy-md-2 { --bs-gutter-y: 0.5rem; } .g-md-3, .gx-md-3 { --bs-gutter-x: 1rem; } .g-md-3, .gy-md-3 { --bs-gutter-y: 1rem; } .g-md-4, .gx-md-4 { --bs-gutter-x: 1.5rem; } .g-md-4, .gy-md-4 { --bs-gutter-y: 1.5rem; } .g-md-5, .gx-md-5 { --bs-gutter-x: 3rem; } .g-md-5, .gy-md-5 { --bs-gutter-y: 3rem; } } @media (min-width: 992px) { .col-lg { flex: 1 0 0%; } .row-cols-lg-auto > * { flex: 0 0 auto; width: auto; } .row-cols-lg-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-lg-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-lg-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-lg-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-lg-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-lg-auto { flex: 0 0 auto; width: auto; } .col-lg-1 { flex: 0 0 auto; width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; width: 25%; } .col-lg-4 { flex: 0 0 auto; width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; width: 50%; } .col-lg-7 { flex: 0 0 auto; width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; width: 75%; } .col-lg-10 { flex: 0 0 auto; width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; width: 100%; } .offset-lg-0 { margin-right: 0; } .offset-lg-1 { margin-right: 8.33333333%; } .offset-lg-2 { margin-right: 16.66666667%; } .offset-lg-3 { margin-right: 25%; } .offset-lg-4 { margin-right: 33.33333333%; } .offset-lg-5 { margin-right: 41.66666667%; } .offset-lg-6 { margin-right: 50%; } .offset-lg-7 { margin-right: 58.33333333%; } .offset-lg-8 { margin-right: 66.66666667%; } .offset-lg-9 { margin-right: 75%; } .offset-lg-10 { margin-right: 83.33333333%; } .offset-lg-11 { margin-right: 91.66666667%; } .g-lg-0, .gx-lg-0 { --bs-gutter-x: 0; } .g-lg-0, .gy-lg-0 { --bs-gutter-y: 0; } .g-lg-1, .gx-lg-1 { --bs-gutter-x: 0.25rem; } .g-lg-1, .gy-lg-1 { --bs-gutter-y: 0.25rem; } .g-lg-2, .gx-lg-2 { --bs-gutter-x: 0.5rem; } .g-lg-2, .gy-lg-2 { --bs-gutter-y: 0.5rem; } .g-lg-3, .gx-lg-3 { --bs-gutter-x: 1rem; } .g-lg-3, .gy-lg-3 { --bs-gutter-y: 1rem; } .g-lg-4, .gx-lg-4 { --bs-gutter-x: 1.5rem; } .g-lg-4, .gy-lg-4 { --bs-gutter-y: 1.5rem; } .g-lg-5, .gx-lg-5 { --bs-gutter-x: 3rem; } .g-lg-5, .gy-lg-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; } .row-cols-xl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xl-auto { flex: 0 0 auto; width: auto; } .col-xl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; width: 25%; } .col-xl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; width: 50%; } .col-xl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; width: 75%; } .col-xl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; width: 100%; } .offset-xl-0 { margin-right: 0; } .offset-xl-1 { margin-right: 8.33333333%; } .offset-xl-2 { margin-right: 16.66666667%; } .offset-xl-3 { margin-right: 25%; } .offset-xl-4 { margin-right: 33.33333333%; } .offset-xl-5 { margin-right: 41.66666667%; } .offset-xl-6 { margin-right: 50%; } .offset-xl-7 { margin-right: 58.33333333%; } .offset-xl-8 { margin-right: 66.66666667%; } .offset-xl-9 { margin-right: 75%; } .offset-xl-10 { margin-right: 83.33333333%; } .offset-xl-11 { margin-right: 91.66666667%; } .g-xl-0, .gx-xl-0 { --bs-gutter-x: 0; } .g-xl-0, .gy-xl-0 { --bs-gutter-y: 0; } .g-xl-1, .gx-xl-1 { --bs-gutter-x: 0.25rem; } .g-xl-1, .gy-xl-1 { --bs-gutter-y: 0.25rem; } .g-xl-2, .gx-xl-2 { --bs-gutter-x: 0.5rem; } .g-xl-2, .gy-xl-2 { --bs-gutter-y: 0.5rem; } .g-xl-3, .gx-xl-3 { --bs-gutter-x: 1rem; } .g-xl-3, .gy-xl-3 { --bs-gutter-y: 1rem; } .g-xl-4, .gx-xl-4 { --bs-gutter-x: 1.5rem; } .g-xl-4, .gy-xl-4 { --bs-gutter-y: 1.5rem; } .g-xl-5, .gx-xl-5 { --bs-gutter-x: 3rem; } .g-xl-5, .gy-xl-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; } .row-cols-xxl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xxl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xxl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xxl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xxl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xxl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xxl-auto { flex: 0 0 auto; width: auto; } .col-xxl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; width: 25%; } .col-xxl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; width: 50%; } .col-xxl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; width: 75%; } .col-xxl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; width: 100%; } .offset-xxl-0 { margin-right: 0; } .offset-xxl-1 { margin-right: 8.33333333%; } .offset-xxl-2 { margin-right: 16.66666667%; } .offset-xxl-3 { margin-right: 25%; } .offset-xxl-4 { margin-right: 33.33333333%; } .offset-xxl-5 { margin-right: 41.66666667%; } .offset-xxl-6 { margin-right: 50%; } .offset-xxl-7 { margin-right: 58.33333333%; } .offset-xxl-8 { margin-right: 66.66666667%; } .offset-xxl-9 { margin-right: 75%; } .offset-xxl-10 { margin-right: 83.33333333%; } .offset-xxl-11 { margin-right: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { --bs-gutter-x: 0; } .g-xxl-0, .gy-xxl-0 { --bs-gutter-y: 0; } .g-xxl-1, .gx-xxl-1 { --bs-gutter-x: 0.25rem; } .g-xxl-1, .gy-xxl-1 { --bs-gutter-y: 0.25rem; } .g-xxl-2, .gx-xxl-2 { --bs-gutter-x: 0.5rem; } .g-xxl-2, .gy-xxl-2 { --bs-gutter-y: 0.5rem; } .g-xxl-3, .gx-xxl-3 { --bs-gutter-x: 1rem; } .g-xxl-3, .gy-xxl-3 { --bs-gutter-y: 1rem; } .g-xxl-4, .gx-xxl-4 { --bs-gutter-x: 1.5rem; } .g-xxl-4, .gy-xxl-4 { --bs-gutter-y: 1.5rem; } .g-xxl-5, .gx-xxl-5 { --bs-gutter-x: 3rem; } .g-xxl-5, .gy-xxl-5 { --bs-gutter-y: 3rem; } } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-auto { margin-left: auto !important; margin-right: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-left: 0 !important; } .me-1 { margin-left: 0.25rem !important; } .me-2 { margin-left: 0.5rem !important; } .me-3 { margin-left: 1rem !important; } .me-4 { margin-left: 1.5rem !important; } .me-5 { margin-left: 3rem !important; } .me-auto { margin-left: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-right: 0 !important; } .ms-1 { margin-right: 0.25rem !important; } .ms-2 { margin-right: 0.5rem !important; } .ms-3 { margin-right: 1rem !important; } .ms-4 { margin-right: 1.5rem !important; } .ms-5 { margin-right: 3rem !important; } .ms-auto { margin-right: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-left: 0 !important; } .pe-1 { padding-left: 0.25rem !important; } .pe-2 { padding-left: 0.5rem !important; } .pe-3 { padding-left: 1rem !important; } .pe-4 { padding-left: 1.5rem !important; } .pe-5 { padding-left: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-right: 0 !important; } .ps-1 { padding-right: 0.25rem !important; } .ps-2 { padding-right: 0.5rem !important; } .ps-3 { padding-right: 1rem !important; } .ps-4 { padding-right: 1.5rem !important; } .ps-5 { padding-right: 3rem !important; } @media (min-width: 576px) { .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-sm-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-sm-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-sm-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-sm-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-sm-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-sm-auto { margin-left: auto !important; margin-right: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-left: 0 !important; } .me-sm-1 { margin-left: 0.25rem !important; } .me-sm-2 { margin-left: 0.5rem !important; } .me-sm-3 { margin-left: 1rem !important; } .me-sm-4 { margin-left: 1.5rem !important; } .me-sm-5 { margin-left: 3rem !important; } .me-sm-auto { margin-left: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-right: 0 !important; } .ms-sm-1 { margin-right: 0.25rem !important; } .ms-sm-2 { margin-right: 0.5rem !important; } .ms-sm-3 { margin-right: 1rem !important; } .ms-sm-4 { margin-right: 1.5rem !important; } .ms-sm-5 { margin-right: 3rem !important; } .ms-sm-auto { margin-right: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-sm-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-sm-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-sm-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-sm-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-sm-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-left: 0 !important; } .pe-sm-1 { padding-left: 0.25rem !important; } .pe-sm-2 { padding-left: 0.5rem !important; } .pe-sm-3 { padding-left: 1rem !important; } .pe-sm-4 { padding-left: 1.5rem !important; } .pe-sm-5 { padding-left: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-right: 0 !important; } .ps-sm-1 { padding-right: 0.25rem !important; } .ps-sm-2 { padding-right: 0.5rem !important; } .ps-sm-3 { padding-right: 1rem !important; } .ps-sm-4 { padding-right: 1.5rem !important; } .ps-sm-5 { padding-right: 3rem !important; } } @media (min-width: 768px) { .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-md-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-md-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-md-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-md-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-md-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-md-auto { margin-left: auto !important; margin-right: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-left: 0 !important; } .me-md-1 { margin-left: 0.25rem !important; } .me-md-2 { margin-left: 0.5rem !important; } .me-md-3 { margin-left: 1rem !important; } .me-md-4 { margin-left: 1.5rem !important; } .me-md-5 { margin-left: 3rem !important; } .me-md-auto { margin-left: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-right: 0 !important; } .ms-md-1 { margin-right: 0.25rem !important; } .ms-md-2 { margin-right: 0.5rem !important; } .ms-md-3 { margin-right: 1rem !important; } .ms-md-4 { margin-right: 1.5rem !important; } .ms-md-5 { margin-right: 3rem !important; } .ms-md-auto { margin-right: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-md-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-md-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-md-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-md-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-md-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-left: 0 !important; } .pe-md-1 { padding-left: 0.25rem !important; } .pe-md-2 { padding-left: 0.5rem !important; } .pe-md-3 { padding-left: 1rem !important; } .pe-md-4 { padding-left: 1.5rem !important; } .pe-md-5 { padding-left: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-right: 0 !important; } .ps-md-1 { padding-right: 0.25rem !important; } .ps-md-2 { padding-right: 0.5rem !important; } .ps-md-3 { padding-right: 1rem !important; } .ps-md-4 { padding-right: 1.5rem !important; } .ps-md-5 { padding-right: 3rem !important; } } @media (min-width: 992px) { .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-lg-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-lg-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-lg-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-lg-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-lg-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-lg-auto { margin-left: auto !important; margin-right: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-left: 0 !important; } .me-lg-1 { margin-left: 0.25rem !important; } .me-lg-2 { margin-left: 0.5rem !important; } .me-lg-3 { margin-left: 1rem !important; } .me-lg-4 { margin-left: 1.5rem !important; } .me-lg-5 { margin-left: 3rem !important; } .me-lg-auto { margin-left: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-right: 0 !important; } .ms-lg-1 { margin-right: 0.25rem !important; } .ms-lg-2 { margin-right: 0.5rem !important; } .ms-lg-3 { margin-right: 1rem !important; } .ms-lg-4 { margin-right: 1.5rem !important; } .ms-lg-5 { margin-right: 3rem !important; } .ms-lg-auto { margin-right: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-lg-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-lg-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-lg-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-lg-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-lg-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-left: 0 !important; } .pe-lg-1 { padding-left: 0.25rem !important; } .pe-lg-2 { padding-left: 0.5rem !important; } .pe-lg-3 { padding-left: 1rem !important; } .pe-lg-4 { padding-left: 1.5rem !important; } .pe-lg-5 { padding-left: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-right: 0 !important; } .ps-lg-1 { padding-right: 0.25rem !important; } .ps-lg-2 { padding-right: 0.5rem !important; } .ps-lg-3 { padding-right: 1rem !important; } .ps-lg-4 { padding-right: 1.5rem !important; } .ps-lg-5 { padding-right: 3rem !important; } } @media (min-width: 1200px) { .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-left: 0 !important; } .me-xl-1 { margin-left: 0.25rem !important; } .me-xl-2 { margin-left: 0.5rem !important; } .me-xl-3 { margin-left: 1rem !important; } .me-xl-4 { margin-left: 1.5rem !important; } .me-xl-5 { margin-left: 3rem !important; } .me-xl-auto { margin-left: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-right: 0 !important; } .ms-xl-1 { margin-right: 0.25rem !important; } .ms-xl-2 { margin-right: 0.5rem !important; } .ms-xl-3 { margin-right: 1rem !important; } .ms-xl-4 { margin-right: 1.5rem !important; } .ms-xl-5 { margin-right: 3rem !important; } .ms-xl-auto { margin-right: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-left: 0 !important; } .pe-xl-1 { padding-left: 0.25rem !important; } .pe-xl-2 { padding-left: 0.5rem !important; } .pe-xl-3 { padding-left: 1rem !important; } .pe-xl-4 { padding-left: 1.5rem !important; } .pe-xl-5 { padding-left: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-right: 0 !important; } .ps-xl-1 { padding-right: 0.25rem !important; } .ps-xl-2 { padding-right: 0.5rem !important; } .ps-xl-3 { padding-right: 1rem !important; } .ps-xl-4 { padding-right: 1.5rem !important; } .ps-xl-5 { padding-right: 3rem !important; } } @media (min-width: 1400px) { .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xxl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xxl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xxl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xxl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xxl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xxl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-left: 0 !important; } .me-xxl-1 { margin-left: 0.25rem !important; } .me-xxl-2 { margin-left: 0.5rem !important; } .me-xxl-3 { margin-left: 1rem !important; } .me-xxl-4 { margin-left: 1.5rem !important; } .me-xxl-5 { margin-left: 3rem !important; } .me-xxl-auto { margin-left: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-right: 0 !important; } .ms-xxl-1 { margin-right: 0.25rem !important; } .ms-xxl-2 { margin-right: 0.5rem !important; } .ms-xxl-3 { margin-right: 1rem !important; } .ms-xxl-4 { margin-right: 1.5rem !important; } .ms-xxl-5 { margin-right: 3rem !important; } .ms-xxl-auto { margin-right: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xxl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xxl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xxl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xxl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xxl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-left: 0 !important; } .pe-xxl-1 { padding-left: 0.25rem !important; } .pe-xxl-2 { padding-left: 0.5rem !important; } .pe-xxl-3 { padding-left: 1rem !important; } .pe-xxl-4 { padding-left: 1.5rem !important; } .pe-xxl-5 { padding-left: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-right: 0 !important; } .ps-xxl-1 { padding-right: 0.25rem !important; } .ps-xxl-2 { padding-right: 0.5rem !important; } .ps-xxl-3 { padding-right: 1rem !important; } .ps-xxl-4 { padding-right: 1.5rem !important; } .ps-xxl-5 { padding-right: 3rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap-grid.rtl.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-reboot.css ================================================ /*! * Bootstrap Reboot v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } *, *::before, *::after { box-sizing: border-box; } @media (prefers-reduced-motion: no-preference) { :root { scroll-behavior: smooth; } } body { margin: 0; font-family: var(--bs-body-font-family); font-size: var(--bs-body-font-size); font-weight: var(--bs-body-font-weight); line-height: var(--bs-body-line-height); color: var(--bs-body-color); text-align: var(--bs-body-text-align); background-color: var(--bs-body-bg); -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } hr { margin: 1rem 0; color: inherit; border: 0; border-top: 1px solid; opacity: 0.25; } h6, h5, h4, h3, h2, h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; } h1 { font-size: calc(1.375rem + 1.5vw); } @media (min-width: 1200px) { h1 { font-size: 2.5rem; } } h2 { font-size: calc(1.325rem + 0.9vw); } @media (min-width: 1200px) { h2 { font-size: 2rem; } } h3 { font-size: calc(1.3rem + 0.6vw); } @media (min-width: 1200px) { h3 { font-size: 1.75rem; } } h4 { font-size: calc(1.275rem + 0.3vw); } @media (min-width: 1200px) { h4 { font-size: 1.5rem; } } h5 { font-size: 1.25rem; } h6 { font-size: 1rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title] { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul { padding-left: 2rem; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: 0.5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small { font-size: 0.875em; } mark { padding: 0.1875em; background-color: var(--bs-highlight-bg); } sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } a { color: var(--bs-link-color); text-decoration: underline; } a:hover { color: var(--bs-link-hover-color); } a:not([href]):not([class]), a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: var(--bs-font-monospace); font-size: 1em; } pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; } pre code { font-size: inherit; color: inherit; word-break: normal; } code { font-size: 0.875em; color: var(--bs-code-color); word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.1875rem 0.375rem; font-size: 0.875em; color: var(--bs-body-bg); background-color: var(--bs-body-color); border-radius: 0.25rem; } kbd kbd { padding: 0; font-size: 1em; } figure { margin: 0 0 1rem; } img, svg { vertical-align: middle; } table { caption-side: bottom; border-collapse: collapse; } caption { padding-top: 0.5rem; padding-bottom: 0.5rem; color: #6c757d; text-align: left; } th { text-align: inherit; text-align: -webkit-match-parent; } thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; } label { display: inline-block; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, select { text-transform: none; } [role=button] { cursor: pointer; } select { word-wrap: normal; } select:disabled { opacity: 1; } [list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { display: none !important; } button, [type=button], [type=reset], [type=submit] { -webkit-appearance: button; } button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } ::-moz-focus-inner { padding: 0; border-style: none; } textarea { resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { float: left; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: calc(1.275rem + 0.3vw); line-height: inherit; } @media (min-width: 1200px) { legend { font-size: 1.5rem; } } legend + * { clear: left; } ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-year-field { padding: 0; } ::-webkit-inner-spin-button { height: auto; } [type=search] { outline-offset: -2px; -webkit-appearance: textfield; } /* rtl:raw: [type="tel"], [type="url"], [type="email"], [type="number"] { direction: ltr; } */ ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-color-swatch-wrapper { padding: 0; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } ::file-selector-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } iframe { border: 0; } summary { display: list-item; cursor: pointer; } progress { vertical-align: baseline; } [hidden] { display: none !important; } /*# sourceMappingURL=bootstrap-reboot.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-reboot.rtl.css ================================================ /*! * Bootstrap Reboot v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } *, *::before, *::after { box-sizing: border-box; } @media (prefers-reduced-motion: no-preference) { :root { scroll-behavior: smooth; } } body { margin: 0; font-family: var(--bs-body-font-family); font-size: var(--bs-body-font-size); font-weight: var(--bs-body-font-weight); line-height: var(--bs-body-line-height); color: var(--bs-body-color); text-align: var(--bs-body-text-align); background-color: var(--bs-body-bg); -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } hr { margin: 1rem 0; color: inherit; border: 0; border-top: 1px solid; opacity: 0.25; } h6, h5, h4, h3, h2, h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; } h1 { font-size: calc(1.375rem + 1.5vw); } @media (min-width: 1200px) { h1 { font-size: 2.5rem; } } h2 { font-size: calc(1.325rem + 0.9vw); } @media (min-width: 1200px) { h2 { font-size: 2rem; } } h3 { font-size: calc(1.3rem + 0.6vw); } @media (min-width: 1200px) { h3 { font-size: 1.75rem; } } h4 { font-size: calc(1.275rem + 0.3vw); } @media (min-width: 1200px) { h4 { font-size: 1.5rem; } } h5 { font-size: 1.25rem; } h6 { font-size: 1rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title] { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul { padding-right: 2rem; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: 0.5rem; margin-right: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small { font-size: 0.875em; } mark { padding: 0.1875em; background-color: var(--bs-highlight-bg); } sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } a { color: var(--bs-link-color); text-decoration: underline; } a:hover { color: var(--bs-link-hover-color); } a:not([href]):not([class]), a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: var(--bs-font-monospace); font-size: 1em; } pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; } pre code { font-size: inherit; color: inherit; word-break: normal; } code { font-size: 0.875em; color: var(--bs-code-color); word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.1875rem 0.375rem; font-size: 0.875em; color: var(--bs-body-bg); background-color: var(--bs-body-color); border-radius: 0.25rem; } kbd kbd { padding: 0; font-size: 1em; } figure { margin: 0 0 1rem; } img, svg { vertical-align: middle; } table { caption-side: bottom; border-collapse: collapse; } caption { padding-top: 0.5rem; padding-bottom: 0.5rem; color: #6c757d; text-align: right; } th { text-align: inherit; text-align: -webkit-match-parent; } thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; } label { display: inline-block; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, select { text-transform: none; } [role=button] { cursor: pointer; } select { word-wrap: normal; } select:disabled { opacity: 1; } [list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { display: none !important; } button, [type=button], [type=reset], [type=submit] { -webkit-appearance: button; } button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } ::-moz-focus-inner { padding: 0; border-style: none; } textarea { resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { float: right; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: calc(1.275rem + 0.3vw); line-height: inherit; } @media (min-width: 1200px) { legend { font-size: 1.5rem; } } legend + * { clear: right; } ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-year-field { padding: 0; } ::-webkit-inner-spin-button { height: auto; } [type=search] { outline-offset: -2px; -webkit-appearance: textfield; } [type="tel"], [type="url"], [type="email"], [type="number"] { direction: ltr; } ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-color-swatch-wrapper { padding: 0; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } ::file-selector-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } iframe { border: 0; } summary { display: list-item; cursor: pointer; } progress { vertical-align: baseline; } [hidden] { display: none !important; } /*# sourceMappingURL=bootstrap-reboot.rtl.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-utilities.css ================================================ /*! * Bootstrap Utilities v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } .clearfix::after { display: block; clear: both; content: ""; } .text-bg-primary { color: #fff !important; background-color: RGBA(13, 110, 253, var(--bs-bg-opacity, 1)) !important; } .text-bg-secondary { color: #fff !important; background-color: RGBA(108, 117, 125, var(--bs-bg-opacity, 1)) !important; } .text-bg-success { color: #fff !important; background-color: RGBA(25, 135, 84, var(--bs-bg-opacity, 1)) !important; } .text-bg-info { color: #000 !important; background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; } .text-bg-warning { color: #000 !important; background-color: RGBA(255, 193, 7, var(--bs-bg-opacity, 1)) !important; } .text-bg-danger { color: #fff !important; background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; } .text-bg-light { color: #000 !important; background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; } .text-bg-dark { color: #fff !important; background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; } .link-primary { color: #0d6efd !important; } .link-primary:hover, .link-primary:focus { color: #0a58ca !important; } .link-secondary { color: #6c757d !important; } .link-secondary:hover, .link-secondary:focus { color: #565e64 !important; } .link-success { color: #198754 !important; } .link-success:hover, .link-success:focus { color: #146c43 !important; } .link-info { color: #0dcaf0 !important; } .link-info:hover, .link-info:focus { color: #3dd5f3 !important; } .link-warning { color: #ffc107 !important; } .link-warning:hover, .link-warning:focus { color: #ffcd39 !important; } .link-danger { color: #dc3545 !important; } .link-danger:hover, .link-danger:focus { color: #b02a37 !important; } .link-light { color: #f8f9fa !important; } .link-light:hover, .link-light:focus { color: #f9fafb !important; } .link-dark { color: #212529 !important; } .link-dark:hover, .link-dark:focus { color: #1a1e21 !important; } .ratio { position: relative; width: 100%; } .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } .ratio > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ratio-1x1 { --bs-aspect-ratio: 100%; } .ratio-4x3 { --bs-aspect-ratio: 75%; } .ratio-16x9 { --bs-aspect-ratio: 56.25%; } .ratio-21x9 { --bs-aspect-ratio: 42.8571428571%; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } @media (min-width: 576px) { .sticky-sm-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-sm-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 768px) { .sticky-md-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-md-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 992px) { .sticky-lg-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-lg-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1200px) { .sticky-xl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1400px) { .sticky-xxl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xxl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } .hstack { display: flex; flex-direction: row; align-items: center; align-self: stretch; } .vstack { display: flex; flex: 1 1 auto; flex-direction: column; align-self: stretch; } .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; content: ""; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .vr { display: inline-block; align-self: stretch; width: 1px; min-height: 1em; background-color: currentcolor; opacity: 0.25; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .float-start { float: left !important; } .float-end { float: right !important; } .float-none { float: none !important; } .opacity-0 { opacity: 0 !important; } .opacity-25 { opacity: 0.25 !important; } .opacity-50 { opacity: 0.5 !important; } .opacity-75 { opacity: 0.75 !important; } .opacity-100 { opacity: 1 !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .overflow-visible { overflow: visible !important; } .overflow-scroll { overflow: scroll !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { left: 0 !important; } .start-50 { left: 50% !important; } .start-100 { left: 100% !important; } .end-0 { right: 0 !important; } .end-50 { right: 50% !important; } .end-100 { right: 100% !important; } .translate-middle { transform: translate(-50%, -50%) !important; } .translate-middle-x { transform: translateX(-50%) !important; } .translate-middle-y { transform: translateY(-50%) !important; } .border { border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-0 { border: 0 !important; } .border-top { border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-top-0 { border-top: 0 !important; } .border-end { border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-end-0 { border-right: 0 !important; } .border-bottom { border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-start { border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-start-0 { border-left: 0 !important; } .border-primary { --bs-border-opacity: 1; border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } .border-secondary { --bs-border-opacity: 1; border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } .border-success { --bs-border-opacity: 1; border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } .border-info { --bs-border-opacity: 1; border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } .border-warning { --bs-border-opacity: 1; border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } .border-danger { --bs-border-opacity: 1; border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } .border-light { --bs-border-opacity: 1; border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } .border-dark { --bs-border-opacity: 1; border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } .border-white { --bs-border-opacity: 1; border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } .border-1 { --bs-border-width: 1px; } .border-2 { --bs-border-width: 2px; } .border-3 { --bs-border-width: 3px; } .border-4 { --bs-border-width: 4px; } .border-5 { --bs-border-width: 5px; } .border-opacity-10 { --bs-border-opacity: 0.1; } .border-opacity-25 { --bs-border-opacity: 0.25; } .border-opacity-50 { --bs-border-opacity: 0.5; } .border-opacity-75 { --bs-border-opacity: 0.75; } .border-opacity-100 { --bs-border-opacity: 1; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .mw-100 { max-width: 100% !important; } .vw-100 { width: 100vw !important; } .min-vw-100 { min-width: 100vw !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mh-100 { max-height: 100% !important; } .vh-100 { height: 100vh !important; } .min-vh-100 { min-height: 100vh !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-auto { margin-right: auto !important; margin-left: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-right: 0 !important; } .me-1 { margin-right: 0.25rem !important; } .me-2 { margin-right: 0.5rem !important; } .me-3 { margin-right: 1rem !important; } .me-4 { margin-right: 1.5rem !important; } .me-5 { margin-right: 3rem !important; } .me-auto { margin-right: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-left: 0 !important; } .ms-1 { margin-left: 0.25rem !important; } .ms-2 { margin-left: 0.5rem !important; } .ms-3 { margin-left: 1rem !important; } .ms-4 { margin-left: 1.5rem !important; } .ms-5 { margin-left: 3rem !important; } .ms-auto { margin-left: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-right: 0 !important; } .pe-1 { padding-right: 0.25rem !important; } .pe-2 { padding-right: 0.5rem !important; } .pe-3 { padding-right: 1rem !important; } .pe-4 { padding-right: 1.5rem !important; } .pe-5 { padding-right: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-left: 0 !important; } .ps-1 { padding-left: 0.25rem !important; } .ps-2 { padding-left: 0.5rem !important; } .ps-3 { padding-left: 1rem !important; } .ps-4 { padding-left: 1.5rem !important; } .ps-5 { padding-left: 3rem !important; } .gap-0 { gap: 0 !important; } .gap-1 { gap: 0.25rem !important; } .gap-2 { gap: 0.5rem !important; } .gap-3 { gap: 1rem !important; } .gap-4 { gap: 1.5rem !important; } .gap-5 { gap: 3rem !important; } .font-monospace { font-family: var(--bs-font-monospace) !important; } .fs-1 { font-size: calc(1.375rem + 1.5vw) !important; } .fs-2 { font-size: calc(1.325rem + 0.9vw) !important; } .fs-3 { font-size: calc(1.3rem + 0.6vw) !important; } .fs-4 { font-size: calc(1.275rem + 0.3vw) !important; } .fs-5 { font-size: 1.25rem !important; } .fs-6 { font-size: 1rem !important; } .fst-italic { font-style: italic !important; } .fst-normal { font-style: normal !important; } .fw-light { font-weight: 300 !important; } .fw-lighter { font-weight: lighter !important; } .fw-normal { font-weight: 400 !important; } .fw-bold { font-weight: 700 !important; } .fw-semibold { font-weight: 600 !important; } .fw-bolder { font-weight: bolder !important; } .lh-1 { line-height: 1 !important; } .lh-sm { line-height: 1.25 !important; } .lh-base { line-height: 1.5 !important; } .lh-lg { line-height: 2 !important; } .text-start { text-align: left !important; } .text-end { text-align: right !important; } .text-center { text-align: center !important; } .text-decoration-none { text-decoration: none !important; } .text-decoration-underline { text-decoration: underline !important; } .text-decoration-line-through { text-decoration: line-through !important; } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } /* rtl:begin:remove */ .text-break { word-wrap: break-word !important; word-break: break-word !important; } /* rtl:end:remove */ .text-primary { --bs-text-opacity: 1; color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } .text-secondary { --bs-text-opacity: 1; color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } .text-success { --bs-text-opacity: 1; color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } .text-info { --bs-text-opacity: 1; color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } .text-warning { --bs-text-opacity: 1; color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } .text-danger { --bs-text-opacity: 1; color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } .text-light { --bs-text-opacity: 1; color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } .text-dark { --bs-text-opacity: 1; color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } .text-black { --bs-text-opacity: 1; color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } .text-white { --bs-text-opacity: 1; color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } .text-body { --bs-text-opacity: 1; color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } .text-muted { --bs-text-opacity: 1; color: #6c757d !important; } .text-black-50 { --bs-text-opacity: 1; color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { --bs-text-opacity: 1; color: rgba(255, 255, 255, 0.5) !important; } .text-reset { --bs-text-opacity: 1; color: inherit !important; } .text-opacity-25 { --bs-text-opacity: 0.25; } .text-opacity-50 { --bs-text-opacity: 0.5; } .text-opacity-75 { --bs-text-opacity: 0.75; } .text-opacity-100 { --bs-text-opacity: 1; } .bg-primary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } .bg-secondary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } .bg-success { --bs-bg-opacity: 1; background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } .bg-info { --bs-bg-opacity: 1; background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } .bg-warning { --bs-bg-opacity: 1; background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } .bg-danger { --bs-bg-opacity: 1; background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } .bg-light { --bs-bg-opacity: 1; background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } .bg-dark { --bs-bg-opacity: 1; background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } .bg-black { --bs-bg-opacity: 1; background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } .bg-white { --bs-bg-opacity: 1; background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } .bg-body { --bs-bg-opacity: 1; background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } .bg-transparent { --bs-bg-opacity: 1; background-color: transparent !important; } .bg-opacity-10 { --bs-bg-opacity: 0.1; } .bg-opacity-25 { --bs-bg-opacity: 0.25; } .bg-opacity-50 { --bs-bg-opacity: 0.5; } .bg-opacity-75 { --bs-bg-opacity: 0.75; } .bg-opacity-100 { --bs-bg-opacity: 1; } .bg-gradient { background-image: var(--bs-gradient) !important; } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; user-select: none !important; } .pe-none { pointer-events: none !important; } .pe-auto { pointer-events: auto !important; } .rounded { border-radius: var(--bs-border-radius) !important; } .rounded-0 { border-radius: 0 !important; } .rounded-1 { border-radius: var(--bs-border-radius-sm) !important; } .rounded-2 { border-radius: var(--bs-border-radius) !important; } .rounded-3 { border-radius: var(--bs-border-radius-lg) !important; } .rounded-4 { border-radius: var(--bs-border-radius-xl) !important; } .rounded-5 { border-radius: var(--bs-border-radius-2xl) !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: var(--bs-border-radius-pill) !important; } .rounded-top { border-top-left-radius: var(--bs-border-radius) !important; border-top-right-radius: var(--bs-border-radius) !important; } .rounded-end { border-top-right-radius: var(--bs-border-radius) !important; border-bottom-right-radius: var(--bs-border-radius) !important; } .rounded-bottom { border-bottom-right-radius: var(--bs-border-radius) !important; border-bottom-left-radius: var(--bs-border-radius) !important; } .rounded-start { border-bottom-left-radius: var(--bs-border-radius) !important; border-top-left-radius: var(--bs-border-radius) !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media (min-width: 576px) { .float-sm-start { float: left !important; } .float-sm-end { float: right !important; } .float-sm-none { float: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-sm-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-sm-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-sm-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-sm-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-sm-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-sm-auto { margin-right: auto !important; margin-left: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-right: 0 !important; } .me-sm-1 { margin-right: 0.25rem !important; } .me-sm-2 { margin-right: 0.5rem !important; } .me-sm-3 { margin-right: 1rem !important; } .me-sm-4 { margin-right: 1.5rem !important; } .me-sm-5 { margin-right: 3rem !important; } .me-sm-auto { margin-right: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-left: 0 !important; } .ms-sm-1 { margin-left: 0.25rem !important; } .ms-sm-2 { margin-left: 0.5rem !important; } .ms-sm-3 { margin-left: 1rem !important; } .ms-sm-4 { margin-left: 1.5rem !important; } .ms-sm-5 { margin-left: 3rem !important; } .ms-sm-auto { margin-left: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-sm-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-sm-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-sm-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-sm-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-sm-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-right: 0 !important; } .pe-sm-1 { padding-right: 0.25rem !important; } .pe-sm-2 { padding-right: 0.5rem !important; } .pe-sm-3 { padding-right: 1rem !important; } .pe-sm-4 { padding-right: 1.5rem !important; } .pe-sm-5 { padding-right: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-left: 0 !important; } .ps-sm-1 { padding-left: 0.25rem !important; } .ps-sm-2 { padding-left: 0.5rem !important; } .ps-sm-3 { padding-left: 1rem !important; } .ps-sm-4 { padding-left: 1.5rem !important; } .ps-sm-5 { padding-left: 3rem !important; } .gap-sm-0 { gap: 0 !important; } .gap-sm-1 { gap: 0.25rem !important; } .gap-sm-2 { gap: 0.5rem !important; } .gap-sm-3 { gap: 1rem !important; } .gap-sm-4 { gap: 1.5rem !important; } .gap-sm-5 { gap: 3rem !important; } .text-sm-start { text-align: left !important; } .text-sm-end { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .float-md-start { float: left !important; } .float-md-end { float: right !important; } .float-md-none { float: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-md-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-md-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-md-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-md-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-md-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-md-auto { margin-right: auto !important; margin-left: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-right: 0 !important; } .me-md-1 { margin-right: 0.25rem !important; } .me-md-2 { margin-right: 0.5rem !important; } .me-md-3 { margin-right: 1rem !important; } .me-md-4 { margin-right: 1.5rem !important; } .me-md-5 { margin-right: 3rem !important; } .me-md-auto { margin-right: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-left: 0 !important; } .ms-md-1 { margin-left: 0.25rem !important; } .ms-md-2 { margin-left: 0.5rem !important; } .ms-md-3 { margin-left: 1rem !important; } .ms-md-4 { margin-left: 1.5rem !important; } .ms-md-5 { margin-left: 3rem !important; } .ms-md-auto { margin-left: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-md-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-md-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-md-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-md-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-md-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-right: 0 !important; } .pe-md-1 { padding-right: 0.25rem !important; } .pe-md-2 { padding-right: 0.5rem !important; } .pe-md-3 { padding-right: 1rem !important; } .pe-md-4 { padding-right: 1.5rem !important; } .pe-md-5 { padding-right: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-left: 0 !important; } .ps-md-1 { padding-left: 0.25rem !important; } .ps-md-2 { padding-left: 0.5rem !important; } .ps-md-3 { padding-left: 1rem !important; } .ps-md-4 { padding-left: 1.5rem !important; } .ps-md-5 { padding-left: 3rem !important; } .gap-md-0 { gap: 0 !important; } .gap-md-1 { gap: 0.25rem !important; } .gap-md-2 { gap: 0.5rem !important; } .gap-md-3 { gap: 1rem !important; } .gap-md-4 { gap: 1.5rem !important; } .gap-md-5 { gap: 3rem !important; } .text-md-start { text-align: left !important; } .text-md-end { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .float-lg-start { float: left !important; } .float-lg-end { float: right !important; } .float-lg-none { float: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-lg-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-lg-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-lg-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-lg-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-lg-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-lg-auto { margin-right: auto !important; margin-left: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-right: 0 !important; } .me-lg-1 { margin-right: 0.25rem !important; } .me-lg-2 { margin-right: 0.5rem !important; } .me-lg-3 { margin-right: 1rem !important; } .me-lg-4 { margin-right: 1.5rem !important; } .me-lg-5 { margin-right: 3rem !important; } .me-lg-auto { margin-right: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-left: 0 !important; } .ms-lg-1 { margin-left: 0.25rem !important; } .ms-lg-2 { margin-left: 0.5rem !important; } .ms-lg-3 { margin-left: 1rem !important; } .ms-lg-4 { margin-left: 1.5rem !important; } .ms-lg-5 { margin-left: 3rem !important; } .ms-lg-auto { margin-left: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-lg-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-lg-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-lg-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-lg-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-lg-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-right: 0 !important; } .pe-lg-1 { padding-right: 0.25rem !important; } .pe-lg-2 { padding-right: 0.5rem !important; } .pe-lg-3 { padding-right: 1rem !important; } .pe-lg-4 { padding-right: 1.5rem !important; } .pe-lg-5 { padding-right: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-left: 0 !important; } .ps-lg-1 { padding-left: 0.25rem !important; } .ps-lg-2 { padding-left: 0.5rem !important; } .ps-lg-3 { padding-left: 1rem !important; } .ps-lg-4 { padding-left: 1.5rem !important; } .ps-lg-5 { padding-left: 3rem !important; } .gap-lg-0 { gap: 0 !important; } .gap-lg-1 { gap: 0.25rem !important; } .gap-lg-2 { gap: 0.5rem !important; } .gap-lg-3 { gap: 1rem !important; } .gap-lg-4 { gap: 1.5rem !important; } .gap-lg-5 { gap: 3rem !important; } .text-lg-start { text-align: left !important; } .text-lg-end { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .float-xl-start { float: left !important; } .float-xl-end { float: right !important; } .float-xl-none { float: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-right: 0 !important; } .me-xl-1 { margin-right: 0.25rem !important; } .me-xl-2 { margin-right: 0.5rem !important; } .me-xl-3 { margin-right: 1rem !important; } .me-xl-4 { margin-right: 1.5rem !important; } .me-xl-5 { margin-right: 3rem !important; } .me-xl-auto { margin-right: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-left: 0 !important; } .ms-xl-1 { margin-left: 0.25rem !important; } .ms-xl-2 { margin-left: 0.5rem !important; } .ms-xl-3 { margin-left: 1rem !important; } .ms-xl-4 { margin-left: 1.5rem !important; } .ms-xl-5 { margin-left: 3rem !important; } .ms-xl-auto { margin-left: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-right: 0 !important; } .pe-xl-1 { padding-right: 0.25rem !important; } .pe-xl-2 { padding-right: 0.5rem !important; } .pe-xl-3 { padding-right: 1rem !important; } .pe-xl-4 { padding-right: 1.5rem !important; } .pe-xl-5 { padding-right: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-left: 0 !important; } .ps-xl-1 { padding-left: 0.25rem !important; } .ps-xl-2 { padding-left: 0.5rem !important; } .ps-xl-3 { padding-left: 1rem !important; } .ps-xl-4 { padding-left: 1.5rem !important; } .ps-xl-5 { padding-left: 3rem !important; } .gap-xl-0 { gap: 0 !important; } .gap-xl-1 { gap: 0.25rem !important; } .gap-xl-2 { gap: 0.5rem !important; } .gap-xl-3 { gap: 1rem !important; } .gap-xl-4 { gap: 1.5rem !important; } .gap-xl-5 { gap: 3rem !important; } .text-xl-start { text-align: left !important; } .text-xl-end { text-align: right !important; } .text-xl-center { text-align: center !important; } } @media (min-width: 1400px) { .float-xxl-start { float: left !important; } .float-xxl-end { float: right !important; } .float-xxl-none { float: none !important; } .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xxl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xxl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xxl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xxl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xxl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xxl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-right: 0 !important; } .me-xxl-1 { margin-right: 0.25rem !important; } .me-xxl-2 { margin-right: 0.5rem !important; } .me-xxl-3 { margin-right: 1rem !important; } .me-xxl-4 { margin-right: 1.5rem !important; } .me-xxl-5 { margin-right: 3rem !important; } .me-xxl-auto { margin-right: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-left: 0 !important; } .ms-xxl-1 { margin-left: 0.25rem !important; } .ms-xxl-2 { margin-left: 0.5rem !important; } .ms-xxl-3 { margin-left: 1rem !important; } .ms-xxl-4 { margin-left: 1.5rem !important; } .ms-xxl-5 { margin-left: 3rem !important; } .ms-xxl-auto { margin-left: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xxl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xxl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xxl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xxl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xxl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-right: 0 !important; } .pe-xxl-1 { padding-right: 0.25rem !important; } .pe-xxl-2 { padding-right: 0.5rem !important; } .pe-xxl-3 { padding-right: 1rem !important; } .pe-xxl-4 { padding-right: 1.5rem !important; } .pe-xxl-5 { padding-right: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-left: 0 !important; } .ps-xxl-1 { padding-left: 0.25rem !important; } .ps-xxl-2 { padding-left: 0.5rem !important; } .ps-xxl-3 { padding-left: 1rem !important; } .ps-xxl-4 { padding-left: 1.5rem !important; } .ps-xxl-5 { padding-left: 3rem !important; } .gap-xxl-0 { gap: 0 !important; } .gap-xxl-1 { gap: 0.25rem !important; } .gap-xxl-2 { gap: 0.5rem !important; } .gap-xxl-3 { gap: 1rem !important; } .gap-xxl-4 { gap: 1.5rem !important; } .gap-xxl-5 { gap: 3rem !important; } .text-xxl-start { text-align: left !important; } .text-xxl-end { text-align: right !important; } .text-xxl-center { text-align: center !important; } } @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; } .fs-2 { font-size: 2rem !important; } .fs-3 { font-size: 1.75rem !important; } .fs-4 { font-size: 1.5rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap-utilities.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap-utilities.rtl.css ================================================ /*! * Bootstrap Utilities v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } .clearfix::after { display: block; clear: both; content: ""; } .text-bg-primary { color: #fff !important; background-color: RGBA(13, 110, 253, var(--bs-bg-opacity, 1)) !important; } .text-bg-secondary { color: #fff !important; background-color: RGBA(108, 117, 125, var(--bs-bg-opacity, 1)) !important; } .text-bg-success { color: #fff !important; background-color: RGBA(25, 135, 84, var(--bs-bg-opacity, 1)) !important; } .text-bg-info { color: #000 !important; background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; } .text-bg-warning { color: #000 !important; background-color: RGBA(255, 193, 7, var(--bs-bg-opacity, 1)) !important; } .text-bg-danger { color: #fff !important; background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; } .text-bg-light { color: #000 !important; background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; } .text-bg-dark { color: #fff !important; background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; } .link-primary { color: #0d6efd !important; } .link-primary:hover, .link-primary:focus { color: #0a58ca !important; } .link-secondary { color: #6c757d !important; } .link-secondary:hover, .link-secondary:focus { color: #565e64 !important; } .link-success { color: #198754 !important; } .link-success:hover, .link-success:focus { color: #146c43 !important; } .link-info { color: #0dcaf0 !important; } .link-info:hover, .link-info:focus { color: #3dd5f3 !important; } .link-warning { color: #ffc107 !important; } .link-warning:hover, .link-warning:focus { color: #ffcd39 !important; } .link-danger { color: #dc3545 !important; } .link-danger:hover, .link-danger:focus { color: #b02a37 !important; } .link-light { color: #f8f9fa !important; } .link-light:hover, .link-light:focus { color: #f9fafb !important; } .link-dark { color: #212529 !important; } .link-dark:hover, .link-dark:focus { color: #1a1e21 !important; } .ratio { position: relative; width: 100%; } .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } .ratio > * { position: absolute; top: 0; right: 0; width: 100%; height: 100%; } .ratio-1x1 { --bs-aspect-ratio: 100%; } .ratio-4x3 { --bs-aspect-ratio: 75%; } .ratio-16x9 { --bs-aspect-ratio: 56.25%; } .ratio-21x9 { --bs-aspect-ratio: 42.8571428571%; } .fixed-top { position: fixed; top: 0; left: 0; right: 0; z-index: 1030; } .fixed-bottom { position: fixed; left: 0; bottom: 0; right: 0; z-index: 1030; } .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } @media (min-width: 576px) { .sticky-sm-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-sm-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 768px) { .sticky-md-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-md-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 992px) { .sticky-lg-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-lg-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1200px) { .sticky-xl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1400px) { .sticky-xxl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xxl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } .hstack { display: flex; flex-direction: row; align-items: center; align-self: stretch; } .vstack { display: flex; flex: 1 1 auto; flex-direction: column; align-self: stretch; } .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } .stretched-link::after { position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 1; content: ""; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .vr { display: inline-block; align-self: stretch; width: 1px; min-height: 1em; background-color: currentcolor; opacity: 0.25; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .float-start { float: right !important; } .float-end { float: left !important; } .float-none { float: none !important; } .opacity-0 { opacity: 0 !important; } .opacity-25 { opacity: 0.25 !important; } .opacity-50 { opacity: 0.5 !important; } .opacity-75 { opacity: 0.75 !important; } .opacity-100 { opacity: 1 !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .overflow-visible { overflow: visible !important; } .overflow-scroll { overflow: scroll !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { right: 0 !important; } .start-50 { right: 50% !important; } .start-100 { right: 100% !important; } .end-0 { left: 0 !important; } .end-50 { left: 50% !important; } .end-100 { left: 100% !important; } .translate-middle { transform: translate(50%, -50%) !important; } .translate-middle-x { transform: translateX(50%) !important; } .translate-middle-y { transform: translateY(-50%) !important; } .border { border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-0 { border: 0 !important; } .border-top { border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-top-0 { border-top: 0 !important; } .border-end { border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-end-0 { border-left: 0 !important; } .border-bottom { border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-start { border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-start-0 { border-right: 0 !important; } .border-primary { --bs-border-opacity: 1; border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } .border-secondary { --bs-border-opacity: 1; border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } .border-success { --bs-border-opacity: 1; border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } .border-info { --bs-border-opacity: 1; border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } .border-warning { --bs-border-opacity: 1; border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } .border-danger { --bs-border-opacity: 1; border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } .border-light { --bs-border-opacity: 1; border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } .border-dark { --bs-border-opacity: 1; border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } .border-white { --bs-border-opacity: 1; border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } .border-1 { --bs-border-width: 1px; } .border-2 { --bs-border-width: 2px; } .border-3 { --bs-border-width: 3px; } .border-4 { --bs-border-width: 4px; } .border-5 { --bs-border-width: 5px; } .border-opacity-10 { --bs-border-opacity: 0.1; } .border-opacity-25 { --bs-border-opacity: 0.25; } .border-opacity-50 { --bs-border-opacity: 0.5; } .border-opacity-75 { --bs-border-opacity: 0.75; } .border-opacity-100 { --bs-border-opacity: 1; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .mw-100 { max-width: 100% !important; } .vw-100 { width: 100vw !important; } .min-vw-100 { min-width: 100vw !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mh-100 { max-height: 100% !important; } .vh-100 { height: 100vh !important; } .min-vh-100 { min-height: 100vh !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-auto { margin-left: auto !important; margin-right: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-left: 0 !important; } .me-1 { margin-left: 0.25rem !important; } .me-2 { margin-left: 0.5rem !important; } .me-3 { margin-left: 1rem !important; } .me-4 { margin-left: 1.5rem !important; } .me-5 { margin-left: 3rem !important; } .me-auto { margin-left: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-right: 0 !important; } .ms-1 { margin-right: 0.25rem !important; } .ms-2 { margin-right: 0.5rem !important; } .ms-3 { margin-right: 1rem !important; } .ms-4 { margin-right: 1.5rem !important; } .ms-5 { margin-right: 3rem !important; } .ms-auto { margin-right: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-left: 0 !important; } .pe-1 { padding-left: 0.25rem !important; } .pe-2 { padding-left: 0.5rem !important; } .pe-3 { padding-left: 1rem !important; } .pe-4 { padding-left: 1.5rem !important; } .pe-5 { padding-left: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-right: 0 !important; } .ps-1 { padding-right: 0.25rem !important; } .ps-2 { padding-right: 0.5rem !important; } .ps-3 { padding-right: 1rem !important; } .ps-4 { padding-right: 1.5rem !important; } .ps-5 { padding-right: 3rem !important; } .gap-0 { gap: 0 !important; } .gap-1 { gap: 0.25rem !important; } .gap-2 { gap: 0.5rem !important; } .gap-3 { gap: 1rem !important; } .gap-4 { gap: 1.5rem !important; } .gap-5 { gap: 3rem !important; } .font-monospace { font-family: var(--bs-font-monospace) !important; } .fs-1 { font-size: calc(1.375rem + 1.5vw) !important; } .fs-2 { font-size: calc(1.325rem + 0.9vw) !important; } .fs-3 { font-size: calc(1.3rem + 0.6vw) !important; } .fs-4 { font-size: calc(1.275rem + 0.3vw) !important; } .fs-5 { font-size: 1.25rem !important; } .fs-6 { font-size: 1rem !important; } .fst-italic { font-style: italic !important; } .fst-normal { font-style: normal !important; } .fw-light { font-weight: 300 !important; } .fw-lighter { font-weight: lighter !important; } .fw-normal { font-weight: 400 !important; } .fw-bold { font-weight: 700 !important; } .fw-semibold { font-weight: 600 !important; } .fw-bolder { font-weight: bolder !important; } .lh-1 { line-height: 1 !important; } .lh-sm { line-height: 1.25 !important; } .lh-base { line-height: 1.5 !important; } .lh-lg { line-height: 2 !important; } .text-start { text-align: right !important; } .text-end { text-align: left !important; } .text-center { text-align: center !important; } .text-decoration-none { text-decoration: none !important; } .text-decoration-underline { text-decoration: underline !important; } .text-decoration-line-through { text-decoration: line-through !important; } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } .text-primary { --bs-text-opacity: 1; color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } .text-secondary { --bs-text-opacity: 1; color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } .text-success { --bs-text-opacity: 1; color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } .text-info { --bs-text-opacity: 1; color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } .text-warning { --bs-text-opacity: 1; color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } .text-danger { --bs-text-opacity: 1; color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } .text-light { --bs-text-opacity: 1; color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } .text-dark { --bs-text-opacity: 1; color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } .text-black { --bs-text-opacity: 1; color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } .text-white { --bs-text-opacity: 1; color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } .text-body { --bs-text-opacity: 1; color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } .text-muted { --bs-text-opacity: 1; color: #6c757d !important; } .text-black-50 { --bs-text-opacity: 1; color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { --bs-text-opacity: 1; color: rgba(255, 255, 255, 0.5) !important; } .text-reset { --bs-text-opacity: 1; color: inherit !important; } .text-opacity-25 { --bs-text-opacity: 0.25; } .text-opacity-50 { --bs-text-opacity: 0.5; } .text-opacity-75 { --bs-text-opacity: 0.75; } .text-opacity-100 { --bs-text-opacity: 1; } .bg-primary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } .bg-secondary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } .bg-success { --bs-bg-opacity: 1; background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } .bg-info { --bs-bg-opacity: 1; background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } .bg-warning { --bs-bg-opacity: 1; background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } .bg-danger { --bs-bg-opacity: 1; background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } .bg-light { --bs-bg-opacity: 1; background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } .bg-dark { --bs-bg-opacity: 1; background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } .bg-black { --bs-bg-opacity: 1; background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } .bg-white { --bs-bg-opacity: 1; background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } .bg-body { --bs-bg-opacity: 1; background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } .bg-transparent { --bs-bg-opacity: 1; background-color: transparent !important; } .bg-opacity-10 { --bs-bg-opacity: 0.1; } .bg-opacity-25 { --bs-bg-opacity: 0.25; } .bg-opacity-50 { --bs-bg-opacity: 0.5; } .bg-opacity-75 { --bs-bg-opacity: 0.75; } .bg-opacity-100 { --bs-bg-opacity: 1; } .bg-gradient { background-image: var(--bs-gradient) !important; } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; user-select: none !important; } .pe-none { pointer-events: none !important; } .pe-auto { pointer-events: auto !important; } .rounded { border-radius: var(--bs-border-radius) !important; } .rounded-0 { border-radius: 0 !important; } .rounded-1 { border-radius: var(--bs-border-radius-sm) !important; } .rounded-2 { border-radius: var(--bs-border-radius) !important; } .rounded-3 { border-radius: var(--bs-border-radius-lg) !important; } .rounded-4 { border-radius: var(--bs-border-radius-xl) !important; } .rounded-5 { border-radius: var(--bs-border-radius-2xl) !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: var(--bs-border-radius-pill) !important; } .rounded-top { border-top-right-radius: var(--bs-border-radius) !important; border-top-left-radius: var(--bs-border-radius) !important; } .rounded-end { border-top-left-radius: var(--bs-border-radius) !important; border-bottom-left-radius: var(--bs-border-radius) !important; } .rounded-bottom { border-bottom-left-radius: var(--bs-border-radius) !important; border-bottom-right-radius: var(--bs-border-radius) !important; } .rounded-start { border-bottom-right-radius: var(--bs-border-radius) !important; border-top-right-radius: var(--bs-border-radius) !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media (min-width: 576px) { .float-sm-start { float: right !important; } .float-sm-end { float: left !important; } .float-sm-none { float: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-sm-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-sm-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-sm-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-sm-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-sm-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-sm-auto { margin-left: auto !important; margin-right: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-left: 0 !important; } .me-sm-1 { margin-left: 0.25rem !important; } .me-sm-2 { margin-left: 0.5rem !important; } .me-sm-3 { margin-left: 1rem !important; } .me-sm-4 { margin-left: 1.5rem !important; } .me-sm-5 { margin-left: 3rem !important; } .me-sm-auto { margin-left: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-right: 0 !important; } .ms-sm-1 { margin-right: 0.25rem !important; } .ms-sm-2 { margin-right: 0.5rem !important; } .ms-sm-3 { margin-right: 1rem !important; } .ms-sm-4 { margin-right: 1.5rem !important; } .ms-sm-5 { margin-right: 3rem !important; } .ms-sm-auto { margin-right: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-sm-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-sm-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-sm-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-sm-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-sm-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-left: 0 !important; } .pe-sm-1 { padding-left: 0.25rem !important; } .pe-sm-2 { padding-left: 0.5rem !important; } .pe-sm-3 { padding-left: 1rem !important; } .pe-sm-4 { padding-left: 1.5rem !important; } .pe-sm-5 { padding-left: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-right: 0 !important; } .ps-sm-1 { padding-right: 0.25rem !important; } .ps-sm-2 { padding-right: 0.5rem !important; } .ps-sm-3 { padding-right: 1rem !important; } .ps-sm-4 { padding-right: 1.5rem !important; } .ps-sm-5 { padding-right: 3rem !important; } .gap-sm-0 { gap: 0 !important; } .gap-sm-1 { gap: 0.25rem !important; } .gap-sm-2 { gap: 0.5rem !important; } .gap-sm-3 { gap: 1rem !important; } .gap-sm-4 { gap: 1.5rem !important; } .gap-sm-5 { gap: 3rem !important; } .text-sm-start { text-align: right !important; } .text-sm-end { text-align: left !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .float-md-start { float: right !important; } .float-md-end { float: left !important; } .float-md-none { float: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-md-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-md-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-md-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-md-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-md-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-md-auto { margin-left: auto !important; margin-right: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-left: 0 !important; } .me-md-1 { margin-left: 0.25rem !important; } .me-md-2 { margin-left: 0.5rem !important; } .me-md-3 { margin-left: 1rem !important; } .me-md-4 { margin-left: 1.5rem !important; } .me-md-5 { margin-left: 3rem !important; } .me-md-auto { margin-left: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-right: 0 !important; } .ms-md-1 { margin-right: 0.25rem !important; } .ms-md-2 { margin-right: 0.5rem !important; } .ms-md-3 { margin-right: 1rem !important; } .ms-md-4 { margin-right: 1.5rem !important; } .ms-md-5 { margin-right: 3rem !important; } .ms-md-auto { margin-right: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-md-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-md-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-md-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-md-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-md-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-left: 0 !important; } .pe-md-1 { padding-left: 0.25rem !important; } .pe-md-2 { padding-left: 0.5rem !important; } .pe-md-3 { padding-left: 1rem !important; } .pe-md-4 { padding-left: 1.5rem !important; } .pe-md-5 { padding-left: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-right: 0 !important; } .ps-md-1 { padding-right: 0.25rem !important; } .ps-md-2 { padding-right: 0.5rem !important; } .ps-md-3 { padding-right: 1rem !important; } .ps-md-4 { padding-right: 1.5rem !important; } .ps-md-5 { padding-right: 3rem !important; } .gap-md-0 { gap: 0 !important; } .gap-md-1 { gap: 0.25rem !important; } .gap-md-2 { gap: 0.5rem !important; } .gap-md-3 { gap: 1rem !important; } .gap-md-4 { gap: 1.5rem !important; } .gap-md-5 { gap: 3rem !important; } .text-md-start { text-align: right !important; } .text-md-end { text-align: left !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .float-lg-start { float: right !important; } .float-lg-end { float: left !important; } .float-lg-none { float: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-lg-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-lg-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-lg-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-lg-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-lg-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-lg-auto { margin-left: auto !important; margin-right: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-left: 0 !important; } .me-lg-1 { margin-left: 0.25rem !important; } .me-lg-2 { margin-left: 0.5rem !important; } .me-lg-3 { margin-left: 1rem !important; } .me-lg-4 { margin-left: 1.5rem !important; } .me-lg-5 { margin-left: 3rem !important; } .me-lg-auto { margin-left: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-right: 0 !important; } .ms-lg-1 { margin-right: 0.25rem !important; } .ms-lg-2 { margin-right: 0.5rem !important; } .ms-lg-3 { margin-right: 1rem !important; } .ms-lg-4 { margin-right: 1.5rem !important; } .ms-lg-5 { margin-right: 3rem !important; } .ms-lg-auto { margin-right: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-lg-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-lg-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-lg-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-lg-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-lg-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-left: 0 !important; } .pe-lg-1 { padding-left: 0.25rem !important; } .pe-lg-2 { padding-left: 0.5rem !important; } .pe-lg-3 { padding-left: 1rem !important; } .pe-lg-4 { padding-left: 1.5rem !important; } .pe-lg-5 { padding-left: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-right: 0 !important; } .ps-lg-1 { padding-right: 0.25rem !important; } .ps-lg-2 { padding-right: 0.5rem !important; } .ps-lg-3 { padding-right: 1rem !important; } .ps-lg-4 { padding-right: 1.5rem !important; } .ps-lg-5 { padding-right: 3rem !important; } .gap-lg-0 { gap: 0 !important; } .gap-lg-1 { gap: 0.25rem !important; } .gap-lg-2 { gap: 0.5rem !important; } .gap-lg-3 { gap: 1rem !important; } .gap-lg-4 { gap: 1.5rem !important; } .gap-lg-5 { gap: 3rem !important; } .text-lg-start { text-align: right !important; } .text-lg-end { text-align: left !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .float-xl-start { float: right !important; } .float-xl-end { float: left !important; } .float-xl-none { float: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-left: 0 !important; } .me-xl-1 { margin-left: 0.25rem !important; } .me-xl-2 { margin-left: 0.5rem !important; } .me-xl-3 { margin-left: 1rem !important; } .me-xl-4 { margin-left: 1.5rem !important; } .me-xl-5 { margin-left: 3rem !important; } .me-xl-auto { margin-left: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-right: 0 !important; } .ms-xl-1 { margin-right: 0.25rem !important; } .ms-xl-2 { margin-right: 0.5rem !important; } .ms-xl-3 { margin-right: 1rem !important; } .ms-xl-4 { margin-right: 1.5rem !important; } .ms-xl-5 { margin-right: 3rem !important; } .ms-xl-auto { margin-right: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-left: 0 !important; } .pe-xl-1 { padding-left: 0.25rem !important; } .pe-xl-2 { padding-left: 0.5rem !important; } .pe-xl-3 { padding-left: 1rem !important; } .pe-xl-4 { padding-left: 1.5rem !important; } .pe-xl-5 { padding-left: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-right: 0 !important; } .ps-xl-1 { padding-right: 0.25rem !important; } .ps-xl-2 { padding-right: 0.5rem !important; } .ps-xl-3 { padding-right: 1rem !important; } .ps-xl-4 { padding-right: 1.5rem !important; } .ps-xl-5 { padding-right: 3rem !important; } .gap-xl-0 { gap: 0 !important; } .gap-xl-1 { gap: 0.25rem !important; } .gap-xl-2 { gap: 0.5rem !important; } .gap-xl-3 { gap: 1rem !important; } .gap-xl-4 { gap: 1.5rem !important; } .gap-xl-5 { gap: 3rem !important; } .text-xl-start { text-align: right !important; } .text-xl-end { text-align: left !important; } .text-xl-center { text-align: center !important; } } @media (min-width: 1400px) { .float-xxl-start { float: right !important; } .float-xxl-end { float: left !important; } .float-xxl-none { float: none !important; } .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xxl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xxl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xxl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xxl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xxl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xxl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-left: 0 !important; } .me-xxl-1 { margin-left: 0.25rem !important; } .me-xxl-2 { margin-left: 0.5rem !important; } .me-xxl-3 { margin-left: 1rem !important; } .me-xxl-4 { margin-left: 1.5rem !important; } .me-xxl-5 { margin-left: 3rem !important; } .me-xxl-auto { margin-left: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-right: 0 !important; } .ms-xxl-1 { margin-right: 0.25rem !important; } .ms-xxl-2 { margin-right: 0.5rem !important; } .ms-xxl-3 { margin-right: 1rem !important; } .ms-xxl-4 { margin-right: 1.5rem !important; } .ms-xxl-5 { margin-right: 3rem !important; } .ms-xxl-auto { margin-right: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xxl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xxl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xxl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xxl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xxl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-left: 0 !important; } .pe-xxl-1 { padding-left: 0.25rem !important; } .pe-xxl-2 { padding-left: 0.5rem !important; } .pe-xxl-3 { padding-left: 1rem !important; } .pe-xxl-4 { padding-left: 1.5rem !important; } .pe-xxl-5 { padding-left: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-right: 0 !important; } .ps-xxl-1 { padding-right: 0.25rem !important; } .ps-xxl-2 { padding-right: 0.5rem !important; } .ps-xxl-3 { padding-right: 1rem !important; } .ps-xxl-4 { padding-right: 1.5rem !important; } .ps-xxl-5 { padding-right: 3rem !important; } .gap-xxl-0 { gap: 0 !important; } .gap-xxl-1 { gap: 0.25rem !important; } .gap-xxl-2 { gap: 0.5rem !important; } .gap-xxl-3 { gap: 1rem !important; } .gap-xxl-4 { gap: 1.5rem !important; } .gap-xxl-5 { gap: 3rem !important; } .text-xxl-start { text-align: right !important; } .text-xxl-end { text-align: left !important; } .text-xxl-center { text-align: center !important; } } @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; } .fs-2 { font-size: 2rem !important; } .fs-3 { font-size: 1.75rem !important; } .fs-4 { font-size: 1.5rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap-utilities.rtl.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap.css ================================================ @charset "UTF-8"; /*! * Bootstrap v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } *, *::before, *::after { box-sizing: border-box; } @media (prefers-reduced-motion: no-preference) { :root { scroll-behavior: smooth; } } body { margin: 0; font-family: var(--bs-body-font-family); font-size: var(--bs-body-font-size); font-weight: var(--bs-body-font-weight); line-height: var(--bs-body-line-height); color: var(--bs-body-color); text-align: var(--bs-body-text-align); background-color: var(--bs-body-bg); -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } hr { margin: 1rem 0; color: inherit; border: 0; border-top: 1px solid; opacity: 0.25; } h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; } h1, .h1 { font-size: calc(1.375rem + 1.5vw); } @media (min-width: 1200px) { h1, .h1 { font-size: 2.5rem; } } h2, .h2 { font-size: calc(1.325rem + 0.9vw); } @media (min-width: 1200px) { h2, .h2 { font-size: 2rem; } } h3, .h3 { font-size: calc(1.3rem + 0.6vw); } @media (min-width: 1200px) { h3, .h3 { font-size: 1.75rem; } } h4, .h4 { font-size: calc(1.275rem + 0.3vw); } @media (min-width: 1200px) { h4, .h4 { font-size: 1.5rem; } } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title] { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul { padding-left: 2rem; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: 0.5rem; margin-left: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small, .small { font-size: 0.875em; } mark, .mark { padding: 0.1875em; background-color: var(--bs-highlight-bg); } sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } a { color: var(--bs-link-color); text-decoration: underline; } a:hover { color: var(--bs-link-hover-color); } a:not([href]):not([class]), a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: var(--bs-font-monospace); font-size: 1em; } pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; } pre code { font-size: inherit; color: inherit; word-break: normal; } code { font-size: 0.875em; color: var(--bs-code-color); word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.1875rem 0.375rem; font-size: 0.875em; color: var(--bs-body-bg); background-color: var(--bs-body-color); border-radius: 0.25rem; } kbd kbd { padding: 0; font-size: 1em; } figure { margin: 0 0 1rem; } img, svg { vertical-align: middle; } table { caption-side: bottom; border-collapse: collapse; } caption { padding-top: 0.5rem; padding-bottom: 0.5rem; color: #6c757d; text-align: left; } th { text-align: inherit; text-align: -webkit-match-parent; } thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; } label { display: inline-block; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, select { text-transform: none; } [role=button] { cursor: pointer; } select { word-wrap: normal; } select:disabled { opacity: 1; } [list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { display: none !important; } button, [type=button], [type=reset], [type=submit] { -webkit-appearance: button; } button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } ::-moz-focus-inner { padding: 0; border-style: none; } textarea { resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { float: left; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: calc(1.275rem + 0.3vw); line-height: inherit; } @media (min-width: 1200px) { legend { font-size: 1.5rem; } } legend + * { clear: left; } ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-year-field { padding: 0; } ::-webkit-inner-spin-button { height: auto; } [type=search] { outline-offset: -2px; -webkit-appearance: textfield; } /* rtl:raw: [type="tel"], [type="url"], [type="email"], [type="number"] { direction: ltr; } */ ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-color-swatch-wrapper { padding: 0; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } ::file-selector-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } iframe { border: 0; } summary { display: list-item; cursor: pointer; } progress { vertical-align: baseline; } [hidden] { display: none !important; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: calc(1.625rem + 4.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-1 { font-size: 5rem; } } .display-2 { font-size: calc(1.575rem + 3.9vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-2 { font-size: 4.5rem; } } .display-3 { font-size: calc(1.525rem + 3.3vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-3 { font-size: 4rem; } } .display-4 { font-size: calc(1.475rem + 2.7vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-4 { font-size: 3.5rem; } } .display-5 { font-size: calc(1.425rem + 2.1vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-5 { font-size: 3rem; } } .display-6 { font-size: calc(1.375rem + 1.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-6 { font-size: 2.5rem; } } .list-unstyled { padding-left: 0; list-style: none; } .list-inline { padding-left: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-right: 0.5rem; } .initialism { font-size: 0.875em; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote > :last-child { margin-bottom: 0; } .blockquote-footer { margin-top: -1rem; margin-bottom: 1rem; font-size: 0.875em; color: #6c757d; } .blockquote-footer::before { content: "— "; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid var(--bs-border-color); border-radius: 0.375rem; max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 0.875em; color: #6c757d; } .container, .container-fluid, .container-xxl, .container-xl, .container-lg, .container-md, .container-sm { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; width: 100%; padding-right: calc(var(--bs-gutter-x) * 0.5); padding-left: calc(var(--bs-gutter-x) * 0.5); margin-right: auto; margin-left: auto; } @media (min-width: 576px) { .container-sm, .container { max-width: 540px; } } @media (min-width: 768px) { .container-md, .container-sm, .container { max-width: 720px; } } @media (min-width: 992px) { .container-lg, .container-md, .container-sm, .container { max-width: 960px; } } @media (min-width: 1200px) { .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1140px; } } @media (min-width: 1400px) { .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1320px; } } .row { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; display: flex; flex-wrap: wrap; margin-top: calc(-1 * var(--bs-gutter-y)); margin-right: calc(-0.5 * var(--bs-gutter-x)); margin-left: calc(-0.5 * var(--bs-gutter-x)); } .row > * { flex-shrink: 0; width: 100%; max-width: 100%; padding-right: calc(var(--bs-gutter-x) * 0.5); padding-left: calc(var(--bs-gutter-x) * 0.5); margin-top: var(--bs-gutter-y); } .col { flex: 1 0 0%; } .row-cols-auto > * { flex: 0 0 auto; width: auto; } .row-cols-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-auto { flex: 0 0 auto; width: auto; } .col-1 { flex: 0 0 auto; width: 8.33333333%; } .col-2 { flex: 0 0 auto; width: 16.66666667%; } .col-3 { flex: 0 0 auto; width: 25%; } .col-4 { flex: 0 0 auto; width: 33.33333333%; } .col-5 { flex: 0 0 auto; width: 41.66666667%; } .col-6 { flex: 0 0 auto; width: 50%; } .col-7 { flex: 0 0 auto; width: 58.33333333%; } .col-8 { flex: 0 0 auto; width: 66.66666667%; } .col-9 { flex: 0 0 auto; width: 75%; } .col-10 { flex: 0 0 auto; width: 83.33333333%; } .col-11 { flex: 0 0 auto; width: 91.66666667%; } .col-12 { flex: 0 0 auto; width: 100%; } .offset-1 { margin-left: 8.33333333%; } .offset-2 { margin-left: 16.66666667%; } .offset-3 { margin-left: 25%; } .offset-4 { margin-left: 33.33333333%; } .offset-5 { margin-left: 41.66666667%; } .offset-6 { margin-left: 50%; } .offset-7 { margin-left: 58.33333333%; } .offset-8 { margin-left: 66.66666667%; } .offset-9 { margin-left: 75%; } .offset-10 { margin-left: 83.33333333%; } .offset-11 { margin-left: 91.66666667%; } .g-0, .gx-0 { --bs-gutter-x: 0; } .g-0, .gy-0 { --bs-gutter-y: 0; } .g-1, .gx-1 { --bs-gutter-x: 0.25rem; } .g-1, .gy-1 { --bs-gutter-y: 0.25rem; } .g-2, .gx-2 { --bs-gutter-x: 0.5rem; } .g-2, .gy-2 { --bs-gutter-y: 0.5rem; } .g-3, .gx-3 { --bs-gutter-x: 1rem; } .g-3, .gy-3 { --bs-gutter-y: 1rem; } .g-4, .gx-4 { --bs-gutter-x: 1.5rem; } .g-4, .gy-4 { --bs-gutter-y: 1.5rem; } .g-5, .gx-5 { --bs-gutter-x: 3rem; } .g-5, .gy-5 { --bs-gutter-y: 3rem; } @media (min-width: 576px) { .col-sm { flex: 1 0 0%; } .row-cols-sm-auto > * { flex: 0 0 auto; width: auto; } .row-cols-sm-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-sm-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-sm-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-sm-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-sm-auto { flex: 0 0 auto; width: auto; } .col-sm-1 { flex: 0 0 auto; width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; width: 25%; } .col-sm-4 { flex: 0 0 auto; width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; width: 50%; } .col-sm-7 { flex: 0 0 auto; width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; width: 75%; } .col-sm-10 { flex: 0 0 auto; width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; width: 100%; } .offset-sm-0 { margin-left: 0; } .offset-sm-1 { margin-left: 8.33333333%; } .offset-sm-2 { margin-left: 16.66666667%; } .offset-sm-3 { margin-left: 25%; } .offset-sm-4 { margin-left: 33.33333333%; } .offset-sm-5 { margin-left: 41.66666667%; } .offset-sm-6 { margin-left: 50%; } .offset-sm-7 { margin-left: 58.33333333%; } .offset-sm-8 { margin-left: 66.66666667%; } .offset-sm-9 { margin-left: 75%; } .offset-sm-10 { margin-left: 83.33333333%; } .offset-sm-11 { margin-left: 91.66666667%; } .g-sm-0, .gx-sm-0 { --bs-gutter-x: 0; } .g-sm-0, .gy-sm-0 { --bs-gutter-y: 0; } .g-sm-1, .gx-sm-1 { --bs-gutter-x: 0.25rem; } .g-sm-1, .gy-sm-1 { --bs-gutter-y: 0.25rem; } .g-sm-2, .gx-sm-2 { --bs-gutter-x: 0.5rem; } .g-sm-2, .gy-sm-2 { --bs-gutter-y: 0.5rem; } .g-sm-3, .gx-sm-3 { --bs-gutter-x: 1rem; } .g-sm-3, .gy-sm-3 { --bs-gutter-y: 1rem; } .g-sm-4, .gx-sm-4 { --bs-gutter-x: 1.5rem; } .g-sm-4, .gy-sm-4 { --bs-gutter-y: 1.5rem; } .g-sm-5, .gx-sm-5 { --bs-gutter-x: 3rem; } .g-sm-5, .gy-sm-5 { --bs-gutter-y: 3rem; } } @media (min-width: 768px) { .col-md { flex: 1 0 0%; } .row-cols-md-auto > * { flex: 0 0 auto; width: auto; } .row-cols-md-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-md-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-md-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-md-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-md-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-md-auto { flex: 0 0 auto; width: auto; } .col-md-1 { flex: 0 0 auto; width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; width: 25%; } .col-md-4 { flex: 0 0 auto; width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; width: 50%; } .col-md-7 { flex: 0 0 auto; width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; width: 75%; } .col-md-10 { flex: 0 0 auto; width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; width: 100%; } .offset-md-0 { margin-left: 0; } .offset-md-1 { margin-left: 8.33333333%; } .offset-md-2 { margin-left: 16.66666667%; } .offset-md-3 { margin-left: 25%; } .offset-md-4 { margin-left: 33.33333333%; } .offset-md-5 { margin-left: 41.66666667%; } .offset-md-6 { margin-left: 50%; } .offset-md-7 { margin-left: 58.33333333%; } .offset-md-8 { margin-left: 66.66666667%; } .offset-md-9 { margin-left: 75%; } .offset-md-10 { margin-left: 83.33333333%; } .offset-md-11 { margin-left: 91.66666667%; } .g-md-0, .gx-md-0 { --bs-gutter-x: 0; } .g-md-0, .gy-md-0 { --bs-gutter-y: 0; } .g-md-1, .gx-md-1 { --bs-gutter-x: 0.25rem; } .g-md-1, .gy-md-1 { --bs-gutter-y: 0.25rem; } .g-md-2, .gx-md-2 { --bs-gutter-x: 0.5rem; } .g-md-2, .gy-md-2 { --bs-gutter-y: 0.5rem; } .g-md-3, .gx-md-3 { --bs-gutter-x: 1rem; } .g-md-3, .gy-md-3 { --bs-gutter-y: 1rem; } .g-md-4, .gx-md-4 { --bs-gutter-x: 1.5rem; } .g-md-4, .gy-md-4 { --bs-gutter-y: 1.5rem; } .g-md-5, .gx-md-5 { --bs-gutter-x: 3rem; } .g-md-5, .gy-md-5 { --bs-gutter-y: 3rem; } } @media (min-width: 992px) { .col-lg { flex: 1 0 0%; } .row-cols-lg-auto > * { flex: 0 0 auto; width: auto; } .row-cols-lg-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-lg-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-lg-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-lg-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-lg-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-lg-auto { flex: 0 0 auto; width: auto; } .col-lg-1 { flex: 0 0 auto; width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; width: 25%; } .col-lg-4 { flex: 0 0 auto; width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; width: 50%; } .col-lg-7 { flex: 0 0 auto; width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; width: 75%; } .col-lg-10 { flex: 0 0 auto; width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; width: 100%; } .offset-lg-0 { margin-left: 0; } .offset-lg-1 { margin-left: 8.33333333%; } .offset-lg-2 { margin-left: 16.66666667%; } .offset-lg-3 { margin-left: 25%; } .offset-lg-4 { margin-left: 33.33333333%; } .offset-lg-5 { margin-left: 41.66666667%; } .offset-lg-6 { margin-left: 50%; } .offset-lg-7 { margin-left: 58.33333333%; } .offset-lg-8 { margin-left: 66.66666667%; } .offset-lg-9 { margin-left: 75%; } .offset-lg-10 { margin-left: 83.33333333%; } .offset-lg-11 { margin-left: 91.66666667%; } .g-lg-0, .gx-lg-0 { --bs-gutter-x: 0; } .g-lg-0, .gy-lg-0 { --bs-gutter-y: 0; } .g-lg-1, .gx-lg-1 { --bs-gutter-x: 0.25rem; } .g-lg-1, .gy-lg-1 { --bs-gutter-y: 0.25rem; } .g-lg-2, .gx-lg-2 { --bs-gutter-x: 0.5rem; } .g-lg-2, .gy-lg-2 { --bs-gutter-y: 0.5rem; } .g-lg-3, .gx-lg-3 { --bs-gutter-x: 1rem; } .g-lg-3, .gy-lg-3 { --bs-gutter-y: 1rem; } .g-lg-4, .gx-lg-4 { --bs-gutter-x: 1.5rem; } .g-lg-4, .gy-lg-4 { --bs-gutter-y: 1.5rem; } .g-lg-5, .gx-lg-5 { --bs-gutter-x: 3rem; } .g-lg-5, .gy-lg-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; } .row-cols-xl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xl-auto { flex: 0 0 auto; width: auto; } .col-xl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; width: 25%; } .col-xl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; width: 50%; } .col-xl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; width: 75%; } .col-xl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; width: 100%; } .offset-xl-0 { margin-left: 0; } .offset-xl-1 { margin-left: 8.33333333%; } .offset-xl-2 { margin-left: 16.66666667%; } .offset-xl-3 { margin-left: 25%; } .offset-xl-4 { margin-left: 33.33333333%; } .offset-xl-5 { margin-left: 41.66666667%; } .offset-xl-6 { margin-left: 50%; } .offset-xl-7 { margin-left: 58.33333333%; } .offset-xl-8 { margin-left: 66.66666667%; } .offset-xl-9 { margin-left: 75%; } .offset-xl-10 { margin-left: 83.33333333%; } .offset-xl-11 { margin-left: 91.66666667%; } .g-xl-0, .gx-xl-0 { --bs-gutter-x: 0; } .g-xl-0, .gy-xl-0 { --bs-gutter-y: 0; } .g-xl-1, .gx-xl-1 { --bs-gutter-x: 0.25rem; } .g-xl-1, .gy-xl-1 { --bs-gutter-y: 0.25rem; } .g-xl-2, .gx-xl-2 { --bs-gutter-x: 0.5rem; } .g-xl-2, .gy-xl-2 { --bs-gutter-y: 0.5rem; } .g-xl-3, .gx-xl-3 { --bs-gutter-x: 1rem; } .g-xl-3, .gy-xl-3 { --bs-gutter-y: 1rem; } .g-xl-4, .gx-xl-4 { --bs-gutter-x: 1.5rem; } .g-xl-4, .gy-xl-4 { --bs-gutter-y: 1.5rem; } .g-xl-5, .gx-xl-5 { --bs-gutter-x: 3rem; } .g-xl-5, .gy-xl-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; } .row-cols-xxl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xxl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xxl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xxl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xxl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xxl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xxl-auto { flex: 0 0 auto; width: auto; } .col-xxl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; width: 25%; } .col-xxl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; width: 50%; } .col-xxl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; width: 75%; } .col-xxl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; width: 100%; } .offset-xxl-0 { margin-left: 0; } .offset-xxl-1 { margin-left: 8.33333333%; } .offset-xxl-2 { margin-left: 16.66666667%; } .offset-xxl-3 { margin-left: 25%; } .offset-xxl-4 { margin-left: 33.33333333%; } .offset-xxl-5 { margin-left: 41.66666667%; } .offset-xxl-6 { margin-left: 50%; } .offset-xxl-7 { margin-left: 58.33333333%; } .offset-xxl-8 { margin-left: 66.66666667%; } .offset-xxl-9 { margin-left: 75%; } .offset-xxl-10 { margin-left: 83.33333333%; } .offset-xxl-11 { margin-left: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { --bs-gutter-x: 0; } .g-xxl-0, .gy-xxl-0 { --bs-gutter-y: 0; } .g-xxl-1, .gx-xxl-1 { --bs-gutter-x: 0.25rem; } .g-xxl-1, .gy-xxl-1 { --bs-gutter-y: 0.25rem; } .g-xxl-2, .gx-xxl-2 { --bs-gutter-x: 0.5rem; } .g-xxl-2, .gy-xxl-2 { --bs-gutter-y: 0.5rem; } .g-xxl-3, .gx-xxl-3 { --bs-gutter-x: 1rem; } .g-xxl-3, .gy-xxl-3 { --bs-gutter-y: 1rem; } .g-xxl-4, .gx-xxl-4 { --bs-gutter-x: 1.5rem; } .g-xxl-4, .gy-xxl-4 { --bs-gutter-y: 1.5rem; } .g-xxl-5, .gx-xxl-5 { --bs-gutter-x: 3rem; } .g-xxl-5, .gy-xxl-5 { --bs-gutter-y: 3rem; } } .table { --bs-table-color: var(--bs-body-color); --bs-table-bg: transparent; --bs-table-border-color: var(--bs-border-color); --bs-table-accent-bg: transparent; --bs-table-striped-color: var(--bs-body-color); --bs-table-striped-bg: rgba(0, 0, 0, 0.05); --bs-table-active-color: var(--bs-body-color); --bs-table-active-bg: rgba(0, 0, 0, 0.1); --bs-table-hover-color: var(--bs-body-color); --bs-table-hover-bg: rgba(0, 0, 0, 0.075); width: 100%; margin-bottom: 1rem; color: var(--bs-table-color); vertical-align: top; border-color: var(--bs-table-border-color); } .table > :not(caption) > * > * { padding: 0.5rem 0.5rem; background-color: var(--bs-table-bg); border-bottom-width: 1px; box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); } .table > tbody { vertical-align: inherit; } .table > thead { vertical-align: bottom; } .table-group-divider { border-top: 2px solid currentcolor; } .caption-top { caption-side: top; } .table-sm > :not(caption) > * > * { padding: 0.25rem 0.25rem; } .table-bordered > :not(caption) > * { border-width: 1px 0; } .table-bordered > :not(caption) > * > * { border-width: 0 1px; } .table-borderless > :not(caption) > * > * { border-bottom-width: 0; } .table-borderless > :not(:first-child) { border-top-width: 0; } .table-striped > tbody > tr:nth-of-type(odd) > * { --bs-table-accent-bg: var(--bs-table-striped-bg); color: var(--bs-table-striped-color); } .table-striped-columns > :not(caption) > tr > :nth-child(even) { --bs-table-accent-bg: var(--bs-table-striped-bg); color: var(--bs-table-striped-color); } .table-active { --bs-table-accent-bg: var(--bs-table-active-bg); color: var(--bs-table-active-color); } .table-hover > tbody > tr:hover > * { --bs-table-accent-bg: var(--bs-table-hover-bg); color: var(--bs-table-hover-color); } .table-primary { --bs-table-color: #000; --bs-table-bg: #cfe2ff; --bs-table-border-color: #bacbe6; --bs-table-striped-bg: #c5d7f2; --bs-table-striped-color: #000; --bs-table-active-bg: #bacbe6; --bs-table-active-color: #000; --bs-table-hover-bg: #bfd1ec; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-secondary { --bs-table-color: #000; --bs-table-bg: #e2e3e5; --bs-table-border-color: #cbccce; --bs-table-striped-bg: #d7d8da; --bs-table-striped-color: #000; --bs-table-active-bg: #cbccce; --bs-table-active-color: #000; --bs-table-hover-bg: #d1d2d4; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-success { --bs-table-color: #000; --bs-table-bg: #d1e7dd; --bs-table-border-color: #bcd0c7; --bs-table-striped-bg: #c7dbd2; --bs-table-striped-color: #000; --bs-table-active-bg: #bcd0c7; --bs-table-active-color: #000; --bs-table-hover-bg: #c1d6cc; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-info { --bs-table-color: #000; --bs-table-bg: #cff4fc; --bs-table-border-color: #badce3; --bs-table-striped-bg: #c5e8ef; --bs-table-striped-color: #000; --bs-table-active-bg: #badce3; --bs-table-active-color: #000; --bs-table-hover-bg: #bfe2e9; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-warning { --bs-table-color: #000; --bs-table-bg: #fff3cd; --bs-table-border-color: #e6dbb9; --bs-table-striped-bg: #f2e7c3; --bs-table-striped-color: #000; --bs-table-active-bg: #e6dbb9; --bs-table-active-color: #000; --bs-table-hover-bg: #ece1be; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-danger { --bs-table-color: #000; --bs-table-bg: #f8d7da; --bs-table-border-color: #dfc2c4; --bs-table-striped-bg: #eccccf; --bs-table-striped-color: #000; --bs-table-active-bg: #dfc2c4; --bs-table-active-color: #000; --bs-table-hover-bg: #e5c7ca; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-light { --bs-table-color: #000; --bs-table-bg: #f8f9fa; --bs-table-border-color: #dfe0e1; --bs-table-striped-bg: #ecedee; --bs-table-striped-color: #000; --bs-table-active-bg: #dfe0e1; --bs-table-active-color: #000; --bs-table-hover-bg: #e5e6e7; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-dark { --bs-table-color: #fff; --bs-table-bg: #212529; --bs-table-border-color: #373b3e; --bs-table-striped-bg: #2c3034; --bs-table-striped-color: #fff; --bs-table-active-bg: #373b3e; --bs-table-active-color: #fff; --bs-table-hover-bg: #323539; --bs-table-hover-color: #fff; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; } @media (max-width: 575.98px) { .table-responsive-sm { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 767.98px) { .table-responsive-md { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 991.98px) { .table-responsive-lg { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1199.98px) { .table-responsive-xl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1399.98px) { .table-responsive-xxl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } .form-label { margin-bottom: 0.5rem; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; } .form-text { margin-top: 0.25rem; font-size: 0.875em; color: #6c757d; } .form-control { display: block; width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; -webkit-appearance: none; -moz-appearance: none; appearance: none; border-radius: 0.375rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control[type=file] { overflow: hidden; } .form-control[type=file]:not(:disabled):not([readonly]) { cursor: pointer; } .form-control:focus { color: #212529; background-color: #fff; border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-control::-webkit-date-and-time-value { height: 1.5em; } .form-control::-moz-placeholder { color: #6c757d; opacity: 1; } .form-control::placeholder { color: #6c757d; opacity: 1; } .form-control:disabled { background-color: #e9ecef; opacity: 1; } .form-control::-webkit-file-upload-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .form-control::file-selector-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control::-webkit-file-upload-button { -webkit-transition: none; transition: none; } .form-control::file-selector-button { transition: none; } } .form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { background-color: #dde0e3; } .form-control:hover:not(:disabled):not([readonly])::file-selector-button { background-color: #dde0e3; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext:focus { outline: 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-right: 0; padding-left: 0; } .form-control-sm { min-height: calc(1.5em + 0.5rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .form-control-sm::-webkit-file-upload-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-sm::file-selector-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-lg { min-height: calc(1.5em + 1rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .form-control-lg::-webkit-file-upload-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } .form-control-lg::file-selector-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } textarea.form-control { min-height: calc(1.5em + 0.75rem + 2px); } textarea.form-control-sm { min-height: calc(1.5em + 0.5rem + 2px); } textarea.form-control-lg { min-height: calc(1.5em + 1rem + 2px); } .form-control-color { width: 3rem; height: calc(1.5em + 0.75rem + 2px); padding: 0.375rem; } .form-control-color:not(:disabled):not([readonly]) { cursor: pointer; } .form-control-color::-moz-color-swatch { border: 0 !important; border-radius: 0.375rem; } .form-control-color::-webkit-color-swatch { border-radius: 0.375rem; } .form-control-color.form-control-sm { height: calc(1.5em + 0.5rem + 2px); } .form-control-color.form-control-lg { height: calc(1.5em + 1rem + 2px); } .form-select { display: block; width: 100%; padding: 0.375rem 2.25rem 0.375rem 0.75rem; -moz-padding-start: calc(0.75rem - 3px); font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right 0.75rem center; background-size: 16px 12px; border: 1px solid #ced4da; border-radius: 0.375rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-select { transition: none; } } .form-select:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-select[multiple], .form-select[size]:not([size="1"]) { padding-right: 0.75rem; background-image: none; } .form-select:disabled { background-color: #e9ecef; } .form-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #212529; } .form-select-sm { padding-top: 0.25rem; padding-bottom: 0.25rem; padding-left: 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .form-select-lg { padding-top: 0.5rem; padding-bottom: 0.5rem; padding-left: 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .form-check { display: block; min-height: 1.5rem; padding-left: 1.5em; margin-bottom: 0.125rem; } .form-check .form-check-input { float: left; margin-left: -1.5em; } .form-check-reverse { padding-right: 1.5em; padding-left: 0; text-align: right; } .form-check-reverse .form-check-input { float: right; margin-right: -1.5em; margin-left: 0; } .form-check-input { width: 1em; height: 1em; margin-top: 0.25em; vertical-align: top; background-color: #fff; background-repeat: no-repeat; background-position: center; background-size: contain; border: 1px solid rgba(0, 0, 0, 0.25); -webkit-appearance: none; -moz-appearance: none; appearance: none; -webkit-print-color-adjust: exact; color-adjust: exact; print-color-adjust: exact; } .form-check-input[type=checkbox] { border-radius: 0.25em; } .form-check-input[type=radio] { border-radius: 50%; } .form-check-input:active { filter: brightness(90%); } .form-check-input:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-check-input:checked { background-color: #0d6efd; border-color: #0d6efd; } .form-check-input:checked[type=checkbox] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); } .form-check-input:checked[type=radio] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); } .form-check-input[type=checkbox]:indeterminate { background-color: #0d6efd; border-color: #0d6efd; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); } .form-check-input:disabled { pointer-events: none; filter: none; opacity: 0.5; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { cursor: default; opacity: 0.5; } .form-switch { padding-left: 2.5em; } .form-switch .form-check-input { width: 2em; margin-left: -2.5em; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); background-position: left center; border-radius: 2em; transition: background-position 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-switch .form-check-input { transition: none; } } .form-switch .form-check-input:focus { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); } .form-switch .form-check-input:checked { background-position: right center; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } .form-switch.form-check-reverse { padding-right: 2.5em; padding-left: 0; } .form-switch.form-check-reverse .form-check-input { margin-right: -2.5em; margin-left: 0; } .form-check-inline { display: inline-block; margin-right: 1rem; } .btn-check { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .btn-check[disabled] + .btn, .btn-check:disabled + .btn { pointer-events: none; filter: none; opacity: 0.65; } .form-range { width: 100%; height: 1.5rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .form-range:focus { outline: 0; } .form-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range::-moz-focus-outer { border: 0; } .form-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .form-range::-webkit-slider-thumb:active { background-color: #b6d4fe; } .form-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .form-range::-moz-range-thumb:active { background-color: #b6d4fe; } .form-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range:disabled { pointer-events: none; } .form-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .form-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .form-floating { position: relative; } .form-floating > .form-control, .form-floating > .form-control-plaintext, .form-floating > .form-select { height: calc(3.5rem + 2px); line-height: 1.25; } .form-floating > label { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 1rem 0.75rem; overflow: hidden; text-align: start; text-overflow: ellipsis; white-space: nowrap; pointer-events: none; border: 1px solid transparent; transform-origin: 0 0; transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-floating > label { transition: none; } } .form-floating > .form-control, .form-floating > .form-control-plaintext { padding: 1rem 0.75rem; } .form-floating > .form-control::-moz-placeholder, .form-floating > .form-control-plaintext::-moz-placeholder { color: transparent; } .form-floating > .form-control::placeholder, .form-floating > .form-control-plaintext::placeholder { color: transparent; } .form-floating > .form-control:not(:-moz-placeholder-shown), .form-floating > .form-control-plaintext:not(:-moz-placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown), .form-floating > .form-control-plaintext:focus, .form-floating > .form-control-plaintext:not(:placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:-webkit-autofill, .form-floating > .form-control-plaintext:-webkit-autofill { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-select { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .form-floating > .form-control:focus ~ label, .form-floating > .form-control:not(:placeholder-shown) ~ label, .form-floating > .form-control-plaintext ~ label, .form-floating > .form-select ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .form-floating > .form-control:-webkit-autofill ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(0.15rem); } .form-floating > .form-control-plaintext ~ label { border-width: 1px 0; } .input-group { position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-select, .input-group > .form-floating { position: relative; flex: 1 1 auto; width: 1%; min-width: 0; } .input-group > .form-control:focus, .input-group > .form-select:focus, .input-group > .form-floating:focus-within { z-index: 5; } .input-group .btn { position: relative; z-index: 2; } .input-group .btn:focus { z-index: 5; } .input-group-text { display: flex; align-items: center; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.375rem; } .input-group-lg > .form-control, .input-group-lg > .form-select, .input-group-lg > .input-group-text, .input-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .input-group-sm > .form-control, .input-group-sm > .form-select, .input-group-sm > .input-group-text, .input-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .input-group-lg > .form-select, .input-group-sm > .form-select { padding-right: 3rem; } .input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), .input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3), .input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-control, .input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-select { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), .input-group.has-validation > .dropdown-toggle:nth-last-child(n+4), .input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-control, .input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-select { border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { margin-left: -1px; border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group > .form-floating:not(:first-child) > .form-control, .input-group > .form-floating:not(:first-child) > .form-select { border-top-left-radius: 0; border-bottom-left-radius: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #198754; } .valid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(25, 135, 84, 0.9); border-radius: 0.375rem; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #198754; padding-right: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-right: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .form-select:valid, .form-select.is-valid { border-color: #198754; } .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { padding-right: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-position: right 0.75rem center, center right 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:valid:focus, .form-select.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-control-color:valid, .form-control-color.is-valid { width: calc(3rem + calc(1.5em + 0.75rem)); } .was-validated .form-check-input:valid, .form-check-input.is-valid { border-color: #198754; } .was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { background-color: #198754; } .was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #198754; } .form-check-inline .form-check-input ~ .valid-feedback { margin-left: 0.5em; } .was-validated .input-group > .form-control:not(:focus):valid, .input-group > .form-control:not(:focus).is-valid, .was-validated .input-group > .form-select:not(:focus):valid, .input-group > .form-select:not(:focus).is-valid, .was-validated .input-group > .form-floating:not(:focus-within):valid, .input-group > .form-floating:not(:focus-within).is-valid { z-index: 3; } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.375rem; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-right: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: right calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-right: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); } .was-validated .form-select:invalid, .form-select.is-invalid { border-color: #dc3545; } .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { padding-right: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-position: right 0.75rem center, center right 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-control-color:invalid, .form-control-color.is-invalid { width: calc(3rem + calc(1.5em + 0.75rem)); } .was-validated .form-check-input:invalid, .form-check-input.is-invalid { border-color: #dc3545; } .was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { background-color: #dc3545; } .was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .form-check-inline .form-check-input ~ .invalid-feedback { margin-left: 0.5em; } .was-validated .input-group > .form-control:not(:focus):invalid, .input-group > .form-control:not(:focus).is-invalid, .was-validated .input-group > .form-select:not(:focus):invalid, .input-group > .form-select:not(:focus).is-invalid, .was-validated .input-group > .form-floating:not(:focus-within):invalid, .input-group > .form-floating:not(:focus-within).is-invalid { z-index: 4; } .btn { --bs-btn-padding-x: 0.75rem; --bs-btn-padding-y: 0.375rem; --bs-btn-font-family: ; --bs-btn-font-size: 1rem; --bs-btn-font-weight: 400; --bs-btn-line-height: 1.5; --bs-btn-color: #212529; --bs-btn-bg: transparent; --bs-btn-border-width: 1px; --bs-btn-border-color: transparent; --bs-btn-border-radius: 0.375rem; --bs-btn-hover-border-color: transparent; --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); --bs-btn-disabled-opacity: 0.65; --bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5); display: inline-block; padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); font-family: var(--bs-btn-font-family); font-size: var(--bs-btn-font-size); font-weight: var(--bs-btn-font-weight); line-height: var(--bs-btn-line-height); color: var(--bs-btn-color); text-align: center; text-decoration: none; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; user-select: none; border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); border-radius: var(--bs-btn-border-radius); background-color: var(--bs-btn-bg); transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: var(--bs-btn-hover-color); background-color: var(--bs-btn-hover-bg); border-color: var(--bs-btn-hover-border-color); } .btn-check + .btn:hover { color: var(--bs-btn-color); background-color: var(--bs-btn-bg); border-color: var(--bs-btn-border-color); } .btn:focus-visible { color: var(--bs-btn-hover-color); background-color: var(--bs-btn-hover-bg); border-color: var(--bs-btn-hover-border-color); outline: 0; box-shadow: var(--bs-btn-focus-box-shadow); } .btn-check:focus-visible + .btn { border-color: var(--bs-btn-hover-border-color); outline: 0; box-shadow: var(--bs-btn-focus-box-shadow); } .btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { color: var(--bs-btn-active-color); background-color: var(--bs-btn-active-bg); border-color: var(--bs-btn-active-border-color); } .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { box-shadow: var(--bs-btn-focus-box-shadow); } .btn:disabled, .btn.disabled, fieldset:disabled .btn { color: var(--bs-btn-disabled-color); pointer-events: none; background-color: var(--bs-btn-disabled-bg); border-color: var(--bs-btn-disabled-border-color); opacity: var(--bs-btn-disabled-opacity); } .btn-primary { --bs-btn-color: #fff; --bs-btn-bg: #0d6efd; --bs-btn-border-color: #0d6efd; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #0b5ed7; --bs-btn-hover-border-color: #0a58ca; --bs-btn-focus-shadow-rgb: 49, 132, 253; --bs-btn-active-color: #fff; --bs-btn-active-bg: #0a58ca; --bs-btn-active-border-color: #0a53be; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #0d6efd; --bs-btn-disabled-border-color: #0d6efd; } .btn-secondary { --bs-btn-color: #fff; --bs-btn-bg: #6c757d; --bs-btn-border-color: #6c757d; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #5c636a; --bs-btn-hover-border-color: #565e64; --bs-btn-focus-shadow-rgb: 130, 138, 145; --bs-btn-active-color: #fff; --bs-btn-active-bg: #565e64; --bs-btn-active-border-color: #51585e; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #6c757d; --bs-btn-disabled-border-color: #6c757d; } .btn-success { --bs-btn-color: #fff; --bs-btn-bg: #198754; --bs-btn-border-color: #198754; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #157347; --bs-btn-hover-border-color: #146c43; --bs-btn-focus-shadow-rgb: 60, 153, 110; --bs-btn-active-color: #fff; --bs-btn-active-bg: #146c43; --bs-btn-active-border-color: #13653f; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #198754; --bs-btn-disabled-border-color: #198754; } .btn-info { --bs-btn-color: #000; --bs-btn-bg: #0dcaf0; --bs-btn-border-color: #0dcaf0; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #31d2f2; --bs-btn-hover-border-color: #25cff2; --bs-btn-focus-shadow-rgb: 11, 172, 204; --bs-btn-active-color: #000; --bs-btn-active-bg: #3dd5f3; --bs-btn-active-border-color: #25cff2; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #0dcaf0; --bs-btn-disabled-border-color: #0dcaf0; } .btn-warning { --bs-btn-color: #000; --bs-btn-bg: #ffc107; --bs-btn-border-color: #ffc107; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #ffca2c; --bs-btn-hover-border-color: #ffc720; --bs-btn-focus-shadow-rgb: 217, 164, 6; --bs-btn-active-color: #000; --bs-btn-active-bg: #ffcd39; --bs-btn-active-border-color: #ffc720; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #ffc107; --bs-btn-disabled-border-color: #ffc107; } .btn-danger { --bs-btn-color: #fff; --bs-btn-bg: #dc3545; --bs-btn-border-color: #dc3545; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #bb2d3b; --bs-btn-hover-border-color: #b02a37; --bs-btn-focus-shadow-rgb: 225, 83, 97; --bs-btn-active-color: #fff; --bs-btn-active-bg: #b02a37; --bs-btn-active-border-color: #a52834; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #dc3545; --bs-btn-disabled-border-color: #dc3545; } .btn-light { --bs-btn-color: #000; --bs-btn-bg: #f8f9fa; --bs-btn-border-color: #f8f9fa; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #d3d4d5; --bs-btn-hover-border-color: #c6c7c8; --bs-btn-focus-shadow-rgb: 211, 212, 213; --bs-btn-active-color: #000; --bs-btn-active-bg: #c6c7c8; --bs-btn-active-border-color: #babbbc; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #f8f9fa; --bs-btn-disabled-border-color: #f8f9fa; } .btn-dark { --bs-btn-color: #fff; --bs-btn-bg: #212529; --bs-btn-border-color: #212529; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #424649; --bs-btn-hover-border-color: #373b3e; --bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-active-color: #fff; --bs-btn-active-bg: #4d5154; --bs-btn-active-border-color: #373b3e; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #212529; --bs-btn-disabled-border-color: #212529; } .btn-outline-primary { --bs-btn-color: #0d6efd; --bs-btn-border-color: #0d6efd; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #0d6efd; --bs-btn-hover-border-color: #0d6efd; --bs-btn-focus-shadow-rgb: 13, 110, 253; --bs-btn-active-color: #fff; --bs-btn-active-bg: #0d6efd; --bs-btn-active-border-color: #0d6efd; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #0d6efd; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #0d6efd; --bs-gradient: none; } .btn-outline-secondary { --bs-btn-color: #6c757d; --bs-btn-border-color: #6c757d; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #6c757d; --bs-btn-hover-border-color: #6c757d; --bs-btn-focus-shadow-rgb: 108, 117, 125; --bs-btn-active-color: #fff; --bs-btn-active-bg: #6c757d; --bs-btn-active-border-color: #6c757d; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #6c757d; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #6c757d; --bs-gradient: none; } .btn-outline-success { --bs-btn-color: #198754; --bs-btn-border-color: #198754; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #198754; --bs-btn-hover-border-color: #198754; --bs-btn-focus-shadow-rgb: 25, 135, 84; --bs-btn-active-color: #fff; --bs-btn-active-bg: #198754; --bs-btn-active-border-color: #198754; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #198754; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #198754; --bs-gradient: none; } .btn-outline-info { --bs-btn-color: #0dcaf0; --bs-btn-border-color: #0dcaf0; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #0dcaf0; --bs-btn-hover-border-color: #0dcaf0; --bs-btn-focus-shadow-rgb: 13, 202, 240; --bs-btn-active-color: #000; --bs-btn-active-bg: #0dcaf0; --bs-btn-active-border-color: #0dcaf0; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #0dcaf0; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #0dcaf0; --bs-gradient: none; } .btn-outline-warning { --bs-btn-color: #ffc107; --bs-btn-border-color: #ffc107; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #ffc107; --bs-btn-hover-border-color: #ffc107; --bs-btn-focus-shadow-rgb: 255, 193, 7; --bs-btn-active-color: #000; --bs-btn-active-bg: #ffc107; --bs-btn-active-border-color: #ffc107; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #ffc107; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #ffc107; --bs-gradient: none; } .btn-outline-danger { --bs-btn-color: #dc3545; --bs-btn-border-color: #dc3545; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #dc3545; --bs-btn-hover-border-color: #dc3545; --bs-btn-focus-shadow-rgb: 220, 53, 69; --bs-btn-active-color: #fff; --bs-btn-active-bg: #dc3545; --bs-btn-active-border-color: #dc3545; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #dc3545; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #dc3545; --bs-gradient: none; } .btn-outline-light { --bs-btn-color: #f8f9fa; --bs-btn-border-color: #f8f9fa; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #f8f9fa; --bs-btn-hover-border-color: #f8f9fa; --bs-btn-focus-shadow-rgb: 248, 249, 250; --bs-btn-active-color: #000; --bs-btn-active-bg: #f8f9fa; --bs-btn-active-border-color: #f8f9fa; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #f8f9fa; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #f8f9fa; --bs-gradient: none; } .btn-outline-dark { --bs-btn-color: #212529; --bs-btn-border-color: #212529; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #212529; --bs-btn-hover-border-color: #212529; --bs-btn-focus-shadow-rgb: 33, 37, 41; --bs-btn-active-color: #fff; --bs-btn-active-bg: #212529; --bs-btn-active-border-color: #212529; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #212529; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #212529; --bs-gradient: none; } .btn-link { --bs-btn-font-weight: 400; --bs-btn-color: var(--bs-link-color); --bs-btn-bg: transparent; --bs-btn-border-color: transparent; --bs-btn-hover-color: var(--bs-link-hover-color); --bs-btn-hover-border-color: transparent; --bs-btn-active-color: var(--bs-link-hover-color); --bs-btn-active-border-color: transparent; --bs-btn-disabled-color: #6c757d; --bs-btn-disabled-border-color: transparent; --bs-btn-box-shadow: none; --bs-btn-focus-shadow-rgb: 49, 132, 253; text-decoration: underline; } .btn-link:focus-visible { color: var(--bs-btn-color); } .btn-link:hover { color: var(--bs-btn-hover-color); } .btn-lg, .btn-group-lg > .btn { --bs-btn-padding-y: 0.5rem; --bs-btn-padding-x: 1rem; --bs-btn-font-size: 1.25rem; --bs-btn-border-radius: 0.5rem; } .btn-sm, .btn-group-sm > .btn { --bs-btn-padding-y: 0.25rem; --bs-btn-padding-x: 0.5rem; --bs-btn-font-size: 0.875rem; --bs-btn-border-radius: 0.25rem; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .collapsing.collapse-horizontal { width: 0; height: auto; transition: width 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing.collapse-horizontal { transition: none; } } .dropup, .dropend, .dropdown, .dropstart, .dropup-center, .dropdown-center { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-right: 0.3em solid transparent; border-bottom: 0; border-left: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-left: 0; } .dropdown-menu { --bs-dropdown-zindex: 1000; --bs-dropdown-min-width: 10rem; --bs-dropdown-padding-x: 0; --bs-dropdown-padding-y: 0.5rem; --bs-dropdown-spacer: 0.125rem; --bs-dropdown-font-size: 1rem; --bs-dropdown-color: #212529; --bs-dropdown-bg: #fff; --bs-dropdown-border-color: var(--bs-border-color-translucent); --bs-dropdown-border-radius: 0.375rem; --bs-dropdown-border-width: 1px; --bs-dropdown-inner-border-radius: calc(0.375rem - 1px); --bs-dropdown-divider-bg: var(--bs-border-color-translucent); --bs-dropdown-divider-margin-y: 0.5rem; --bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-dropdown-link-color: #212529; --bs-dropdown-link-hover-color: #1e2125; --bs-dropdown-link-hover-bg: #e9ecef; --bs-dropdown-link-active-color: #fff; --bs-dropdown-link-active-bg: #0d6efd; --bs-dropdown-link-disabled-color: #adb5bd; --bs-dropdown-item-padding-x: 1rem; --bs-dropdown-item-padding-y: 0.25rem; --bs-dropdown-header-color: #6c757d; --bs-dropdown-header-padding-x: 1rem; --bs-dropdown-header-padding-y: 0.5rem; position: absolute; z-index: var(--bs-dropdown-zindex); display: none; min-width: var(--bs-dropdown-min-width); padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); margin: 0; font-size: var(--bs-dropdown-font-size); color: var(--bs-dropdown-color); text-align: left; list-style: none; background-color: var(--bs-dropdown-bg); background-clip: padding-box; border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); border-radius: var(--bs-dropdown-border-radius); } .dropdown-menu[data-bs-popper] { top: 100%; left: 0; margin-top: var(--bs-dropdown-spacer); } .dropdown-menu-start { --bs-position: start; } .dropdown-menu-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-end { --bs-position: end; } .dropdown-menu-end[data-bs-popper] { right: 0; left: auto; } @media (min-width: 576px) { .dropdown-menu-sm-start { --bs-position: start; } .dropdown-menu-sm-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-sm-end { --bs-position: end; } .dropdown-menu-sm-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 768px) { .dropdown-menu-md-start { --bs-position: start; } .dropdown-menu-md-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-md-end { --bs-position: end; } .dropdown-menu-md-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-start { --bs-position: start; } .dropdown-menu-lg-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-lg-end { --bs-position: end; } .dropdown-menu-lg-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-start { --bs-position: start; } .dropdown-menu-xl-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-xl-end { --bs-position: end; } .dropdown-menu-xl-end[data-bs-popper] { right: 0; left: auto; } } @media (min-width: 1400px) { .dropdown-menu-xxl-start { --bs-position: start; } .dropdown-menu-xxl-start[data-bs-popper] { right: auto; left: 0; } .dropdown-menu-xxl-end { --bs-position: end; } .dropdown-menu-xxl-end[data-bs-popper] { right: 0; left: auto; } } .dropup .dropdown-menu[data-bs-popper] { top: auto; bottom: 100%; margin-top: 0; margin-bottom: var(--bs-dropdown-spacer); } .dropup .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-right: 0.3em solid transparent; border-bottom: 0.3em solid; border-left: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-left: 0; } .dropend .dropdown-menu[data-bs-popper] { top: 0; right: auto; left: 100%; margin-top: 0; margin-left: var(--bs-dropdown-spacer); } .dropend .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0; border-bottom: 0.3em solid transparent; border-left: 0.3em solid; } .dropend .dropdown-toggle:empty::after { margin-left: 0; } .dropend .dropdown-toggle::after { vertical-align: 0; } .dropstart .dropdown-menu[data-bs-popper] { top: 0; right: 100%; left: auto; margin-top: 0; margin-right: var(--bs-dropdown-spacer); } .dropstart .dropdown-toggle::after { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; } .dropstart .dropdown-toggle::after { display: none; } .dropstart .dropdown-toggle::before { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-right: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropstart .dropdown-toggle:empty::after { margin-left: 0; } .dropstart .dropdown-toggle::before { vertical-align: 0; } .dropdown-divider { height: 0; margin: var(--bs-dropdown-divider-margin-y) 0; overflow: hidden; border-top: 1px solid var(--bs-dropdown-divider-bg); opacity: 1; } .dropdown-item { display: block; width: 100%; padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); clear: both; font-weight: 400; color: var(--bs-dropdown-link-color); text-align: inherit; text-decoration: none; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: var(--bs-dropdown-link-hover-color); background-color: var(--bs-dropdown-link-hover-bg); } .dropdown-item.active, .dropdown-item:active { color: var(--bs-dropdown-link-active-color); text-decoration: none; background-color: var(--bs-dropdown-link-active-bg); } .dropdown-item.disabled, .dropdown-item:disabled { color: var(--bs-dropdown-link-disabled-color); pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x); margin-bottom: 0; font-size: 0.875rem; color: var(--bs-dropdown-header-color); white-space: nowrap; } .dropdown-item-text { display: block; padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); color: var(--bs-dropdown-link-color); } .dropdown-menu-dark { --bs-dropdown-color: #dee2e6; --bs-dropdown-bg: #343a40; --bs-dropdown-border-color: var(--bs-border-color-translucent); --bs-dropdown-box-shadow: ; --bs-dropdown-link-color: #dee2e6; --bs-dropdown-link-hover-color: #fff; --bs-dropdown-divider-bg: var(--bs-border-color-translucent); --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); --bs-dropdown-link-active-color: #fff; --bs-dropdown-link-active-bg: #0d6efd; --bs-dropdown-link-disabled-color: #adb5bd; --bs-dropdown-header-color: #adb5bd; } .btn-group, .btn-group-vertical { position: relative; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; flex: 1 1 auto; } .btn-group > .btn-check:checked + .btn, .btn-group > .btn-check:focus + .btn, .btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn-check:checked + .btn, .btn-group-vertical > .btn-check:focus + .btn, .btn-group-vertical > .btn:hover, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: flex; flex-wrap: wrap; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group { border-radius: 0.375rem; } .btn-group > :not(.btn-check:first-child) + .btn, .btn-group > .btn-group:not(:first-child) { margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn.dropdown-toggle-split:first-child, .btn-group > .btn-group:not(:last-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .btn-group > .btn:nth-child(n+3), .btn-group > :not(.btn-check) + .btn, .btn-group > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .dropdown-toggle-split { padding-right: 0.5625rem; padding-left: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { margin-left: 0; } .dropstart .dropdown-toggle-split::before { margin-right: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-right: 0.375rem; padding-left: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-right: 0.75rem; padding-left: 0.75rem; } .btn-group-vertical { flex-direction: column; align-items: flex-start; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } .btn-group-vertical > .btn ~ .btn, .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-left-radius: 0; border-top-right-radius: 0; } .nav { --bs-nav-link-padding-x: 1rem; --bs-nav-link-padding-y: 0.5rem; --bs-nav-link-font-weight: ; --bs-nav-link-color: var(--bs-link-color); --bs-nav-link-hover-color: var(--bs-link-hover-color); --bs-nav-link-disabled-color: #6c757d; display: flex; flex-wrap: wrap; padding-left: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); font-size: var(--bs-nav-link-font-size); font-weight: var(--bs-nav-link-font-weight); color: var(--bs-nav-link-color); text-decoration: none; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .nav-link { transition: none; } } .nav-link:hover, .nav-link:focus { color: var(--bs-nav-link-hover-color); } .nav-link.disabled { color: var(--bs-nav-link-disabled-color); pointer-events: none; cursor: default; } .nav-tabs { --bs-nav-tabs-border-width: 1px; --bs-nav-tabs-border-color: #dee2e6; --bs-nav-tabs-border-radius: 0.375rem; --bs-nav-tabs-link-hover-border-color: #e9ecef #e9ecef #dee2e6; --bs-nav-tabs-link-active-color: #495057; --bs-nav-tabs-link-active-bg: #fff; --bs-nav-tabs-link-active-border-color: #dee2e6 #dee2e6 #fff; border-bottom: var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color); } .nav-tabs .nav-link { margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); background: none; border: var(--bs-nav-tabs-border-width) solid transparent; border-top-left-radius: var(--bs-nav-tabs-border-radius); border-top-right-radius: var(--bs-nav-tabs-border-radius); } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { isolation: isolate; border-color: var(--bs-nav-tabs-link-hover-border-color); } .nav-tabs .nav-link.disabled, .nav-tabs .nav-link:disabled { color: var(--bs-nav-link-disabled-color); background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: var(--bs-nav-tabs-link-active-color); background-color: var(--bs-nav-tabs-link-active-bg); border-color: var(--bs-nav-tabs-link-active-border-color); } .nav-tabs .dropdown-menu { margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); border-top-left-radius: 0; border-top-right-radius: 0; } .nav-pills { --bs-nav-pills-border-radius: 0.375rem; --bs-nav-pills-link-active-color: #fff; --bs-nav-pills-link-active-bg: #0d6efd; } .nav-pills .nav-link { background: none; border: 0; border-radius: var(--bs-nav-pills-border-radius); } .nav-pills .nav-link:disabled { color: var(--bs-nav-link-disabled-color); background-color: transparent; border-color: transparent; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: var(--bs-nav-pills-link-active-color); background-color: var(--bs-nav-pills-link-active-bg); } .nav-fill > .nav-link, .nav-fill .nav-item { flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { flex-basis: 0; flex-grow: 1; text-align: center; } .nav-fill .nav-item .nav-link, .nav-justified .nav-item .nav-link { width: 100%; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { --bs-navbar-padding-x: 0; --bs-navbar-padding-y: 0.5rem; --bs-navbar-color: rgba(0, 0, 0, 0.55); --bs-navbar-hover-color: rgba(0, 0, 0, 0.7); --bs-navbar-disabled-color: rgba(0, 0, 0, 0.3); --bs-navbar-active-color: rgba(0, 0, 0, 0.9); --bs-navbar-brand-padding-y: 0.3125rem; --bs-navbar-brand-margin-end: 1rem; --bs-navbar-brand-font-size: 1.25rem; --bs-navbar-brand-color: rgba(0, 0, 0, 0.9); --bs-navbar-brand-hover-color: rgba(0, 0, 0, 0.9); --bs-navbar-nav-link-padding-x: 0.5rem; --bs-navbar-toggler-padding-y: 0.25rem; --bs-navbar-toggler-padding-x: 0.75rem; --bs-navbar-toggler-font-size: 1.25rem; --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); --bs-navbar-toggler-border-color: rgba(0, 0, 0, 0.1); --bs-navbar-toggler-border-radius: 0.375rem; --bs-navbar-toggler-focus-width: 0.25rem; --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); } .navbar > .container, .navbar > .container-fluid, .navbar > .container-sm, .navbar > .container-md, .navbar > .container-lg, .navbar > .container-xl, .navbar > .container-xxl { display: flex; flex-wrap: inherit; align-items: center; justify-content: space-between; } .navbar-brand { padding-top: var(--bs-navbar-brand-padding-y); padding-bottom: var(--bs-navbar-brand-padding-y); margin-right: var(--bs-navbar-brand-margin-end); font-size: var(--bs-navbar-brand-font-size); color: var(--bs-navbar-brand-color); text-decoration: none; white-space: nowrap; } .navbar-brand:hover, .navbar-brand:focus { color: var(--bs-navbar-brand-hover-color); } .navbar-nav { --bs-nav-link-padding-x: 0; --bs-nav-link-padding-y: 0.5rem; --bs-nav-link-font-weight: ; --bs-nav-link-color: var(--bs-navbar-color); --bs-nav-link-hover-color: var(--bs-navbar-hover-color); --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); display: flex; flex-direction: column; padding-left: 0; margin-bottom: 0; list-style: none; } .navbar-nav .show > .nav-link, .navbar-nav .nav-link.active { color: var(--bs-navbar-active-color); } .navbar-nav .dropdown-menu { position: static; } .navbar-text { padding-top: 0.5rem; padding-bottom: 0.5rem; color: var(--bs-navbar-color); } .navbar-text a, .navbar-text a:hover, .navbar-text a:focus { color: var(--bs-navbar-active-color); } .navbar-collapse { flex-basis: 100%; flex-grow: 1; align-items: center; } .navbar-toggler { padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); font-size: var(--bs-navbar-toggler-font-size); line-height: 1; color: var(--bs-navbar-color); background-color: transparent; border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); border-radius: var(--bs-navbar-toggler-border-radius); transition: var(--bs-navbar-toggler-transition); } @media (prefers-reduced-motion: reduce) { .navbar-toggler { transition: none; } } .navbar-toggler:hover { text-decoration: none; } .navbar-toggler:focus { text-decoration: none; outline: 0; box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; background-image: var(--bs-navbar-toggler-icon-bg); background-repeat: no-repeat; background-position: center; background-size: 100%; } .navbar-nav-scroll { max-height: var(--bs-scroll-height, 75vh); overflow-y: auto; } @media (min-width: 576px) { .navbar-expand-sm { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } .navbar-expand-sm .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-sm .offcanvas .offcanvas-header { display: none; } .navbar-expand-sm .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 768px) { .navbar-expand-md { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-md .navbar-nav { flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } .navbar-expand-md .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-md .offcanvas .offcanvas-header { display: none; } .navbar-expand-md .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 992px) { .navbar-expand-lg { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } .navbar-expand-lg .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-lg .offcanvas .offcanvas-header { display: none; } .navbar-expand-lg .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 1200px) { .navbar-expand-xl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } .navbar-expand-xl .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-xl .offcanvas .offcanvas-header { display: none; } .navbar-expand-xl .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 1400px) { .navbar-expand-xxl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xxl .navbar-nav { flex-direction: row; } .navbar-expand-xxl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xxl .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-xxl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xxl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xxl .navbar-toggler { display: none; } .navbar-expand-xxl .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-xxl .offcanvas .offcanvas-header { display: none; } .navbar-expand-xxl .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } .navbar-expand { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand .navbar-nav { flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-right: var(--bs-navbar-nav-link-padding-x); padding-left: var(--bs-navbar-nav-link-padding-x); } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-expand .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand .offcanvas .offcanvas-header { display: none; } .navbar-expand .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } .navbar-dark { --bs-navbar-color: rgba(255, 255, 255, 0.55); --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); --bs-navbar-active-color: #fff; --bs-navbar-brand-color: #fff; --bs-navbar-brand-hover-color: #fff; --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .card { --bs-card-spacer-y: 1rem; --bs-card-spacer-x: 1rem; --bs-card-title-spacer-y: 0.5rem; --bs-card-border-width: 1px; --bs-card-border-color: var(--bs-border-color-translucent); --bs-card-border-radius: 0.375rem; --bs-card-box-shadow: ; --bs-card-inner-border-radius: calc(0.375rem - 1px); --bs-card-cap-padding-y: 0.5rem; --bs-card-cap-padding-x: 1rem; --bs-card-cap-bg: rgba(0, 0, 0, 0.03); --bs-card-cap-color: ; --bs-card-height: ; --bs-card-color: ; --bs-card-bg: #fff; --bs-card-img-overlay-padding: 1rem; --bs-card-group-margin: 0.75rem; position: relative; display: flex; flex-direction: column; min-width: 0; height: var(--bs-card-height); word-wrap: break-word; background-color: var(--bs-card-bg); background-clip: border-box; border: var(--bs-card-border-width) solid var(--bs-card-border-color); border-radius: var(--bs-card-border-radius); } .card > hr { margin-right: 0; margin-left: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-left-radius: var(--bs-card-inner-border-radius); border-top-right-radius: var(--bs-card-inner-border-radius); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-right-radius: var(--bs-card-inner-border-radius); border-bottom-left-radius: var(--bs-card-inner-border-radius); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { flex: 1 1 auto; padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); color: var(--bs-card-color); } .card-title { margin-bottom: var(--bs-card-title-spacer-y); } .card-subtitle { margin-top: calc(-0.5 * var(--bs-card-title-spacer-y)); margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link + .card-link { margin-left: var(--bs-card-spacer-x); } .card-header { padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); margin-bottom: 0; color: var(--bs-card-cap-color); background-color: var(--bs-card-cap-bg); border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); } .card-header:first-child { border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0; } .card-footer { padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); color: var(--bs-card-cap-color); background-color: var(--bs-card-cap-bg); border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); } .card-footer:last-child { border-radius: 0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius); } .card-header-tabs { margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); border-bottom: 0; } .card-header-tabs .nav-link.active { background-color: var(--bs-card-bg); border-bottom-color: var(--bs-card-bg); } .card-header-pills { margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); } .card-img-overlay { position: absolute; top: 0; right: 0; bottom: 0; left: 0; padding: var(--bs-card-img-overlay-padding); border-radius: var(--bs-card-inner-border-radius); } .card-img, .card-img-top, .card-img-bottom { width: 100%; } .card-img, .card-img-top { border-top-left-radius: var(--bs-card-inner-border-radius); border-top-right-radius: var(--bs-card-inner-border-radius); } .card-img, .card-img-bottom { border-bottom-right-radius: var(--bs-card-inner-border-radius); border-bottom-left-radius: var(--bs-card-inner-border-radius); } .card-group > .card { margin-bottom: var(--bs-card-group-margin); } @media (min-width: 576px) { .card-group { display: flex; flex-flow: row wrap; } .card-group > .card { flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-left: 0; border-left: 0; } .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } } .accordion { --bs-accordion-color: #212529; --bs-accordion-bg: #fff; --bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; --bs-accordion-border-color: var(--bs-border-color); --bs-accordion-border-width: 1px; --bs-accordion-border-radius: 0.375rem; --bs-accordion-inner-border-radius: calc(0.375rem - 1px); --bs-accordion-btn-padding-x: 1.25rem; --bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-color: #212529; --bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-focus-border-color: #86b7fe; --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); --bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-y: 1rem; --bs-accordion-active-color: #0c63e4; --bs-accordion-active-bg: #e7f1ff; } .accordion-button { position: relative; display: flex; align-items: center; width: 100%; padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); font-size: 1rem; color: var(--bs-accordion-btn-color); text-align: left; background-color: var(--bs-accordion-btn-bg); border: 0; border-radius: 0; overflow-anchor: none; transition: var(--bs-accordion-transition); } @media (prefers-reduced-motion: reduce) { .accordion-button { transition: none; } } .accordion-button:not(.collapsed) { color: var(--bs-accordion-active-color); background-color: var(--bs-accordion-active-bg); box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); } .accordion-button:not(.collapsed)::after { background-image: var(--bs-accordion-btn-active-icon); transform: var(--bs-accordion-btn-icon-transform); } .accordion-button::after { flex-shrink: 0; width: var(--bs-accordion-btn-icon-width); height: var(--bs-accordion-btn-icon-width); margin-left: auto; content: ""; background-image: var(--bs-accordion-btn-icon); background-repeat: no-repeat; background-size: var(--bs-accordion-btn-icon-width); transition: var(--bs-accordion-btn-icon-transition); } @media (prefers-reduced-motion: reduce) { .accordion-button::after { transition: none; } } .accordion-button:hover { z-index: 2; } .accordion-button:focus { z-index: 3; border-color: var(--bs-accordion-btn-focus-border-color); outline: 0; box-shadow: var(--bs-accordion-btn-focus-box-shadow); } .accordion-header { margin-bottom: 0; } .accordion-item { color: var(--bs-accordion-color); background-color: var(--bs-accordion-bg); border: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color); } .accordion-item:first-of-type { border-top-left-radius: var(--bs-accordion-border-radius); border-top-right-radius: var(--bs-accordion-border-radius); } .accordion-item:first-of-type .accordion-button { border-top-left-radius: var(--bs-accordion-inner-border-radius); border-top-right-radius: var(--bs-accordion-inner-border-radius); } .accordion-item:not(:first-of-type) { border-top: 0; } .accordion-item:last-of-type { border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius); } .accordion-item:last-of-type .accordion-button.collapsed { border-bottom-right-radius: var(--bs-accordion-inner-border-radius); border-bottom-left-radius: var(--bs-accordion-inner-border-radius); } .accordion-item:last-of-type .accordion-collapse { border-bottom-right-radius: var(--bs-accordion-border-radius); border-bottom-left-radius: var(--bs-accordion-border-radius); } .accordion-body { padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); } .accordion-flush .accordion-collapse { border-width: 0; } .accordion-flush .accordion-item { border-right: 0; border-left: 0; border-radius: 0; } .accordion-flush .accordion-item:first-child { border-top: 0; } .accordion-flush .accordion-item:last-child { border-bottom: 0; } .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed { border-radius: 0; } .breadcrumb { --bs-breadcrumb-padding-x: 0; --bs-breadcrumb-padding-y: 0; --bs-breadcrumb-margin-bottom: 1rem; --bs-breadcrumb-bg: ; --bs-breadcrumb-border-radius: ; --bs-breadcrumb-divider-color: #6c757d; --bs-breadcrumb-item-padding-x: 0.5rem; --bs-breadcrumb-item-active-color: #6c757d; display: flex; flex-wrap: wrap; padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); margin-bottom: var(--bs-breadcrumb-margin-bottom); font-size: var(--bs-breadcrumb-font-size); list-style: none; background-color: var(--bs-breadcrumb-bg); border-radius: var(--bs-breadcrumb-border-radius); } .breadcrumb-item + .breadcrumb-item { padding-left: var(--bs-breadcrumb-item-padding-x); } .breadcrumb-item + .breadcrumb-item::before { float: left; padding-right: var(--bs-breadcrumb-item-padding-x); color: var(--bs-breadcrumb-divider-color); content: var(--bs-breadcrumb-divider, "/") /* rtl: var(--bs-breadcrumb-divider, "/") */; } .breadcrumb-item.active { color: var(--bs-breadcrumb-item-active-color); } .pagination { --bs-pagination-padding-x: 0.75rem; --bs-pagination-padding-y: 0.375rem; --bs-pagination-font-size: 1rem; --bs-pagination-color: var(--bs-link-color); --bs-pagination-bg: #fff; --bs-pagination-border-width: 1px; --bs-pagination-border-color: #dee2e6; --bs-pagination-border-radius: 0.375rem; --bs-pagination-hover-color: var(--bs-link-hover-color); --bs-pagination-hover-bg: #e9ecef; --bs-pagination-hover-border-color: #dee2e6; --bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-bg: #e9ecef; --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); --bs-pagination-active-color: #fff; --bs-pagination-active-bg: #0d6efd; --bs-pagination-active-border-color: #0d6efd; --bs-pagination-disabled-color: #6c757d; --bs-pagination-disabled-bg: #fff; --bs-pagination-disabled-border-color: #dee2e6; display: flex; padding-left: 0; list-style: none; } .page-link { position: relative; display: block; padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); font-size: var(--bs-pagination-font-size); color: var(--bs-pagination-color); text-decoration: none; background-color: var(--bs-pagination-bg); border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .page-link { transition: none; } } .page-link:hover { z-index: 2; color: var(--bs-pagination-hover-color); background-color: var(--bs-pagination-hover-bg); border-color: var(--bs-pagination-hover-border-color); } .page-link:focus { z-index: 3; color: var(--bs-pagination-focus-color); background-color: var(--bs-pagination-focus-bg); outline: 0; box-shadow: var(--bs-pagination-focus-box-shadow); } .page-link.active, .active > .page-link { z-index: 3; color: var(--bs-pagination-active-color); background-color: var(--bs-pagination-active-bg); border-color: var(--bs-pagination-active-border-color); } .page-link.disabled, .disabled > .page-link { color: var(--bs-pagination-disabled-color); pointer-events: none; background-color: var(--bs-pagination-disabled-bg); border-color: var(--bs-pagination-disabled-border-color); } .page-item:not(:first-child) .page-link { margin-left: -1px; } .page-item:first-child .page-link { border-top-left-radius: var(--bs-pagination-border-radius); border-bottom-left-radius: var(--bs-pagination-border-radius); } .page-item:last-child .page-link { border-top-right-radius: var(--bs-pagination-border-radius); border-bottom-right-radius: var(--bs-pagination-border-radius); } .pagination-lg { --bs-pagination-padding-x: 1.5rem; --bs-pagination-padding-y: 0.75rem; --bs-pagination-font-size: 1.25rem; --bs-pagination-border-radius: 0.5rem; } .pagination-sm { --bs-pagination-padding-x: 0.5rem; --bs-pagination-padding-y: 0.25rem; --bs-pagination-font-size: 0.875rem; --bs-pagination-border-radius: 0.25rem; } .badge { --bs-badge-padding-x: 0.65em; --bs-badge-padding-y: 0.35em; --bs-badge-font-size: 0.75em; --bs-badge-font-weight: 700; --bs-badge-color: #fff; --bs-badge-border-radius: 0.375rem; display: inline-block; padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x); font-size: var(--bs-badge-font-size); font-weight: var(--bs-badge-font-weight); line-height: 1; color: var(--bs-badge-color); text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: var(--bs-badge-border-radius); } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .alert { --bs-alert-bg: transparent; --bs-alert-padding-x: 1rem; --bs-alert-padding-y: 1rem; --bs-alert-margin-bottom: 1rem; --bs-alert-color: inherit; --bs-alert-border-color: transparent; --bs-alert-border: 1px solid var(--bs-alert-border-color); --bs-alert-border-radius: 0.375rem; position: relative; padding: var(--bs-alert-padding-y) var(--bs-alert-padding-x); margin-bottom: var(--bs-alert-margin-bottom); color: var(--bs-alert-color); background-color: var(--bs-alert-bg); border: var(--bs-alert-border); border-radius: var(--bs-alert-border-radius); } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-right: 3rem; } .alert-dismissible .btn-close { position: absolute; top: 0; right: 0; z-index: 2; padding: 1.25rem 1rem; } .alert-primary { --bs-alert-color: #084298; --bs-alert-bg: #cfe2ff; --bs-alert-border-color: #b6d4fe; } .alert-primary .alert-link { color: #06357a; } .alert-secondary { --bs-alert-color: #41464b; --bs-alert-bg: #e2e3e5; --bs-alert-border-color: #d3d6d8; } .alert-secondary .alert-link { color: #34383c; } .alert-success { --bs-alert-color: #0f5132; --bs-alert-bg: #d1e7dd; --bs-alert-border-color: #badbcc; } .alert-success .alert-link { color: #0c4128; } .alert-info { --bs-alert-color: #055160; --bs-alert-bg: #cff4fc; --bs-alert-border-color: #b6effb; } .alert-info .alert-link { color: #04414d; } .alert-warning { --bs-alert-color: #664d03; --bs-alert-bg: #fff3cd; --bs-alert-border-color: #ffecb5; } .alert-warning .alert-link { color: #523e02; } .alert-danger { --bs-alert-color: #842029; --bs-alert-bg: #f8d7da; --bs-alert-border-color: #f5c2c7; } .alert-danger .alert-link { color: #6a1a21; } .alert-light { --bs-alert-color: #636464; --bs-alert-bg: #fefefe; --bs-alert-border-color: #fdfdfe; } .alert-light .alert-link { color: #4f5050; } .alert-dark { --bs-alert-color: #141619; --bs-alert-bg: #d3d3d4; --bs-alert-border-color: #bcbebf; } .alert-dark .alert-link { color: #101214; } @keyframes progress-bar-stripes { 0% { background-position-x: 1rem; } } .progress { --bs-progress-height: 1rem; --bs-progress-font-size: 0.75rem; --bs-progress-bg: #e9ecef; --bs-progress-border-radius: 0.375rem; --bs-progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); --bs-progress-bar-color: #fff; --bs-progress-bar-bg: #0d6efd; --bs-progress-bar-transition: width 0.6s ease; display: flex; height: var(--bs-progress-height); overflow: hidden; font-size: var(--bs-progress-font-size); background-color: var(--bs-progress-bg); border-radius: var(--bs-progress-border-radius); } .progress-bar { display: flex; flex-direction: column; justify-content: center; overflow: hidden; color: var(--bs-progress-bar-color); text-align: center; white-space: nowrap; background-color: var(--bs-progress-bar-bg); transition: var(--bs-progress-bar-transition); } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: var(--bs-progress-height) var(--bs-progress-height); } .progress-bar-animated { animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { animation: none; } } .list-group { --bs-list-group-color: #212529; --bs-list-group-bg: #fff; --bs-list-group-border-color: rgba(0, 0, 0, 0.125); --bs-list-group-border-width: 1px; --bs-list-group-border-radius: 0.375rem; --bs-list-group-item-padding-x: 1rem; --bs-list-group-item-padding-y: 0.5rem; --bs-list-group-action-color: #495057; --bs-list-group-action-hover-color: #495057; --bs-list-group-action-hover-bg: #f8f9fa; --bs-list-group-action-active-color: #212529; --bs-list-group-action-active-bg: #e9ecef; --bs-list-group-disabled-color: #6c757d; --bs-list-group-disabled-bg: #fff; --bs-list-group-active-color: #fff; --bs-list-group-active-bg: #0d6efd; --bs-list-group-active-border-color: #0d6efd; display: flex; flex-direction: column; padding-left: 0; margin-bottom: 0; border-radius: var(--bs-list-group-border-radius); } .list-group-numbered { list-style-type: none; counter-reset: section; } .list-group-numbered > .list-group-item::before { content: counters(section, ".") ". "; counter-increment: section; } .list-group-item-action { width: 100%; color: var(--bs-list-group-action-color); text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: var(--bs-list-group-action-hover-color); text-decoration: none; background-color: var(--bs-list-group-action-hover-bg); } .list-group-item-action:active { color: var(--bs-list-group-action-active-color); background-color: var(--bs-list-group-action-active-bg); } .list-group-item { position: relative; display: block; padding: var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x); color: var(--bs-list-group-color); text-decoration: none; background-color: var(--bs-list-group-bg); border: var(--bs-list-group-border-width) solid var(--bs-list-group-border-color); } .list-group-item:first-child { border-top-left-radius: inherit; border-top-right-radius: inherit; } .list-group-item:last-child { border-bottom-right-radius: inherit; border-bottom-left-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: var(--bs-list-group-disabled-color); pointer-events: none; background-color: var(--bs-list-group-disabled-bg); } .list-group-item.active { z-index: 2; color: var(--bs-list-group-active-color); background-color: var(--bs-list-group-active-bg); border-color: var(--bs-list-group-active-border-color); } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: calc(-1 * var(--bs-list-group-border-width)); border-top-width: var(--bs-list-group-border-width); } .list-group-horizontal { flex-direction: row; } .list-group-horizontal > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } @media (min-width: 576px) { .list-group-horizontal-sm { flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } } @media (min-width: 768px) { .list-group-horizontal-md { flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } } @media (min-width: 992px) { .list-group-horizontal-lg { flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } } @media (min-width: 1200px) { .list-group-horizontal-xl { flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } } @media (min-width: 1400px) { .list-group-horizontal-xxl { flex-direction: row; } .list-group-horizontal-xxl > .list-group-item:first-child:not(:last-child) { border-bottom-left-radius: var(--bs-list-group-border-radius); border-top-right-radius: 0; } .list-group-horizontal-xxl > .list-group-item:last-child:not(:first-child) { border-top-right-radius: var(--bs-list-group-border-radius); border-bottom-left-radius: 0; } .list-group-horizontal-xxl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-left-width: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { margin-left: calc(-1 * var(--bs-list-group-border-width)); border-left-width: var(--bs-list-group-border-width); } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 var(--bs-list-group-border-width); } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #084298; background-color: #cfe2ff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #084298; background-color: #bacbe6; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #084298; border-color: #084298; } .list-group-item-secondary { color: #41464b; background-color: #e2e3e5; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #41464b; background-color: #cbccce; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #41464b; border-color: #41464b; } .list-group-item-success { color: #0f5132; background-color: #d1e7dd; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #0f5132; background-color: #bcd0c7; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #0f5132; border-color: #0f5132; } .list-group-item-info { color: #055160; background-color: #cff4fc; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #055160; background-color: #badce3; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #055160; border-color: #055160; } .list-group-item-warning { color: #664d03; background-color: #fff3cd; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #664d03; background-color: #e6dbb9; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #664d03; border-color: #664d03; } .list-group-item-danger { color: #842029; background-color: #f8d7da; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #842029; background-color: #dfc2c4; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #842029; border-color: #842029; } .list-group-item-light { color: #636464; background-color: #fefefe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #636464; background-color: #e5e5e5; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #636464; border-color: #636464; } .list-group-item-dark { color: #141619; background-color: #d3d3d4; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #141619; background-color: #bebebf; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #141619; border-color: #141619; } .btn-close { box-sizing: content-box; width: 1em; height: 1em; padding: 0.25em 0.25em; color: #000; background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; border: 0; border-radius: 0.375rem; opacity: 0.5; } .btn-close:hover { color: #000; text-decoration: none; opacity: 0.75; } .btn-close:focus { outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); opacity: 1; } .btn-close:disabled, .btn-close.disabled { pointer-events: none; -webkit-user-select: none; -moz-user-select: none; user-select: none; opacity: 0.25; } .btn-close-white { filter: invert(1) grayscale(100%) brightness(200%); } .toast { --bs-toast-zindex: 1090; --bs-toast-padding-x: 0.75rem; --bs-toast-padding-y: 0.5rem; --bs-toast-spacing: 1.5rem; --bs-toast-max-width: 350px; --bs-toast-font-size: 0.875rem; --bs-toast-color: ; --bs-toast-bg: rgba(255, 255, 255, 0.85); --bs-toast-border-width: 1px; --bs-toast-border-color: var(--bs-border-color-translucent); --bs-toast-border-radius: 0.375rem; --bs-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-toast-header-color: #6c757d; --bs-toast-header-bg: rgba(255, 255, 255, 0.85); --bs-toast-header-border-color: rgba(0, 0, 0, 0.05); width: var(--bs-toast-max-width); max-width: 100%; font-size: var(--bs-toast-font-size); color: var(--bs-toast-color); pointer-events: auto; background-color: var(--bs-toast-bg); background-clip: padding-box; border: var(--bs-toast-border-width) solid var(--bs-toast-border-color); box-shadow: var(--bs-toast-box-shadow); border-radius: var(--bs-toast-border-radius); } .toast.showing { opacity: 0; } .toast:not(.show) { display: none; } .toast-container { --bs-toast-zindex: 1090; position: absolute; z-index: var(--bs-toast-zindex); width: -webkit-max-content; width: -moz-max-content; width: max-content; max-width: 100%; pointer-events: none; } .toast-container > :not(:last-child) { margin-bottom: var(--bs-toast-spacing); } .toast-header { display: flex; align-items: center; padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x); color: var(--bs-toast-header-color); background-color: var(--bs-toast-header-bg); background-clip: padding-box; border-bottom: var(--bs-toast-border-width) solid var(--bs-toast-header-border-color); border-top-left-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); border-top-right-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); } .toast-header .btn-close { margin-right: calc(-0.5 * var(--bs-toast-padding-x)); margin-left: var(--bs-toast-padding-x); } .toast-body { padding: var(--bs-toast-padding-x); word-wrap: break-word; } .modal { --bs-modal-zindex: 1055; --bs-modal-width: 500px; --bs-modal-padding: 1rem; --bs-modal-margin: 0.5rem; --bs-modal-color: ; --bs-modal-bg: #fff; --bs-modal-border-color: var(--bs-border-color-translucent); --bs-modal-border-width: 1px; --bs-modal-border-radius: 0.5rem; --bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); --bs-modal-inner-border-radius: calc(0.5rem - 1px); --bs-modal-header-padding-x: 1rem; --bs-modal-header-padding-y: 1rem; --bs-modal-header-padding: 1rem 1rem; --bs-modal-header-border-color: var(--bs-border-color); --bs-modal-header-border-width: 1px; --bs-modal-title-line-height: 1.5; --bs-modal-footer-gap: 0.5rem; --bs-modal-footer-bg: ; --bs-modal-footer-border-color: var(--bs-border-color); --bs-modal-footer-border-width: 1px; position: fixed; top: 0; left: 0; z-index: var(--bs-modal-zindex); display: none; width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; outline: 0; } .modal-dialog { position: relative; width: auto; margin: var(--bs-modal-margin); pointer-events: none; } .modal.fade .modal-dialog { transition: transform 0.3s ease-out; transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { transform: none; } .modal.modal-static .modal-dialog { transform: scale(1.02); } .modal-dialog-scrollable { height: calc(100% - var(--bs-modal-margin) * 2); } .modal-dialog-scrollable .modal-content { max-height: 100%; overflow: hidden; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: flex; align-items: center; min-height: calc(100% - var(--bs-modal-margin) * 2); } .modal-content { position: relative; display: flex; flex-direction: column; width: 100%; color: var(--bs-modal-color); pointer-events: auto; background-color: var(--bs-modal-bg); background-clip: padding-box; border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); border-radius: var(--bs-modal-border-radius); outline: 0; } .modal-backdrop { --bs-backdrop-zindex: 1050; --bs-backdrop-bg: #000; --bs-backdrop-opacity: 0.5; position: fixed; top: 0; left: 0; z-index: var(--bs-backdrop-zindex); width: 100vw; height: 100vh; background-color: var(--bs-backdrop-bg); } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: var(--bs-backdrop-opacity); } .modal-header { display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; padding: var(--bs-modal-header-padding); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-top-left-radius: var(--bs-modal-inner-border-radius); border-top-right-radius: var(--bs-modal-inner-border-radius); } .modal-header .btn-close { padding: calc(var(--bs-modal-header-padding-y) * 0.5) calc(var(--bs-modal-header-padding-x) * 0.5); margin: calc(-0.5 * var(--bs-modal-header-padding-y)) calc(-0.5 * var(--bs-modal-header-padding-x)) calc(-0.5 * var(--bs-modal-header-padding-y)) auto; } .modal-title { margin-bottom: 0; line-height: var(--bs-modal-title-line-height); } .modal-body { position: relative; flex: 1 1 auto; padding: var(--bs-modal-padding); } .modal-footer { display: flex; flex-shrink: 0; flex-wrap: wrap; align-items: center; justify-content: flex-end; padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * 0.5); background-color: var(--bs-modal-footer-bg); border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); border-bottom-right-radius: var(--bs-modal-inner-border-radius); border-bottom-left-radius: var(--bs-modal-inner-border-radius); } .modal-footer > * { margin: calc(var(--bs-modal-footer-gap) * 0.5); } @media (min-width: 576px) { .modal { --bs-modal-margin: 1.75rem; --bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); } .modal-dialog { max-width: var(--bs-modal-width); margin-right: auto; margin-left: auto; } .modal-sm { --bs-modal-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { --bs-modal-width: 800px; } } @media (min-width: 1200px) { .modal-xl { --bs-modal-width: 1140px; } } .modal-fullscreen { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen .modal-header, .modal-fullscreen .modal-footer { border-radius: 0; } .modal-fullscreen .modal-body { overflow-y: auto; } @media (max-width: 575.98px) { .modal-fullscreen-sm-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-sm-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-sm-down .modal-header, .modal-fullscreen-sm-down .modal-footer { border-radius: 0; } .modal-fullscreen-sm-down .modal-body { overflow-y: auto; } } @media (max-width: 767.98px) { .modal-fullscreen-md-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-md-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-md-down .modal-header, .modal-fullscreen-md-down .modal-footer { border-radius: 0; } .modal-fullscreen-md-down .modal-body { overflow-y: auto; } } @media (max-width: 991.98px) { .modal-fullscreen-lg-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-lg-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-lg-down .modal-header, .modal-fullscreen-lg-down .modal-footer { border-radius: 0; } .modal-fullscreen-lg-down .modal-body { overflow-y: auto; } } @media (max-width: 1199.98px) { .modal-fullscreen-xl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xl-down .modal-header, .modal-fullscreen-xl-down .modal-footer { border-radius: 0; } .modal-fullscreen-xl-down .modal-body { overflow-y: auto; } } @media (max-width: 1399.98px) { .modal-fullscreen-xxl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xxl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xxl-down .modal-header, .modal-fullscreen-xxl-down .modal-footer { border-radius: 0; } .modal-fullscreen-xxl-down .modal-body { overflow-y: auto; } } .tooltip { --bs-tooltip-zindex: 1080; --bs-tooltip-max-width: 200px; --bs-tooltip-padding-x: 0.5rem; --bs-tooltip-padding-y: 0.25rem; --bs-tooltip-margin: ; --bs-tooltip-font-size: 0.875rem; --bs-tooltip-color: #fff; --bs-tooltip-bg: #000; --bs-tooltip-border-radius: 0.375rem; --bs-tooltip-opacity: 0.9; --bs-tooltip-arrow-width: 0.8rem; --bs-tooltip-arrow-height: 0.4rem; z-index: var(--bs-tooltip-zindex); display: block; padding: var(--bs-tooltip-arrow-height); margin: var(--bs-tooltip-margin); font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; white-space: normal; word-spacing: normal; line-break: auto; font-size: var(--bs-tooltip-font-size); word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: var(--bs-tooltip-opacity); } .tooltip .tooltip-arrow { display: block; width: var(--bs-tooltip-arrow-width); height: var(--bs-tooltip-arrow-height); } .tooltip .tooltip-arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { bottom: 0; } .bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { top: -1px; border-width: var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; border-top-color: var(--bs-tooltip-bg); } /* rtl:begin:ignore */ .bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { left: 0; width: var(--bs-tooltip-arrow-height); height: var(--bs-tooltip-arrow-width); } .bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { right: -1px; border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; border-right-color: var(--bs-tooltip-bg); } /* rtl:end:ignore */ .bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { top: 0; } .bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { bottom: -1px; border-width: 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); border-bottom-color: var(--bs-tooltip-bg); } /* rtl:begin:ignore */ .bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { right: 0; width: var(--bs-tooltip-arrow-height); height: var(--bs-tooltip-arrow-width); } .bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { left: -1px; border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); border-left-color: var(--bs-tooltip-bg); } /* rtl:end:ignore */ .tooltip-inner { max-width: var(--bs-tooltip-max-width); padding: var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x); color: var(--bs-tooltip-color); text-align: center; background-color: var(--bs-tooltip-bg); border-radius: var(--bs-tooltip-border-radius); } .popover { --bs-popover-zindex: 1070; --bs-popover-max-width: 276px; --bs-popover-font-size: 0.875rem; --bs-popover-bg: #fff; --bs-popover-border-width: 1px; --bs-popover-border-color: var(--bs-border-color-translucent); --bs-popover-border-radius: 0.5rem; --bs-popover-inner-border-radius: calc(0.5rem - 1px); --bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-popover-header-padding-x: 1rem; --bs-popover-header-padding-y: 0.5rem; --bs-popover-header-font-size: 1rem; --bs-popover-header-color: ; --bs-popover-header-bg: #f0f0f0; --bs-popover-body-padding-x: 1rem; --bs-popover-body-padding-y: 1rem; --bs-popover-body-color: #212529; --bs-popover-arrow-width: 1rem; --bs-popover-arrow-height: 0.5rem; --bs-popover-arrow-border: var(--bs-popover-border-color); z-index: var(--bs-popover-zindex); display: block; max-width: var(--bs-popover-max-width); font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: left; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; white-space: normal; word-spacing: normal; line-break: auto; font-size: var(--bs-popover-font-size); word-wrap: break-word; background-color: var(--bs-popover-bg); background-clip: padding-box; border: var(--bs-popover-border-width) solid var(--bs-popover-border-color); border-radius: var(--bs-popover-border-radius); } .popover .popover-arrow { display: block; width: var(--bs-popover-arrow-width); height: var(--bs-popover-arrow-height); } .popover .popover-arrow::before, .popover .popover-arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; border-width: 0; } .bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { bottom: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); } .bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before, .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { border-width: var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; } .bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { bottom: 0; border-top-color: var(--bs-popover-arrow-border); } .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { bottom: var(--bs-popover-border-width); border-top-color: var(--bs-popover-bg); } /* rtl:begin:ignore */ .bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { left: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); width: var(--bs-popover-arrow-height); height: var(--bs-popover-arrow-width); } .bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before, .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { border-width: calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; } .bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { left: 0; border-right-color: var(--bs-popover-arrow-border); } .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { left: var(--bs-popover-border-width); border-right-color: var(--bs-popover-bg); } /* rtl:end:ignore */ .bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { top: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); } .bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before, .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { border-width: 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); } .bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { top: 0; border-bottom-color: var(--bs-popover-arrow-border); } .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { top: var(--bs-popover-border-width); border-bottom-color: var(--bs-popover-bg); } .bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { position: absolute; top: 0; left: 50%; display: block; width: var(--bs-popover-arrow-width); margin-left: calc(-0.5 * var(--bs-popover-arrow-width)); content: ""; border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-header-bg); } /* rtl:begin:ignore */ .bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { right: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); width: var(--bs-popover-arrow-height); height: var(--bs-popover-arrow-width); } .bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before, .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { border-width: calc(var(--bs-popover-arrow-width) * 0.5) 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); } .bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { right: 0; border-left-color: var(--bs-popover-arrow-border); } .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { right: var(--bs-popover-border-width); border-left-color: var(--bs-popover-bg); } /* rtl:end:ignore */ .popover-header { padding: var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x); margin-bottom: 0; font-size: var(--bs-popover-header-font-size); color: var(--bs-popover-header-color); background-color: var(--bs-popover-header-bg); border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-border-color); border-top-left-radius: var(--bs-popover-inner-border-radius); border-top-right-radius: var(--bs-popover-inner-border-radius); } .popover-header:empty { display: none; } .popover-body { padding: var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x); color: var(--bs-popover-body-color); } .carousel { position: relative; } .carousel.pointer-event { touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: left; width: 100%; margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: transform 0.6s ease-in-out; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-start), .active.carousel-item-end { transform: translateX(100%); } .carousel-item-prev:not(.carousel-item-end), .active.carousel-item-start { transform: translateX(-100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-start, .carousel-fade .carousel-item-prev.carousel-item-end { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: flex; align-items: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { left: 0; } .carousel-control-next { right: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 2rem; height: 2rem; background-repeat: no-repeat; background-position: 50%; background-size: 100% 100%; } /* rtl:options: { "autoRename": true, "stringMap":[ { "name" : "prev-next", "search" : "prev", "replace" : "next" } ] } */ .carousel-control-prev-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); } .carousel-control-next-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); } .carousel-indicators { position: absolute; right: 0; bottom: 0; left: 0; z-index: 2; display: flex; justify-content: center; padding: 0; margin-right: 15%; margin-bottom: 1rem; margin-left: 15%; list-style: none; } .carousel-indicators [data-bs-target] { box-sizing: content-box; flex: 0 1 auto; width: 30px; height: 3px; padding: 0; margin-right: 3px; margin-left: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: 0.5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators [data-bs-target] { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; right: 15%; bottom: 1.25rem; left: 15%; padding-top: 1.25rem; padding-bottom: 1.25rem; color: #fff; text-align: center; } .carousel-dark .carousel-control-prev-icon, .carousel-dark .carousel-control-next-icon { filter: invert(1) grayscale(100); } .carousel-dark .carousel-indicators [data-bs-target] { background-color: #000; } .carousel-dark .carousel-caption { color: #000; } .spinner-grow, .spinner-border { display: inline-block; width: var(--bs-spinner-width); height: var(--bs-spinner-height); vertical-align: var(--bs-spinner-vertical-align); border-radius: 50%; animation: var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name); } @keyframes spinner-border { to { transform: rotate(360deg) /* rtl:ignore */; } } .spinner-border { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; --bs-spinner-vertical-align: -0.125em; --bs-spinner-border-width: 0.25em; --bs-spinner-animation-speed: 0.75s; --bs-spinner-animation-name: spinner-border; border: var(--bs-spinner-border-width) solid currentcolor; border-right-color: transparent; } .spinner-border-sm { --bs-spinner-width: 1rem; --bs-spinner-height: 1rem; --bs-spinner-border-width: 0.2em; } @keyframes spinner-grow { 0% { transform: scale(0); } 50% { opacity: 1; transform: none; } } .spinner-grow { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; --bs-spinner-vertical-align: -0.125em; --bs-spinner-animation-speed: 0.75s; --bs-spinner-animation-name: spinner-grow; background-color: currentcolor; opacity: 0; } .spinner-grow-sm { --bs-spinner-width: 1rem; --bs-spinner-height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { --bs-spinner-animation-speed: 1.5s; } } .offcanvas, .offcanvas-xxl, .offcanvas-xl, .offcanvas-lg, .offcanvas-md, .offcanvas-sm { --bs-offcanvas-zindex: 1045; --bs-offcanvas-width: 400px; --bs-offcanvas-height: 30vh; --bs-offcanvas-padding-x: 1rem; --bs-offcanvas-padding-y: 1rem; --bs-offcanvas-color: ; --bs-offcanvas-bg: #fff; --bs-offcanvas-border-width: 1px; --bs-offcanvas-border-color: var(--bs-border-color-translucent); --bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); } @media (max-width: 575.98px) { .offcanvas-sm { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 575.98px) and (prefers-reduced-motion: reduce) { .offcanvas-sm { transition: none; } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 575.98px) { .offcanvas-sm.showing, .offcanvas-sm.show:not(.hiding) { transform: none; } } @media (max-width: 575.98px) { .offcanvas-sm.showing, .offcanvas-sm.hiding, .offcanvas-sm.show { visibility: visible; } } @media (min-width: 576px) { .offcanvas-sm { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-sm .offcanvas-header { display: none; } .offcanvas-sm .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 767.98px) { .offcanvas-md { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 767.98px) and (prefers-reduced-motion: reduce) { .offcanvas-md { transition: none; } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 767.98px) { .offcanvas-md.showing, .offcanvas-md.show:not(.hiding) { transform: none; } } @media (max-width: 767.98px) { .offcanvas-md.showing, .offcanvas-md.hiding, .offcanvas-md.show { visibility: visible; } } @media (min-width: 768px) { .offcanvas-md { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-md .offcanvas-header { display: none; } .offcanvas-md .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 991.98px) { .offcanvas-lg { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 991.98px) and (prefers-reduced-motion: reduce) { .offcanvas-lg { transition: none; } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 991.98px) { .offcanvas-lg.showing, .offcanvas-lg.show:not(.hiding) { transform: none; } } @media (max-width: 991.98px) { .offcanvas-lg.showing, .offcanvas-lg.hiding, .offcanvas-lg.show { visibility: visible; } } @media (min-width: 992px) { .offcanvas-lg { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-lg .offcanvas-header { display: none; } .offcanvas-lg .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 1199.98px) { .offcanvas-xl { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 1199.98px) and (prefers-reduced-motion: reduce) { .offcanvas-xl { transition: none; } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.showing, .offcanvas-xl.show:not(.hiding) { transform: none; } } @media (max-width: 1199.98px) { .offcanvas-xl.showing, .offcanvas-xl.hiding, .offcanvas-xl.show { visibility: visible; } } @media (min-width: 1200px) { .offcanvas-xl { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-xl .offcanvas-header { display: none; } .offcanvas-xl .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 1399.98px) { .offcanvas-xxl { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 1399.98px) and (prefers-reduced-motion: reduce) { .offcanvas-xxl { transition: none; } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.showing, .offcanvas-xxl.show:not(.hiding) { transform: none; } } @media (max-width: 1399.98px) { .offcanvas-xxl.showing, .offcanvas-xxl.hiding, .offcanvas-xxl.show { visibility: visible; } } @media (min-width: 1400px) { .offcanvas-xxl { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-xxl .offcanvas-header { display: none; } .offcanvas-xxl .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } .offcanvas { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .offcanvas { transition: none; } } .offcanvas.offcanvas-start { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } .offcanvas.offcanvas-end { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } .offcanvas.offcanvas-top { top: 0; right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } .offcanvas.offcanvas-bottom { right: 0; left: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } .offcanvas.showing, .offcanvas.show:not(.hiding) { transform: none; } .offcanvas.showing, .offcanvas.hiding, .offcanvas.show { visibility: visible; } .offcanvas-backdrop { position: fixed; top: 0; left: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .offcanvas-backdrop.fade { opacity: 0; } .offcanvas-backdrop.show { opacity: 0.5; } .offcanvas-header { display: flex; align-items: center; justify-content: space-between; padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); } .offcanvas-header .btn-close { padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y)); margin-right: calc(-0.5 * var(--bs-offcanvas-padding-x)); margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y)); } .offcanvas-title { margin-bottom: 0; line-height: 1.5; } .offcanvas-body { flex-grow: 1; padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); overflow-y: auto; } .placeholder { display: inline-block; min-height: 1em; vertical-align: middle; cursor: wait; background-color: currentcolor; opacity: 0.5; } .placeholder.btn::before { display: inline-block; content: ""; } .placeholder-xs { min-height: 0.6em; } .placeholder-sm { min-height: 0.8em; } .placeholder-lg { min-height: 1.2em; } .placeholder-glow .placeholder { animation: placeholder-glow 2s ease-in-out infinite; } @keyframes placeholder-glow { 50% { opacity: 0.2; } } .placeholder-wave { -webkit-mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); -webkit-mask-size: 200% 100%; mask-size: 200% 100%; animation: placeholder-wave 2s linear infinite; } @keyframes placeholder-wave { 100% { -webkit-mask-position: -200% 0%; mask-position: -200% 0%; } } .clearfix::after { display: block; clear: both; content: ""; } .text-bg-primary { color: #fff !important; background-color: RGBA(13, 110, 253, var(--bs-bg-opacity, 1)) !important; } .text-bg-secondary { color: #fff !important; background-color: RGBA(108, 117, 125, var(--bs-bg-opacity, 1)) !important; } .text-bg-success { color: #fff !important; background-color: RGBA(25, 135, 84, var(--bs-bg-opacity, 1)) !important; } .text-bg-info { color: #000 !important; background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; } .text-bg-warning { color: #000 !important; background-color: RGBA(255, 193, 7, var(--bs-bg-opacity, 1)) !important; } .text-bg-danger { color: #fff !important; background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; } .text-bg-light { color: #000 !important; background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; } .text-bg-dark { color: #fff !important; background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; } .link-primary { color: #0d6efd !important; } .link-primary:hover, .link-primary:focus { color: #0a58ca !important; } .link-secondary { color: #6c757d !important; } .link-secondary:hover, .link-secondary:focus { color: #565e64 !important; } .link-success { color: #198754 !important; } .link-success:hover, .link-success:focus { color: #146c43 !important; } .link-info { color: #0dcaf0 !important; } .link-info:hover, .link-info:focus { color: #3dd5f3 !important; } .link-warning { color: #ffc107 !important; } .link-warning:hover, .link-warning:focus { color: #ffcd39 !important; } .link-danger { color: #dc3545 !important; } .link-danger:hover, .link-danger:focus { color: #b02a37 !important; } .link-light { color: #f8f9fa !important; } .link-light:hover, .link-light:focus { color: #f9fafb !important; } .link-dark { color: #212529 !important; } .link-dark:hover, .link-dark:focus { color: #1a1e21 !important; } .ratio { position: relative; width: 100%; } .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } .ratio > * { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ratio-1x1 { --bs-aspect-ratio: 100%; } .ratio-4x3 { --bs-aspect-ratio: 75%; } .ratio-16x9 { --bs-aspect-ratio: 56.25%; } .ratio-21x9 { --bs-aspect-ratio: 42.8571428571%; } .fixed-top { position: fixed; top: 0; right: 0; left: 0; z-index: 1030; } .fixed-bottom { position: fixed; right: 0; bottom: 0; left: 0; z-index: 1030; } .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } @media (min-width: 576px) { .sticky-sm-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-sm-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 768px) { .sticky-md-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-md-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 992px) { .sticky-lg-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-lg-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1200px) { .sticky-xl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1400px) { .sticky-xxl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xxl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } .hstack { display: flex; flex-direction: row; align-items: center; align-self: stretch; } .vstack { display: flex; flex: 1 1 auto; flex-direction: column; align-self: stretch; } .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } .stretched-link::after { position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: 1; content: ""; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .vr { display: inline-block; align-self: stretch; width: 1px; min-height: 1em; background-color: currentcolor; opacity: 0.25; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .float-start { float: left !important; } .float-end { float: right !important; } .float-none { float: none !important; } .opacity-0 { opacity: 0 !important; } .opacity-25 { opacity: 0.25 !important; } .opacity-50 { opacity: 0.5 !important; } .opacity-75 { opacity: 0.75 !important; } .opacity-100 { opacity: 1 !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .overflow-visible { overflow: visible !important; } .overflow-scroll { overflow: scroll !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { left: 0 !important; } .start-50 { left: 50% !important; } .start-100 { left: 100% !important; } .end-0 { right: 0 !important; } .end-50 { right: 50% !important; } .end-100 { right: 100% !important; } .translate-middle { transform: translate(-50%, -50%) !important; } .translate-middle-x { transform: translateX(-50%) !important; } .translate-middle-y { transform: translateY(-50%) !important; } .border { border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-0 { border: 0 !important; } .border-top { border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-top-0 { border-top: 0 !important; } .border-end { border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-end-0 { border-right: 0 !important; } .border-bottom { border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-start { border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-start-0 { border-left: 0 !important; } .border-primary { --bs-border-opacity: 1; border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } .border-secondary { --bs-border-opacity: 1; border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } .border-success { --bs-border-opacity: 1; border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } .border-info { --bs-border-opacity: 1; border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } .border-warning { --bs-border-opacity: 1; border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } .border-danger { --bs-border-opacity: 1; border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } .border-light { --bs-border-opacity: 1; border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } .border-dark { --bs-border-opacity: 1; border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } .border-white { --bs-border-opacity: 1; border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } .border-1 { --bs-border-width: 1px; } .border-2 { --bs-border-width: 2px; } .border-3 { --bs-border-width: 3px; } .border-4 { --bs-border-width: 4px; } .border-5 { --bs-border-width: 5px; } .border-opacity-10 { --bs-border-opacity: 0.1; } .border-opacity-25 { --bs-border-opacity: 0.25; } .border-opacity-50 { --bs-border-opacity: 0.5; } .border-opacity-75 { --bs-border-opacity: 0.75; } .border-opacity-100 { --bs-border-opacity: 1; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .mw-100 { max-width: 100% !important; } .vw-100 { width: 100vw !important; } .min-vw-100 { min-width: 100vw !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mh-100 { max-height: 100% !important; } .vh-100 { height: 100vh !important; } .min-vh-100 { min-height: 100vh !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-auto { margin-right: auto !important; margin-left: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-right: 0 !important; } .me-1 { margin-right: 0.25rem !important; } .me-2 { margin-right: 0.5rem !important; } .me-3 { margin-right: 1rem !important; } .me-4 { margin-right: 1.5rem !important; } .me-5 { margin-right: 3rem !important; } .me-auto { margin-right: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-left: 0 !important; } .ms-1 { margin-left: 0.25rem !important; } .ms-2 { margin-left: 0.5rem !important; } .ms-3 { margin-left: 1rem !important; } .ms-4 { margin-left: 1.5rem !important; } .ms-5 { margin-left: 3rem !important; } .ms-auto { margin-left: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-right: 0 !important; } .pe-1 { padding-right: 0.25rem !important; } .pe-2 { padding-right: 0.5rem !important; } .pe-3 { padding-right: 1rem !important; } .pe-4 { padding-right: 1.5rem !important; } .pe-5 { padding-right: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-left: 0 !important; } .ps-1 { padding-left: 0.25rem !important; } .ps-2 { padding-left: 0.5rem !important; } .ps-3 { padding-left: 1rem !important; } .ps-4 { padding-left: 1.5rem !important; } .ps-5 { padding-left: 3rem !important; } .gap-0 { gap: 0 !important; } .gap-1 { gap: 0.25rem !important; } .gap-2 { gap: 0.5rem !important; } .gap-3 { gap: 1rem !important; } .gap-4 { gap: 1.5rem !important; } .gap-5 { gap: 3rem !important; } .font-monospace { font-family: var(--bs-font-monospace) !important; } .fs-1 { font-size: calc(1.375rem + 1.5vw) !important; } .fs-2 { font-size: calc(1.325rem + 0.9vw) !important; } .fs-3 { font-size: calc(1.3rem + 0.6vw) !important; } .fs-4 { font-size: calc(1.275rem + 0.3vw) !important; } .fs-5 { font-size: 1.25rem !important; } .fs-6 { font-size: 1rem !important; } .fst-italic { font-style: italic !important; } .fst-normal { font-style: normal !important; } .fw-light { font-weight: 300 !important; } .fw-lighter { font-weight: lighter !important; } .fw-normal { font-weight: 400 !important; } .fw-bold { font-weight: 700 !important; } .fw-semibold { font-weight: 600 !important; } .fw-bolder { font-weight: bolder !important; } .lh-1 { line-height: 1 !important; } .lh-sm { line-height: 1.25 !important; } .lh-base { line-height: 1.5 !important; } .lh-lg { line-height: 2 !important; } .text-start { text-align: left !important; } .text-end { text-align: right !important; } .text-center { text-align: center !important; } .text-decoration-none { text-decoration: none !important; } .text-decoration-underline { text-decoration: underline !important; } .text-decoration-line-through { text-decoration: line-through !important; } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } /* rtl:begin:remove */ .text-break { word-wrap: break-word !important; word-break: break-word !important; } /* rtl:end:remove */ .text-primary { --bs-text-opacity: 1; color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } .text-secondary { --bs-text-opacity: 1; color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } .text-success { --bs-text-opacity: 1; color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } .text-info { --bs-text-opacity: 1; color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } .text-warning { --bs-text-opacity: 1; color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } .text-danger { --bs-text-opacity: 1; color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } .text-light { --bs-text-opacity: 1; color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } .text-dark { --bs-text-opacity: 1; color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } .text-black { --bs-text-opacity: 1; color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } .text-white { --bs-text-opacity: 1; color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } .text-body { --bs-text-opacity: 1; color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } .text-muted { --bs-text-opacity: 1; color: #6c757d !important; } .text-black-50 { --bs-text-opacity: 1; color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { --bs-text-opacity: 1; color: rgba(255, 255, 255, 0.5) !important; } .text-reset { --bs-text-opacity: 1; color: inherit !important; } .text-opacity-25 { --bs-text-opacity: 0.25; } .text-opacity-50 { --bs-text-opacity: 0.5; } .text-opacity-75 { --bs-text-opacity: 0.75; } .text-opacity-100 { --bs-text-opacity: 1; } .bg-primary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } .bg-secondary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } .bg-success { --bs-bg-opacity: 1; background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } .bg-info { --bs-bg-opacity: 1; background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } .bg-warning { --bs-bg-opacity: 1; background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } .bg-danger { --bs-bg-opacity: 1; background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } .bg-light { --bs-bg-opacity: 1; background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } .bg-dark { --bs-bg-opacity: 1; background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } .bg-black { --bs-bg-opacity: 1; background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } .bg-white { --bs-bg-opacity: 1; background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } .bg-body { --bs-bg-opacity: 1; background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } .bg-transparent { --bs-bg-opacity: 1; background-color: transparent !important; } .bg-opacity-10 { --bs-bg-opacity: 0.1; } .bg-opacity-25 { --bs-bg-opacity: 0.25; } .bg-opacity-50 { --bs-bg-opacity: 0.5; } .bg-opacity-75 { --bs-bg-opacity: 0.75; } .bg-opacity-100 { --bs-bg-opacity: 1; } .bg-gradient { background-image: var(--bs-gradient) !important; } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; user-select: none !important; } .pe-none { pointer-events: none !important; } .pe-auto { pointer-events: auto !important; } .rounded { border-radius: var(--bs-border-radius) !important; } .rounded-0 { border-radius: 0 !important; } .rounded-1 { border-radius: var(--bs-border-radius-sm) !important; } .rounded-2 { border-radius: var(--bs-border-radius) !important; } .rounded-3 { border-radius: var(--bs-border-radius-lg) !important; } .rounded-4 { border-radius: var(--bs-border-radius-xl) !important; } .rounded-5 { border-radius: var(--bs-border-radius-2xl) !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: var(--bs-border-radius-pill) !important; } .rounded-top { border-top-left-radius: var(--bs-border-radius) !important; border-top-right-radius: var(--bs-border-radius) !important; } .rounded-end { border-top-right-radius: var(--bs-border-radius) !important; border-bottom-right-radius: var(--bs-border-radius) !important; } .rounded-bottom { border-bottom-right-radius: var(--bs-border-radius) !important; border-bottom-left-radius: var(--bs-border-radius) !important; } .rounded-start { border-bottom-left-radius: var(--bs-border-radius) !important; border-top-left-radius: var(--bs-border-radius) !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media (min-width: 576px) { .float-sm-start { float: left !important; } .float-sm-end { float: right !important; } .float-sm-none { float: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-sm-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-sm-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-sm-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-sm-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-sm-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-sm-auto { margin-right: auto !important; margin-left: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-right: 0 !important; } .me-sm-1 { margin-right: 0.25rem !important; } .me-sm-2 { margin-right: 0.5rem !important; } .me-sm-3 { margin-right: 1rem !important; } .me-sm-4 { margin-right: 1.5rem !important; } .me-sm-5 { margin-right: 3rem !important; } .me-sm-auto { margin-right: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-left: 0 !important; } .ms-sm-1 { margin-left: 0.25rem !important; } .ms-sm-2 { margin-left: 0.5rem !important; } .ms-sm-3 { margin-left: 1rem !important; } .ms-sm-4 { margin-left: 1.5rem !important; } .ms-sm-5 { margin-left: 3rem !important; } .ms-sm-auto { margin-left: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-sm-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-sm-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-sm-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-sm-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-sm-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-right: 0 !important; } .pe-sm-1 { padding-right: 0.25rem !important; } .pe-sm-2 { padding-right: 0.5rem !important; } .pe-sm-3 { padding-right: 1rem !important; } .pe-sm-4 { padding-right: 1.5rem !important; } .pe-sm-5 { padding-right: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-left: 0 !important; } .ps-sm-1 { padding-left: 0.25rem !important; } .ps-sm-2 { padding-left: 0.5rem !important; } .ps-sm-3 { padding-left: 1rem !important; } .ps-sm-4 { padding-left: 1.5rem !important; } .ps-sm-5 { padding-left: 3rem !important; } .gap-sm-0 { gap: 0 !important; } .gap-sm-1 { gap: 0.25rem !important; } .gap-sm-2 { gap: 0.5rem !important; } .gap-sm-3 { gap: 1rem !important; } .gap-sm-4 { gap: 1.5rem !important; } .gap-sm-5 { gap: 3rem !important; } .text-sm-start { text-align: left !important; } .text-sm-end { text-align: right !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .float-md-start { float: left !important; } .float-md-end { float: right !important; } .float-md-none { float: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-md-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-md-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-md-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-md-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-md-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-md-auto { margin-right: auto !important; margin-left: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-right: 0 !important; } .me-md-1 { margin-right: 0.25rem !important; } .me-md-2 { margin-right: 0.5rem !important; } .me-md-3 { margin-right: 1rem !important; } .me-md-4 { margin-right: 1.5rem !important; } .me-md-5 { margin-right: 3rem !important; } .me-md-auto { margin-right: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-left: 0 !important; } .ms-md-1 { margin-left: 0.25rem !important; } .ms-md-2 { margin-left: 0.5rem !important; } .ms-md-3 { margin-left: 1rem !important; } .ms-md-4 { margin-left: 1.5rem !important; } .ms-md-5 { margin-left: 3rem !important; } .ms-md-auto { margin-left: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-md-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-md-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-md-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-md-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-md-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-right: 0 !important; } .pe-md-1 { padding-right: 0.25rem !important; } .pe-md-2 { padding-right: 0.5rem !important; } .pe-md-3 { padding-right: 1rem !important; } .pe-md-4 { padding-right: 1.5rem !important; } .pe-md-5 { padding-right: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-left: 0 !important; } .ps-md-1 { padding-left: 0.25rem !important; } .ps-md-2 { padding-left: 0.5rem !important; } .ps-md-3 { padding-left: 1rem !important; } .ps-md-4 { padding-left: 1.5rem !important; } .ps-md-5 { padding-left: 3rem !important; } .gap-md-0 { gap: 0 !important; } .gap-md-1 { gap: 0.25rem !important; } .gap-md-2 { gap: 0.5rem !important; } .gap-md-3 { gap: 1rem !important; } .gap-md-4 { gap: 1.5rem !important; } .gap-md-5 { gap: 3rem !important; } .text-md-start { text-align: left !important; } .text-md-end { text-align: right !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .float-lg-start { float: left !important; } .float-lg-end { float: right !important; } .float-lg-none { float: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-lg-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-lg-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-lg-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-lg-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-lg-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-lg-auto { margin-right: auto !important; margin-left: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-right: 0 !important; } .me-lg-1 { margin-right: 0.25rem !important; } .me-lg-2 { margin-right: 0.5rem !important; } .me-lg-3 { margin-right: 1rem !important; } .me-lg-4 { margin-right: 1.5rem !important; } .me-lg-5 { margin-right: 3rem !important; } .me-lg-auto { margin-right: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-left: 0 !important; } .ms-lg-1 { margin-left: 0.25rem !important; } .ms-lg-2 { margin-left: 0.5rem !important; } .ms-lg-3 { margin-left: 1rem !important; } .ms-lg-4 { margin-left: 1.5rem !important; } .ms-lg-5 { margin-left: 3rem !important; } .ms-lg-auto { margin-left: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-lg-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-lg-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-lg-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-lg-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-lg-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-right: 0 !important; } .pe-lg-1 { padding-right: 0.25rem !important; } .pe-lg-2 { padding-right: 0.5rem !important; } .pe-lg-3 { padding-right: 1rem !important; } .pe-lg-4 { padding-right: 1.5rem !important; } .pe-lg-5 { padding-right: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-left: 0 !important; } .ps-lg-1 { padding-left: 0.25rem !important; } .ps-lg-2 { padding-left: 0.5rem !important; } .ps-lg-3 { padding-left: 1rem !important; } .ps-lg-4 { padding-left: 1.5rem !important; } .ps-lg-5 { padding-left: 3rem !important; } .gap-lg-0 { gap: 0 !important; } .gap-lg-1 { gap: 0.25rem !important; } .gap-lg-2 { gap: 0.5rem !important; } .gap-lg-3 { gap: 1rem !important; } .gap-lg-4 { gap: 1.5rem !important; } .gap-lg-5 { gap: 3rem !important; } .text-lg-start { text-align: left !important; } .text-lg-end { text-align: right !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .float-xl-start { float: left !important; } .float-xl-end { float: right !important; } .float-xl-none { float: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-right: 0 !important; } .me-xl-1 { margin-right: 0.25rem !important; } .me-xl-2 { margin-right: 0.5rem !important; } .me-xl-3 { margin-right: 1rem !important; } .me-xl-4 { margin-right: 1.5rem !important; } .me-xl-5 { margin-right: 3rem !important; } .me-xl-auto { margin-right: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-left: 0 !important; } .ms-xl-1 { margin-left: 0.25rem !important; } .ms-xl-2 { margin-left: 0.5rem !important; } .ms-xl-3 { margin-left: 1rem !important; } .ms-xl-4 { margin-left: 1.5rem !important; } .ms-xl-5 { margin-left: 3rem !important; } .ms-xl-auto { margin-left: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-right: 0 !important; } .pe-xl-1 { padding-right: 0.25rem !important; } .pe-xl-2 { padding-right: 0.5rem !important; } .pe-xl-3 { padding-right: 1rem !important; } .pe-xl-4 { padding-right: 1.5rem !important; } .pe-xl-5 { padding-right: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-left: 0 !important; } .ps-xl-1 { padding-left: 0.25rem !important; } .ps-xl-2 { padding-left: 0.5rem !important; } .ps-xl-3 { padding-left: 1rem !important; } .ps-xl-4 { padding-left: 1.5rem !important; } .ps-xl-5 { padding-left: 3rem !important; } .gap-xl-0 { gap: 0 !important; } .gap-xl-1 { gap: 0.25rem !important; } .gap-xl-2 { gap: 0.5rem !important; } .gap-xl-3 { gap: 1rem !important; } .gap-xl-4 { gap: 1.5rem !important; } .gap-xl-5 { gap: 3rem !important; } .text-xl-start { text-align: left !important; } .text-xl-end { text-align: right !important; } .text-xl-center { text-align: center !important; } } @media (min-width: 1400px) { .float-xxl-start { float: left !important; } .float-xxl-end { float: right !important; } .float-xxl-none { float: none !important; } .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-right: 0 !important; margin-left: 0 !important; } .mx-xxl-1 { margin-right: 0.25rem !important; margin-left: 0.25rem !important; } .mx-xxl-2 { margin-right: 0.5rem !important; margin-left: 0.5rem !important; } .mx-xxl-3 { margin-right: 1rem !important; margin-left: 1rem !important; } .mx-xxl-4 { margin-right: 1.5rem !important; margin-left: 1.5rem !important; } .mx-xxl-5 { margin-right: 3rem !important; margin-left: 3rem !important; } .mx-xxl-auto { margin-right: auto !important; margin-left: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-right: 0 !important; } .me-xxl-1 { margin-right: 0.25rem !important; } .me-xxl-2 { margin-right: 0.5rem !important; } .me-xxl-3 { margin-right: 1rem !important; } .me-xxl-4 { margin-right: 1.5rem !important; } .me-xxl-5 { margin-right: 3rem !important; } .me-xxl-auto { margin-right: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-left: 0 !important; } .ms-xxl-1 { margin-left: 0.25rem !important; } .ms-xxl-2 { margin-left: 0.5rem !important; } .ms-xxl-3 { margin-left: 1rem !important; } .ms-xxl-4 { margin-left: 1.5rem !important; } .ms-xxl-5 { margin-left: 3rem !important; } .ms-xxl-auto { margin-left: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-right: 0 !important; padding-left: 0 !important; } .px-xxl-1 { padding-right: 0.25rem !important; padding-left: 0.25rem !important; } .px-xxl-2 { padding-right: 0.5rem !important; padding-left: 0.5rem !important; } .px-xxl-3 { padding-right: 1rem !important; padding-left: 1rem !important; } .px-xxl-4 { padding-right: 1.5rem !important; padding-left: 1.5rem !important; } .px-xxl-5 { padding-right: 3rem !important; padding-left: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-right: 0 !important; } .pe-xxl-1 { padding-right: 0.25rem !important; } .pe-xxl-2 { padding-right: 0.5rem !important; } .pe-xxl-3 { padding-right: 1rem !important; } .pe-xxl-4 { padding-right: 1.5rem !important; } .pe-xxl-5 { padding-right: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-left: 0 !important; } .ps-xxl-1 { padding-left: 0.25rem !important; } .ps-xxl-2 { padding-left: 0.5rem !important; } .ps-xxl-3 { padding-left: 1rem !important; } .ps-xxl-4 { padding-left: 1.5rem !important; } .ps-xxl-5 { padding-left: 3rem !important; } .gap-xxl-0 { gap: 0 !important; } .gap-xxl-1 { gap: 0.25rem !important; } .gap-xxl-2 { gap: 0.5rem !important; } .gap-xxl-3 { gap: 1rem !important; } .gap-xxl-4 { gap: 1.5rem !important; } .gap-xxl-5 { gap: 3rem !important; } .text-xxl-start { text-align: left !important; } .text-xxl-end { text-align: right !important; } .text-xxl-center { text-align: center !important; } } @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; } .fs-2 { font-size: 2rem !important; } .fs-3 { font-size: 1.75rem !important; } .fs-4 { font-size: 1.5rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/css/bootstrap.rtl.css ================================================ @charset "UTF-8"; /*! * Bootstrap v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors * Copyright 2011-2022 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ :root { --bs-blue: #0d6efd; --bs-indigo: #6610f2; --bs-purple: #6f42c1; --bs-pink: #d63384; --bs-red: #dc3545; --bs-orange: #fd7e14; --bs-yellow: #ffc107; --bs-green: #198754; --bs-teal: #20c997; --bs-cyan: #0dcaf0; --bs-black: #000; --bs-white: #fff; --bs-gray: #6c757d; --bs-gray-dark: #343a40; --bs-gray-100: #f8f9fa; --bs-gray-200: #e9ecef; --bs-gray-300: #dee2e6; --bs-gray-400: #ced4da; --bs-gray-500: #adb5bd; --bs-gray-600: #6c757d; --bs-gray-700: #495057; --bs-gray-800: #343a40; --bs-gray-900: #212529; --bs-primary: #0d6efd; --bs-secondary: #6c757d; --bs-success: #198754; --bs-info: #0dcaf0; --bs-warning: #ffc107; --bs-danger: #dc3545; --bs-light: #f8f9fa; --bs-dark: #212529; --bs-primary-rgb: 13, 110, 253; --bs-secondary-rgb: 108, 117, 125; --bs-success-rgb: 25, 135, 84; --bs-info-rgb: 13, 202, 240; --bs-warning-rgb: 255, 193, 7; --bs-danger-rgb: 220, 53, 69; --bs-light-rgb: 248, 249, 250; --bs-dark-rgb: 33, 37, 41; --bs-white-rgb: 255, 255, 255; --bs-black-rgb: 0, 0, 0; --bs-body-color-rgb: 33, 37, 41; --bs-body-bg-rgb: 255, 255, 255; --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); --bs-body-font-family: var(--bs-font-sans-serif); --bs-body-font-size: 1rem; --bs-body-font-weight: 400; --bs-body-line-height: 1.5; --bs-body-color: #212529; --bs-body-bg: #fff; --bs-border-width: 1px; --bs-border-style: solid; --bs-border-color: #dee2e6; --bs-border-color-translucent: rgba(0, 0, 0, 0.175); --bs-border-radius: 0.375rem; --bs-border-radius-sm: 0.25rem; --bs-border-radius-lg: 0.5rem; --bs-border-radius-xl: 1rem; --bs-border-radius-2xl: 2rem; --bs-border-radius-pill: 50rem; --bs-link-color: #0d6efd; --bs-link-hover-color: #0a58ca; --bs-code-color: #d63384; --bs-highlight-bg: #fff3cd; } *, *::before, *::after { box-sizing: border-box; } @media (prefers-reduced-motion: no-preference) { :root { scroll-behavior: smooth; } } body { margin: 0; font-family: var(--bs-body-font-family); font-size: var(--bs-body-font-size); font-weight: var(--bs-body-font-weight); line-height: var(--bs-body-line-height); color: var(--bs-body-color); text-align: var(--bs-body-text-align); background-color: var(--bs-body-bg); -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } hr { margin: 1rem 0; color: inherit; border: 0; border-top: 1px solid; opacity: 0.25; } h6, .h6, h5, .h5, h4, .h4, h3, .h3, h2, .h2, h1, .h1 { margin-top: 0; margin-bottom: 0.5rem; font-weight: 500; line-height: 1.2; } h1, .h1 { font-size: calc(1.375rem + 1.5vw); } @media (min-width: 1200px) { h1, .h1 { font-size: 2.5rem; } } h2, .h2 { font-size: calc(1.325rem + 0.9vw); } @media (min-width: 1200px) { h2, .h2 { font-size: 2rem; } } h3, .h3 { font-size: calc(1.3rem + 0.6vw); } @media (min-width: 1200px) { h3, .h3 { font-size: 1.75rem; } } h4, .h4 { font-size: calc(1.275rem + 0.3vw); } @media (min-width: 1200px) { h4, .h4 { font-size: 1.5rem; } } h5, .h5 { font-size: 1.25rem; } h6, .h6 { font-size: 1rem; } p { margin-top: 0; margin-bottom: 1rem; } abbr[title] { -webkit-text-decoration: underline dotted; text-decoration: underline dotted; cursor: help; -webkit-text-decoration-skip-ink: none; text-decoration-skip-ink: none; } address { margin-bottom: 1rem; font-style: normal; line-height: inherit; } ol, ul { padding-right: 2rem; } ol, ul, dl { margin-top: 0; margin-bottom: 1rem; } ol ol, ul ul, ol ul, ul ol { margin-bottom: 0; } dt { font-weight: 700; } dd { margin-bottom: 0.5rem; margin-right: 0; } blockquote { margin: 0 0 1rem; } b, strong { font-weight: bolder; } small, .small { font-size: 0.875em; } mark, .mark { padding: 0.1875em; background-color: var(--bs-highlight-bg); } sub, sup { position: relative; font-size: 0.75em; line-height: 0; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } a { color: var(--bs-link-color); text-decoration: underline; } a:hover { color: var(--bs-link-hover-color); } a:not([href]):not([class]), a:not([href]):not([class]):hover { color: inherit; text-decoration: none; } pre, code, kbd, samp { font-family: var(--bs-font-monospace); font-size: 1em; } pre { display: block; margin-top: 0; margin-bottom: 1rem; overflow: auto; font-size: 0.875em; } pre code { font-size: inherit; color: inherit; word-break: normal; } code { font-size: 0.875em; color: var(--bs-code-color); word-wrap: break-word; } a > code { color: inherit; } kbd { padding: 0.1875rem 0.375rem; font-size: 0.875em; color: var(--bs-body-bg); background-color: var(--bs-body-color); border-radius: 0.25rem; } kbd kbd { padding: 0; font-size: 1em; } figure { margin: 0 0 1rem; } img, svg { vertical-align: middle; } table { caption-side: bottom; border-collapse: collapse; } caption { padding-top: 0.5rem; padding-bottom: 0.5rem; color: #6c757d; text-align: right; } th { text-align: inherit; text-align: -webkit-match-parent; } thead, tbody, tfoot, tr, td, th { border-color: inherit; border-style: solid; border-width: 0; } label { display: inline-block; } button { border-radius: 0; } button:focus:not(:focus-visible) { outline: 0; } input, button, select, optgroup, textarea { margin: 0; font-family: inherit; font-size: inherit; line-height: inherit; } button, select { text-transform: none; } [role=button] { cursor: pointer; } select { word-wrap: normal; } select:disabled { opacity: 1; } [list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator { display: none !important; } button, [type=button], [type=reset], [type=submit] { -webkit-appearance: button; } button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } ::-moz-focus-inner { padding: 0; border-style: none; } textarea { resize: vertical; } fieldset { min-width: 0; padding: 0; margin: 0; border: 0; } legend { float: right; width: 100%; padding: 0; margin-bottom: 0.5rem; font-size: calc(1.275rem + 0.3vw); line-height: inherit; } @media (min-width: 1200px) { legend { font-size: 1.5rem; } } legend + * { clear: right; } ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-year-field { padding: 0; } ::-webkit-inner-spin-button { height: auto; } [type=search] { outline-offset: -2px; -webkit-appearance: textfield; } [type="tel"], [type="url"], [type="email"], [type="number"] { direction: ltr; } ::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-color-swatch-wrapper { padding: 0; } ::-webkit-file-upload-button { font: inherit; -webkit-appearance: button; } ::file-selector-button { font: inherit; -webkit-appearance: button; } output { display: inline-block; } iframe { border: 0; } summary { display: list-item; cursor: pointer; } progress { vertical-align: baseline; } [hidden] { display: none !important; } .lead { font-size: 1.25rem; font-weight: 300; } .display-1 { font-size: calc(1.625rem + 4.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-1 { font-size: 5rem; } } .display-2 { font-size: calc(1.575rem + 3.9vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-2 { font-size: 4.5rem; } } .display-3 { font-size: calc(1.525rem + 3.3vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-3 { font-size: 4rem; } } .display-4 { font-size: calc(1.475rem + 2.7vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-4 { font-size: 3.5rem; } } .display-5 { font-size: calc(1.425rem + 2.1vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-5 { font-size: 3rem; } } .display-6 { font-size: calc(1.375rem + 1.5vw); font-weight: 300; line-height: 1.2; } @media (min-width: 1200px) { .display-6 { font-size: 2.5rem; } } .list-unstyled { padding-right: 0; list-style: none; } .list-inline { padding-right: 0; list-style: none; } .list-inline-item { display: inline-block; } .list-inline-item:not(:last-child) { margin-left: 0.5rem; } .initialism { font-size: 0.875em; text-transform: uppercase; } .blockquote { margin-bottom: 1rem; font-size: 1.25rem; } .blockquote > :last-child { margin-bottom: 0; } .blockquote-footer { margin-top: -1rem; margin-bottom: 1rem; font-size: 0.875em; color: #6c757d; } .blockquote-footer::before { content: "— "; } .img-fluid { max-width: 100%; height: auto; } .img-thumbnail { padding: 0.25rem; background-color: #fff; border: 1px solid var(--bs-border-color); border-radius: 0.375rem; max-width: 100%; height: auto; } .figure { display: inline-block; } .figure-img { margin-bottom: 0.5rem; line-height: 1; } .figure-caption { font-size: 0.875em; color: #6c757d; } .container, .container-fluid, .container-xxl, .container-xl, .container-lg, .container-md, .container-sm { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; width: 100%; padding-left: calc(var(--bs-gutter-x) * 0.5); padding-right: calc(var(--bs-gutter-x) * 0.5); margin-left: auto; margin-right: auto; } @media (min-width: 576px) { .container-sm, .container { max-width: 540px; } } @media (min-width: 768px) { .container-md, .container-sm, .container { max-width: 720px; } } @media (min-width: 992px) { .container-lg, .container-md, .container-sm, .container { max-width: 960px; } } @media (min-width: 1200px) { .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1140px; } } @media (min-width: 1400px) { .container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container { max-width: 1320px; } } .row { --bs-gutter-x: 1.5rem; --bs-gutter-y: 0; display: flex; flex-wrap: wrap; margin-top: calc(-1 * var(--bs-gutter-y)); margin-left: calc(-0.5 * var(--bs-gutter-x)); margin-right: calc(-0.5 * var(--bs-gutter-x)); } .row > * { flex-shrink: 0; width: 100%; max-width: 100%; padding-left: calc(var(--bs-gutter-x) * 0.5); padding-right: calc(var(--bs-gutter-x) * 0.5); margin-top: var(--bs-gutter-y); } .col { flex: 1 0 0%; } .row-cols-auto > * { flex: 0 0 auto; width: auto; } .row-cols-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-auto { flex: 0 0 auto; width: auto; } .col-1 { flex: 0 0 auto; width: 8.33333333%; } .col-2 { flex: 0 0 auto; width: 16.66666667%; } .col-3 { flex: 0 0 auto; width: 25%; } .col-4 { flex: 0 0 auto; width: 33.33333333%; } .col-5 { flex: 0 0 auto; width: 41.66666667%; } .col-6 { flex: 0 0 auto; width: 50%; } .col-7 { flex: 0 0 auto; width: 58.33333333%; } .col-8 { flex: 0 0 auto; width: 66.66666667%; } .col-9 { flex: 0 0 auto; width: 75%; } .col-10 { flex: 0 0 auto; width: 83.33333333%; } .col-11 { flex: 0 0 auto; width: 91.66666667%; } .col-12 { flex: 0 0 auto; width: 100%; } .offset-1 { margin-right: 8.33333333%; } .offset-2 { margin-right: 16.66666667%; } .offset-3 { margin-right: 25%; } .offset-4 { margin-right: 33.33333333%; } .offset-5 { margin-right: 41.66666667%; } .offset-6 { margin-right: 50%; } .offset-7 { margin-right: 58.33333333%; } .offset-8 { margin-right: 66.66666667%; } .offset-9 { margin-right: 75%; } .offset-10 { margin-right: 83.33333333%; } .offset-11 { margin-right: 91.66666667%; } .g-0, .gx-0 { --bs-gutter-x: 0; } .g-0, .gy-0 { --bs-gutter-y: 0; } .g-1, .gx-1 { --bs-gutter-x: 0.25rem; } .g-1, .gy-1 { --bs-gutter-y: 0.25rem; } .g-2, .gx-2 { --bs-gutter-x: 0.5rem; } .g-2, .gy-2 { --bs-gutter-y: 0.5rem; } .g-3, .gx-3 { --bs-gutter-x: 1rem; } .g-3, .gy-3 { --bs-gutter-y: 1rem; } .g-4, .gx-4 { --bs-gutter-x: 1.5rem; } .g-4, .gy-4 { --bs-gutter-y: 1.5rem; } .g-5, .gx-5 { --bs-gutter-x: 3rem; } .g-5, .gy-5 { --bs-gutter-y: 3rem; } @media (min-width: 576px) { .col-sm { flex: 1 0 0%; } .row-cols-sm-auto > * { flex: 0 0 auto; width: auto; } .row-cols-sm-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-sm-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-sm-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-sm-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-sm-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-sm-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-sm-auto { flex: 0 0 auto; width: auto; } .col-sm-1 { flex: 0 0 auto; width: 8.33333333%; } .col-sm-2 { flex: 0 0 auto; width: 16.66666667%; } .col-sm-3 { flex: 0 0 auto; width: 25%; } .col-sm-4 { flex: 0 0 auto; width: 33.33333333%; } .col-sm-5 { flex: 0 0 auto; width: 41.66666667%; } .col-sm-6 { flex: 0 0 auto; width: 50%; } .col-sm-7 { flex: 0 0 auto; width: 58.33333333%; } .col-sm-8 { flex: 0 0 auto; width: 66.66666667%; } .col-sm-9 { flex: 0 0 auto; width: 75%; } .col-sm-10 { flex: 0 0 auto; width: 83.33333333%; } .col-sm-11 { flex: 0 0 auto; width: 91.66666667%; } .col-sm-12 { flex: 0 0 auto; width: 100%; } .offset-sm-0 { margin-right: 0; } .offset-sm-1 { margin-right: 8.33333333%; } .offset-sm-2 { margin-right: 16.66666667%; } .offset-sm-3 { margin-right: 25%; } .offset-sm-4 { margin-right: 33.33333333%; } .offset-sm-5 { margin-right: 41.66666667%; } .offset-sm-6 { margin-right: 50%; } .offset-sm-7 { margin-right: 58.33333333%; } .offset-sm-8 { margin-right: 66.66666667%; } .offset-sm-9 { margin-right: 75%; } .offset-sm-10 { margin-right: 83.33333333%; } .offset-sm-11 { margin-right: 91.66666667%; } .g-sm-0, .gx-sm-0 { --bs-gutter-x: 0; } .g-sm-0, .gy-sm-0 { --bs-gutter-y: 0; } .g-sm-1, .gx-sm-1 { --bs-gutter-x: 0.25rem; } .g-sm-1, .gy-sm-1 { --bs-gutter-y: 0.25rem; } .g-sm-2, .gx-sm-2 { --bs-gutter-x: 0.5rem; } .g-sm-2, .gy-sm-2 { --bs-gutter-y: 0.5rem; } .g-sm-3, .gx-sm-3 { --bs-gutter-x: 1rem; } .g-sm-3, .gy-sm-3 { --bs-gutter-y: 1rem; } .g-sm-4, .gx-sm-4 { --bs-gutter-x: 1.5rem; } .g-sm-4, .gy-sm-4 { --bs-gutter-y: 1.5rem; } .g-sm-5, .gx-sm-5 { --bs-gutter-x: 3rem; } .g-sm-5, .gy-sm-5 { --bs-gutter-y: 3rem; } } @media (min-width: 768px) { .col-md { flex: 1 0 0%; } .row-cols-md-auto > * { flex: 0 0 auto; width: auto; } .row-cols-md-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-md-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-md-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-md-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-md-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-md-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-md-auto { flex: 0 0 auto; width: auto; } .col-md-1 { flex: 0 0 auto; width: 8.33333333%; } .col-md-2 { flex: 0 0 auto; width: 16.66666667%; } .col-md-3 { flex: 0 0 auto; width: 25%; } .col-md-4 { flex: 0 0 auto; width: 33.33333333%; } .col-md-5 { flex: 0 0 auto; width: 41.66666667%; } .col-md-6 { flex: 0 0 auto; width: 50%; } .col-md-7 { flex: 0 0 auto; width: 58.33333333%; } .col-md-8 { flex: 0 0 auto; width: 66.66666667%; } .col-md-9 { flex: 0 0 auto; width: 75%; } .col-md-10 { flex: 0 0 auto; width: 83.33333333%; } .col-md-11 { flex: 0 0 auto; width: 91.66666667%; } .col-md-12 { flex: 0 0 auto; width: 100%; } .offset-md-0 { margin-right: 0; } .offset-md-1 { margin-right: 8.33333333%; } .offset-md-2 { margin-right: 16.66666667%; } .offset-md-3 { margin-right: 25%; } .offset-md-4 { margin-right: 33.33333333%; } .offset-md-5 { margin-right: 41.66666667%; } .offset-md-6 { margin-right: 50%; } .offset-md-7 { margin-right: 58.33333333%; } .offset-md-8 { margin-right: 66.66666667%; } .offset-md-9 { margin-right: 75%; } .offset-md-10 { margin-right: 83.33333333%; } .offset-md-11 { margin-right: 91.66666667%; } .g-md-0, .gx-md-0 { --bs-gutter-x: 0; } .g-md-0, .gy-md-0 { --bs-gutter-y: 0; } .g-md-1, .gx-md-1 { --bs-gutter-x: 0.25rem; } .g-md-1, .gy-md-1 { --bs-gutter-y: 0.25rem; } .g-md-2, .gx-md-2 { --bs-gutter-x: 0.5rem; } .g-md-2, .gy-md-2 { --bs-gutter-y: 0.5rem; } .g-md-3, .gx-md-3 { --bs-gutter-x: 1rem; } .g-md-3, .gy-md-3 { --bs-gutter-y: 1rem; } .g-md-4, .gx-md-4 { --bs-gutter-x: 1.5rem; } .g-md-4, .gy-md-4 { --bs-gutter-y: 1.5rem; } .g-md-5, .gx-md-5 { --bs-gutter-x: 3rem; } .g-md-5, .gy-md-5 { --bs-gutter-y: 3rem; } } @media (min-width: 992px) { .col-lg { flex: 1 0 0%; } .row-cols-lg-auto > * { flex: 0 0 auto; width: auto; } .row-cols-lg-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-lg-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-lg-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-lg-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-lg-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-lg-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-lg-auto { flex: 0 0 auto; width: auto; } .col-lg-1 { flex: 0 0 auto; width: 8.33333333%; } .col-lg-2 { flex: 0 0 auto; width: 16.66666667%; } .col-lg-3 { flex: 0 0 auto; width: 25%; } .col-lg-4 { flex: 0 0 auto; width: 33.33333333%; } .col-lg-5 { flex: 0 0 auto; width: 41.66666667%; } .col-lg-6 { flex: 0 0 auto; width: 50%; } .col-lg-7 { flex: 0 0 auto; width: 58.33333333%; } .col-lg-8 { flex: 0 0 auto; width: 66.66666667%; } .col-lg-9 { flex: 0 0 auto; width: 75%; } .col-lg-10 { flex: 0 0 auto; width: 83.33333333%; } .col-lg-11 { flex: 0 0 auto; width: 91.66666667%; } .col-lg-12 { flex: 0 0 auto; width: 100%; } .offset-lg-0 { margin-right: 0; } .offset-lg-1 { margin-right: 8.33333333%; } .offset-lg-2 { margin-right: 16.66666667%; } .offset-lg-3 { margin-right: 25%; } .offset-lg-4 { margin-right: 33.33333333%; } .offset-lg-5 { margin-right: 41.66666667%; } .offset-lg-6 { margin-right: 50%; } .offset-lg-7 { margin-right: 58.33333333%; } .offset-lg-8 { margin-right: 66.66666667%; } .offset-lg-9 { margin-right: 75%; } .offset-lg-10 { margin-right: 83.33333333%; } .offset-lg-11 { margin-right: 91.66666667%; } .g-lg-0, .gx-lg-0 { --bs-gutter-x: 0; } .g-lg-0, .gy-lg-0 { --bs-gutter-y: 0; } .g-lg-1, .gx-lg-1 { --bs-gutter-x: 0.25rem; } .g-lg-1, .gy-lg-1 { --bs-gutter-y: 0.25rem; } .g-lg-2, .gx-lg-2 { --bs-gutter-x: 0.5rem; } .g-lg-2, .gy-lg-2 { --bs-gutter-y: 0.5rem; } .g-lg-3, .gx-lg-3 { --bs-gutter-x: 1rem; } .g-lg-3, .gy-lg-3 { --bs-gutter-y: 1rem; } .g-lg-4, .gx-lg-4 { --bs-gutter-x: 1.5rem; } .g-lg-4, .gy-lg-4 { --bs-gutter-y: 1.5rem; } .g-lg-5, .gx-lg-5 { --bs-gutter-x: 3rem; } .g-lg-5, .gy-lg-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1200px) { .col-xl { flex: 1 0 0%; } .row-cols-xl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xl-auto { flex: 0 0 auto; width: auto; } .col-xl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xl-3 { flex: 0 0 auto; width: 25%; } .col-xl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xl-6 { flex: 0 0 auto; width: 50%; } .col-xl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xl-9 { flex: 0 0 auto; width: 75%; } .col-xl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xl-12 { flex: 0 0 auto; width: 100%; } .offset-xl-0 { margin-right: 0; } .offset-xl-1 { margin-right: 8.33333333%; } .offset-xl-2 { margin-right: 16.66666667%; } .offset-xl-3 { margin-right: 25%; } .offset-xl-4 { margin-right: 33.33333333%; } .offset-xl-5 { margin-right: 41.66666667%; } .offset-xl-6 { margin-right: 50%; } .offset-xl-7 { margin-right: 58.33333333%; } .offset-xl-8 { margin-right: 66.66666667%; } .offset-xl-9 { margin-right: 75%; } .offset-xl-10 { margin-right: 83.33333333%; } .offset-xl-11 { margin-right: 91.66666667%; } .g-xl-0, .gx-xl-0 { --bs-gutter-x: 0; } .g-xl-0, .gy-xl-0 { --bs-gutter-y: 0; } .g-xl-1, .gx-xl-1 { --bs-gutter-x: 0.25rem; } .g-xl-1, .gy-xl-1 { --bs-gutter-y: 0.25rem; } .g-xl-2, .gx-xl-2 { --bs-gutter-x: 0.5rem; } .g-xl-2, .gy-xl-2 { --bs-gutter-y: 0.5rem; } .g-xl-3, .gx-xl-3 { --bs-gutter-x: 1rem; } .g-xl-3, .gy-xl-3 { --bs-gutter-y: 1rem; } .g-xl-4, .gx-xl-4 { --bs-gutter-x: 1.5rem; } .g-xl-4, .gy-xl-4 { --bs-gutter-y: 1.5rem; } .g-xl-5, .gx-xl-5 { --bs-gutter-x: 3rem; } .g-xl-5, .gy-xl-5 { --bs-gutter-y: 3rem; } } @media (min-width: 1400px) { .col-xxl { flex: 1 0 0%; } .row-cols-xxl-auto > * { flex: 0 0 auto; width: auto; } .row-cols-xxl-1 > * { flex: 0 0 auto; width: 100%; } .row-cols-xxl-2 > * { flex: 0 0 auto; width: 50%; } .row-cols-xxl-3 > * { flex: 0 0 auto; width: 33.3333333333%; } .row-cols-xxl-4 > * { flex: 0 0 auto; width: 25%; } .row-cols-xxl-5 > * { flex: 0 0 auto; width: 20%; } .row-cols-xxl-6 > * { flex: 0 0 auto; width: 16.6666666667%; } .col-xxl-auto { flex: 0 0 auto; width: auto; } .col-xxl-1 { flex: 0 0 auto; width: 8.33333333%; } .col-xxl-2 { flex: 0 0 auto; width: 16.66666667%; } .col-xxl-3 { flex: 0 0 auto; width: 25%; } .col-xxl-4 { flex: 0 0 auto; width: 33.33333333%; } .col-xxl-5 { flex: 0 0 auto; width: 41.66666667%; } .col-xxl-6 { flex: 0 0 auto; width: 50%; } .col-xxl-7 { flex: 0 0 auto; width: 58.33333333%; } .col-xxl-8 { flex: 0 0 auto; width: 66.66666667%; } .col-xxl-9 { flex: 0 0 auto; width: 75%; } .col-xxl-10 { flex: 0 0 auto; width: 83.33333333%; } .col-xxl-11 { flex: 0 0 auto; width: 91.66666667%; } .col-xxl-12 { flex: 0 0 auto; width: 100%; } .offset-xxl-0 { margin-right: 0; } .offset-xxl-1 { margin-right: 8.33333333%; } .offset-xxl-2 { margin-right: 16.66666667%; } .offset-xxl-3 { margin-right: 25%; } .offset-xxl-4 { margin-right: 33.33333333%; } .offset-xxl-5 { margin-right: 41.66666667%; } .offset-xxl-6 { margin-right: 50%; } .offset-xxl-7 { margin-right: 58.33333333%; } .offset-xxl-8 { margin-right: 66.66666667%; } .offset-xxl-9 { margin-right: 75%; } .offset-xxl-10 { margin-right: 83.33333333%; } .offset-xxl-11 { margin-right: 91.66666667%; } .g-xxl-0, .gx-xxl-0 { --bs-gutter-x: 0; } .g-xxl-0, .gy-xxl-0 { --bs-gutter-y: 0; } .g-xxl-1, .gx-xxl-1 { --bs-gutter-x: 0.25rem; } .g-xxl-1, .gy-xxl-1 { --bs-gutter-y: 0.25rem; } .g-xxl-2, .gx-xxl-2 { --bs-gutter-x: 0.5rem; } .g-xxl-2, .gy-xxl-2 { --bs-gutter-y: 0.5rem; } .g-xxl-3, .gx-xxl-3 { --bs-gutter-x: 1rem; } .g-xxl-3, .gy-xxl-3 { --bs-gutter-y: 1rem; } .g-xxl-4, .gx-xxl-4 { --bs-gutter-x: 1.5rem; } .g-xxl-4, .gy-xxl-4 { --bs-gutter-y: 1.5rem; } .g-xxl-5, .gx-xxl-5 { --bs-gutter-x: 3rem; } .g-xxl-5, .gy-xxl-5 { --bs-gutter-y: 3rem; } } .table { --bs-table-color: var(--bs-body-color); --bs-table-bg: transparent; --bs-table-border-color: var(--bs-border-color); --bs-table-accent-bg: transparent; --bs-table-striped-color: var(--bs-body-color); --bs-table-striped-bg: rgba(0, 0, 0, 0.05); --bs-table-active-color: var(--bs-body-color); --bs-table-active-bg: rgba(0, 0, 0, 0.1); --bs-table-hover-color: var(--bs-body-color); --bs-table-hover-bg: rgba(0, 0, 0, 0.075); width: 100%; margin-bottom: 1rem; color: var(--bs-table-color); vertical-align: top; border-color: var(--bs-table-border-color); } .table > :not(caption) > * > * { padding: 0.5rem 0.5rem; background-color: var(--bs-table-bg); border-bottom-width: 1px; box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); } .table > tbody { vertical-align: inherit; } .table > thead { vertical-align: bottom; } .table-group-divider { border-top: 2px solid currentcolor; } .caption-top { caption-side: top; } .table-sm > :not(caption) > * > * { padding: 0.25rem 0.25rem; } .table-bordered > :not(caption) > * { border-width: 1px 0; } .table-bordered > :not(caption) > * > * { border-width: 0 1px; } .table-borderless > :not(caption) > * > * { border-bottom-width: 0; } .table-borderless > :not(:first-child) { border-top-width: 0; } .table-striped > tbody > tr:nth-of-type(odd) > * { --bs-table-accent-bg: var(--bs-table-striped-bg); color: var(--bs-table-striped-color); } .table-striped-columns > :not(caption) > tr > :nth-child(even) { --bs-table-accent-bg: var(--bs-table-striped-bg); color: var(--bs-table-striped-color); } .table-active { --bs-table-accent-bg: var(--bs-table-active-bg); color: var(--bs-table-active-color); } .table-hover > tbody > tr:hover > * { --bs-table-accent-bg: var(--bs-table-hover-bg); color: var(--bs-table-hover-color); } .table-primary { --bs-table-color: #000; --bs-table-bg: #cfe2ff; --bs-table-border-color: #bacbe6; --bs-table-striped-bg: #c5d7f2; --bs-table-striped-color: #000; --bs-table-active-bg: #bacbe6; --bs-table-active-color: #000; --bs-table-hover-bg: #bfd1ec; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-secondary { --bs-table-color: #000; --bs-table-bg: #e2e3e5; --bs-table-border-color: #cbccce; --bs-table-striped-bg: #d7d8da; --bs-table-striped-color: #000; --bs-table-active-bg: #cbccce; --bs-table-active-color: #000; --bs-table-hover-bg: #d1d2d4; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-success { --bs-table-color: #000; --bs-table-bg: #d1e7dd; --bs-table-border-color: #bcd0c7; --bs-table-striped-bg: #c7dbd2; --bs-table-striped-color: #000; --bs-table-active-bg: #bcd0c7; --bs-table-active-color: #000; --bs-table-hover-bg: #c1d6cc; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-info { --bs-table-color: #000; --bs-table-bg: #cff4fc; --bs-table-border-color: #badce3; --bs-table-striped-bg: #c5e8ef; --bs-table-striped-color: #000; --bs-table-active-bg: #badce3; --bs-table-active-color: #000; --bs-table-hover-bg: #bfe2e9; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-warning { --bs-table-color: #000; --bs-table-bg: #fff3cd; --bs-table-border-color: #e6dbb9; --bs-table-striped-bg: #f2e7c3; --bs-table-striped-color: #000; --bs-table-active-bg: #e6dbb9; --bs-table-active-color: #000; --bs-table-hover-bg: #ece1be; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-danger { --bs-table-color: #000; --bs-table-bg: #f8d7da; --bs-table-border-color: #dfc2c4; --bs-table-striped-bg: #eccccf; --bs-table-striped-color: #000; --bs-table-active-bg: #dfc2c4; --bs-table-active-color: #000; --bs-table-hover-bg: #e5c7ca; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-light { --bs-table-color: #000; --bs-table-bg: #f8f9fa; --bs-table-border-color: #dfe0e1; --bs-table-striped-bg: #ecedee; --bs-table-striped-color: #000; --bs-table-active-bg: #dfe0e1; --bs-table-active-color: #000; --bs-table-hover-bg: #e5e6e7; --bs-table-hover-color: #000; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-dark { --bs-table-color: #fff; --bs-table-bg: #212529; --bs-table-border-color: #373b3e; --bs-table-striped-bg: #2c3034; --bs-table-striped-color: #fff; --bs-table-active-bg: #373b3e; --bs-table-active-color: #fff; --bs-table-hover-bg: #323539; --bs-table-hover-color: #fff; color: var(--bs-table-color); border-color: var(--bs-table-border-color); } .table-responsive { overflow-x: auto; -webkit-overflow-scrolling: touch; } @media (max-width: 575.98px) { .table-responsive-sm { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 767.98px) { .table-responsive-md { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 991.98px) { .table-responsive-lg { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1199.98px) { .table-responsive-xl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } @media (max-width: 1399.98px) { .table-responsive-xxl { overflow-x: auto; -webkit-overflow-scrolling: touch; } } .form-label { margin-bottom: 0.5rem; } .col-form-label { padding-top: calc(0.375rem + 1px); padding-bottom: calc(0.375rem + 1px); margin-bottom: 0; font-size: inherit; line-height: 1.5; } .col-form-label-lg { padding-top: calc(0.5rem + 1px); padding-bottom: calc(0.5rem + 1px); font-size: 1.25rem; } .col-form-label-sm { padding-top: calc(0.25rem + 1px); padding-bottom: calc(0.25rem + 1px); font-size: 0.875rem; } .form-text { margin-top: 0.25rem; font-size: 0.875em; color: #6c757d; } .form-control { display: block; width: 100%; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-clip: padding-box; border: 1px solid #ced4da; -webkit-appearance: none; -moz-appearance: none; appearance: none; border-radius: 0.375rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control { transition: none; } } .form-control[type=file] { overflow: hidden; } .form-control[type=file]:not(:disabled):not([readonly]) { cursor: pointer; } .form-control:focus { color: #212529; background-color: #fff; border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-control::-webkit-date-and-time-value { height: 1.5em; } .form-control::-moz-placeholder { color: #6c757d; opacity: 1; } .form-control::placeholder { color: #6c757d; opacity: 1; } .form-control:disabled { background-color: #e9ecef; opacity: 1; } .form-control::-webkit-file-upload-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; -webkit-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } .form-control::file-selector-button { padding: 0.375rem 0.75rem; margin: -0.375rem -0.75rem; -webkit-margin-end: 0.75rem; margin-inline-end: 0.75rem; color: #212529; background-color: #e9ecef; pointer-events: none; border-color: inherit; border-style: solid; border-width: 0; border-inline-end-width: 1px; border-radius: 0; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-control::-webkit-file-upload-button { -webkit-transition: none; transition: none; } .form-control::file-selector-button { transition: none; } } .form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { background-color: #dde0e3; } .form-control:hover:not(:disabled):not([readonly])::file-selector-button { background-color: #dde0e3; } .form-control-plaintext { display: block; width: 100%; padding: 0.375rem 0; margin-bottom: 0; line-height: 1.5; color: #212529; background-color: transparent; border: solid transparent; border-width: 1px 0; } .form-control-plaintext:focus { outline: 0; } .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { padding-left: 0; padding-right: 0; } .form-control-sm { min-height: calc(1.5em + 0.5rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .form-control-sm::-webkit-file-upload-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-sm::file-selector-button { padding: 0.25rem 0.5rem; margin: -0.25rem -0.5rem; -webkit-margin-end: 0.5rem; margin-inline-end: 0.5rem; } .form-control-lg { min-height: calc(1.5em + 1rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .form-control-lg::-webkit-file-upload-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } .form-control-lg::file-selector-button { padding: 0.5rem 1rem; margin: -0.5rem -1rem; -webkit-margin-end: 1rem; margin-inline-end: 1rem; } textarea.form-control { min-height: calc(1.5em + 0.75rem + 2px); } textarea.form-control-sm { min-height: calc(1.5em + 0.5rem + 2px); } textarea.form-control-lg { min-height: calc(1.5em + 1rem + 2px); } .form-control-color { width: 3rem; height: calc(1.5em + 0.75rem + 2px); padding: 0.375rem; } .form-control-color:not(:disabled):not([readonly]) { cursor: pointer; } .form-control-color::-moz-color-swatch { border: 0 !important; border-radius: 0.375rem; } .form-control-color::-webkit-color-swatch { border-radius: 0.375rem; } .form-control-color.form-control-sm { height: calc(1.5em + 0.5rem + 2px); } .form-control-color.form-control-lg { height: calc(1.5em + 1rem + 2px); } .form-select { display: block; width: 100%; padding: 0.375rem 0.75rem 0.375rem 2.25rem; -moz-padding-start: calc(0.75rem - 3px); font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; background-color: #fff; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: left 0.75rem center; background-size: 16px 12px; border: 1px solid #ced4da; border-radius: 0.375rem; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-select { transition: none; } } .form-select:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-select[multiple], .form-select[size]:not([size="1"]) { padding-left: 0.75rem; background-image: none; } .form-select:disabled { background-color: #e9ecef; } .form-select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #212529; } .form-select-sm { padding-top: 0.25rem; padding-bottom: 0.25rem; padding-right: 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .form-select-lg { padding-top: 0.5rem; padding-bottom: 0.5rem; padding-right: 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .form-check { display: block; min-height: 1.5rem; padding-right: 1.5em; margin-bottom: 0.125rem; } .form-check .form-check-input { float: right; margin-right: -1.5em; } .form-check-reverse { padding-left: 1.5em; padding-right: 0; text-align: left; } .form-check-reverse .form-check-input { float: left; margin-left: -1.5em; margin-right: 0; } .form-check-input { width: 1em; height: 1em; margin-top: 0.25em; vertical-align: top; background-color: #fff; background-repeat: no-repeat; background-position: center; background-size: contain; border: 1px solid rgba(0, 0, 0, 0.25); -webkit-appearance: none; -moz-appearance: none; appearance: none; -webkit-print-color-adjust: exact; color-adjust: exact; print-color-adjust: exact; } .form-check-input[type=checkbox] { border-radius: 0.25em; } .form-check-input[type=radio] { border-radius: 50%; } .form-check-input:active { filter: brightness(90%); } .form-check-input:focus { border-color: #86b7fe; outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-check-input:checked { background-color: #0d6efd; border-color: #0d6efd; } .form-check-input:checked[type=checkbox] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='m6 10 3 3 6-6'/%3e%3c/svg%3e"); } .form-check-input:checked[type=radio] { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e"); } .form-check-input[type=checkbox]:indeterminate { background-color: #0d6efd; border-color: #0d6efd; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e"); } .form-check-input:disabled { pointer-events: none; filter: none; opacity: 0.5; } .form-check-input[disabled] ~ .form-check-label, .form-check-input:disabled ~ .form-check-label { cursor: default; opacity: 0.5; } .form-switch { padding-right: 2.5em; } .form-switch .form-check-input { width: 2em; margin-right: -2.5em; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); background-position: right center; border-radius: 2em; transition: background-position 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-switch .form-check-input { transition: none; } } .form-switch .form-check-input:focus { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e"); } .form-switch .form-check-input:checked { background-position: left center; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } .form-switch.form-check-reverse { padding-left: 2.5em; padding-right: 0; } .form-switch.form-check-reverse .form-check-input { margin-left: -2.5em; margin-right: 0; } .form-check-inline { display: inline-block; margin-left: 1rem; } .btn-check { position: absolute; clip: rect(0, 0, 0, 0); pointer-events: none; } .btn-check[disabled] + .btn, .btn-check:disabled + .btn { pointer-events: none; filter: none; opacity: 0.65; } .form-range { width: 100%; height: 1.5rem; padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; appearance: none; } .form-range:focus { outline: 0; } .form-range:focus::-webkit-slider-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range:focus::-moz-range-thumb { box-shadow: 0 0 0 1px #fff, 0 0 0 0.25rem rgba(13, 110, 253, 0.25); } .form-range::-moz-focus-outer { border: 0; } .form-range::-webkit-slider-thumb { width: 1rem; height: 1rem; margin-top: -0.25rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -webkit-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -webkit-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-webkit-slider-thumb { -webkit-transition: none; transition: none; } } .form-range::-webkit-slider-thumb:active { background-color: #b6d4fe; } .form-range::-webkit-slider-runnable-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range::-moz-range-thumb { width: 1rem; height: 1rem; background-color: #0d6efd; border: 0; border-radius: 1rem; -moz-transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; -moz-appearance: none; appearance: none; } @media (prefers-reduced-motion: reduce) { .form-range::-moz-range-thumb { -moz-transition: none; transition: none; } } .form-range::-moz-range-thumb:active { background-color: #b6d4fe; } .form-range::-moz-range-track { width: 100%; height: 0.5rem; color: transparent; cursor: pointer; background-color: #dee2e6; border-color: transparent; border-radius: 1rem; } .form-range:disabled { pointer-events: none; } .form-range:disabled::-webkit-slider-thumb { background-color: #adb5bd; } .form-range:disabled::-moz-range-thumb { background-color: #adb5bd; } .form-floating { position: relative; } .form-floating > .form-control, .form-floating > .form-control-plaintext, .form-floating > .form-select { height: calc(3.5rem + 2px); line-height: 1.25; } .form-floating > label { position: absolute; top: 0; right: 0; width: 100%; height: 100%; padding: 1rem 0.75rem; overflow: hidden; text-align: start; text-overflow: ellipsis; white-space: nowrap; pointer-events: none; border: 1px solid transparent; transform-origin: 100% 0; transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; } @media (prefers-reduced-motion: reduce) { .form-floating > label { transition: none; } } .form-floating > .form-control, .form-floating > .form-control-plaintext { padding: 1rem 0.75rem; } .form-floating > .form-control::-moz-placeholder, .form-floating > .form-control-plaintext::-moz-placeholder { color: transparent; } .form-floating > .form-control::placeholder, .form-floating > .form-control-plaintext::placeholder { color: transparent; } .form-floating > .form-control:not(:-moz-placeholder-shown), .form-floating > .form-control-plaintext:not(:-moz-placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown), .form-floating > .form-control-plaintext:focus, .form-floating > .form-control-plaintext:not(:placeholder-shown) { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:-webkit-autofill, .form-floating > .form-control-plaintext:-webkit-autofill { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-select { padding-top: 1.625rem; padding-bottom: 0.625rem; } .form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(-0.15rem); } .form-floating > .form-control:focus ~ label, .form-floating > .form-control:not(:placeholder-shown) ~ label, .form-floating > .form-control-plaintext ~ label, .form-floating > .form-select ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(-0.15rem); } .form-floating > .form-control:-webkit-autofill ~ label { opacity: 0.65; transform: scale(0.85) translateY(-0.5rem) translateX(-0.15rem); } .form-floating > .form-control-plaintext ~ label { border-width: 1px 0; } .input-group { position: relative; display: flex; flex-wrap: wrap; align-items: stretch; width: 100%; } .input-group > .form-control, .input-group > .form-select, .input-group > .form-floating { position: relative; flex: 1 1 auto; width: 1%; min-width: 0; } .input-group > .form-control:focus, .input-group > .form-select:focus, .input-group > .form-floating:focus-within { z-index: 5; } .input-group .btn { position: relative; z-index: 2; } .input-group .btn:focus { z-index: 5; } .input-group-text { display: flex; align-items: center; padding: 0.375rem 0.75rem; font-size: 1rem; font-weight: 400; line-height: 1.5; color: #212529; text-align: center; white-space: nowrap; background-color: #e9ecef; border: 1px solid #ced4da; border-radius: 0.375rem; } .input-group-lg > .form-control, .input-group-lg > .form-select, .input-group-lg > .input-group-text, .input-group-lg > .btn { padding: 0.5rem 1rem; font-size: 1.25rem; border-radius: 0.5rem; } .input-group-sm > .form-control, .input-group-sm > .form-select, .input-group-sm > .input-group-text, .input-group-sm > .btn { padding: 0.25rem 0.5rem; font-size: 0.875rem; border-radius: 0.25rem; } .input-group-lg > .form-select, .input-group-sm > .form-select { padding-left: 3rem; } .input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), .input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3), .input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-control, .input-group:not(.has-validation) > .form-floating:not(:last-child) > .form-select { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu):not(.form-floating), .input-group.has-validation > .dropdown-toggle:nth-last-child(n+4), .input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-control, .input-group.has-validation > .form-floating:nth-last-child(n+3) > .form-select { border-top-left-radius: 0; border-bottom-left-radius: 0; } .input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { margin-right: -1px; border-top-right-radius: 0; border-bottom-right-radius: 0; } .input-group > .form-floating:not(:first-child) > .form-control, .input-group > .form-floating:not(:first-child) > .form-select { border-top-right-radius: 0; border-bottom-right-radius: 0; } .valid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #198754; } .valid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(25, 135, 84, 0.9); border-radius: 0.375rem; } .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip, .is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip { display: block; } .was-validated .form-control:valid, .form-control.is-valid { border-color: #198754; padding-left: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: left calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated textarea.form-control:valid, textarea.form-control.is-valid { padding-left: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) left calc(0.375em + 0.1875rem); } .was-validated .form-select:valid, .form-select.is-valid { border-color: #198754; } .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"], .form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"] { padding-left: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); background-position: left 0.75rem center, center left 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:valid:focus, .form-select.is-valid:focus { border-color: #198754; box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-control-color:valid, .form-control-color.is-valid { width: calc(3rem + calc(1.5em + 0.75rem)); } .was-validated .form-check-input:valid, .form-check-input.is-valid { border-color: #198754; } .was-validated .form-check-input:valid:checked, .form-check-input.is-valid:checked { background-color: #198754; } .was-validated .form-check-input:valid:focus, .form-check-input.is-valid:focus { box-shadow: 0 0 0 0.25rem rgba(25, 135, 84, 0.25); } .was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { color: #198754; } .form-check-inline .form-check-input ~ .valid-feedback { margin-right: 0.5em; } .was-validated .input-group > .form-control:not(:focus):valid, .input-group > .form-control:not(:focus).is-valid, .was-validated .input-group > .form-select:not(:focus):valid, .input-group > .form-select:not(:focus).is-valid, .was-validated .input-group > .form-floating:not(:focus-within):valid, .input-group > .form-floating:not(:focus-within).is-valid { z-index: 3; } .invalid-feedback { display: none; width: 100%; margin-top: 0.25rem; font-size: 0.875em; color: #dc3545; } .invalid-tooltip { position: absolute; top: 100%; z-index: 5; display: none; max-width: 100%; padding: 0.25rem 0.5rem; margin-top: 0.1rem; font-size: 0.875rem; color: #fff; background-color: rgba(220, 53, 69, 0.9); border-radius: 0.375rem; } .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip, .is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip { display: block; } .was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; padding-left: calc(1.5em + 0.75rem); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-repeat: no-repeat; background-position: left calc(0.375em + 0.1875rem) center; background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { padding-left: calc(1.5em + 0.75rem); background-position: top calc(0.375em + 0.1875rem) left calc(0.375em + 0.1875rem); } .was-validated .form-select:invalid, .form-select.is-invalid { border-color: #dc3545; } .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"], .form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"] { padding-left: 4.125rem; background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); background-position: left 0.75rem center, center left 2.25rem; background-size: 16px 12px, calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } .was-validated .form-select:invalid:focus, .form-select.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-control-color:invalid, .form-control-color.is-invalid { width: calc(3rem + calc(1.5em + 0.75rem)); } .was-validated .form-check-input:invalid, .form-check-input.is-invalid { border-color: #dc3545; } .was-validated .form-check-input:invalid:checked, .form-check-input.is-invalid:checked { background-color: #dc3545; } .was-validated .form-check-input:invalid:focus, .form-check-input.is-invalid:focus { box-shadow: 0 0 0 0.25rem rgba(220, 53, 69, 0.25); } .was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { color: #dc3545; } .form-check-inline .form-check-input ~ .invalid-feedback { margin-right: 0.5em; } .was-validated .input-group > .form-control:not(:focus):invalid, .input-group > .form-control:not(:focus).is-invalid, .was-validated .input-group > .form-select:not(:focus):invalid, .input-group > .form-select:not(:focus).is-invalid, .was-validated .input-group > .form-floating:not(:focus-within):invalid, .input-group > .form-floating:not(:focus-within).is-invalid { z-index: 4; } .btn { --bs-btn-padding-x: 0.75rem; --bs-btn-padding-y: 0.375rem; --bs-btn-font-family: ; --bs-btn-font-size: 1rem; --bs-btn-font-weight: 400; --bs-btn-line-height: 1.5; --bs-btn-color: #212529; --bs-btn-bg: transparent; --bs-btn-border-width: 1px; --bs-btn-border-color: transparent; --bs-btn-border-radius: 0.375rem; --bs-btn-hover-border-color: transparent; --bs-btn-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); --bs-btn-disabled-opacity: 0.65; --bs-btn-focus-box-shadow: 0 0 0 0.25rem rgba(var(--bs-btn-focus-shadow-rgb), .5); display: inline-block; padding: var(--bs-btn-padding-y) var(--bs-btn-padding-x); font-family: var(--bs-btn-font-family); font-size: var(--bs-btn-font-size); font-weight: var(--bs-btn-font-weight); line-height: var(--bs-btn-line-height); color: var(--bs-btn-color); text-align: center; text-decoration: none; vertical-align: middle; cursor: pointer; -webkit-user-select: none; -moz-user-select: none; user-select: none; border: var(--bs-btn-border-width) solid var(--bs-btn-border-color); border-radius: var(--bs-btn-border-radius); background-color: var(--bs-btn-bg); transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .btn { transition: none; } } .btn:hover { color: var(--bs-btn-hover-color); background-color: var(--bs-btn-hover-bg); border-color: var(--bs-btn-hover-border-color); } .btn-check + .btn:hover { color: var(--bs-btn-color); background-color: var(--bs-btn-bg); border-color: var(--bs-btn-border-color); } .btn:focus-visible { color: var(--bs-btn-hover-color); background-color: var(--bs-btn-hover-bg); border-color: var(--bs-btn-hover-border-color); outline: 0; box-shadow: var(--bs-btn-focus-box-shadow); } .btn-check:focus-visible + .btn { border-color: var(--bs-btn-hover-border-color); outline: 0; box-shadow: var(--bs-btn-focus-box-shadow); } .btn-check:checked + .btn, :not(.btn-check) + .btn:active, .btn:first-child:active, .btn.active, .btn.show { color: var(--bs-btn-active-color); background-color: var(--bs-btn-active-bg); border-color: var(--bs-btn-active-border-color); } .btn-check:checked + .btn:focus-visible, :not(.btn-check) + .btn:active:focus-visible, .btn:first-child:active:focus-visible, .btn.active:focus-visible, .btn.show:focus-visible { box-shadow: var(--bs-btn-focus-box-shadow); } .btn:disabled, .btn.disabled, fieldset:disabled .btn { color: var(--bs-btn-disabled-color); pointer-events: none; background-color: var(--bs-btn-disabled-bg); border-color: var(--bs-btn-disabled-border-color); opacity: var(--bs-btn-disabled-opacity); } .btn-primary { --bs-btn-color: #fff; --bs-btn-bg: #0d6efd; --bs-btn-border-color: #0d6efd; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #0b5ed7; --bs-btn-hover-border-color: #0a58ca; --bs-btn-focus-shadow-rgb: 49, 132, 253; --bs-btn-active-color: #fff; --bs-btn-active-bg: #0a58ca; --bs-btn-active-border-color: #0a53be; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #0d6efd; --bs-btn-disabled-border-color: #0d6efd; } .btn-secondary { --bs-btn-color: #fff; --bs-btn-bg: #6c757d; --bs-btn-border-color: #6c757d; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #5c636a; --bs-btn-hover-border-color: #565e64; --bs-btn-focus-shadow-rgb: 130, 138, 145; --bs-btn-active-color: #fff; --bs-btn-active-bg: #565e64; --bs-btn-active-border-color: #51585e; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #6c757d; --bs-btn-disabled-border-color: #6c757d; } .btn-success { --bs-btn-color: #fff; --bs-btn-bg: #198754; --bs-btn-border-color: #198754; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #157347; --bs-btn-hover-border-color: #146c43; --bs-btn-focus-shadow-rgb: 60, 153, 110; --bs-btn-active-color: #fff; --bs-btn-active-bg: #146c43; --bs-btn-active-border-color: #13653f; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #198754; --bs-btn-disabled-border-color: #198754; } .btn-info { --bs-btn-color: #000; --bs-btn-bg: #0dcaf0; --bs-btn-border-color: #0dcaf0; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #31d2f2; --bs-btn-hover-border-color: #25cff2; --bs-btn-focus-shadow-rgb: 11, 172, 204; --bs-btn-active-color: #000; --bs-btn-active-bg: #3dd5f3; --bs-btn-active-border-color: #25cff2; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #0dcaf0; --bs-btn-disabled-border-color: #0dcaf0; } .btn-warning { --bs-btn-color: #000; --bs-btn-bg: #ffc107; --bs-btn-border-color: #ffc107; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #ffca2c; --bs-btn-hover-border-color: #ffc720; --bs-btn-focus-shadow-rgb: 217, 164, 6; --bs-btn-active-color: #000; --bs-btn-active-bg: #ffcd39; --bs-btn-active-border-color: #ffc720; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #ffc107; --bs-btn-disabled-border-color: #ffc107; } .btn-danger { --bs-btn-color: #fff; --bs-btn-bg: #dc3545; --bs-btn-border-color: #dc3545; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #bb2d3b; --bs-btn-hover-border-color: #b02a37; --bs-btn-focus-shadow-rgb: 225, 83, 97; --bs-btn-active-color: #fff; --bs-btn-active-bg: #b02a37; --bs-btn-active-border-color: #a52834; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #dc3545; --bs-btn-disabled-border-color: #dc3545; } .btn-light { --bs-btn-color: #000; --bs-btn-bg: #f8f9fa; --bs-btn-border-color: #f8f9fa; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #d3d4d5; --bs-btn-hover-border-color: #c6c7c8; --bs-btn-focus-shadow-rgb: 211, 212, 213; --bs-btn-active-color: #000; --bs-btn-active-bg: #c6c7c8; --bs-btn-active-border-color: #babbbc; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #000; --bs-btn-disabled-bg: #f8f9fa; --bs-btn-disabled-border-color: #f8f9fa; } .btn-dark { --bs-btn-color: #fff; --bs-btn-bg: #212529; --bs-btn-border-color: #212529; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #424649; --bs-btn-hover-border-color: #373b3e; --bs-btn-focus-shadow-rgb: 66, 70, 73; --bs-btn-active-color: #fff; --bs-btn-active-bg: #4d5154; --bs-btn-active-border-color: #373b3e; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #fff; --bs-btn-disabled-bg: #212529; --bs-btn-disabled-border-color: #212529; } .btn-outline-primary { --bs-btn-color: #0d6efd; --bs-btn-border-color: #0d6efd; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #0d6efd; --bs-btn-hover-border-color: #0d6efd; --bs-btn-focus-shadow-rgb: 13, 110, 253; --bs-btn-active-color: #fff; --bs-btn-active-bg: #0d6efd; --bs-btn-active-border-color: #0d6efd; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #0d6efd; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #0d6efd; --bs-gradient: none; } .btn-outline-secondary { --bs-btn-color: #6c757d; --bs-btn-border-color: #6c757d; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #6c757d; --bs-btn-hover-border-color: #6c757d; --bs-btn-focus-shadow-rgb: 108, 117, 125; --bs-btn-active-color: #fff; --bs-btn-active-bg: #6c757d; --bs-btn-active-border-color: #6c757d; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #6c757d; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #6c757d; --bs-gradient: none; } .btn-outline-success { --bs-btn-color: #198754; --bs-btn-border-color: #198754; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #198754; --bs-btn-hover-border-color: #198754; --bs-btn-focus-shadow-rgb: 25, 135, 84; --bs-btn-active-color: #fff; --bs-btn-active-bg: #198754; --bs-btn-active-border-color: #198754; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #198754; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #198754; --bs-gradient: none; } .btn-outline-info { --bs-btn-color: #0dcaf0; --bs-btn-border-color: #0dcaf0; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #0dcaf0; --bs-btn-hover-border-color: #0dcaf0; --bs-btn-focus-shadow-rgb: 13, 202, 240; --bs-btn-active-color: #000; --bs-btn-active-bg: #0dcaf0; --bs-btn-active-border-color: #0dcaf0; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #0dcaf0; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #0dcaf0; --bs-gradient: none; } .btn-outline-warning { --bs-btn-color: #ffc107; --bs-btn-border-color: #ffc107; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #ffc107; --bs-btn-hover-border-color: #ffc107; --bs-btn-focus-shadow-rgb: 255, 193, 7; --bs-btn-active-color: #000; --bs-btn-active-bg: #ffc107; --bs-btn-active-border-color: #ffc107; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #ffc107; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #ffc107; --bs-gradient: none; } .btn-outline-danger { --bs-btn-color: #dc3545; --bs-btn-border-color: #dc3545; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #dc3545; --bs-btn-hover-border-color: #dc3545; --bs-btn-focus-shadow-rgb: 220, 53, 69; --bs-btn-active-color: #fff; --bs-btn-active-bg: #dc3545; --bs-btn-active-border-color: #dc3545; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #dc3545; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #dc3545; --bs-gradient: none; } .btn-outline-light { --bs-btn-color: #f8f9fa; --bs-btn-border-color: #f8f9fa; --bs-btn-hover-color: #000; --bs-btn-hover-bg: #f8f9fa; --bs-btn-hover-border-color: #f8f9fa; --bs-btn-focus-shadow-rgb: 248, 249, 250; --bs-btn-active-color: #000; --bs-btn-active-bg: #f8f9fa; --bs-btn-active-border-color: #f8f9fa; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #f8f9fa; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #f8f9fa; --bs-gradient: none; } .btn-outline-dark { --bs-btn-color: #212529; --bs-btn-border-color: #212529; --bs-btn-hover-color: #fff; --bs-btn-hover-bg: #212529; --bs-btn-hover-border-color: #212529; --bs-btn-focus-shadow-rgb: 33, 37, 41; --bs-btn-active-color: #fff; --bs-btn-active-bg: #212529; --bs-btn-active-border-color: #212529; --bs-btn-active-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); --bs-btn-disabled-color: #212529; --bs-btn-disabled-bg: transparent; --bs-btn-disabled-border-color: #212529; --bs-gradient: none; } .btn-link { --bs-btn-font-weight: 400; --bs-btn-color: var(--bs-link-color); --bs-btn-bg: transparent; --bs-btn-border-color: transparent; --bs-btn-hover-color: var(--bs-link-hover-color); --bs-btn-hover-border-color: transparent; --bs-btn-active-color: var(--bs-link-hover-color); --bs-btn-active-border-color: transparent; --bs-btn-disabled-color: #6c757d; --bs-btn-disabled-border-color: transparent; --bs-btn-box-shadow: none; --bs-btn-focus-shadow-rgb: 49, 132, 253; text-decoration: underline; } .btn-link:focus-visible { color: var(--bs-btn-color); } .btn-link:hover { color: var(--bs-btn-hover-color); } .btn-lg, .btn-group-lg > .btn { --bs-btn-padding-y: 0.5rem; --bs-btn-padding-x: 1rem; --bs-btn-font-size: 1.25rem; --bs-btn-border-radius: 0.5rem; } .btn-sm, .btn-group-sm > .btn { --bs-btn-padding-y: 0.25rem; --bs-btn-padding-x: 0.5rem; --bs-btn-font-size: 0.875rem; --bs-btn-border-radius: 0.25rem; } .fade { transition: opacity 0.15s linear; } @media (prefers-reduced-motion: reduce) { .fade { transition: none; } } .fade:not(.show) { opacity: 0; } .collapse:not(.show) { display: none; } .collapsing { height: 0; overflow: hidden; transition: height 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } } .collapsing.collapse-horizontal { width: 0; height: auto; transition: width 0.35s ease; } @media (prefers-reduced-motion: reduce) { .collapsing.collapse-horizontal { transition: none; } } .dropup, .dropend, .dropdown, .dropstart, .dropup-center, .dropdown-center { position: relative; } .dropdown-toggle { white-space: nowrap; } .dropdown-toggle::after { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid; border-left: 0.3em solid transparent; border-bottom: 0; border-right: 0.3em solid transparent; } .dropdown-toggle:empty::after { margin-right: 0; } .dropdown-menu { --bs-dropdown-zindex: 1000; --bs-dropdown-min-width: 10rem; --bs-dropdown-padding-x: 0; --bs-dropdown-padding-y: 0.5rem; --bs-dropdown-spacer: 0.125rem; --bs-dropdown-font-size: 1rem; --bs-dropdown-color: #212529; --bs-dropdown-bg: #fff; --bs-dropdown-border-color: var(--bs-border-color-translucent); --bs-dropdown-border-radius: 0.375rem; --bs-dropdown-border-width: 1px; --bs-dropdown-inner-border-radius: calc(0.375rem - 1px); --bs-dropdown-divider-bg: var(--bs-border-color-translucent); --bs-dropdown-divider-margin-y: 0.5rem; --bs-dropdown-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-dropdown-link-color: #212529; --bs-dropdown-link-hover-color: #1e2125; --bs-dropdown-link-hover-bg: #e9ecef; --bs-dropdown-link-active-color: #fff; --bs-dropdown-link-active-bg: #0d6efd; --bs-dropdown-link-disabled-color: #adb5bd; --bs-dropdown-item-padding-x: 1rem; --bs-dropdown-item-padding-y: 0.25rem; --bs-dropdown-header-color: #6c757d; --bs-dropdown-header-padding-x: 1rem; --bs-dropdown-header-padding-y: 0.5rem; position: absolute; z-index: var(--bs-dropdown-zindex); display: none; min-width: var(--bs-dropdown-min-width); padding: var(--bs-dropdown-padding-y) var(--bs-dropdown-padding-x); margin: 0; font-size: var(--bs-dropdown-font-size); color: var(--bs-dropdown-color); text-align: right; list-style: none; background-color: var(--bs-dropdown-bg); background-clip: padding-box; border: var(--bs-dropdown-border-width) solid var(--bs-dropdown-border-color); border-radius: var(--bs-dropdown-border-radius); } .dropdown-menu[data-bs-popper] { top: 100%; right: 0; margin-top: var(--bs-dropdown-spacer); } .dropdown-menu-start { --bs-position: start; } .dropdown-menu-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-end { --bs-position: end; } .dropdown-menu-end[data-bs-popper] { left: 0; right: auto; } @media (min-width: 576px) { .dropdown-menu-sm-start { --bs-position: start; } .dropdown-menu-sm-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-sm-end { --bs-position: end; } .dropdown-menu-sm-end[data-bs-popper] { left: 0; right: auto; } } @media (min-width: 768px) { .dropdown-menu-md-start { --bs-position: start; } .dropdown-menu-md-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-md-end { --bs-position: end; } .dropdown-menu-md-end[data-bs-popper] { left: 0; right: auto; } } @media (min-width: 992px) { .dropdown-menu-lg-start { --bs-position: start; } .dropdown-menu-lg-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-lg-end { --bs-position: end; } .dropdown-menu-lg-end[data-bs-popper] { left: 0; right: auto; } } @media (min-width: 1200px) { .dropdown-menu-xl-start { --bs-position: start; } .dropdown-menu-xl-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-xl-end { --bs-position: end; } .dropdown-menu-xl-end[data-bs-popper] { left: 0; right: auto; } } @media (min-width: 1400px) { .dropdown-menu-xxl-start { --bs-position: start; } .dropdown-menu-xxl-start[data-bs-popper] { left: auto; right: 0; } .dropdown-menu-xxl-end { --bs-position: end; } .dropdown-menu-xxl-end[data-bs-popper] { left: 0; right: auto; } } .dropup .dropdown-menu[data-bs-popper] { top: auto; bottom: 100%; margin-top: 0; margin-bottom: var(--bs-dropdown-spacer); } .dropup .dropdown-toggle::after { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0; border-left: 0.3em solid transparent; border-bottom: 0.3em solid; border-right: 0.3em solid transparent; } .dropup .dropdown-toggle:empty::after { margin-right: 0; } .dropend .dropdown-menu[data-bs-popper] { top: 0; left: auto; right: 100%; margin-top: 0; margin-right: var(--bs-dropdown-spacer); } .dropend .dropdown-toggle::after { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-left: 0; border-bottom: 0.3em solid transparent; border-right: 0.3em solid; } .dropend .dropdown-toggle:empty::after { margin-right: 0; } .dropend .dropdown-toggle::after { vertical-align: 0; } .dropstart .dropdown-menu[data-bs-popper] { top: 0; left: 100%; right: auto; margin-top: 0; margin-left: var(--bs-dropdown-spacer); } .dropstart .dropdown-toggle::after { display: inline-block; margin-right: 0.255em; vertical-align: 0.255em; content: ""; } .dropstart .dropdown-toggle::after { display: none; } .dropstart .dropdown-toggle::before { display: inline-block; margin-left: 0.255em; vertical-align: 0.255em; content: ""; border-top: 0.3em solid transparent; border-left: 0.3em solid; border-bottom: 0.3em solid transparent; } .dropstart .dropdown-toggle:empty::after { margin-right: 0; } .dropstart .dropdown-toggle::before { vertical-align: 0; } .dropdown-divider { height: 0; margin: var(--bs-dropdown-divider-margin-y) 0; overflow: hidden; border-top: 1px solid var(--bs-dropdown-divider-bg); opacity: 1; } .dropdown-item { display: block; width: 100%; padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); clear: both; font-weight: 400; color: var(--bs-dropdown-link-color); text-align: inherit; text-decoration: none; white-space: nowrap; background-color: transparent; border: 0; } .dropdown-item:hover, .dropdown-item:focus { color: var(--bs-dropdown-link-hover-color); background-color: var(--bs-dropdown-link-hover-bg); } .dropdown-item.active, .dropdown-item:active { color: var(--bs-dropdown-link-active-color); text-decoration: none; background-color: var(--bs-dropdown-link-active-bg); } .dropdown-item.disabled, .dropdown-item:disabled { color: var(--bs-dropdown-link-disabled-color); pointer-events: none; background-color: transparent; } .dropdown-menu.show { display: block; } .dropdown-header { display: block; padding: var(--bs-dropdown-header-padding-y) var(--bs-dropdown-header-padding-x); margin-bottom: 0; font-size: 0.875rem; color: var(--bs-dropdown-header-color); white-space: nowrap; } .dropdown-item-text { display: block; padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x); color: var(--bs-dropdown-link-color); } .dropdown-menu-dark { --bs-dropdown-color: #dee2e6; --bs-dropdown-bg: #343a40; --bs-dropdown-border-color: var(--bs-border-color-translucent); --bs-dropdown-box-shadow: ; --bs-dropdown-link-color: #dee2e6; --bs-dropdown-link-hover-color: #fff; --bs-dropdown-divider-bg: var(--bs-border-color-translucent); --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.15); --bs-dropdown-link-active-color: #fff; --bs-dropdown-link-active-bg: #0d6efd; --bs-dropdown-link-disabled-color: #adb5bd; --bs-dropdown-header-color: #adb5bd; } .btn-group, .btn-group-vertical { position: relative; display: inline-flex; vertical-align: middle; } .btn-group > .btn, .btn-group-vertical > .btn { position: relative; flex: 1 1 auto; } .btn-group > .btn-check:checked + .btn, .btn-group > .btn-check:focus + .btn, .btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn-check:checked + .btn, .btn-group-vertical > .btn-check:focus + .btn, .btn-group-vertical > .btn:hover, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn.active { z-index: 1; } .btn-toolbar { display: flex; flex-wrap: wrap; justify-content: flex-start; } .btn-toolbar .input-group { width: auto; } .btn-group { border-radius: 0.375rem; } .btn-group > :not(.btn-check:first-child) + .btn, .btn-group > .btn-group:not(:first-child) { margin-right: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), .btn-group > .btn.dropdown-toggle-split:first-child, .btn-group > .btn-group:not(:last-child) > .btn { border-top-left-radius: 0; border-bottom-left-radius: 0; } .btn-group > .btn:nth-child(n+3), .btn-group > :not(.btn-check) + .btn, .btn-group > .btn-group:not(:first-child) > .btn { border-top-right-radius: 0; border-bottom-right-radius: 0; } .dropdown-toggle-split { padding-left: 0.5625rem; padding-right: 0.5625rem; } .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after { margin-right: 0; } .dropstart .dropdown-toggle-split::before { margin-left: 0; } .btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { padding-left: 0.375rem; padding-right: 0.375rem; } .btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { padding-left: 0.75rem; padding-right: 0.75rem; } .btn-group-vertical { flex-direction: column; align-items: flex-start; justify-content: center; } .btn-group-vertical > .btn, .btn-group-vertical > .btn-group { width: 100%; } .btn-group-vertical > .btn:not(:first-child), .btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), .btn-group-vertical > .btn-group:not(:last-child) > .btn { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } .btn-group-vertical > .btn ~ .btn, .btn-group-vertical > .btn-group:not(:first-child) > .btn { border-top-right-radius: 0; border-top-left-radius: 0; } .nav { --bs-nav-link-padding-x: 1rem; --bs-nav-link-padding-y: 0.5rem; --bs-nav-link-font-weight: ; --bs-nav-link-color: var(--bs-link-color); --bs-nav-link-hover-color: var(--bs-link-hover-color); --bs-nav-link-disabled-color: #6c757d; display: flex; flex-wrap: wrap; padding-right: 0; margin-bottom: 0; list-style: none; } .nav-link { display: block; padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x); font-size: var(--bs-nav-link-font-size); font-weight: var(--bs-nav-link-font-weight); color: var(--bs-nav-link-color); text-decoration: none; transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .nav-link { transition: none; } } .nav-link:hover, .nav-link:focus { color: var(--bs-nav-link-hover-color); } .nav-link.disabled { color: var(--bs-nav-link-disabled-color); pointer-events: none; cursor: default; } .nav-tabs { --bs-nav-tabs-border-width: 1px; --bs-nav-tabs-border-color: #dee2e6; --bs-nav-tabs-border-radius: 0.375rem; --bs-nav-tabs-link-hover-border-color: #e9ecef #e9ecef #dee2e6; --bs-nav-tabs-link-active-color: #495057; --bs-nav-tabs-link-active-bg: #fff; --bs-nav-tabs-link-active-border-color: #dee2e6 #dee2e6 #fff; border-bottom: var(--bs-nav-tabs-border-width) solid var(--bs-nav-tabs-border-color); } .nav-tabs .nav-link { margin-bottom: calc(-1 * var(--bs-nav-tabs-border-width)); background: none; border: var(--bs-nav-tabs-border-width) solid transparent; border-top-right-radius: var(--bs-nav-tabs-border-radius); border-top-left-radius: var(--bs-nav-tabs-border-radius); } .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { isolation: isolate; border-color: var(--bs-nav-tabs-link-hover-border-color); } .nav-tabs .nav-link.disabled, .nav-tabs .nav-link:disabled { color: var(--bs-nav-link-disabled-color); background-color: transparent; border-color: transparent; } .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { color: var(--bs-nav-tabs-link-active-color); background-color: var(--bs-nav-tabs-link-active-bg); border-color: var(--bs-nav-tabs-link-active-border-color); } .nav-tabs .dropdown-menu { margin-top: calc(-1 * var(--bs-nav-tabs-border-width)); border-top-right-radius: 0; border-top-left-radius: 0; } .nav-pills { --bs-nav-pills-border-radius: 0.375rem; --bs-nav-pills-link-active-color: #fff; --bs-nav-pills-link-active-bg: #0d6efd; } .nav-pills .nav-link { background: none; border: 0; border-radius: var(--bs-nav-pills-border-radius); } .nav-pills .nav-link:disabled { color: var(--bs-nav-link-disabled-color); background-color: transparent; border-color: transparent; } .nav-pills .nav-link.active, .nav-pills .show > .nav-link { color: var(--bs-nav-pills-link-active-color); background-color: var(--bs-nav-pills-link-active-bg); } .nav-fill > .nav-link, .nav-fill .nav-item { flex: 1 1 auto; text-align: center; } .nav-justified > .nav-link, .nav-justified .nav-item { flex-basis: 0; flex-grow: 1; text-align: center; } .nav-fill .nav-item .nav-link, .nav-justified .nav-item .nav-link { width: 100%; } .tab-content > .tab-pane { display: none; } .tab-content > .active { display: block; } .navbar { --bs-navbar-padding-x: 0; --bs-navbar-padding-y: 0.5rem; --bs-navbar-color: rgba(0, 0, 0, 0.55); --bs-navbar-hover-color: rgba(0, 0, 0, 0.7); --bs-navbar-disabled-color: rgba(0, 0, 0, 0.3); --bs-navbar-active-color: rgba(0, 0, 0, 0.9); --bs-navbar-brand-padding-y: 0.3125rem; --bs-navbar-brand-margin-end: 1rem; --bs-navbar-brand-font-size: 1.25rem; --bs-navbar-brand-color: rgba(0, 0, 0, 0.9); --bs-navbar-brand-hover-color: rgba(0, 0, 0, 0.9); --bs-navbar-nav-link-padding-x: 0.5rem; --bs-navbar-toggler-padding-y: 0.25rem; --bs-navbar-toggler-padding-x: 0.75rem; --bs-navbar-toggler-font-size: 1.25rem; --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); --bs-navbar-toggler-border-color: rgba(0, 0, 0, 0.1); --bs-navbar-toggler-border-radius: 0.375rem; --bs-navbar-toggler-focus-width: 0.25rem; --bs-navbar-toggler-transition: box-shadow 0.15s ease-in-out; position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; padding: var(--bs-navbar-padding-y) var(--bs-navbar-padding-x); } .navbar > .container, .navbar > .container-fluid, .navbar > .container-sm, .navbar > .container-md, .navbar > .container-lg, .navbar > .container-xl, .navbar > .container-xxl { display: flex; flex-wrap: inherit; align-items: center; justify-content: space-between; } .navbar-brand { padding-top: var(--bs-navbar-brand-padding-y); padding-bottom: var(--bs-navbar-brand-padding-y); margin-left: var(--bs-navbar-brand-margin-end); font-size: var(--bs-navbar-brand-font-size); color: var(--bs-navbar-brand-color); text-decoration: none; white-space: nowrap; } .navbar-brand:hover, .navbar-brand:focus { color: var(--bs-navbar-brand-hover-color); } .navbar-nav { --bs-nav-link-padding-x: 0; --bs-nav-link-padding-y: 0.5rem; --bs-nav-link-font-weight: ; --bs-nav-link-color: var(--bs-navbar-color); --bs-nav-link-hover-color: var(--bs-navbar-hover-color); --bs-nav-link-disabled-color: var(--bs-navbar-disabled-color); display: flex; flex-direction: column; padding-right: 0; margin-bottom: 0; list-style: none; } .navbar-nav .show > .nav-link, .navbar-nav .nav-link.active { color: var(--bs-navbar-active-color); } .navbar-nav .dropdown-menu { position: static; } .navbar-text { padding-top: 0.5rem; padding-bottom: 0.5rem; color: var(--bs-navbar-color); } .navbar-text a, .navbar-text a:hover, .navbar-text a:focus { color: var(--bs-navbar-active-color); } .navbar-collapse { flex-basis: 100%; flex-grow: 1; align-items: center; } .navbar-toggler { padding: var(--bs-navbar-toggler-padding-y) var(--bs-navbar-toggler-padding-x); font-size: var(--bs-navbar-toggler-font-size); line-height: 1; color: var(--bs-navbar-color); background-color: transparent; border: var(--bs-border-width) solid var(--bs-navbar-toggler-border-color); border-radius: var(--bs-navbar-toggler-border-radius); transition: var(--bs-navbar-toggler-transition); } @media (prefers-reduced-motion: reduce) { .navbar-toggler { transition: none; } } .navbar-toggler:hover { text-decoration: none; } .navbar-toggler:focus { text-decoration: none; outline: 0; box-shadow: 0 0 0 var(--bs-navbar-toggler-focus-width); } .navbar-toggler-icon { display: inline-block; width: 1.5em; height: 1.5em; vertical-align: middle; background-image: var(--bs-navbar-toggler-icon-bg); background-repeat: no-repeat; background-position: center; background-size: 100%; } .navbar-nav-scroll { max-height: var(--bs-scroll-height, 75vh); overflow-y: auto; } @media (min-width: 576px) { .navbar-expand-sm { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-sm .navbar-nav { flex-direction: row; } .navbar-expand-sm .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-sm .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-sm .navbar-nav-scroll { overflow: visible; } .navbar-expand-sm .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-sm .navbar-toggler { display: none; } .navbar-expand-sm .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-sm .offcanvas .offcanvas-header { display: none; } .navbar-expand-sm .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 768px) { .navbar-expand-md { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-md .navbar-nav { flex-direction: row; } .navbar-expand-md .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-md .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-md .navbar-nav-scroll { overflow: visible; } .navbar-expand-md .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-md .navbar-toggler { display: none; } .navbar-expand-md .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-md .offcanvas .offcanvas-header { display: none; } .navbar-expand-md .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 992px) { .navbar-expand-lg { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-lg .navbar-nav { flex-direction: row; } .navbar-expand-lg .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-lg .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-lg .navbar-nav-scroll { overflow: visible; } .navbar-expand-lg .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-lg .navbar-toggler { display: none; } .navbar-expand-lg .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-lg .offcanvas .offcanvas-header { display: none; } .navbar-expand-lg .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 1200px) { .navbar-expand-xl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xl .navbar-nav { flex-direction: row; } .navbar-expand-xl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xl .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-xl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xl .navbar-toggler { display: none; } .navbar-expand-xl .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-xl .offcanvas .offcanvas-header { display: none; } .navbar-expand-xl .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } @media (min-width: 1400px) { .navbar-expand-xxl { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand-xxl .navbar-nav { flex-direction: row; } .navbar-expand-xxl .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand-xxl .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand-xxl .navbar-nav-scroll { overflow: visible; } .navbar-expand-xxl .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand-xxl .navbar-toggler { display: none; } .navbar-expand-xxl .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand-xxl .offcanvas .offcanvas-header { display: none; } .navbar-expand-xxl .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } } .navbar-expand { flex-wrap: nowrap; justify-content: flex-start; } .navbar-expand .navbar-nav { flex-direction: row; } .navbar-expand .navbar-nav .dropdown-menu { position: absolute; } .navbar-expand .navbar-nav .nav-link { padding-left: var(--bs-navbar-nav-link-padding-x); padding-right: var(--bs-navbar-nav-link-padding-x); } .navbar-expand .navbar-nav-scroll { overflow: visible; } .navbar-expand .navbar-collapse { display: flex !important; flex-basis: auto; } .navbar-expand .navbar-toggler { display: none; } .navbar-expand .offcanvas { position: static; z-index: auto; flex-grow: 1; width: auto !important; height: auto !important; visibility: visible !important; background-color: transparent !important; border: 0 !important; transform: none !important; transition: none; } .navbar-expand .offcanvas .offcanvas-header { display: none; } .navbar-expand .offcanvas .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; } .navbar-dark { --bs-navbar-color: rgba(255, 255, 255, 0.55); --bs-navbar-hover-color: rgba(255, 255, 255, 0.75); --bs-navbar-disabled-color: rgba(255, 255, 255, 0.25); --bs-navbar-active-color: #fff; --bs-navbar-brand-color: #fff; --bs-navbar-brand-hover-color: #fff; --bs-navbar-toggler-border-color: rgba(255, 255, 255, 0.1); --bs-navbar-toggler-icon-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .card { --bs-card-spacer-y: 1rem; --bs-card-spacer-x: 1rem; --bs-card-title-spacer-y: 0.5rem; --bs-card-border-width: 1px; --bs-card-border-color: var(--bs-border-color-translucent); --bs-card-border-radius: 0.375rem; --bs-card-box-shadow: ; --bs-card-inner-border-radius: calc(0.375rem - 1px); --bs-card-cap-padding-y: 0.5rem; --bs-card-cap-padding-x: 1rem; --bs-card-cap-bg: rgba(0, 0, 0, 0.03); --bs-card-cap-color: ; --bs-card-height: ; --bs-card-color: ; --bs-card-bg: #fff; --bs-card-img-overlay-padding: 1rem; --bs-card-group-margin: 0.75rem; position: relative; display: flex; flex-direction: column; min-width: 0; height: var(--bs-card-height); word-wrap: break-word; background-color: var(--bs-card-bg); background-clip: border-box; border: var(--bs-card-border-width) solid var(--bs-card-border-color); border-radius: var(--bs-card-border-radius); } .card > hr { margin-left: 0; margin-right: 0; } .card > .list-group { border-top: inherit; border-bottom: inherit; } .card > .list-group:first-child { border-top-width: 0; border-top-right-radius: var(--bs-card-inner-border-radius); border-top-left-radius: var(--bs-card-inner-border-radius); } .card > .list-group:last-child { border-bottom-width: 0; border-bottom-left-radius: var(--bs-card-inner-border-radius); border-bottom-right-radius: var(--bs-card-inner-border-radius); } .card > .card-header + .list-group, .card > .list-group + .card-footer { border-top: 0; } .card-body { flex: 1 1 auto; padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); color: var(--bs-card-color); } .card-title { margin-bottom: var(--bs-card-title-spacer-y); } .card-subtitle { margin-top: calc(-0.5 * var(--bs-card-title-spacer-y)); margin-bottom: 0; } .card-text:last-child { margin-bottom: 0; } .card-link + .card-link { margin-right: var(--bs-card-spacer-x); } .card-header { padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); margin-bottom: 0; color: var(--bs-card-cap-color); background-color: var(--bs-card-cap-bg); border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color); } .card-header:first-child { border-radius: var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius) 0 0; } .card-footer { padding: var(--bs-card-cap-padding-y) var(--bs-card-cap-padding-x); color: var(--bs-card-cap-color); background-color: var(--bs-card-cap-bg); border-top: var(--bs-card-border-width) solid var(--bs-card-border-color); } .card-footer:last-child { border-radius: 0 0 var(--bs-card-inner-border-radius) var(--bs-card-inner-border-radius); } .card-header-tabs { margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); margin-bottom: calc(-1 * var(--bs-card-cap-padding-y)); margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); border-bottom: 0; } .card-header-tabs .nav-link.active { background-color: var(--bs-card-bg); border-bottom-color: var(--bs-card-bg); } .card-header-pills { margin-left: calc(-0.5 * var(--bs-card-cap-padding-x)); margin-right: calc(-0.5 * var(--bs-card-cap-padding-x)); } .card-img-overlay { position: absolute; top: 0; left: 0; bottom: 0; right: 0; padding: var(--bs-card-img-overlay-padding); border-radius: var(--bs-card-inner-border-radius); } .card-img, .card-img-top, .card-img-bottom { width: 100%; } .card-img, .card-img-top { border-top-right-radius: var(--bs-card-inner-border-radius); border-top-left-radius: var(--bs-card-inner-border-radius); } .card-img, .card-img-bottom { border-bottom-left-radius: var(--bs-card-inner-border-radius); border-bottom-right-radius: var(--bs-card-inner-border-radius); } .card-group > .card { margin-bottom: var(--bs-card-group-margin); } @media (min-width: 576px) { .card-group { display: flex; flex-flow: row wrap; } .card-group > .card { flex: 1 0 0%; margin-bottom: 0; } .card-group > .card + .card { margin-right: 0; border-right: 0; } .card-group > .card:not(:last-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .card-group > .card:not(:last-child) .card-img-top, .card-group > .card:not(:last-child) .card-header { border-top-left-radius: 0; } .card-group > .card:not(:last-child) .card-img-bottom, .card-group > .card:not(:last-child) .card-footer { border-bottom-left-radius: 0; } .card-group > .card:not(:first-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .card-group > .card:not(:first-child) .card-img-top, .card-group > .card:not(:first-child) .card-header { border-top-right-radius: 0; } .card-group > .card:not(:first-child) .card-img-bottom, .card-group > .card:not(:first-child) .card-footer { border-bottom-right-radius: 0; } } .accordion { --bs-accordion-color: #212529; --bs-accordion-bg: #fff; --bs-accordion-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, border-radius 0.15s ease; --bs-accordion-border-color: var(--bs-border-color); --bs-accordion-border-width: 1px; --bs-accordion-border-radius: 0.375rem; --bs-accordion-inner-border-radius: calc(0.375rem - 1px); --bs-accordion-btn-padding-x: 1.25rem; --bs-accordion-btn-padding-y: 1rem; --bs-accordion-btn-color: #212529; --bs-accordion-btn-bg: var(--bs-accordion-bg); --bs-accordion-btn-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-icon-width: 1.25rem; --bs-accordion-btn-icon-transform: rotate(-180deg); --bs-accordion-btn-icon-transition: transform 0.2s ease-in-out; --bs-accordion-btn-active-icon: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); --bs-accordion-btn-focus-border-color: #86b7fe; --bs-accordion-btn-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); --bs-accordion-body-padding-x: 1.25rem; --bs-accordion-body-padding-y: 1rem; --bs-accordion-active-color: #0c63e4; --bs-accordion-active-bg: #e7f1ff; } .accordion-button { position: relative; display: flex; align-items: center; width: 100%; padding: var(--bs-accordion-btn-padding-y) var(--bs-accordion-btn-padding-x); font-size: 1rem; color: var(--bs-accordion-btn-color); text-align: right; background-color: var(--bs-accordion-btn-bg); border: 0; border-radius: 0; overflow-anchor: none; transition: var(--bs-accordion-transition); } @media (prefers-reduced-motion: reduce) { .accordion-button { transition: none; } } .accordion-button:not(.collapsed) { color: var(--bs-accordion-active-color); background-color: var(--bs-accordion-active-bg); box-shadow: inset 0 calc(-1 * var(--bs-accordion-border-width)) 0 var(--bs-accordion-border-color); } .accordion-button:not(.collapsed)::after { background-image: var(--bs-accordion-btn-active-icon); transform: var(--bs-accordion-btn-icon-transform); } .accordion-button::after { flex-shrink: 0; width: var(--bs-accordion-btn-icon-width); height: var(--bs-accordion-btn-icon-width); margin-right: auto; content: ""; background-image: var(--bs-accordion-btn-icon); background-repeat: no-repeat; background-size: var(--bs-accordion-btn-icon-width); transition: var(--bs-accordion-btn-icon-transition); } @media (prefers-reduced-motion: reduce) { .accordion-button::after { transition: none; } } .accordion-button:hover { z-index: 2; } .accordion-button:focus { z-index: 3; border-color: var(--bs-accordion-btn-focus-border-color); outline: 0; box-shadow: var(--bs-accordion-btn-focus-box-shadow); } .accordion-header { margin-bottom: 0; } .accordion-item { color: var(--bs-accordion-color); background-color: var(--bs-accordion-bg); border: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color); } .accordion-item:first-of-type { border-top-right-radius: var(--bs-accordion-border-radius); border-top-left-radius: var(--bs-accordion-border-radius); } .accordion-item:first-of-type .accordion-button { border-top-right-radius: var(--bs-accordion-inner-border-radius); border-top-left-radius: var(--bs-accordion-inner-border-radius); } .accordion-item:not(:first-of-type) { border-top: 0; } .accordion-item:last-of-type { border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius); } .accordion-item:last-of-type .accordion-button.collapsed { border-bottom-left-radius: var(--bs-accordion-inner-border-radius); border-bottom-right-radius: var(--bs-accordion-inner-border-radius); } .accordion-item:last-of-type .accordion-collapse { border-bottom-left-radius: var(--bs-accordion-border-radius); border-bottom-right-radius: var(--bs-accordion-border-radius); } .accordion-body { padding: var(--bs-accordion-body-padding-y) var(--bs-accordion-body-padding-x); } .accordion-flush .accordion-collapse { border-width: 0; } .accordion-flush .accordion-item { border-left: 0; border-right: 0; border-radius: 0; } .accordion-flush .accordion-item:first-child { border-top: 0; } .accordion-flush .accordion-item:last-child { border-bottom: 0; } .accordion-flush .accordion-item .accordion-button, .accordion-flush .accordion-item .accordion-button.collapsed { border-radius: 0; } .breadcrumb { --bs-breadcrumb-padding-x: 0; --bs-breadcrumb-padding-y: 0; --bs-breadcrumb-margin-bottom: 1rem; --bs-breadcrumb-bg: ; --bs-breadcrumb-border-radius: ; --bs-breadcrumb-divider-color: #6c757d; --bs-breadcrumb-item-padding-x: 0.5rem; --bs-breadcrumb-item-active-color: #6c757d; display: flex; flex-wrap: wrap; padding: var(--bs-breadcrumb-padding-y) var(--bs-breadcrumb-padding-x); margin-bottom: var(--bs-breadcrumb-margin-bottom); font-size: var(--bs-breadcrumb-font-size); list-style: none; background-color: var(--bs-breadcrumb-bg); border-radius: var(--bs-breadcrumb-border-radius); } .breadcrumb-item + .breadcrumb-item { padding-right: var(--bs-breadcrumb-item-padding-x); } .breadcrumb-item + .breadcrumb-item::before { float: right; padding-left: var(--bs-breadcrumb-item-padding-x); color: var(--bs-breadcrumb-divider-color); content: var(--bs-breadcrumb-divider, "/") ; } .breadcrumb-item.active { color: var(--bs-breadcrumb-item-active-color); } .pagination { --bs-pagination-padding-x: 0.75rem; --bs-pagination-padding-y: 0.375rem; --bs-pagination-font-size: 1rem; --bs-pagination-color: var(--bs-link-color); --bs-pagination-bg: #fff; --bs-pagination-border-width: 1px; --bs-pagination-border-color: #dee2e6; --bs-pagination-border-radius: 0.375rem; --bs-pagination-hover-color: var(--bs-link-hover-color); --bs-pagination-hover-bg: #e9ecef; --bs-pagination-hover-border-color: #dee2e6; --bs-pagination-focus-color: var(--bs-link-hover-color); --bs-pagination-focus-bg: #e9ecef; --bs-pagination-focus-box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); --bs-pagination-active-color: #fff; --bs-pagination-active-bg: #0d6efd; --bs-pagination-active-border-color: #0d6efd; --bs-pagination-disabled-color: #6c757d; --bs-pagination-disabled-bg: #fff; --bs-pagination-disabled-border-color: #dee2e6; display: flex; padding-right: 0; list-style: none; } .page-link { position: relative; display: block; padding: var(--bs-pagination-padding-y) var(--bs-pagination-padding-x); font-size: var(--bs-pagination-font-size); color: var(--bs-pagination-color); text-decoration: none; background-color: var(--bs-pagination-bg); border: var(--bs-pagination-border-width) solid var(--bs-pagination-border-color); transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } @media (prefers-reduced-motion: reduce) { .page-link { transition: none; } } .page-link:hover { z-index: 2; color: var(--bs-pagination-hover-color); background-color: var(--bs-pagination-hover-bg); border-color: var(--bs-pagination-hover-border-color); } .page-link:focus { z-index: 3; color: var(--bs-pagination-focus-color); background-color: var(--bs-pagination-focus-bg); outline: 0; box-shadow: var(--bs-pagination-focus-box-shadow); } .page-link.active, .active > .page-link { z-index: 3; color: var(--bs-pagination-active-color); background-color: var(--bs-pagination-active-bg); border-color: var(--bs-pagination-active-border-color); } .page-link.disabled, .disabled > .page-link { color: var(--bs-pagination-disabled-color); pointer-events: none; background-color: var(--bs-pagination-disabled-bg); border-color: var(--bs-pagination-disabled-border-color); } .page-item:not(:first-child) .page-link { margin-right: -1px; } .page-item:first-child .page-link { border-top-right-radius: var(--bs-pagination-border-radius); border-bottom-right-radius: var(--bs-pagination-border-radius); } .page-item:last-child .page-link { border-top-left-radius: var(--bs-pagination-border-radius); border-bottom-left-radius: var(--bs-pagination-border-radius); } .pagination-lg { --bs-pagination-padding-x: 1.5rem; --bs-pagination-padding-y: 0.75rem; --bs-pagination-font-size: 1.25rem; --bs-pagination-border-radius: 0.5rem; } .pagination-sm { --bs-pagination-padding-x: 0.5rem; --bs-pagination-padding-y: 0.25rem; --bs-pagination-font-size: 0.875rem; --bs-pagination-border-radius: 0.25rem; } .badge { --bs-badge-padding-x: 0.65em; --bs-badge-padding-y: 0.35em; --bs-badge-font-size: 0.75em; --bs-badge-font-weight: 700; --bs-badge-color: #fff; --bs-badge-border-radius: 0.375rem; display: inline-block; padding: var(--bs-badge-padding-y) var(--bs-badge-padding-x); font-size: var(--bs-badge-font-size); font-weight: var(--bs-badge-font-weight); line-height: 1; color: var(--bs-badge-color); text-align: center; white-space: nowrap; vertical-align: baseline; border-radius: var(--bs-badge-border-radius); } .badge:empty { display: none; } .btn .badge { position: relative; top: -1px; } .alert { --bs-alert-bg: transparent; --bs-alert-padding-x: 1rem; --bs-alert-padding-y: 1rem; --bs-alert-margin-bottom: 1rem; --bs-alert-color: inherit; --bs-alert-border-color: transparent; --bs-alert-border: 1px solid var(--bs-alert-border-color); --bs-alert-border-radius: 0.375rem; position: relative; padding: var(--bs-alert-padding-y) var(--bs-alert-padding-x); margin-bottom: var(--bs-alert-margin-bottom); color: var(--bs-alert-color); background-color: var(--bs-alert-bg); border: var(--bs-alert-border); border-radius: var(--bs-alert-border-radius); } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } .alert-dismissible { padding-left: 3rem; } .alert-dismissible .btn-close { position: absolute; top: 0; left: 0; z-index: 2; padding: 1.25rem 1rem; } .alert-primary { --bs-alert-color: #084298; --bs-alert-bg: #cfe2ff; --bs-alert-border-color: #b6d4fe; } .alert-primary .alert-link { color: #06357a; } .alert-secondary { --bs-alert-color: #41464b; --bs-alert-bg: #e2e3e5; --bs-alert-border-color: #d3d6d8; } .alert-secondary .alert-link { color: #34383c; } .alert-success { --bs-alert-color: #0f5132; --bs-alert-bg: #d1e7dd; --bs-alert-border-color: #badbcc; } .alert-success .alert-link { color: #0c4128; } .alert-info { --bs-alert-color: #055160; --bs-alert-bg: #cff4fc; --bs-alert-border-color: #b6effb; } .alert-info .alert-link { color: #04414d; } .alert-warning { --bs-alert-color: #664d03; --bs-alert-bg: #fff3cd; --bs-alert-border-color: #ffecb5; } .alert-warning .alert-link { color: #523e02; } .alert-danger { --bs-alert-color: #842029; --bs-alert-bg: #f8d7da; --bs-alert-border-color: #f5c2c7; } .alert-danger .alert-link { color: #6a1a21; } .alert-light { --bs-alert-color: #636464; --bs-alert-bg: #fefefe; --bs-alert-border-color: #fdfdfe; } .alert-light .alert-link { color: #4f5050; } .alert-dark { --bs-alert-color: #141619; --bs-alert-bg: #d3d3d4; --bs-alert-border-color: #bcbebf; } .alert-dark .alert-link { color: #101214; } @keyframes progress-bar-stripes { 0% { background-position-x: 1rem; } } .progress { --bs-progress-height: 1rem; --bs-progress-font-size: 0.75rem; --bs-progress-bg: #e9ecef; --bs-progress-border-radius: 0.375rem; --bs-progress-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.075); --bs-progress-bar-color: #fff; --bs-progress-bar-bg: #0d6efd; --bs-progress-bar-transition: width 0.6s ease; display: flex; height: var(--bs-progress-height); overflow: hidden; font-size: var(--bs-progress-font-size); background-color: var(--bs-progress-bg); border-radius: var(--bs-progress-border-radius); } .progress-bar { display: flex; flex-direction: column; justify-content: center; overflow: hidden; color: var(--bs-progress-bar-color); text-align: center; white-space: nowrap; background-color: var(--bs-progress-bar-bg); transition: var(--bs-progress-bar-transition); } @media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } } .progress-bar-striped { background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); background-size: var(--bs-progress-height) var(--bs-progress-height); } .progress-bar-animated { animation: 1s linear infinite progress-bar-stripes; } @media (prefers-reduced-motion: reduce) { .progress-bar-animated { animation: none; } } .list-group { --bs-list-group-color: #212529; --bs-list-group-bg: #fff; --bs-list-group-border-color: rgba(0, 0, 0, 0.125); --bs-list-group-border-width: 1px; --bs-list-group-border-radius: 0.375rem; --bs-list-group-item-padding-x: 1rem; --bs-list-group-item-padding-y: 0.5rem; --bs-list-group-action-color: #495057; --bs-list-group-action-hover-color: #495057; --bs-list-group-action-hover-bg: #f8f9fa; --bs-list-group-action-active-color: #212529; --bs-list-group-action-active-bg: #e9ecef; --bs-list-group-disabled-color: #6c757d; --bs-list-group-disabled-bg: #fff; --bs-list-group-active-color: #fff; --bs-list-group-active-bg: #0d6efd; --bs-list-group-active-border-color: #0d6efd; display: flex; flex-direction: column; padding-right: 0; margin-bottom: 0; border-radius: var(--bs-list-group-border-radius); } .list-group-numbered { list-style-type: none; counter-reset: section; } .list-group-numbered > .list-group-item::before { content: counters(section, ".") ". "; counter-increment: section; } .list-group-item-action { width: 100%; color: var(--bs-list-group-action-color); text-align: inherit; } .list-group-item-action:hover, .list-group-item-action:focus { z-index: 1; color: var(--bs-list-group-action-hover-color); text-decoration: none; background-color: var(--bs-list-group-action-hover-bg); } .list-group-item-action:active { color: var(--bs-list-group-action-active-color); background-color: var(--bs-list-group-action-active-bg); } .list-group-item { position: relative; display: block; padding: var(--bs-list-group-item-padding-y) var(--bs-list-group-item-padding-x); color: var(--bs-list-group-color); text-decoration: none; background-color: var(--bs-list-group-bg); border: var(--bs-list-group-border-width) solid var(--bs-list-group-border-color); } .list-group-item:first-child { border-top-right-radius: inherit; border-top-left-radius: inherit; } .list-group-item:last-child { border-bottom-left-radius: inherit; border-bottom-right-radius: inherit; } .list-group-item.disabled, .list-group-item:disabled { color: var(--bs-list-group-disabled-color); pointer-events: none; background-color: var(--bs-list-group-disabled-bg); } .list-group-item.active { z-index: 2; color: var(--bs-list-group-active-color); background-color: var(--bs-list-group-active-bg); border-color: var(--bs-list-group-active-border-color); } .list-group-item + .list-group-item { border-top-width: 0; } .list-group-item + .list-group-item.active { margin-top: calc(-1 * var(--bs-list-group-border-width)); border-top-width: var(--bs-list-group-border-width); } .list-group-horizontal { flex-direction: row; } .list-group-horizontal > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal > .list-group-item.active { margin-top: 0; } .list-group-horizontal > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } @media (min-width: 576px) { .list-group-horizontal-sm { flex-direction: row; } .list-group-horizontal-sm > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal-sm > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal-sm > .list-group-item.active { margin-top: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal-sm > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } } @media (min-width: 768px) { .list-group-horizontal-md { flex-direction: row; } .list-group-horizontal-md > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal-md > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal-md > .list-group-item.active { margin-top: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal-md > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } } @media (min-width: 992px) { .list-group-horizontal-lg { flex-direction: row; } .list-group-horizontal-lg > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal-lg > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal-lg > .list-group-item.active { margin-top: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal-lg > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } } @media (min-width: 1200px) { .list-group-horizontal-xl { flex-direction: row; } .list-group-horizontal-xl > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal-xl > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal-xl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal-xl > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } } @media (min-width: 1400px) { .list-group-horizontal-xxl { flex-direction: row; } .list-group-horizontal-xxl > .list-group-item:first-child:not(:last-child) { border-bottom-right-radius: var(--bs-list-group-border-radius); border-top-left-radius: 0; } .list-group-horizontal-xxl > .list-group-item:last-child:not(:first-child) { border-top-left-radius: var(--bs-list-group-border-radius); border-bottom-right-radius: 0; } .list-group-horizontal-xxl > .list-group-item.active { margin-top: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item { border-top-width: var(--bs-list-group-border-width); border-right-width: 0; } .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { margin-right: calc(-1 * var(--bs-list-group-border-width)); border-right-width: var(--bs-list-group-border-width); } } .list-group-flush { border-radius: 0; } .list-group-flush > .list-group-item { border-width: 0 0 var(--bs-list-group-border-width); } .list-group-flush > .list-group-item:last-child { border-bottom-width: 0; } .list-group-item-primary { color: #084298; background-color: #cfe2ff; } .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { color: #084298; background-color: #bacbe6; } .list-group-item-primary.list-group-item-action.active { color: #fff; background-color: #084298; border-color: #084298; } .list-group-item-secondary { color: #41464b; background-color: #e2e3e5; } .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { color: #41464b; background-color: #cbccce; } .list-group-item-secondary.list-group-item-action.active { color: #fff; background-color: #41464b; border-color: #41464b; } .list-group-item-success { color: #0f5132; background-color: #d1e7dd; } .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { color: #0f5132; background-color: #bcd0c7; } .list-group-item-success.list-group-item-action.active { color: #fff; background-color: #0f5132; border-color: #0f5132; } .list-group-item-info { color: #055160; background-color: #cff4fc; } .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { color: #055160; background-color: #badce3; } .list-group-item-info.list-group-item-action.active { color: #fff; background-color: #055160; border-color: #055160; } .list-group-item-warning { color: #664d03; background-color: #fff3cd; } .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { color: #664d03; background-color: #e6dbb9; } .list-group-item-warning.list-group-item-action.active { color: #fff; background-color: #664d03; border-color: #664d03; } .list-group-item-danger { color: #842029; background-color: #f8d7da; } .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { color: #842029; background-color: #dfc2c4; } .list-group-item-danger.list-group-item-action.active { color: #fff; background-color: #842029; border-color: #842029; } .list-group-item-light { color: #636464; background-color: #fefefe; } .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { color: #636464; background-color: #e5e5e5; } .list-group-item-light.list-group-item-action.active { color: #fff; background-color: #636464; border-color: #636464; } .list-group-item-dark { color: #141619; background-color: #d3d3d4; } .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { color: #141619; background-color: #bebebf; } .list-group-item-dark.list-group-item-action.active { color: #fff; background-color: #141619; border-color: #141619; } .btn-close { box-sizing: content-box; width: 1em; height: 1em; padding: 0.25em 0.25em; color: #000; background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; border: 0; border-radius: 0.375rem; opacity: 0.5; } .btn-close:hover { color: #000; text-decoration: none; opacity: 0.75; } .btn-close:focus { outline: 0; box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25); opacity: 1; } .btn-close:disabled, .btn-close.disabled { pointer-events: none; -webkit-user-select: none; -moz-user-select: none; user-select: none; opacity: 0.25; } .btn-close-white { filter: invert(1) grayscale(100%) brightness(200%); } .toast { --bs-toast-zindex: 1090; --bs-toast-padding-x: 0.75rem; --bs-toast-padding-y: 0.5rem; --bs-toast-spacing: 1.5rem; --bs-toast-max-width: 350px; --bs-toast-font-size: 0.875rem; --bs-toast-color: ; --bs-toast-bg: rgba(255, 255, 255, 0.85); --bs-toast-border-width: 1px; --bs-toast-border-color: var(--bs-border-color-translucent); --bs-toast-border-radius: 0.375rem; --bs-toast-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-toast-header-color: #6c757d; --bs-toast-header-bg: rgba(255, 255, 255, 0.85); --bs-toast-header-border-color: rgba(0, 0, 0, 0.05); width: var(--bs-toast-max-width); max-width: 100%; font-size: var(--bs-toast-font-size); color: var(--bs-toast-color); pointer-events: auto; background-color: var(--bs-toast-bg); background-clip: padding-box; border: var(--bs-toast-border-width) solid var(--bs-toast-border-color); box-shadow: var(--bs-toast-box-shadow); border-radius: var(--bs-toast-border-radius); } .toast.showing { opacity: 0; } .toast:not(.show) { display: none; } .toast-container { --bs-toast-zindex: 1090; position: absolute; z-index: var(--bs-toast-zindex); width: -webkit-max-content; width: -moz-max-content; width: max-content; max-width: 100%; pointer-events: none; } .toast-container > :not(:last-child) { margin-bottom: var(--bs-toast-spacing); } .toast-header { display: flex; align-items: center; padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x); color: var(--bs-toast-header-color); background-color: var(--bs-toast-header-bg); background-clip: padding-box; border-bottom: var(--bs-toast-border-width) solid var(--bs-toast-header-border-color); border-top-right-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); border-top-left-radius: calc(var(--bs-toast-border-radius) - var(--bs-toast-border-width)); } .toast-header .btn-close { margin-left: calc(-0.5 * var(--bs-toast-padding-x)); margin-right: var(--bs-toast-padding-x); } .toast-body { padding: var(--bs-toast-padding-x); word-wrap: break-word; } .modal { --bs-modal-zindex: 1055; --bs-modal-width: 500px; --bs-modal-padding: 1rem; --bs-modal-margin: 0.5rem; --bs-modal-color: ; --bs-modal-bg: #fff; --bs-modal-border-color: var(--bs-border-color-translucent); --bs-modal-border-width: 1px; --bs-modal-border-radius: 0.5rem; --bs-modal-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); --bs-modal-inner-border-radius: calc(0.5rem - 1px); --bs-modal-header-padding-x: 1rem; --bs-modal-header-padding-y: 1rem; --bs-modal-header-padding: 1rem 1rem; --bs-modal-header-border-color: var(--bs-border-color); --bs-modal-header-border-width: 1px; --bs-modal-title-line-height: 1.5; --bs-modal-footer-gap: 0.5rem; --bs-modal-footer-bg: ; --bs-modal-footer-border-color: var(--bs-border-color); --bs-modal-footer-border-width: 1px; position: fixed; top: 0; right: 0; z-index: var(--bs-modal-zindex); display: none; width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; outline: 0; } .modal-dialog { position: relative; width: auto; margin: var(--bs-modal-margin); pointer-events: none; } .modal.fade .modal-dialog { transition: transform 0.3s ease-out; transform: translate(0, -50px); } @media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { transform: none; } .modal.modal-static .modal-dialog { transform: scale(1.02); } .modal-dialog-scrollable { height: calc(100% - var(--bs-modal-margin) * 2); } .modal-dialog-scrollable .modal-content { max-height: 100%; overflow: hidden; } .modal-dialog-scrollable .modal-body { overflow-y: auto; } .modal-dialog-centered { display: flex; align-items: center; min-height: calc(100% - var(--bs-modal-margin) * 2); } .modal-content { position: relative; display: flex; flex-direction: column; width: 100%; color: var(--bs-modal-color); pointer-events: auto; background-color: var(--bs-modal-bg); background-clip: padding-box; border: var(--bs-modal-border-width) solid var(--bs-modal-border-color); border-radius: var(--bs-modal-border-radius); outline: 0; } .modal-backdrop { --bs-backdrop-zindex: 1050; --bs-backdrop-bg: #000; --bs-backdrop-opacity: 0.5; position: fixed; top: 0; right: 0; z-index: var(--bs-backdrop-zindex); width: 100vw; height: 100vh; background-color: var(--bs-backdrop-bg); } .modal-backdrop.fade { opacity: 0; } .modal-backdrop.show { opacity: var(--bs-backdrop-opacity); } .modal-header { display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; padding: var(--bs-modal-header-padding); border-bottom: var(--bs-modal-header-border-width) solid var(--bs-modal-header-border-color); border-top-right-radius: var(--bs-modal-inner-border-radius); border-top-left-radius: var(--bs-modal-inner-border-radius); } .modal-header .btn-close { padding: calc(var(--bs-modal-header-padding-y) * 0.5) calc(var(--bs-modal-header-padding-x) * 0.5); margin: calc(-0.5 * var(--bs-modal-header-padding-y)) auto calc(-0.5 * var(--bs-modal-header-padding-y)) calc(-0.5 * var(--bs-modal-header-padding-x)); } .modal-title { margin-bottom: 0; line-height: var(--bs-modal-title-line-height); } .modal-body { position: relative; flex: 1 1 auto; padding: var(--bs-modal-padding); } .modal-footer { display: flex; flex-shrink: 0; flex-wrap: wrap; align-items: center; justify-content: flex-end; padding: calc(var(--bs-modal-padding) - var(--bs-modal-footer-gap) * 0.5); background-color: var(--bs-modal-footer-bg); border-top: var(--bs-modal-footer-border-width) solid var(--bs-modal-footer-border-color); border-bottom-left-radius: var(--bs-modal-inner-border-radius); border-bottom-right-radius: var(--bs-modal-inner-border-radius); } .modal-footer > * { margin: calc(var(--bs-modal-footer-gap) * 0.5); } @media (min-width: 576px) { .modal { --bs-modal-margin: 1.75rem; --bs-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); } .modal-dialog { max-width: var(--bs-modal-width); margin-left: auto; margin-right: auto; } .modal-sm { --bs-modal-width: 300px; } } @media (min-width: 992px) { .modal-lg, .modal-xl { --bs-modal-width: 800px; } } @media (min-width: 1200px) { .modal-xl { --bs-modal-width: 1140px; } } .modal-fullscreen { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen .modal-header, .modal-fullscreen .modal-footer { border-radius: 0; } .modal-fullscreen .modal-body { overflow-y: auto; } @media (max-width: 575.98px) { .modal-fullscreen-sm-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-sm-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-sm-down .modal-header, .modal-fullscreen-sm-down .modal-footer { border-radius: 0; } .modal-fullscreen-sm-down .modal-body { overflow-y: auto; } } @media (max-width: 767.98px) { .modal-fullscreen-md-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-md-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-md-down .modal-header, .modal-fullscreen-md-down .modal-footer { border-radius: 0; } .modal-fullscreen-md-down .modal-body { overflow-y: auto; } } @media (max-width: 991.98px) { .modal-fullscreen-lg-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-lg-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-lg-down .modal-header, .modal-fullscreen-lg-down .modal-footer { border-radius: 0; } .modal-fullscreen-lg-down .modal-body { overflow-y: auto; } } @media (max-width: 1199.98px) { .modal-fullscreen-xl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xl-down .modal-header, .modal-fullscreen-xl-down .modal-footer { border-radius: 0; } .modal-fullscreen-xl-down .modal-body { overflow-y: auto; } } @media (max-width: 1399.98px) { .modal-fullscreen-xxl-down { width: 100vw; max-width: none; height: 100%; margin: 0; } .modal-fullscreen-xxl-down .modal-content { height: 100%; border: 0; border-radius: 0; } .modal-fullscreen-xxl-down .modal-header, .modal-fullscreen-xxl-down .modal-footer { border-radius: 0; } .modal-fullscreen-xxl-down .modal-body { overflow-y: auto; } } .tooltip { --bs-tooltip-zindex: 1080; --bs-tooltip-max-width: 200px; --bs-tooltip-padding-x: 0.5rem; --bs-tooltip-padding-y: 0.25rem; --bs-tooltip-margin: ; --bs-tooltip-font-size: 0.875rem; --bs-tooltip-color: #fff; --bs-tooltip-bg: #000; --bs-tooltip-border-radius: 0.375rem; --bs-tooltip-opacity: 0.9; --bs-tooltip-arrow-width: 0.8rem; --bs-tooltip-arrow-height: 0.4rem; z-index: var(--bs-tooltip-zindex); display: block; padding: var(--bs-tooltip-arrow-height); margin: var(--bs-tooltip-margin); font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: right; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; white-space: normal; word-spacing: normal; line-break: auto; font-size: var(--bs-tooltip-font-size); word-wrap: break-word; opacity: 0; } .tooltip.show { opacity: var(--bs-tooltip-opacity); } .tooltip .tooltip-arrow { display: block; width: var(--bs-tooltip-arrow-width); height: var(--bs-tooltip-arrow-height); } .tooltip .tooltip-arrow::before { position: absolute; content: ""; border-color: transparent; border-style: solid; } .bs-tooltip-top .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow { bottom: 0; } .bs-tooltip-top .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before { top: -1px; border-width: var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; border-top-color: var(--bs-tooltip-bg); } .bs-tooltip-end .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow { left: 0; width: var(--bs-tooltip-arrow-height); height: var(--bs-tooltip-arrow-width); } .bs-tooltip-end .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before { right: -1px; border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height) calc(var(--bs-tooltip-arrow-width) * 0.5) 0; border-right-color: var(--bs-tooltip-bg); } .bs-tooltip-bottom .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow { top: 0; } .bs-tooltip-bottom .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before { bottom: -1px; border-width: 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); border-bottom-color: var(--bs-tooltip-bg); } .bs-tooltip-start .tooltip-arrow, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow { right: 0; width: var(--bs-tooltip-arrow-height); height: var(--bs-tooltip-arrow-width); } .bs-tooltip-start .tooltip-arrow::before, .bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before { left: -1px; border-width: calc(var(--bs-tooltip-arrow-width) * 0.5) 0 calc(var(--bs-tooltip-arrow-width) * 0.5) var(--bs-tooltip-arrow-height); border-left-color: var(--bs-tooltip-bg); } .tooltip-inner { max-width: var(--bs-tooltip-max-width); padding: var(--bs-tooltip-padding-y) var(--bs-tooltip-padding-x); color: var(--bs-tooltip-color); text-align: center; background-color: var(--bs-tooltip-bg); border-radius: var(--bs-tooltip-border-radius); } .popover { --bs-popover-zindex: 1070; --bs-popover-max-width: 276px; --bs-popover-font-size: 0.875rem; --bs-popover-bg: #fff; --bs-popover-border-width: 1px; --bs-popover-border-color: var(--bs-border-color-translucent); --bs-popover-border-radius: 0.5rem; --bs-popover-inner-border-radius: calc(0.5rem - 1px); --bs-popover-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15); --bs-popover-header-padding-x: 1rem; --bs-popover-header-padding-y: 0.5rem; --bs-popover-header-font-size: 1rem; --bs-popover-header-color: ; --bs-popover-header-bg: #f0f0f0; --bs-popover-body-padding-x: 1rem; --bs-popover-body-padding-y: 1rem; --bs-popover-body-color: #212529; --bs-popover-arrow-width: 1rem; --bs-popover-arrow-height: 0.5rem; --bs-popover-arrow-border: var(--bs-popover-border-color); z-index: var(--bs-popover-zindex); display: block; max-width: var(--bs-popover-max-width); font-family: var(--bs-font-sans-serif); font-style: normal; font-weight: 400; line-height: 1.5; text-align: right; text-align: start; text-decoration: none; text-shadow: none; text-transform: none; letter-spacing: normal; word-break: normal; white-space: normal; word-spacing: normal; line-break: auto; font-size: var(--bs-popover-font-size); word-wrap: break-word; background-color: var(--bs-popover-bg); background-clip: padding-box; border: var(--bs-popover-border-width) solid var(--bs-popover-border-color); border-radius: var(--bs-popover-border-radius); } .popover .popover-arrow { display: block; width: var(--bs-popover-arrow-width); height: var(--bs-popover-arrow-height); } .popover .popover-arrow::before, .popover .popover-arrow::after { position: absolute; display: block; content: ""; border-color: transparent; border-style: solid; border-width: 0; } .bs-popover-top > .popover-arrow, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow { bottom: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); } .bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before, .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { border-width: var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; } .bs-popover-top > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before { bottom: 0; border-top-color: var(--bs-popover-arrow-border); } .bs-popover-top > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after { bottom: var(--bs-popover-border-width); border-top-color: var(--bs-popover-bg); } .bs-popover-end > .popover-arrow, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow { left: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); width: var(--bs-popover-arrow-height); height: var(--bs-popover-arrow-width); } .bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before, .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { border-width: calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height) calc(var(--bs-popover-arrow-width) * 0.5) 0; } .bs-popover-end > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before { left: 0; border-right-color: var(--bs-popover-arrow-border); } .bs-popover-end > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after { left: var(--bs-popover-border-width); border-right-color: var(--bs-popover-bg); } .bs-popover-bottom > .popover-arrow, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow { top: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); } .bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before, .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { border-width: 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); } .bs-popover-bottom > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before { top: 0; border-bottom-color: var(--bs-popover-arrow-border); } .bs-popover-bottom > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after { top: var(--bs-popover-border-width); border-bottom-color: var(--bs-popover-bg); } .bs-popover-bottom .popover-header::before, .bs-popover-auto[data-popper-placement^=bottom] .popover-header::before { position: absolute; top: 0; right: 50%; display: block; width: var(--bs-popover-arrow-width); margin-right: calc(-0.5 * var(--bs-popover-arrow-width)); content: ""; border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-header-bg); } .bs-popover-start > .popover-arrow, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow { right: calc(-1 * (var(--bs-popover-arrow-height)) - var(--bs-popover-border-width)); width: var(--bs-popover-arrow-height); height: var(--bs-popover-arrow-width); } .bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before, .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { border-width: calc(var(--bs-popover-arrow-width) * 0.5) 0 calc(var(--bs-popover-arrow-width) * 0.5) var(--bs-popover-arrow-height); } .bs-popover-start > .popover-arrow::before, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before { right: 0; border-left-color: var(--bs-popover-arrow-border); } .bs-popover-start > .popover-arrow::after, .bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after { right: var(--bs-popover-border-width); border-left-color: var(--bs-popover-bg); } .popover-header { padding: var(--bs-popover-header-padding-y) var(--bs-popover-header-padding-x); margin-bottom: 0; font-size: var(--bs-popover-header-font-size); color: var(--bs-popover-header-color); background-color: var(--bs-popover-header-bg); border-bottom: var(--bs-popover-border-width) solid var(--bs-popover-border-color); border-top-right-radius: var(--bs-popover-inner-border-radius); border-top-left-radius: var(--bs-popover-inner-border-radius); } .popover-header:empty { display: none; } .popover-body { padding: var(--bs-popover-body-padding-y) var(--bs-popover-body-padding-x); color: var(--bs-popover-body-color); } .carousel { position: relative; } .carousel.pointer-event { touch-action: pan-y; } .carousel-inner { position: relative; width: 100%; overflow: hidden; } .carousel-inner::after { display: block; clear: both; content: ""; } .carousel-item { position: relative; display: none; float: right; width: 100%; margin-left: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; transition: transform 0.6s ease-in-out; } @media (prefers-reduced-motion: reduce) { .carousel-item { transition: none; } } .carousel-item.active, .carousel-item-next, .carousel-item-prev { display: block; } .carousel-item-next:not(.carousel-item-start), .active.carousel-item-end { transform: translateX(-100%); } .carousel-item-prev:not(.carousel-item-end), .active.carousel-item-start { transform: translateX(100%); } .carousel-fade .carousel-item { opacity: 0; transition-property: opacity; transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-start, .carousel-fade .carousel-item-prev.carousel-item-end { z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { z-index: 0; opacity: 0; transition: opacity 0s 0.6s; } @media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-start, .carousel-fade .active.carousel-item-end { transition: none; } } .carousel-control-prev, .carousel-control-next { position: absolute; top: 0; bottom: 0; z-index: 1; display: flex; align-items: center; justify-content: center; width: 15%; padding: 0; color: #fff; text-align: center; background: none; border: 0; opacity: 0.5; transition: opacity 0.15s ease; } @media (prefers-reduced-motion: reduce) { .carousel-control-prev, .carousel-control-next { transition: none; } } .carousel-control-prev:hover, .carousel-control-prev:focus, .carousel-control-next:hover, .carousel-control-next:focus { color: #fff; text-decoration: none; outline: 0; opacity: 0.9; } .carousel-control-prev { right: 0; } .carousel-control-next { left: 0; } .carousel-control-prev-icon, .carousel-control-next-icon { display: inline-block; width: 2rem; height: 2rem; background-repeat: no-repeat; background-position: 50%; background-size: 100% 100%; } .carousel-control-next-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e"); } .carousel-control-prev-icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); } .carousel-indicators { position: absolute; left: 0; bottom: 0; right: 0; z-index: 2; display: flex; justify-content: center; padding: 0; margin-left: 15%; margin-bottom: 1rem; margin-right: 15%; list-style: none; } .carousel-indicators [data-bs-target] { box-sizing: content-box; flex: 0 1 auto; width: 30px; height: 3px; padding: 0; margin-left: 3px; margin-right: 3px; text-indent: -999px; cursor: pointer; background-color: #fff; background-clip: padding-box; border: 0; border-top: 10px solid transparent; border-bottom: 10px solid transparent; opacity: 0.5; transition: opacity 0.6s ease; } @media (prefers-reduced-motion: reduce) { .carousel-indicators [data-bs-target] { transition: none; } } .carousel-indicators .active { opacity: 1; } .carousel-caption { position: absolute; left: 15%; bottom: 1.25rem; right: 15%; padding-top: 1.25rem; padding-bottom: 1.25rem; color: #fff; text-align: center; } .carousel-dark .carousel-control-next-icon, .carousel-dark .carousel-control-prev-icon { filter: invert(1) grayscale(100); } .carousel-dark .carousel-indicators [data-bs-target] { background-color: #000; } .carousel-dark .carousel-caption { color: #000; } .spinner-grow, .spinner-border { display: inline-block; width: var(--bs-spinner-width); height: var(--bs-spinner-height); vertical-align: var(--bs-spinner-vertical-align); border-radius: 50%; animation: var(--bs-spinner-animation-speed) linear infinite var(--bs-spinner-animation-name); } @keyframes spinner-border { to { transform: rotate(360deg) ; } } .spinner-border { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; --bs-spinner-vertical-align: -0.125em; --bs-spinner-border-width: 0.25em; --bs-spinner-animation-speed: 0.75s; --bs-spinner-animation-name: spinner-border; border: var(--bs-spinner-border-width) solid currentcolor; border-left-color: transparent; } .spinner-border-sm { --bs-spinner-width: 1rem; --bs-spinner-height: 1rem; --bs-spinner-border-width: 0.2em; } @keyframes spinner-grow { 0% { transform: scale(0); } 50% { opacity: 1; transform: none; } } .spinner-grow { --bs-spinner-width: 2rem; --bs-spinner-height: 2rem; --bs-spinner-vertical-align: -0.125em; --bs-spinner-animation-speed: 0.75s; --bs-spinner-animation-name: spinner-grow; background-color: currentcolor; opacity: 0; } .spinner-grow-sm { --bs-spinner-width: 1rem; --bs-spinner-height: 1rem; } @media (prefers-reduced-motion: reduce) { .spinner-border, .spinner-grow { --bs-spinner-animation-speed: 1.5s; } } .offcanvas, .offcanvas-xxl, .offcanvas-xl, .offcanvas-lg, .offcanvas-md, .offcanvas-sm { --bs-offcanvas-zindex: 1045; --bs-offcanvas-width: 400px; --bs-offcanvas-height: 30vh; --bs-offcanvas-padding-x: 1rem; --bs-offcanvas-padding-y: 1rem; --bs-offcanvas-color: ; --bs-offcanvas-bg: #fff; --bs-offcanvas-border-width: 1px; --bs-offcanvas-border-color: var(--bs-border-color-translucent); --bs-offcanvas-box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); } @media (max-width: 575.98px) { .offcanvas-sm { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 575.98px) and (prefers-reduced-motion: reduce) { .offcanvas-sm { transition: none; } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 575.98px) { .offcanvas-sm.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 575.98px) { .offcanvas-sm.showing, .offcanvas-sm.show:not(.hiding) { transform: none; } } @media (max-width: 575.98px) { .offcanvas-sm.showing, .offcanvas-sm.hiding, .offcanvas-sm.show { visibility: visible; } } @media (min-width: 576px) { .offcanvas-sm { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-sm .offcanvas-header { display: none; } .offcanvas-sm .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 767.98px) { .offcanvas-md { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 767.98px) and (prefers-reduced-motion: reduce) { .offcanvas-md { transition: none; } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 767.98px) { .offcanvas-md.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 767.98px) { .offcanvas-md.showing, .offcanvas-md.show:not(.hiding) { transform: none; } } @media (max-width: 767.98px) { .offcanvas-md.showing, .offcanvas-md.hiding, .offcanvas-md.show { visibility: visible; } } @media (min-width: 768px) { .offcanvas-md { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-md .offcanvas-header { display: none; } .offcanvas-md .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 991.98px) { .offcanvas-lg { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 991.98px) and (prefers-reduced-motion: reduce) { .offcanvas-lg { transition: none; } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 991.98px) { .offcanvas-lg.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 991.98px) { .offcanvas-lg.showing, .offcanvas-lg.show:not(.hiding) { transform: none; } } @media (max-width: 991.98px) { .offcanvas-lg.showing, .offcanvas-lg.hiding, .offcanvas-lg.show { visibility: visible; } } @media (min-width: 992px) { .offcanvas-lg { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-lg .offcanvas-header { display: none; } .offcanvas-lg .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 1199.98px) { .offcanvas-xl { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 1199.98px) and (prefers-reduced-motion: reduce) { .offcanvas-xl { transition: none; } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 1199.98px) { .offcanvas-xl.showing, .offcanvas-xl.show:not(.hiding) { transform: none; } } @media (max-width: 1199.98px) { .offcanvas-xl.showing, .offcanvas-xl.hiding, .offcanvas-xl.show { visibility: visible; } } @media (min-width: 1200px) { .offcanvas-xl { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-xl .offcanvas-header { display: none; } .offcanvas-xl .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } @media (max-width: 1399.98px) { .offcanvas-xxl { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } } @media (max-width: 1399.98px) and (prefers-reduced-motion: reduce) { .offcanvas-xxl { transition: none; } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } } @media (max-width: 1399.98px) { .offcanvas-xxl.showing, .offcanvas-xxl.show:not(.hiding) { transform: none; } } @media (max-width: 1399.98px) { .offcanvas-xxl.showing, .offcanvas-xxl.hiding, .offcanvas-xxl.show { visibility: visible; } } @media (min-width: 1400px) { .offcanvas-xxl { --bs-offcanvas-height: auto; --bs-offcanvas-border-width: 0; background-color: transparent !important; } .offcanvas-xxl .offcanvas-header { display: none; } .offcanvas-xxl .offcanvas-body { display: flex; flex-grow: 0; padding: 0; overflow-y: visible; background-color: transparent !important; } } .offcanvas { position: fixed; bottom: 0; z-index: var(--bs-offcanvas-zindex); display: flex; flex-direction: column; max-width: 100%; color: var(--bs-offcanvas-color); visibility: hidden; background-color: var(--bs-offcanvas-bg); background-clip: padding-box; outline: 0; transition: transform 0.3s ease-in-out; } @media (prefers-reduced-motion: reduce) { .offcanvas { transition: none; } } .offcanvas.offcanvas-start { top: 0; right: 0; width: var(--bs-offcanvas-width); border-left: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(100%); } .offcanvas.offcanvas-end { top: 0; left: 0; width: var(--bs-offcanvas-width); border-right: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateX(-100%); } .offcanvas.offcanvas-top { top: 0; left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-bottom: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(-100%); } .offcanvas.offcanvas-bottom { left: 0; right: 0; height: var(--bs-offcanvas-height); max-height: 100%; border-top: var(--bs-offcanvas-border-width) solid var(--bs-offcanvas-border-color); transform: translateY(100%); } .offcanvas.showing, .offcanvas.show:not(.hiding) { transform: none; } .offcanvas.showing, .offcanvas.hiding, .offcanvas.show { visibility: visible; } .offcanvas-backdrop { position: fixed; top: 0; right: 0; z-index: 1040; width: 100vw; height: 100vh; background-color: #000; } .offcanvas-backdrop.fade { opacity: 0; } .offcanvas-backdrop.show { opacity: 0.5; } .offcanvas-header { display: flex; align-items: center; justify-content: space-between; padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); } .offcanvas-header .btn-close { padding: calc(var(--bs-offcanvas-padding-y) * 0.5) calc(var(--bs-offcanvas-padding-x) * 0.5); margin-top: calc(-0.5 * var(--bs-offcanvas-padding-y)); margin-left: calc(-0.5 * var(--bs-offcanvas-padding-x)); margin-bottom: calc(-0.5 * var(--bs-offcanvas-padding-y)); } .offcanvas-title { margin-bottom: 0; line-height: 1.5; } .offcanvas-body { flex-grow: 1; padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x); overflow-y: auto; } .placeholder { display: inline-block; min-height: 1em; vertical-align: middle; cursor: wait; background-color: currentcolor; opacity: 0.5; } .placeholder.btn::before { display: inline-block; content: ""; } .placeholder-xs { min-height: 0.6em; } .placeholder-sm { min-height: 0.8em; } .placeholder-lg { min-height: 1.2em; } .placeholder-glow .placeholder { animation: placeholder-glow 2s ease-in-out infinite; } @keyframes placeholder-glow { 50% { opacity: 0.2; } } .placeholder-wave { -webkit-mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); mask-image: linear-gradient(130deg, #000 55%, rgba(0, 0, 0, 0.8) 75%, #000 95%); -webkit-mask-size: 200% 100%; mask-size: 200% 100%; animation: placeholder-wave 2s linear infinite; } @keyframes placeholder-wave { 100% { -webkit-mask-position: -200% 0%; mask-position: -200% 0%; } } .clearfix::after { display: block; clear: both; content: ""; } .text-bg-primary { color: #fff !important; background-color: RGBA(13, 110, 253, var(--bs-bg-opacity, 1)) !important; } .text-bg-secondary { color: #fff !important; background-color: RGBA(108, 117, 125, var(--bs-bg-opacity, 1)) !important; } .text-bg-success { color: #fff !important; background-color: RGBA(25, 135, 84, var(--bs-bg-opacity, 1)) !important; } .text-bg-info { color: #000 !important; background-color: RGBA(13, 202, 240, var(--bs-bg-opacity, 1)) !important; } .text-bg-warning { color: #000 !important; background-color: RGBA(255, 193, 7, var(--bs-bg-opacity, 1)) !important; } .text-bg-danger { color: #fff !important; background-color: RGBA(220, 53, 69, var(--bs-bg-opacity, 1)) !important; } .text-bg-light { color: #000 !important; background-color: RGBA(248, 249, 250, var(--bs-bg-opacity, 1)) !important; } .text-bg-dark { color: #fff !important; background-color: RGBA(33, 37, 41, var(--bs-bg-opacity, 1)) !important; } .link-primary { color: #0d6efd !important; } .link-primary:hover, .link-primary:focus { color: #0a58ca !important; } .link-secondary { color: #6c757d !important; } .link-secondary:hover, .link-secondary:focus { color: #565e64 !important; } .link-success { color: #198754 !important; } .link-success:hover, .link-success:focus { color: #146c43 !important; } .link-info { color: #0dcaf0 !important; } .link-info:hover, .link-info:focus { color: #3dd5f3 !important; } .link-warning { color: #ffc107 !important; } .link-warning:hover, .link-warning:focus { color: #ffcd39 !important; } .link-danger { color: #dc3545 !important; } .link-danger:hover, .link-danger:focus { color: #b02a37 !important; } .link-light { color: #f8f9fa !important; } .link-light:hover, .link-light:focus { color: #f9fafb !important; } .link-dark { color: #212529 !important; } .link-dark:hover, .link-dark:focus { color: #1a1e21 !important; } .ratio { position: relative; width: 100%; } .ratio::before { display: block; padding-top: var(--bs-aspect-ratio); content: ""; } .ratio > * { position: absolute; top: 0; right: 0; width: 100%; height: 100%; } .ratio-1x1 { --bs-aspect-ratio: 100%; } .ratio-4x3 { --bs-aspect-ratio: 75%; } .ratio-16x9 { --bs-aspect-ratio: 56.25%; } .ratio-21x9 { --bs-aspect-ratio: 42.8571428571%; } .fixed-top { position: fixed; top: 0; left: 0; right: 0; z-index: 1030; } .fixed-bottom { position: fixed; left: 0; bottom: 0; right: 0; z-index: 1030; } .sticky-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } @media (min-width: 576px) { .sticky-sm-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-sm-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 768px) { .sticky-md-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-md-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 992px) { .sticky-lg-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-lg-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1200px) { .sticky-xl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } @media (min-width: 1400px) { .sticky-xxl-top { position: -webkit-sticky; position: sticky; top: 0; z-index: 1020; } .sticky-xxl-bottom { position: -webkit-sticky; position: sticky; bottom: 0; z-index: 1020; } } .hstack { display: flex; flex-direction: row; align-items: center; align-self: stretch; } .vstack { display: flex; flex: 1 1 auto; flex-direction: column; align-self: stretch; } .visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } .stretched-link::after { position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 1; content: ""; } .text-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .vr { display: inline-block; align-self: stretch; width: 1px; min-height: 1em; background-color: currentcolor; opacity: 0.25; } .align-baseline { vertical-align: baseline !important; } .align-top { vertical-align: top !important; } .align-middle { vertical-align: middle !important; } .align-bottom { vertical-align: bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; } .align-text-top { vertical-align: text-top !important; } .float-start { float: right !important; } .float-end { float: left !important; } .float-none { float: none !important; } .opacity-0 { opacity: 0 !important; } .opacity-25 { opacity: 0.25 !important; } .opacity-50 { opacity: 0.5 !important; } .opacity-75 { opacity: 0.75 !important; } .opacity-100 { opacity: 1 !important; } .overflow-auto { overflow: auto !important; } .overflow-hidden { overflow: hidden !important; } .overflow-visible { overflow: visible !important; } .overflow-scroll { overflow: scroll !important; } .d-inline { display: inline !important; } .d-inline-block { display: inline-block !important; } .d-block { display: block !important; } .d-grid { display: grid !important; } .d-table { display: table !important; } .d-table-row { display: table-row !important; } .d-table-cell { display: table-cell !important; } .d-flex { display: flex !important; } .d-inline-flex { display: inline-flex !important; } .d-none { display: none !important; } .shadow { box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; } .shadow-sm { box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; } .shadow-lg { box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; } .shadow-none { box-shadow: none !important; } .position-static { position: static !important; } .position-relative { position: relative !important; } .position-absolute { position: absolute !important; } .position-fixed { position: fixed !important; } .position-sticky { position: -webkit-sticky !important; position: sticky !important; } .top-0 { top: 0 !important; } .top-50 { top: 50% !important; } .top-100 { top: 100% !important; } .bottom-0 { bottom: 0 !important; } .bottom-50 { bottom: 50% !important; } .bottom-100 { bottom: 100% !important; } .start-0 { right: 0 !important; } .start-50 { right: 50% !important; } .start-100 { right: 100% !important; } .end-0 { left: 0 !important; } .end-50 { left: 50% !important; } .end-100 { left: 100% !important; } .translate-middle { transform: translate(50%, -50%) !important; } .translate-middle-x { transform: translateX(50%) !important; } .translate-middle-y { transform: translateY(-50%) !important; } .border { border: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-0 { border: 0 !important; } .border-top { border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-top-0 { border-top: 0 !important; } .border-end { border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-end-0 { border-left: 0 !important; } .border-bottom { border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-bottom-0 { border-bottom: 0 !important; } .border-start { border-right: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important; } .border-start-0 { border-right: 0 !important; } .border-primary { --bs-border-opacity: 1; border-color: rgba(var(--bs-primary-rgb), var(--bs-border-opacity)) !important; } .border-secondary { --bs-border-opacity: 1; border-color: rgba(var(--bs-secondary-rgb), var(--bs-border-opacity)) !important; } .border-success { --bs-border-opacity: 1; border-color: rgba(var(--bs-success-rgb), var(--bs-border-opacity)) !important; } .border-info { --bs-border-opacity: 1; border-color: rgba(var(--bs-info-rgb), var(--bs-border-opacity)) !important; } .border-warning { --bs-border-opacity: 1; border-color: rgba(var(--bs-warning-rgb), var(--bs-border-opacity)) !important; } .border-danger { --bs-border-opacity: 1; border-color: rgba(var(--bs-danger-rgb), var(--bs-border-opacity)) !important; } .border-light { --bs-border-opacity: 1; border-color: rgba(var(--bs-light-rgb), var(--bs-border-opacity)) !important; } .border-dark { --bs-border-opacity: 1; border-color: rgba(var(--bs-dark-rgb), var(--bs-border-opacity)) !important; } .border-white { --bs-border-opacity: 1; border-color: rgba(var(--bs-white-rgb), var(--bs-border-opacity)) !important; } .border-1 { --bs-border-width: 1px; } .border-2 { --bs-border-width: 2px; } .border-3 { --bs-border-width: 3px; } .border-4 { --bs-border-width: 4px; } .border-5 { --bs-border-width: 5px; } .border-opacity-10 { --bs-border-opacity: 0.1; } .border-opacity-25 { --bs-border-opacity: 0.25; } .border-opacity-50 { --bs-border-opacity: 0.5; } .border-opacity-75 { --bs-border-opacity: 0.75; } .border-opacity-100 { --bs-border-opacity: 1; } .w-25 { width: 25% !important; } .w-50 { width: 50% !important; } .w-75 { width: 75% !important; } .w-100 { width: 100% !important; } .w-auto { width: auto !important; } .mw-100 { max-width: 100% !important; } .vw-100 { width: 100vw !important; } .min-vw-100 { min-width: 100vw !important; } .h-25 { height: 25% !important; } .h-50 { height: 50% !important; } .h-75 { height: 75% !important; } .h-100 { height: 100% !important; } .h-auto { height: auto !important; } .mh-100 { max-height: 100% !important; } .vh-100 { height: 100vh !important; } .min-vh-100 { min-height: 100vh !important; } .flex-fill { flex: 1 1 auto !important; } .flex-row { flex-direction: row !important; } .flex-column { flex-direction: column !important; } .flex-row-reverse { flex-direction: row-reverse !important; } .flex-column-reverse { flex-direction: column-reverse !important; } .flex-grow-0 { flex-grow: 0 !important; } .flex-grow-1 { flex-grow: 1 !important; } .flex-shrink-0 { flex-shrink: 0 !important; } .flex-shrink-1 { flex-shrink: 1 !important; } .flex-wrap { flex-wrap: wrap !important; } .flex-nowrap { flex-wrap: nowrap !important; } .flex-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-start { justify-content: flex-start !important; } .justify-content-end { justify-content: flex-end !important; } .justify-content-center { justify-content: center !important; } .justify-content-between { justify-content: space-between !important; } .justify-content-around { justify-content: space-around !important; } .justify-content-evenly { justify-content: space-evenly !important; } .align-items-start { align-items: flex-start !important; } .align-items-end { align-items: flex-end !important; } .align-items-center { align-items: center !important; } .align-items-baseline { align-items: baseline !important; } .align-items-stretch { align-items: stretch !important; } .align-content-start { align-content: flex-start !important; } .align-content-end { align-content: flex-end !important; } .align-content-center { align-content: center !important; } .align-content-between { align-content: space-between !important; } .align-content-around { align-content: space-around !important; } .align-content-stretch { align-content: stretch !important; } .align-self-auto { align-self: auto !important; } .align-self-start { align-self: flex-start !important; } .align-self-end { align-self: flex-end !important; } .align-self-center { align-self: center !important; } .align-self-baseline { align-self: baseline !important; } .align-self-stretch { align-self: stretch !important; } .order-first { order: -1 !important; } .order-0 { order: 0 !important; } .order-1 { order: 1 !important; } .order-2 { order: 2 !important; } .order-3 { order: 3 !important; } .order-4 { order: 4 !important; } .order-5 { order: 5 !important; } .order-last { order: 6 !important; } .m-0 { margin: 0 !important; } .m-1 { margin: 0.25rem !important; } .m-2 { margin: 0.5rem !important; } .m-3 { margin: 1rem !important; } .m-4 { margin: 1.5rem !important; } .m-5 { margin: 3rem !important; } .m-auto { margin: auto !important; } .mx-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-auto { margin-left: auto !important; margin-right: auto !important; } .my-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-0 { margin-top: 0 !important; } .mt-1 { margin-top: 0.25rem !important; } .mt-2 { margin-top: 0.5rem !important; } .mt-3 { margin-top: 1rem !important; } .mt-4 { margin-top: 1.5rem !important; } .mt-5 { margin-top: 3rem !important; } .mt-auto { margin-top: auto !important; } .me-0 { margin-left: 0 !important; } .me-1 { margin-left: 0.25rem !important; } .me-2 { margin-left: 0.5rem !important; } .me-3 { margin-left: 1rem !important; } .me-4 { margin-left: 1.5rem !important; } .me-5 { margin-left: 3rem !important; } .me-auto { margin-left: auto !important; } .mb-0 { margin-bottom: 0 !important; } .mb-1 { margin-bottom: 0.25rem !important; } .mb-2 { margin-bottom: 0.5rem !important; } .mb-3 { margin-bottom: 1rem !important; } .mb-4 { margin-bottom: 1.5rem !important; } .mb-5 { margin-bottom: 3rem !important; } .mb-auto { margin-bottom: auto !important; } .ms-0 { margin-right: 0 !important; } .ms-1 { margin-right: 0.25rem !important; } .ms-2 { margin-right: 0.5rem !important; } .ms-3 { margin-right: 1rem !important; } .ms-4 { margin-right: 1.5rem !important; } .ms-5 { margin-right: 3rem !important; } .ms-auto { margin-right: auto !important; } .p-0 { padding: 0 !important; } .p-1 { padding: 0.25rem !important; } .p-2 { padding: 0.5rem !important; } .p-3 { padding: 1rem !important; } .p-4 { padding: 1.5rem !important; } .p-5 { padding: 3rem !important; } .px-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-0 { padding-top: 0 !important; } .pt-1 { padding-top: 0.25rem !important; } .pt-2 { padding-top: 0.5rem !important; } .pt-3 { padding-top: 1rem !important; } .pt-4 { padding-top: 1.5rem !important; } .pt-5 { padding-top: 3rem !important; } .pe-0 { padding-left: 0 !important; } .pe-1 { padding-left: 0.25rem !important; } .pe-2 { padding-left: 0.5rem !important; } .pe-3 { padding-left: 1rem !important; } .pe-4 { padding-left: 1.5rem !important; } .pe-5 { padding-left: 3rem !important; } .pb-0 { padding-bottom: 0 !important; } .pb-1 { padding-bottom: 0.25rem !important; } .pb-2 { padding-bottom: 0.5rem !important; } .pb-3 { padding-bottom: 1rem !important; } .pb-4 { padding-bottom: 1.5rem !important; } .pb-5 { padding-bottom: 3rem !important; } .ps-0 { padding-right: 0 !important; } .ps-1 { padding-right: 0.25rem !important; } .ps-2 { padding-right: 0.5rem !important; } .ps-3 { padding-right: 1rem !important; } .ps-4 { padding-right: 1.5rem !important; } .ps-5 { padding-right: 3rem !important; } .gap-0 { gap: 0 !important; } .gap-1 { gap: 0.25rem !important; } .gap-2 { gap: 0.5rem !important; } .gap-3 { gap: 1rem !important; } .gap-4 { gap: 1.5rem !important; } .gap-5 { gap: 3rem !important; } .font-monospace { font-family: var(--bs-font-monospace) !important; } .fs-1 { font-size: calc(1.375rem + 1.5vw) !important; } .fs-2 { font-size: calc(1.325rem + 0.9vw) !important; } .fs-3 { font-size: calc(1.3rem + 0.6vw) !important; } .fs-4 { font-size: calc(1.275rem + 0.3vw) !important; } .fs-5 { font-size: 1.25rem !important; } .fs-6 { font-size: 1rem !important; } .fst-italic { font-style: italic !important; } .fst-normal { font-style: normal !important; } .fw-light { font-weight: 300 !important; } .fw-lighter { font-weight: lighter !important; } .fw-normal { font-weight: 400 !important; } .fw-bold { font-weight: 700 !important; } .fw-semibold { font-weight: 600 !important; } .fw-bolder { font-weight: bolder !important; } .lh-1 { line-height: 1 !important; } .lh-sm { line-height: 1.25 !important; } .lh-base { line-height: 1.5 !important; } .lh-lg { line-height: 2 !important; } .text-start { text-align: right !important; } .text-end { text-align: left !important; } .text-center { text-align: center !important; } .text-decoration-none { text-decoration: none !important; } .text-decoration-underline { text-decoration: underline !important; } .text-decoration-line-through { text-decoration: line-through !important; } .text-lowercase { text-transform: lowercase !important; } .text-uppercase { text-transform: uppercase !important; } .text-capitalize { text-transform: capitalize !important; } .text-wrap { white-space: normal !important; } .text-nowrap { white-space: nowrap !important; } .text-primary { --bs-text-opacity: 1; color: rgba(var(--bs-primary-rgb), var(--bs-text-opacity)) !important; } .text-secondary { --bs-text-opacity: 1; color: rgba(var(--bs-secondary-rgb), var(--bs-text-opacity)) !important; } .text-success { --bs-text-opacity: 1; color: rgba(var(--bs-success-rgb), var(--bs-text-opacity)) !important; } .text-info { --bs-text-opacity: 1; color: rgba(var(--bs-info-rgb), var(--bs-text-opacity)) !important; } .text-warning { --bs-text-opacity: 1; color: rgba(var(--bs-warning-rgb), var(--bs-text-opacity)) !important; } .text-danger { --bs-text-opacity: 1; color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; } .text-light { --bs-text-opacity: 1; color: rgba(var(--bs-light-rgb), var(--bs-text-opacity)) !important; } .text-dark { --bs-text-opacity: 1; color: rgba(var(--bs-dark-rgb), var(--bs-text-opacity)) !important; } .text-black { --bs-text-opacity: 1; color: rgba(var(--bs-black-rgb), var(--bs-text-opacity)) !important; } .text-white { --bs-text-opacity: 1; color: rgba(var(--bs-white-rgb), var(--bs-text-opacity)) !important; } .text-body { --bs-text-opacity: 1; color: rgba(var(--bs-body-color-rgb), var(--bs-text-opacity)) !important; } .text-muted { --bs-text-opacity: 1; color: #6c757d !important; } .text-black-50 { --bs-text-opacity: 1; color: rgba(0, 0, 0, 0.5) !important; } .text-white-50 { --bs-text-opacity: 1; color: rgba(255, 255, 255, 0.5) !important; } .text-reset { --bs-text-opacity: 1; color: inherit !important; } .text-opacity-25 { --bs-text-opacity: 0.25; } .text-opacity-50 { --bs-text-opacity: 0.5; } .text-opacity-75 { --bs-text-opacity: 0.75; } .text-opacity-100 { --bs-text-opacity: 1; } .bg-primary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-primary-rgb), var(--bs-bg-opacity)) !important; } .bg-secondary { --bs-bg-opacity: 1; background-color: rgba(var(--bs-secondary-rgb), var(--bs-bg-opacity)) !important; } .bg-success { --bs-bg-opacity: 1; background-color: rgba(var(--bs-success-rgb), var(--bs-bg-opacity)) !important; } .bg-info { --bs-bg-opacity: 1; background-color: rgba(var(--bs-info-rgb), var(--bs-bg-opacity)) !important; } .bg-warning { --bs-bg-opacity: 1; background-color: rgba(var(--bs-warning-rgb), var(--bs-bg-opacity)) !important; } .bg-danger { --bs-bg-opacity: 1; background-color: rgba(var(--bs-danger-rgb), var(--bs-bg-opacity)) !important; } .bg-light { --bs-bg-opacity: 1; background-color: rgba(var(--bs-light-rgb), var(--bs-bg-opacity)) !important; } .bg-dark { --bs-bg-opacity: 1; background-color: rgba(var(--bs-dark-rgb), var(--bs-bg-opacity)) !important; } .bg-black { --bs-bg-opacity: 1; background-color: rgba(var(--bs-black-rgb), var(--bs-bg-opacity)) !important; } .bg-white { --bs-bg-opacity: 1; background-color: rgba(var(--bs-white-rgb), var(--bs-bg-opacity)) !important; } .bg-body { --bs-bg-opacity: 1; background-color: rgba(var(--bs-body-bg-rgb), var(--bs-bg-opacity)) !important; } .bg-transparent { --bs-bg-opacity: 1; background-color: transparent !important; } .bg-opacity-10 { --bs-bg-opacity: 0.1; } .bg-opacity-25 { --bs-bg-opacity: 0.25; } .bg-opacity-50 { --bs-bg-opacity: 0.5; } .bg-opacity-75 { --bs-bg-opacity: 0.75; } .bg-opacity-100 { --bs-bg-opacity: 1; } .bg-gradient { background-image: var(--bs-gradient) !important; } .user-select-all { -webkit-user-select: all !important; -moz-user-select: all !important; user-select: all !important; } .user-select-auto { -webkit-user-select: auto !important; -moz-user-select: auto !important; user-select: auto !important; } .user-select-none { -webkit-user-select: none !important; -moz-user-select: none !important; user-select: none !important; } .pe-none { pointer-events: none !important; } .pe-auto { pointer-events: auto !important; } .rounded { border-radius: var(--bs-border-radius) !important; } .rounded-0 { border-radius: 0 !important; } .rounded-1 { border-radius: var(--bs-border-radius-sm) !important; } .rounded-2 { border-radius: var(--bs-border-radius) !important; } .rounded-3 { border-radius: var(--bs-border-radius-lg) !important; } .rounded-4 { border-radius: var(--bs-border-radius-xl) !important; } .rounded-5 { border-radius: var(--bs-border-radius-2xl) !important; } .rounded-circle { border-radius: 50% !important; } .rounded-pill { border-radius: var(--bs-border-radius-pill) !important; } .rounded-top { border-top-right-radius: var(--bs-border-radius) !important; border-top-left-radius: var(--bs-border-radius) !important; } .rounded-end { border-top-left-radius: var(--bs-border-radius) !important; border-bottom-left-radius: var(--bs-border-radius) !important; } .rounded-bottom { border-bottom-left-radius: var(--bs-border-radius) !important; border-bottom-right-radius: var(--bs-border-radius) !important; } .rounded-start { border-bottom-right-radius: var(--bs-border-radius) !important; border-top-right-radius: var(--bs-border-radius) !important; } .visible { visibility: visible !important; } .invisible { visibility: hidden !important; } @media (min-width: 576px) { .float-sm-start { float: right !important; } .float-sm-end { float: left !important; } .float-sm-none { float: none !important; } .d-sm-inline { display: inline !important; } .d-sm-inline-block { display: inline-block !important; } .d-sm-block { display: block !important; } .d-sm-grid { display: grid !important; } .d-sm-table { display: table !important; } .d-sm-table-row { display: table-row !important; } .d-sm-table-cell { display: table-cell !important; } .d-sm-flex { display: flex !important; } .d-sm-inline-flex { display: inline-flex !important; } .d-sm-none { display: none !important; } .flex-sm-fill { flex: 1 1 auto !important; } .flex-sm-row { flex-direction: row !important; } .flex-sm-column { flex-direction: column !important; } .flex-sm-row-reverse { flex-direction: row-reverse !important; } .flex-sm-column-reverse { flex-direction: column-reverse !important; } .flex-sm-grow-0 { flex-grow: 0 !important; } .flex-sm-grow-1 { flex-grow: 1 !important; } .flex-sm-shrink-0 { flex-shrink: 0 !important; } .flex-sm-shrink-1 { flex-shrink: 1 !important; } .flex-sm-wrap { flex-wrap: wrap !important; } .flex-sm-nowrap { flex-wrap: nowrap !important; } .flex-sm-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-sm-start { justify-content: flex-start !important; } .justify-content-sm-end { justify-content: flex-end !important; } .justify-content-sm-center { justify-content: center !important; } .justify-content-sm-between { justify-content: space-between !important; } .justify-content-sm-around { justify-content: space-around !important; } .justify-content-sm-evenly { justify-content: space-evenly !important; } .align-items-sm-start { align-items: flex-start !important; } .align-items-sm-end { align-items: flex-end !important; } .align-items-sm-center { align-items: center !important; } .align-items-sm-baseline { align-items: baseline !important; } .align-items-sm-stretch { align-items: stretch !important; } .align-content-sm-start { align-content: flex-start !important; } .align-content-sm-end { align-content: flex-end !important; } .align-content-sm-center { align-content: center !important; } .align-content-sm-between { align-content: space-between !important; } .align-content-sm-around { align-content: space-around !important; } .align-content-sm-stretch { align-content: stretch !important; } .align-self-sm-auto { align-self: auto !important; } .align-self-sm-start { align-self: flex-start !important; } .align-self-sm-end { align-self: flex-end !important; } .align-self-sm-center { align-self: center !important; } .align-self-sm-baseline { align-self: baseline !important; } .align-self-sm-stretch { align-self: stretch !important; } .order-sm-first { order: -1 !important; } .order-sm-0 { order: 0 !important; } .order-sm-1 { order: 1 !important; } .order-sm-2 { order: 2 !important; } .order-sm-3 { order: 3 !important; } .order-sm-4 { order: 4 !important; } .order-sm-5 { order: 5 !important; } .order-sm-last { order: 6 !important; } .m-sm-0 { margin: 0 !important; } .m-sm-1 { margin: 0.25rem !important; } .m-sm-2 { margin: 0.5rem !important; } .m-sm-3 { margin: 1rem !important; } .m-sm-4 { margin: 1.5rem !important; } .m-sm-5 { margin: 3rem !important; } .m-sm-auto { margin: auto !important; } .mx-sm-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-sm-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-sm-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-sm-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-sm-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-sm-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-sm-auto { margin-left: auto !important; margin-right: auto !important; } .my-sm-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-sm-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-sm-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-sm-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-sm-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-sm-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-sm-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-sm-0 { margin-top: 0 !important; } .mt-sm-1 { margin-top: 0.25rem !important; } .mt-sm-2 { margin-top: 0.5rem !important; } .mt-sm-3 { margin-top: 1rem !important; } .mt-sm-4 { margin-top: 1.5rem !important; } .mt-sm-5 { margin-top: 3rem !important; } .mt-sm-auto { margin-top: auto !important; } .me-sm-0 { margin-left: 0 !important; } .me-sm-1 { margin-left: 0.25rem !important; } .me-sm-2 { margin-left: 0.5rem !important; } .me-sm-3 { margin-left: 1rem !important; } .me-sm-4 { margin-left: 1.5rem !important; } .me-sm-5 { margin-left: 3rem !important; } .me-sm-auto { margin-left: auto !important; } .mb-sm-0 { margin-bottom: 0 !important; } .mb-sm-1 { margin-bottom: 0.25rem !important; } .mb-sm-2 { margin-bottom: 0.5rem !important; } .mb-sm-3 { margin-bottom: 1rem !important; } .mb-sm-4 { margin-bottom: 1.5rem !important; } .mb-sm-5 { margin-bottom: 3rem !important; } .mb-sm-auto { margin-bottom: auto !important; } .ms-sm-0 { margin-right: 0 !important; } .ms-sm-1 { margin-right: 0.25rem !important; } .ms-sm-2 { margin-right: 0.5rem !important; } .ms-sm-3 { margin-right: 1rem !important; } .ms-sm-4 { margin-right: 1.5rem !important; } .ms-sm-5 { margin-right: 3rem !important; } .ms-sm-auto { margin-right: auto !important; } .p-sm-0 { padding: 0 !important; } .p-sm-1 { padding: 0.25rem !important; } .p-sm-2 { padding: 0.5rem !important; } .p-sm-3 { padding: 1rem !important; } .p-sm-4 { padding: 1.5rem !important; } .p-sm-5 { padding: 3rem !important; } .px-sm-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-sm-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-sm-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-sm-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-sm-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-sm-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-sm-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-sm-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-sm-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-sm-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-sm-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-sm-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-sm-0 { padding-top: 0 !important; } .pt-sm-1 { padding-top: 0.25rem !important; } .pt-sm-2 { padding-top: 0.5rem !important; } .pt-sm-3 { padding-top: 1rem !important; } .pt-sm-4 { padding-top: 1.5rem !important; } .pt-sm-5 { padding-top: 3rem !important; } .pe-sm-0 { padding-left: 0 !important; } .pe-sm-1 { padding-left: 0.25rem !important; } .pe-sm-2 { padding-left: 0.5rem !important; } .pe-sm-3 { padding-left: 1rem !important; } .pe-sm-4 { padding-left: 1.5rem !important; } .pe-sm-5 { padding-left: 3rem !important; } .pb-sm-0 { padding-bottom: 0 !important; } .pb-sm-1 { padding-bottom: 0.25rem !important; } .pb-sm-2 { padding-bottom: 0.5rem !important; } .pb-sm-3 { padding-bottom: 1rem !important; } .pb-sm-4 { padding-bottom: 1.5rem !important; } .pb-sm-5 { padding-bottom: 3rem !important; } .ps-sm-0 { padding-right: 0 !important; } .ps-sm-1 { padding-right: 0.25rem !important; } .ps-sm-2 { padding-right: 0.5rem !important; } .ps-sm-3 { padding-right: 1rem !important; } .ps-sm-4 { padding-right: 1.5rem !important; } .ps-sm-5 { padding-right: 3rem !important; } .gap-sm-0 { gap: 0 !important; } .gap-sm-1 { gap: 0.25rem !important; } .gap-sm-2 { gap: 0.5rem !important; } .gap-sm-3 { gap: 1rem !important; } .gap-sm-4 { gap: 1.5rem !important; } .gap-sm-5 { gap: 3rem !important; } .text-sm-start { text-align: right !important; } .text-sm-end { text-align: left !important; } .text-sm-center { text-align: center !important; } } @media (min-width: 768px) { .float-md-start { float: right !important; } .float-md-end { float: left !important; } .float-md-none { float: none !important; } .d-md-inline { display: inline !important; } .d-md-inline-block { display: inline-block !important; } .d-md-block { display: block !important; } .d-md-grid { display: grid !important; } .d-md-table { display: table !important; } .d-md-table-row { display: table-row !important; } .d-md-table-cell { display: table-cell !important; } .d-md-flex { display: flex !important; } .d-md-inline-flex { display: inline-flex !important; } .d-md-none { display: none !important; } .flex-md-fill { flex: 1 1 auto !important; } .flex-md-row { flex-direction: row !important; } .flex-md-column { flex-direction: column !important; } .flex-md-row-reverse { flex-direction: row-reverse !important; } .flex-md-column-reverse { flex-direction: column-reverse !important; } .flex-md-grow-0 { flex-grow: 0 !important; } .flex-md-grow-1 { flex-grow: 1 !important; } .flex-md-shrink-0 { flex-shrink: 0 !important; } .flex-md-shrink-1 { flex-shrink: 1 !important; } .flex-md-wrap { flex-wrap: wrap !important; } .flex-md-nowrap { flex-wrap: nowrap !important; } .flex-md-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-md-start { justify-content: flex-start !important; } .justify-content-md-end { justify-content: flex-end !important; } .justify-content-md-center { justify-content: center !important; } .justify-content-md-between { justify-content: space-between !important; } .justify-content-md-around { justify-content: space-around !important; } .justify-content-md-evenly { justify-content: space-evenly !important; } .align-items-md-start { align-items: flex-start !important; } .align-items-md-end { align-items: flex-end !important; } .align-items-md-center { align-items: center !important; } .align-items-md-baseline { align-items: baseline !important; } .align-items-md-stretch { align-items: stretch !important; } .align-content-md-start { align-content: flex-start !important; } .align-content-md-end { align-content: flex-end !important; } .align-content-md-center { align-content: center !important; } .align-content-md-between { align-content: space-between !important; } .align-content-md-around { align-content: space-around !important; } .align-content-md-stretch { align-content: stretch !important; } .align-self-md-auto { align-self: auto !important; } .align-self-md-start { align-self: flex-start !important; } .align-self-md-end { align-self: flex-end !important; } .align-self-md-center { align-self: center !important; } .align-self-md-baseline { align-self: baseline !important; } .align-self-md-stretch { align-self: stretch !important; } .order-md-first { order: -1 !important; } .order-md-0 { order: 0 !important; } .order-md-1 { order: 1 !important; } .order-md-2 { order: 2 !important; } .order-md-3 { order: 3 !important; } .order-md-4 { order: 4 !important; } .order-md-5 { order: 5 !important; } .order-md-last { order: 6 !important; } .m-md-0 { margin: 0 !important; } .m-md-1 { margin: 0.25rem !important; } .m-md-2 { margin: 0.5rem !important; } .m-md-3 { margin: 1rem !important; } .m-md-4 { margin: 1.5rem !important; } .m-md-5 { margin: 3rem !important; } .m-md-auto { margin: auto !important; } .mx-md-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-md-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-md-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-md-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-md-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-md-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-md-auto { margin-left: auto !important; margin-right: auto !important; } .my-md-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-md-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-md-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-md-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-md-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-md-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-md-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-md-0 { margin-top: 0 !important; } .mt-md-1 { margin-top: 0.25rem !important; } .mt-md-2 { margin-top: 0.5rem !important; } .mt-md-3 { margin-top: 1rem !important; } .mt-md-4 { margin-top: 1.5rem !important; } .mt-md-5 { margin-top: 3rem !important; } .mt-md-auto { margin-top: auto !important; } .me-md-0 { margin-left: 0 !important; } .me-md-1 { margin-left: 0.25rem !important; } .me-md-2 { margin-left: 0.5rem !important; } .me-md-3 { margin-left: 1rem !important; } .me-md-4 { margin-left: 1.5rem !important; } .me-md-5 { margin-left: 3rem !important; } .me-md-auto { margin-left: auto !important; } .mb-md-0 { margin-bottom: 0 !important; } .mb-md-1 { margin-bottom: 0.25rem !important; } .mb-md-2 { margin-bottom: 0.5rem !important; } .mb-md-3 { margin-bottom: 1rem !important; } .mb-md-4 { margin-bottom: 1.5rem !important; } .mb-md-5 { margin-bottom: 3rem !important; } .mb-md-auto { margin-bottom: auto !important; } .ms-md-0 { margin-right: 0 !important; } .ms-md-1 { margin-right: 0.25rem !important; } .ms-md-2 { margin-right: 0.5rem !important; } .ms-md-3 { margin-right: 1rem !important; } .ms-md-4 { margin-right: 1.5rem !important; } .ms-md-5 { margin-right: 3rem !important; } .ms-md-auto { margin-right: auto !important; } .p-md-0 { padding: 0 !important; } .p-md-1 { padding: 0.25rem !important; } .p-md-2 { padding: 0.5rem !important; } .p-md-3 { padding: 1rem !important; } .p-md-4 { padding: 1.5rem !important; } .p-md-5 { padding: 3rem !important; } .px-md-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-md-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-md-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-md-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-md-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-md-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-md-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-md-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-md-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-md-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-md-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-md-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-md-0 { padding-top: 0 !important; } .pt-md-1 { padding-top: 0.25rem !important; } .pt-md-2 { padding-top: 0.5rem !important; } .pt-md-3 { padding-top: 1rem !important; } .pt-md-4 { padding-top: 1.5rem !important; } .pt-md-5 { padding-top: 3rem !important; } .pe-md-0 { padding-left: 0 !important; } .pe-md-1 { padding-left: 0.25rem !important; } .pe-md-2 { padding-left: 0.5rem !important; } .pe-md-3 { padding-left: 1rem !important; } .pe-md-4 { padding-left: 1.5rem !important; } .pe-md-5 { padding-left: 3rem !important; } .pb-md-0 { padding-bottom: 0 !important; } .pb-md-1 { padding-bottom: 0.25rem !important; } .pb-md-2 { padding-bottom: 0.5rem !important; } .pb-md-3 { padding-bottom: 1rem !important; } .pb-md-4 { padding-bottom: 1.5rem !important; } .pb-md-5 { padding-bottom: 3rem !important; } .ps-md-0 { padding-right: 0 !important; } .ps-md-1 { padding-right: 0.25rem !important; } .ps-md-2 { padding-right: 0.5rem !important; } .ps-md-3 { padding-right: 1rem !important; } .ps-md-4 { padding-right: 1.5rem !important; } .ps-md-5 { padding-right: 3rem !important; } .gap-md-0 { gap: 0 !important; } .gap-md-1 { gap: 0.25rem !important; } .gap-md-2 { gap: 0.5rem !important; } .gap-md-3 { gap: 1rem !important; } .gap-md-4 { gap: 1.5rem !important; } .gap-md-5 { gap: 3rem !important; } .text-md-start { text-align: right !important; } .text-md-end { text-align: left !important; } .text-md-center { text-align: center !important; } } @media (min-width: 992px) { .float-lg-start { float: right !important; } .float-lg-end { float: left !important; } .float-lg-none { float: none !important; } .d-lg-inline { display: inline !important; } .d-lg-inline-block { display: inline-block !important; } .d-lg-block { display: block !important; } .d-lg-grid { display: grid !important; } .d-lg-table { display: table !important; } .d-lg-table-row { display: table-row !important; } .d-lg-table-cell { display: table-cell !important; } .d-lg-flex { display: flex !important; } .d-lg-inline-flex { display: inline-flex !important; } .d-lg-none { display: none !important; } .flex-lg-fill { flex: 1 1 auto !important; } .flex-lg-row { flex-direction: row !important; } .flex-lg-column { flex-direction: column !important; } .flex-lg-row-reverse { flex-direction: row-reverse !important; } .flex-lg-column-reverse { flex-direction: column-reverse !important; } .flex-lg-grow-0 { flex-grow: 0 !important; } .flex-lg-grow-1 { flex-grow: 1 !important; } .flex-lg-shrink-0 { flex-shrink: 0 !important; } .flex-lg-shrink-1 { flex-shrink: 1 !important; } .flex-lg-wrap { flex-wrap: wrap !important; } .flex-lg-nowrap { flex-wrap: nowrap !important; } .flex-lg-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-lg-start { justify-content: flex-start !important; } .justify-content-lg-end { justify-content: flex-end !important; } .justify-content-lg-center { justify-content: center !important; } .justify-content-lg-between { justify-content: space-between !important; } .justify-content-lg-around { justify-content: space-around !important; } .justify-content-lg-evenly { justify-content: space-evenly !important; } .align-items-lg-start { align-items: flex-start !important; } .align-items-lg-end { align-items: flex-end !important; } .align-items-lg-center { align-items: center !important; } .align-items-lg-baseline { align-items: baseline !important; } .align-items-lg-stretch { align-items: stretch !important; } .align-content-lg-start { align-content: flex-start !important; } .align-content-lg-end { align-content: flex-end !important; } .align-content-lg-center { align-content: center !important; } .align-content-lg-between { align-content: space-between !important; } .align-content-lg-around { align-content: space-around !important; } .align-content-lg-stretch { align-content: stretch !important; } .align-self-lg-auto { align-self: auto !important; } .align-self-lg-start { align-self: flex-start !important; } .align-self-lg-end { align-self: flex-end !important; } .align-self-lg-center { align-self: center !important; } .align-self-lg-baseline { align-self: baseline !important; } .align-self-lg-stretch { align-self: stretch !important; } .order-lg-first { order: -1 !important; } .order-lg-0 { order: 0 !important; } .order-lg-1 { order: 1 !important; } .order-lg-2 { order: 2 !important; } .order-lg-3 { order: 3 !important; } .order-lg-4 { order: 4 !important; } .order-lg-5 { order: 5 !important; } .order-lg-last { order: 6 !important; } .m-lg-0 { margin: 0 !important; } .m-lg-1 { margin: 0.25rem !important; } .m-lg-2 { margin: 0.5rem !important; } .m-lg-3 { margin: 1rem !important; } .m-lg-4 { margin: 1.5rem !important; } .m-lg-5 { margin: 3rem !important; } .m-lg-auto { margin: auto !important; } .mx-lg-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-lg-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-lg-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-lg-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-lg-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-lg-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-lg-auto { margin-left: auto !important; margin-right: auto !important; } .my-lg-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-lg-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-lg-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-lg-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-lg-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-lg-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-lg-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-lg-0 { margin-top: 0 !important; } .mt-lg-1 { margin-top: 0.25rem !important; } .mt-lg-2 { margin-top: 0.5rem !important; } .mt-lg-3 { margin-top: 1rem !important; } .mt-lg-4 { margin-top: 1.5rem !important; } .mt-lg-5 { margin-top: 3rem !important; } .mt-lg-auto { margin-top: auto !important; } .me-lg-0 { margin-left: 0 !important; } .me-lg-1 { margin-left: 0.25rem !important; } .me-lg-2 { margin-left: 0.5rem !important; } .me-lg-3 { margin-left: 1rem !important; } .me-lg-4 { margin-left: 1.5rem !important; } .me-lg-5 { margin-left: 3rem !important; } .me-lg-auto { margin-left: auto !important; } .mb-lg-0 { margin-bottom: 0 !important; } .mb-lg-1 { margin-bottom: 0.25rem !important; } .mb-lg-2 { margin-bottom: 0.5rem !important; } .mb-lg-3 { margin-bottom: 1rem !important; } .mb-lg-4 { margin-bottom: 1.5rem !important; } .mb-lg-5 { margin-bottom: 3rem !important; } .mb-lg-auto { margin-bottom: auto !important; } .ms-lg-0 { margin-right: 0 !important; } .ms-lg-1 { margin-right: 0.25rem !important; } .ms-lg-2 { margin-right: 0.5rem !important; } .ms-lg-3 { margin-right: 1rem !important; } .ms-lg-4 { margin-right: 1.5rem !important; } .ms-lg-5 { margin-right: 3rem !important; } .ms-lg-auto { margin-right: auto !important; } .p-lg-0 { padding: 0 !important; } .p-lg-1 { padding: 0.25rem !important; } .p-lg-2 { padding: 0.5rem !important; } .p-lg-3 { padding: 1rem !important; } .p-lg-4 { padding: 1.5rem !important; } .p-lg-5 { padding: 3rem !important; } .px-lg-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-lg-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-lg-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-lg-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-lg-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-lg-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-lg-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-lg-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-lg-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-lg-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-lg-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-lg-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-lg-0 { padding-top: 0 !important; } .pt-lg-1 { padding-top: 0.25rem !important; } .pt-lg-2 { padding-top: 0.5rem !important; } .pt-lg-3 { padding-top: 1rem !important; } .pt-lg-4 { padding-top: 1.5rem !important; } .pt-lg-5 { padding-top: 3rem !important; } .pe-lg-0 { padding-left: 0 !important; } .pe-lg-1 { padding-left: 0.25rem !important; } .pe-lg-2 { padding-left: 0.5rem !important; } .pe-lg-3 { padding-left: 1rem !important; } .pe-lg-4 { padding-left: 1.5rem !important; } .pe-lg-5 { padding-left: 3rem !important; } .pb-lg-0 { padding-bottom: 0 !important; } .pb-lg-1 { padding-bottom: 0.25rem !important; } .pb-lg-2 { padding-bottom: 0.5rem !important; } .pb-lg-3 { padding-bottom: 1rem !important; } .pb-lg-4 { padding-bottom: 1.5rem !important; } .pb-lg-5 { padding-bottom: 3rem !important; } .ps-lg-0 { padding-right: 0 !important; } .ps-lg-1 { padding-right: 0.25rem !important; } .ps-lg-2 { padding-right: 0.5rem !important; } .ps-lg-3 { padding-right: 1rem !important; } .ps-lg-4 { padding-right: 1.5rem !important; } .ps-lg-5 { padding-right: 3rem !important; } .gap-lg-0 { gap: 0 !important; } .gap-lg-1 { gap: 0.25rem !important; } .gap-lg-2 { gap: 0.5rem !important; } .gap-lg-3 { gap: 1rem !important; } .gap-lg-4 { gap: 1.5rem !important; } .gap-lg-5 { gap: 3rem !important; } .text-lg-start { text-align: right !important; } .text-lg-end { text-align: left !important; } .text-lg-center { text-align: center !important; } } @media (min-width: 1200px) { .float-xl-start { float: right !important; } .float-xl-end { float: left !important; } .float-xl-none { float: none !important; } .d-xl-inline { display: inline !important; } .d-xl-inline-block { display: inline-block !important; } .d-xl-block { display: block !important; } .d-xl-grid { display: grid !important; } .d-xl-table { display: table !important; } .d-xl-table-row { display: table-row !important; } .d-xl-table-cell { display: table-cell !important; } .d-xl-flex { display: flex !important; } .d-xl-inline-flex { display: inline-flex !important; } .d-xl-none { display: none !important; } .flex-xl-fill { flex: 1 1 auto !important; } .flex-xl-row { flex-direction: row !important; } .flex-xl-column { flex-direction: column !important; } .flex-xl-row-reverse { flex-direction: row-reverse !important; } .flex-xl-column-reverse { flex-direction: column-reverse !important; } .flex-xl-grow-0 { flex-grow: 0 !important; } .flex-xl-grow-1 { flex-grow: 1 !important; } .flex-xl-shrink-0 { flex-shrink: 0 !important; } .flex-xl-shrink-1 { flex-shrink: 1 !important; } .flex-xl-wrap { flex-wrap: wrap !important; } .flex-xl-nowrap { flex-wrap: nowrap !important; } .flex-xl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xl-start { justify-content: flex-start !important; } .justify-content-xl-end { justify-content: flex-end !important; } .justify-content-xl-center { justify-content: center !important; } .justify-content-xl-between { justify-content: space-between !important; } .justify-content-xl-around { justify-content: space-around !important; } .justify-content-xl-evenly { justify-content: space-evenly !important; } .align-items-xl-start { align-items: flex-start !important; } .align-items-xl-end { align-items: flex-end !important; } .align-items-xl-center { align-items: center !important; } .align-items-xl-baseline { align-items: baseline !important; } .align-items-xl-stretch { align-items: stretch !important; } .align-content-xl-start { align-content: flex-start !important; } .align-content-xl-end { align-content: flex-end !important; } .align-content-xl-center { align-content: center !important; } .align-content-xl-between { align-content: space-between !important; } .align-content-xl-around { align-content: space-around !important; } .align-content-xl-stretch { align-content: stretch !important; } .align-self-xl-auto { align-self: auto !important; } .align-self-xl-start { align-self: flex-start !important; } .align-self-xl-end { align-self: flex-end !important; } .align-self-xl-center { align-self: center !important; } .align-self-xl-baseline { align-self: baseline !important; } .align-self-xl-stretch { align-self: stretch !important; } .order-xl-first { order: -1 !important; } .order-xl-0 { order: 0 !important; } .order-xl-1 { order: 1 !important; } .order-xl-2 { order: 2 !important; } .order-xl-3 { order: 3 !important; } .order-xl-4 { order: 4 !important; } .order-xl-5 { order: 5 !important; } .order-xl-last { order: 6 !important; } .m-xl-0 { margin: 0 !important; } .m-xl-1 { margin: 0.25rem !important; } .m-xl-2 { margin: 0.5rem !important; } .m-xl-3 { margin: 1rem !important; } .m-xl-4 { margin: 1.5rem !important; } .m-xl-5 { margin: 3rem !important; } .m-xl-auto { margin: auto !important; } .mx-xl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xl-0 { margin-top: 0 !important; } .mt-xl-1 { margin-top: 0.25rem !important; } .mt-xl-2 { margin-top: 0.5rem !important; } .mt-xl-3 { margin-top: 1rem !important; } .mt-xl-4 { margin-top: 1.5rem !important; } .mt-xl-5 { margin-top: 3rem !important; } .mt-xl-auto { margin-top: auto !important; } .me-xl-0 { margin-left: 0 !important; } .me-xl-1 { margin-left: 0.25rem !important; } .me-xl-2 { margin-left: 0.5rem !important; } .me-xl-3 { margin-left: 1rem !important; } .me-xl-4 { margin-left: 1.5rem !important; } .me-xl-5 { margin-left: 3rem !important; } .me-xl-auto { margin-left: auto !important; } .mb-xl-0 { margin-bottom: 0 !important; } .mb-xl-1 { margin-bottom: 0.25rem !important; } .mb-xl-2 { margin-bottom: 0.5rem !important; } .mb-xl-3 { margin-bottom: 1rem !important; } .mb-xl-4 { margin-bottom: 1.5rem !important; } .mb-xl-5 { margin-bottom: 3rem !important; } .mb-xl-auto { margin-bottom: auto !important; } .ms-xl-0 { margin-right: 0 !important; } .ms-xl-1 { margin-right: 0.25rem !important; } .ms-xl-2 { margin-right: 0.5rem !important; } .ms-xl-3 { margin-right: 1rem !important; } .ms-xl-4 { margin-right: 1.5rem !important; } .ms-xl-5 { margin-right: 3rem !important; } .ms-xl-auto { margin-right: auto !important; } .p-xl-0 { padding: 0 !important; } .p-xl-1 { padding: 0.25rem !important; } .p-xl-2 { padding: 0.5rem !important; } .p-xl-3 { padding: 1rem !important; } .p-xl-4 { padding: 1.5rem !important; } .p-xl-5 { padding: 3rem !important; } .px-xl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xl-0 { padding-top: 0 !important; } .pt-xl-1 { padding-top: 0.25rem !important; } .pt-xl-2 { padding-top: 0.5rem !important; } .pt-xl-3 { padding-top: 1rem !important; } .pt-xl-4 { padding-top: 1.5rem !important; } .pt-xl-5 { padding-top: 3rem !important; } .pe-xl-0 { padding-left: 0 !important; } .pe-xl-1 { padding-left: 0.25rem !important; } .pe-xl-2 { padding-left: 0.5rem !important; } .pe-xl-3 { padding-left: 1rem !important; } .pe-xl-4 { padding-left: 1.5rem !important; } .pe-xl-5 { padding-left: 3rem !important; } .pb-xl-0 { padding-bottom: 0 !important; } .pb-xl-1 { padding-bottom: 0.25rem !important; } .pb-xl-2 { padding-bottom: 0.5rem !important; } .pb-xl-3 { padding-bottom: 1rem !important; } .pb-xl-4 { padding-bottom: 1.5rem !important; } .pb-xl-5 { padding-bottom: 3rem !important; } .ps-xl-0 { padding-right: 0 !important; } .ps-xl-1 { padding-right: 0.25rem !important; } .ps-xl-2 { padding-right: 0.5rem !important; } .ps-xl-3 { padding-right: 1rem !important; } .ps-xl-4 { padding-right: 1.5rem !important; } .ps-xl-5 { padding-right: 3rem !important; } .gap-xl-0 { gap: 0 !important; } .gap-xl-1 { gap: 0.25rem !important; } .gap-xl-2 { gap: 0.5rem !important; } .gap-xl-3 { gap: 1rem !important; } .gap-xl-4 { gap: 1.5rem !important; } .gap-xl-5 { gap: 3rem !important; } .text-xl-start { text-align: right !important; } .text-xl-end { text-align: left !important; } .text-xl-center { text-align: center !important; } } @media (min-width: 1400px) { .float-xxl-start { float: right !important; } .float-xxl-end { float: left !important; } .float-xxl-none { float: none !important; } .d-xxl-inline { display: inline !important; } .d-xxl-inline-block { display: inline-block !important; } .d-xxl-block { display: block !important; } .d-xxl-grid { display: grid !important; } .d-xxl-table { display: table !important; } .d-xxl-table-row { display: table-row !important; } .d-xxl-table-cell { display: table-cell !important; } .d-xxl-flex { display: flex !important; } .d-xxl-inline-flex { display: inline-flex !important; } .d-xxl-none { display: none !important; } .flex-xxl-fill { flex: 1 1 auto !important; } .flex-xxl-row { flex-direction: row !important; } .flex-xxl-column { flex-direction: column !important; } .flex-xxl-row-reverse { flex-direction: row-reverse !important; } .flex-xxl-column-reverse { flex-direction: column-reverse !important; } .flex-xxl-grow-0 { flex-grow: 0 !important; } .flex-xxl-grow-1 { flex-grow: 1 !important; } .flex-xxl-shrink-0 { flex-shrink: 0 !important; } .flex-xxl-shrink-1 { flex-shrink: 1 !important; } .flex-xxl-wrap { flex-wrap: wrap !important; } .flex-xxl-nowrap { flex-wrap: nowrap !important; } .flex-xxl-wrap-reverse { flex-wrap: wrap-reverse !important; } .justify-content-xxl-start { justify-content: flex-start !important; } .justify-content-xxl-end { justify-content: flex-end !important; } .justify-content-xxl-center { justify-content: center !important; } .justify-content-xxl-between { justify-content: space-between !important; } .justify-content-xxl-around { justify-content: space-around !important; } .justify-content-xxl-evenly { justify-content: space-evenly !important; } .align-items-xxl-start { align-items: flex-start !important; } .align-items-xxl-end { align-items: flex-end !important; } .align-items-xxl-center { align-items: center !important; } .align-items-xxl-baseline { align-items: baseline !important; } .align-items-xxl-stretch { align-items: stretch !important; } .align-content-xxl-start { align-content: flex-start !important; } .align-content-xxl-end { align-content: flex-end !important; } .align-content-xxl-center { align-content: center !important; } .align-content-xxl-between { align-content: space-between !important; } .align-content-xxl-around { align-content: space-around !important; } .align-content-xxl-stretch { align-content: stretch !important; } .align-self-xxl-auto { align-self: auto !important; } .align-self-xxl-start { align-self: flex-start !important; } .align-self-xxl-end { align-self: flex-end !important; } .align-self-xxl-center { align-self: center !important; } .align-self-xxl-baseline { align-self: baseline !important; } .align-self-xxl-stretch { align-self: stretch !important; } .order-xxl-first { order: -1 !important; } .order-xxl-0 { order: 0 !important; } .order-xxl-1 { order: 1 !important; } .order-xxl-2 { order: 2 !important; } .order-xxl-3 { order: 3 !important; } .order-xxl-4 { order: 4 !important; } .order-xxl-5 { order: 5 !important; } .order-xxl-last { order: 6 !important; } .m-xxl-0 { margin: 0 !important; } .m-xxl-1 { margin: 0.25rem !important; } .m-xxl-2 { margin: 0.5rem !important; } .m-xxl-3 { margin: 1rem !important; } .m-xxl-4 { margin: 1.5rem !important; } .m-xxl-5 { margin: 3rem !important; } .m-xxl-auto { margin: auto !important; } .mx-xxl-0 { margin-left: 0 !important; margin-right: 0 !important; } .mx-xxl-1 { margin-left: 0.25rem !important; margin-right: 0.25rem !important; } .mx-xxl-2 { margin-left: 0.5rem !important; margin-right: 0.5rem !important; } .mx-xxl-3 { margin-left: 1rem !important; margin-right: 1rem !important; } .mx-xxl-4 { margin-left: 1.5rem !important; margin-right: 1.5rem !important; } .mx-xxl-5 { margin-left: 3rem !important; margin-right: 3rem !important; } .mx-xxl-auto { margin-left: auto !important; margin-right: auto !important; } .my-xxl-0 { margin-top: 0 !important; margin-bottom: 0 !important; } .my-xxl-1 { margin-top: 0.25rem !important; margin-bottom: 0.25rem !important; } .my-xxl-2 { margin-top: 0.5rem !important; margin-bottom: 0.5rem !important; } .my-xxl-3 { margin-top: 1rem !important; margin-bottom: 1rem !important; } .my-xxl-4 { margin-top: 1.5rem !important; margin-bottom: 1.5rem !important; } .my-xxl-5 { margin-top: 3rem !important; margin-bottom: 3rem !important; } .my-xxl-auto { margin-top: auto !important; margin-bottom: auto !important; } .mt-xxl-0 { margin-top: 0 !important; } .mt-xxl-1 { margin-top: 0.25rem !important; } .mt-xxl-2 { margin-top: 0.5rem !important; } .mt-xxl-3 { margin-top: 1rem !important; } .mt-xxl-4 { margin-top: 1.5rem !important; } .mt-xxl-5 { margin-top: 3rem !important; } .mt-xxl-auto { margin-top: auto !important; } .me-xxl-0 { margin-left: 0 !important; } .me-xxl-1 { margin-left: 0.25rem !important; } .me-xxl-2 { margin-left: 0.5rem !important; } .me-xxl-3 { margin-left: 1rem !important; } .me-xxl-4 { margin-left: 1.5rem !important; } .me-xxl-5 { margin-left: 3rem !important; } .me-xxl-auto { margin-left: auto !important; } .mb-xxl-0 { margin-bottom: 0 !important; } .mb-xxl-1 { margin-bottom: 0.25rem !important; } .mb-xxl-2 { margin-bottom: 0.5rem !important; } .mb-xxl-3 { margin-bottom: 1rem !important; } .mb-xxl-4 { margin-bottom: 1.5rem !important; } .mb-xxl-5 { margin-bottom: 3rem !important; } .mb-xxl-auto { margin-bottom: auto !important; } .ms-xxl-0 { margin-right: 0 !important; } .ms-xxl-1 { margin-right: 0.25rem !important; } .ms-xxl-2 { margin-right: 0.5rem !important; } .ms-xxl-3 { margin-right: 1rem !important; } .ms-xxl-4 { margin-right: 1.5rem !important; } .ms-xxl-5 { margin-right: 3rem !important; } .ms-xxl-auto { margin-right: auto !important; } .p-xxl-0 { padding: 0 !important; } .p-xxl-1 { padding: 0.25rem !important; } .p-xxl-2 { padding: 0.5rem !important; } .p-xxl-3 { padding: 1rem !important; } .p-xxl-4 { padding: 1.5rem !important; } .p-xxl-5 { padding: 3rem !important; } .px-xxl-0 { padding-left: 0 !important; padding-right: 0 !important; } .px-xxl-1 { padding-left: 0.25rem !important; padding-right: 0.25rem !important; } .px-xxl-2 { padding-left: 0.5rem !important; padding-right: 0.5rem !important; } .px-xxl-3 { padding-left: 1rem !important; padding-right: 1rem !important; } .px-xxl-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; } .px-xxl-5 { padding-left: 3rem !important; padding-right: 3rem !important; } .py-xxl-0 { padding-top: 0 !important; padding-bottom: 0 !important; } .py-xxl-1 { padding-top: 0.25rem !important; padding-bottom: 0.25rem !important; } .py-xxl-2 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; } .py-xxl-3 { padding-top: 1rem !important; padding-bottom: 1rem !important; } .py-xxl-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } .py-xxl-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; } .pt-xxl-0 { padding-top: 0 !important; } .pt-xxl-1 { padding-top: 0.25rem !important; } .pt-xxl-2 { padding-top: 0.5rem !important; } .pt-xxl-3 { padding-top: 1rem !important; } .pt-xxl-4 { padding-top: 1.5rem !important; } .pt-xxl-5 { padding-top: 3rem !important; } .pe-xxl-0 { padding-left: 0 !important; } .pe-xxl-1 { padding-left: 0.25rem !important; } .pe-xxl-2 { padding-left: 0.5rem !important; } .pe-xxl-3 { padding-left: 1rem !important; } .pe-xxl-4 { padding-left: 1.5rem !important; } .pe-xxl-5 { padding-left: 3rem !important; } .pb-xxl-0 { padding-bottom: 0 !important; } .pb-xxl-1 { padding-bottom: 0.25rem !important; } .pb-xxl-2 { padding-bottom: 0.5rem !important; } .pb-xxl-3 { padding-bottom: 1rem !important; } .pb-xxl-4 { padding-bottom: 1.5rem !important; } .pb-xxl-5 { padding-bottom: 3rem !important; } .ps-xxl-0 { padding-right: 0 !important; } .ps-xxl-1 { padding-right: 0.25rem !important; } .ps-xxl-2 { padding-right: 0.5rem !important; } .ps-xxl-3 { padding-right: 1rem !important; } .ps-xxl-4 { padding-right: 1.5rem !important; } .ps-xxl-5 { padding-right: 3rem !important; } .gap-xxl-0 { gap: 0 !important; } .gap-xxl-1 { gap: 0.25rem !important; } .gap-xxl-2 { gap: 0.5rem !important; } .gap-xxl-3 { gap: 1rem !important; } .gap-xxl-4 { gap: 1.5rem !important; } .gap-xxl-5 { gap: 3rem !important; } .text-xxl-start { text-align: right !important; } .text-xxl-end { text-align: left !important; } .text-xxl-center { text-align: center !important; } } @media (min-width: 1200px) { .fs-1 { font-size: 2.5rem !important; } .fs-2 { font-size: 2rem !important; } .fs-3 { font-size: 1.75rem !important; } .fs-4 { font-size: 1.5rem !important; } } @media print { .d-print-inline { display: inline !important; } .d-print-inline-block { display: inline-block !important; } .d-print-block { display: block !important; } .d-print-grid { display: grid !important; } .d-print-table { display: table !important; } .d-print-table-row { display: table-row !important; } .d-print-table-cell { display: table-cell !important; } .d-print-flex { display: flex !important; } .d-print-inline-flex { display: inline-flex !important; } .d-print-none { display: none !important; } } /*# sourceMappingURL=bootstrap.rtl.css.map */ ================================================ FILE: cachecloud-web/src/main/resources/assets/vendor/bootstrap/js/bootstrap.bundle.js ================================================ /*! * Bootstrap v5.2.3 (https://getbootstrap.com/) * Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory()); })(this, (function () { 'use strict'; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/index.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const MAX_UID = 1000000; const MILLISECONDS_MULTIPLIER = 1000; const TRANSITION_END = 'transitionend'; // Shout-out Angus Croll (https://goo.gl/pxwQGp) const toType = object => { if (object === null || object === undefined) { return `${object}`; } return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase(); }; /** * Public Util API */ const getUID = prefix => { do { prefix += Math.floor(Math.random() * MAX_UID); } while (document.getElementById(prefix)); return prefix; }; const getSelector = element => { let selector = element.getAttribute('data-bs-target'); if (!selector || selector === '#') { let hrefAttribute = element.getAttribute('href'); // The only valid content that could double as a selector are IDs or classes, // so everything starting with `#` or `.`. If a "real" URL is used as the selector, // `document.querySelector` will rightfully complain it is invalid. // See https://github.com/twbs/bootstrap/issues/32273 if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) { return null; } // Just in case some CMS puts out a full URL with the anchor appended if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) { hrefAttribute = `#${hrefAttribute.split('#')[1]}`; } selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null; } return selector; }; const getSelectorFromElement = element => { const selector = getSelector(element); if (selector) { return document.querySelector(selector) ? selector : null; } return null; }; const getElementFromSelector = element => { const selector = getSelector(element); return selector ? document.querySelector(selector) : null; }; const getTransitionDurationFromElement = element => { if (!element) { return 0; } // Get transition-duration of the element let { transitionDuration, transitionDelay } = window.getComputedStyle(element); const floatTransitionDuration = Number.parseFloat(transitionDuration); const floatTransitionDelay = Number.parseFloat(transitionDelay); // Return 0 if element or transition duration is not found if (!floatTransitionDuration && !floatTransitionDelay) { return 0; } // If multiple durations are defined, take the first transitionDuration = transitionDuration.split(',')[0]; transitionDelay = transitionDelay.split(',')[0]; return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; }; const triggerTransitionEnd = element => { element.dispatchEvent(new Event(TRANSITION_END)); }; const isElement$1 = object => { if (!object || typeof object !== 'object') { return false; } if (typeof object.jquery !== 'undefined') { object = object[0]; } return typeof object.nodeType !== 'undefined'; }; const getElement = object => { // it's a jQuery object or a node element if (isElement$1(object)) { return object.jquery ? object[0] : object; } if (typeof object === 'string' && object.length > 0) { return document.querySelector(object); } return null; }; const isVisible = element => { if (!isElement$1(element) || element.getClientRects().length === 0) { return false; } const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible'; // Handle `details` element as its content may falsie appear visible when it is closed const closedDetails = element.closest('details:not([open])'); if (!closedDetails) { return elementIsVisible; } if (closedDetails !== element) { const summary = element.closest('summary'); if (summary && summary.parentNode !== closedDetails) { return false; } if (summary === null) { return false; } } return elementIsVisible; }; const isDisabled = element => { if (!element || element.nodeType !== Node.ELEMENT_NODE) { return true; } if (element.classList.contains('disabled')) { return true; } if (typeof element.disabled !== 'undefined') { return element.disabled; } return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false'; }; const findShadowRoot = element => { if (!document.documentElement.attachShadow) { return null; } // Can find the shadow root otherwise it'll return the document if (typeof element.getRootNode === 'function') { const root = element.getRootNode(); return root instanceof ShadowRoot ? root : null; } if (element instanceof ShadowRoot) { return element; } // when we don't find a shadow root if (!element.parentNode) { return null; } return findShadowRoot(element.parentNode); }; const noop = () => {}; /** * Trick to restart an element's animation * * @param {HTMLElement} element * @return void * * @see https://www.charistheo.io/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation */ const reflow = element => { element.offsetHeight; // eslint-disable-line no-unused-expressions }; const getjQuery = () => { if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) { return window.jQuery; } return null; }; const DOMContentLoadedCallbacks = []; const onDOMContentLoaded = callback => { if (document.readyState === 'loading') { // add listener on the first call when the document is in loading state if (!DOMContentLoadedCallbacks.length) { document.addEventListener('DOMContentLoaded', () => { for (const callback of DOMContentLoadedCallbacks) { callback(); } }); } DOMContentLoadedCallbacks.push(callback); } else { callback(); } }; const isRTL = () => document.documentElement.dir === 'rtl'; const defineJQueryPlugin = plugin => { onDOMContentLoaded(() => { const $ = getjQuery(); /* istanbul ignore if */ if ($) { const name = plugin.NAME; const JQUERY_NO_CONFLICT = $.fn[name]; $.fn[name] = plugin.jQueryInterface; $.fn[name].Constructor = plugin; $.fn[name].noConflict = () => { $.fn[name] = JQUERY_NO_CONFLICT; return plugin.jQueryInterface; }; } }); }; const execute = callback => { if (typeof callback === 'function') { callback(); } }; const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { if (!waitForTransition) { execute(callback); return; } const durationPadding = 5; const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding; let called = false; const handler = ({ target }) => { if (target !== transitionElement) { return; } called = true; transitionElement.removeEventListener(TRANSITION_END, handler); execute(callback); }; transitionElement.addEventListener(TRANSITION_END, handler); setTimeout(() => { if (!called) { triggerTransitionEnd(transitionElement); } }, emulatedDuration); }; /** * Return the previous/next element of a list. * * @param {array} list The list of elements * @param activeElement The active element * @param shouldGetNext Choose to get next or previous element * @param isCycleAllowed * @return {Element|elem} The proper element */ const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => { const listLength = list.length; let index = list.indexOf(activeElement); // if the element does not exist in the list return an element // depending on the direction and if cycle is allowed if (index === -1) { return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]; } index += shouldGetNext ? 1 : -1; if (isCycleAllowed) { index = (index + listLength) % listLength; } return list[Math.max(0, Math.min(index, listLength - 1))]; }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): dom/event-handler.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const namespaceRegex = /[^.]*(?=\..*)\.|.*/; const stripNameRegex = /\..*/; const stripUidRegex = /::\d+$/; const eventRegistry = {}; // Events storage let uidEvent = 1; const customEvents = { mouseenter: 'mouseover', mouseleave: 'mouseout' }; const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']); /** * Private methods */ function makeEventUid(element, uid) { return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++; } function getElementEvents(element) { const uid = makeEventUid(element); element.uidEvent = uid; eventRegistry[uid] = eventRegistry[uid] || {}; return eventRegistry[uid]; } function bootstrapHandler(element, fn) { return function handler(event) { hydrateObj(event, { delegateTarget: element }); if (handler.oneOff) { EventHandler.off(element, event.type, fn); } return fn.apply(element, [event]); }; } function bootstrapDelegationHandler(element, selector, fn) { return function handler(event) { const domElements = element.querySelectorAll(selector); for (let { target } = event; target && target !== this; target = target.parentNode) { for (const domElement of domElements) { if (domElement !== target) { continue; } hydrateObj(event, { delegateTarget: target }); if (handler.oneOff) { EventHandler.off(element, event.type, selector, fn); } return fn.apply(target, [event]); } } }; } function findHandler(events, callable, delegationSelector = null) { return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector); } function normalizeParameters(originalTypeEvent, handler, delegationFunction) { const isDelegated = typeof handler === 'string'; // todo: tooltip passes `false` instead of selector, so we need to check const callable = isDelegated ? delegationFunction : handler || delegationFunction; let typeEvent = getTypeEvent(originalTypeEvent); if (!nativeEvents.has(typeEvent)) { typeEvent = originalTypeEvent; } return [isDelegated, callable, typeEvent]; } function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) { if (typeof originalTypeEvent !== 'string' || !element) { return; } let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position // this prevents the handler from being dispatched the same way as mouseover or mouseout does if (originalTypeEvent in customEvents) { const wrapFunction = fn => { return function (event) { if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) { return fn.call(this, event); } }; }; callable = wrapFunction(callable); } const events = getElementEvents(element); const handlers = events[typeEvent] || (events[typeEvent] = {}); const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null); if (previousFunction) { previousFunction.oneOff = previousFunction.oneOff && oneOff; return; } const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, '')); const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable); fn.delegationSelector = isDelegated ? handler : null; fn.callable = callable; fn.oneOff = oneOff; fn.uidEvent = uid; handlers[uid] = fn; element.addEventListener(typeEvent, fn, isDelegated); } function removeHandler(element, events, typeEvent, handler, delegationSelector) { const fn = findHandler(events[typeEvent], handler, delegationSelector); if (!fn) { return; } element.removeEventListener(typeEvent, fn, Boolean(delegationSelector)); delete events[typeEvent][fn.uidEvent]; } function removeNamespacedHandlers(element, events, typeEvent, namespace) { const storeElementEvent = events[typeEvent] || {}; for (const handlerKey of Object.keys(storeElementEvent)) { if (handlerKey.includes(namespace)) { const event = storeElementEvent[handlerKey]; removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); } } } function getTypeEvent(event) { // allow to get the native events from namespaced events ('click.bs.button' --> 'click') event = event.replace(stripNameRegex, ''); return customEvents[event] || event; } const EventHandler = { on(element, event, handler, delegationFunction) { addHandler(element, event, handler, delegationFunction, false); }, one(element, event, handler, delegationFunction) { addHandler(element, event, handler, delegationFunction, true); }, off(element, originalTypeEvent, handler, delegationFunction) { if (typeof originalTypeEvent !== 'string' || !element) { return; } const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction); const inNamespace = typeEvent !== originalTypeEvent; const events = getElementEvents(element); const storeElementEvent = events[typeEvent] || {}; const isNamespace = originalTypeEvent.startsWith('.'); if (typeof callable !== 'undefined') { // Simplest case: handler is passed, remove that listener ONLY. if (!Object.keys(storeElementEvent).length) { return; } removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null); return; } if (isNamespace) { for (const elementEvent of Object.keys(events)) { removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1)); } } for (const keyHandlers of Object.keys(storeElementEvent)) { const handlerKey = keyHandlers.replace(stripUidRegex, ''); if (!inNamespace || originalTypeEvent.includes(handlerKey)) { const event = storeElementEvent[keyHandlers]; removeHandler(element, events, typeEvent, event.callable, event.delegationSelector); } } }, trigger(element, event, args) { if (typeof event !== 'string' || !element) { return null; } const $ = getjQuery(); const typeEvent = getTypeEvent(event); const inNamespace = event !== typeEvent; let jQueryEvent = null; let bubbles = true; let nativeDispatch = true; let defaultPrevented = false; if (inNamespace && $) { jQueryEvent = $.Event(event, args); $(element).trigger(jQueryEvent); bubbles = !jQueryEvent.isPropagationStopped(); nativeDispatch = !jQueryEvent.isImmediatePropagationStopped(); defaultPrevented = jQueryEvent.isDefaultPrevented(); } let evt = new Event(event, { bubbles, cancelable: true }); evt = hydrateObj(evt, args); if (defaultPrevented) { evt.preventDefault(); } if (nativeDispatch) { element.dispatchEvent(evt); } if (evt.defaultPrevented && jQueryEvent) { jQueryEvent.preventDefault(); } return evt; } }; function hydrateObj(obj, meta) { for (const [key, value] of Object.entries(meta || {})) { try { obj[key] = value; } catch (_unused) { Object.defineProperty(obj, key, { configurable: true, get() { return value; } }); } } return obj; } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): dom/data.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const elementMap = new Map(); const Data = { set(element, key, instance) { if (!elementMap.has(element)) { elementMap.set(element, new Map()); } const instanceMap = elementMap.get(element); // make it clear we only want one instance per element // can be removed later when multiple key/instances are fine to be used if (!instanceMap.has(key) && instanceMap.size !== 0) { // eslint-disable-next-line no-console console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`); return; } instanceMap.set(key, instance); }, get(element, key) { if (elementMap.has(element)) { return elementMap.get(element).get(key) || null; } return null; }, remove(element, key) { if (!elementMap.has(element)) { return; } const instanceMap = elementMap.get(element); instanceMap.delete(key); // free up element references if there are no instances left for an element if (instanceMap.size === 0) { elementMap.delete(element); } } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): dom/manipulator.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ function normalizeData(value) { if (value === 'true') { return true; } if (value === 'false') { return false; } if (value === Number(value).toString()) { return Number(value); } if (value === '' || value === 'null') { return null; } if (typeof value !== 'string') { return value; } try { return JSON.parse(decodeURIComponent(value)); } catch (_unused) { return value; } } function normalizeDataKey(key) { return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`); } const Manipulator = { setDataAttribute(element, key, value) { element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value); }, removeDataAttribute(element, key) { element.removeAttribute(`data-bs-${normalizeDataKey(key)}`); }, getDataAttributes(element) { if (!element) { return {}; } const attributes = {}; const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig')); for (const key of bsKeys) { let pureKey = key.replace(/^bs/, ''); pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1, pureKey.length); attributes[pureKey] = normalizeData(element.dataset[key]); } return attributes; }, getDataAttribute(element, key) { return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`)); } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/config.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Class definition */ class Config { // Getters static get Default() { return {}; } static get DefaultType() { return {}; } static get NAME() { throw new Error('You have to implement the static method "NAME", for each component!'); } _getConfig(config) { config = this._mergeConfigObj(config); config = this._configAfterMerge(config); this._typeCheckConfig(config); return config; } _configAfterMerge(config) { return config; } _mergeConfigObj(config, element) { const jsonConfig = isElement$1(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse return { ...this.constructor.Default, ...(typeof jsonConfig === 'object' ? jsonConfig : {}), ...(isElement$1(element) ? Manipulator.getDataAttributes(element) : {}), ...(typeof config === 'object' ? config : {}) }; } _typeCheckConfig(config, configTypes = this.constructor.DefaultType) { for (const property of Object.keys(configTypes)) { const expectedTypes = configTypes[property]; const value = config[property]; const valueType = isElement$1(value) ? 'element' : toType(value); if (!new RegExp(expectedTypes).test(valueType)) { throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`); } } } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): base-component.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const VERSION = '5.2.3'; /** * Class definition */ class BaseComponent extends Config { constructor(element, config) { super(); element = getElement(element); if (!element) { return; } this._element = element; this._config = this._getConfig(config); Data.set(this._element, this.constructor.DATA_KEY, this); } // Public dispose() { Data.remove(this._element, this.constructor.DATA_KEY); EventHandler.off(this._element, this.constructor.EVENT_KEY); for (const propertyName of Object.getOwnPropertyNames(this)) { this[propertyName] = null; } } _queueCallback(callback, element, isAnimated = true) { executeAfterTransition(callback, element, isAnimated); } _getConfig(config) { config = this._mergeConfigObj(config, this._element); config = this._configAfterMerge(config); this._typeCheckConfig(config); return config; } // Static static getInstance(element) { return Data.get(getElement(element), this.DATA_KEY); } static getOrCreateInstance(element, config = {}) { return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null); } static get VERSION() { return VERSION; } static get DATA_KEY() { return `bs.${this.NAME}`; } static get EVENT_KEY() { return `.${this.DATA_KEY}`; } static eventName(name) { return `${name}${this.EVENT_KEY}`; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/component-functions.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const enableDismissTrigger = (component, method = 'hide') => { const clickEvent = `click.dismiss${component.EVENT_KEY}`; const name = component.NAME; EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function (event) { if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } if (isDisabled(this)) { return; } const target = getElementFromSelector(this) || this.closest(`.${name}`); const instance = component.getOrCreateInstance(target); // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method instance[method](); }); }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): alert.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$f = 'alert'; const DATA_KEY$a = 'bs.alert'; const EVENT_KEY$b = `.${DATA_KEY$a}`; const EVENT_CLOSE = `close${EVENT_KEY$b}`; const EVENT_CLOSED = `closed${EVENT_KEY$b}`; const CLASS_NAME_FADE$5 = 'fade'; const CLASS_NAME_SHOW$8 = 'show'; /** * Class definition */ class Alert extends BaseComponent { // Getters static get NAME() { return NAME$f; } // Public close() { const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE); if (closeEvent.defaultPrevented) { return; } this._element.classList.remove(CLASS_NAME_SHOW$8); const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5); this._queueCallback(() => this._destroyElement(), this._element, isAnimated); } // Private _destroyElement() { this._element.remove(); EventHandler.trigger(this._element, EVENT_CLOSED); this.dispose(); } // Static static jQueryInterface(config) { return this.each(function () { const data = Alert.getOrCreateInstance(this); if (typeof config !== 'string') { return; } if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { throw new TypeError(`No method named "${config}"`); } data[config](this); }); } } /** * Data API implementation */ enableDismissTrigger(Alert, 'close'); /** * jQuery */ defineJQueryPlugin(Alert); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): button.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$e = 'button'; const DATA_KEY$9 = 'bs.button'; const EVENT_KEY$a = `.${DATA_KEY$9}`; const DATA_API_KEY$6 = '.data-api'; const CLASS_NAME_ACTIVE$3 = 'active'; const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]'; const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`; /** * Class definition */ class Button extends BaseComponent { // Getters static get NAME() { return NAME$e; } // Public toggle() { // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3)); } // Static static jQueryInterface(config) { return this.each(function () { const data = Button.getOrCreateInstance(this); if (config === 'toggle') { data[config](); } }); } } /** * Data API implementation */ EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => { event.preventDefault(); const button = event.target.closest(SELECTOR_DATA_TOGGLE$5); const data = Button.getOrCreateInstance(button); data.toggle(); }); /** * jQuery */ defineJQueryPlugin(Button); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): dom/selector-engine.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const SelectorEngine = { find(selector, element = document.documentElement) { return [].concat(...Element.prototype.querySelectorAll.call(element, selector)); }, findOne(selector, element = document.documentElement) { return Element.prototype.querySelector.call(element, selector); }, children(element, selector) { return [].concat(...element.children).filter(child => child.matches(selector)); }, parents(element, selector) { const parents = []; let ancestor = element.parentNode.closest(selector); while (ancestor) { parents.push(ancestor); ancestor = ancestor.parentNode.closest(selector); } return parents; }, prev(element, selector) { let previous = element.previousElementSibling; while (previous) { if (previous.matches(selector)) { return [previous]; } previous = previous.previousElementSibling; } return []; }, // TODO: this is now unused; remove later along with prev() next(element, selector) { let next = element.nextElementSibling; while (next) { if (next.matches(selector)) { return [next]; } next = next.nextElementSibling; } return []; }, focusableChildren(element) { const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(','); return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el)); } }; /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/swipe.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$d = 'swipe'; const EVENT_KEY$9 = '.bs.swipe'; const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`; const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`; const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`; const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`; const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`; const POINTER_TYPE_TOUCH = 'touch'; const POINTER_TYPE_PEN = 'pen'; const CLASS_NAME_POINTER_EVENT = 'pointer-event'; const SWIPE_THRESHOLD = 40; const Default$c = { endCallback: null, leftCallback: null, rightCallback: null }; const DefaultType$c = { endCallback: '(function|null)', leftCallback: '(function|null)', rightCallback: '(function|null)' }; /** * Class definition */ class Swipe extends Config { constructor(element, config) { super(); this._element = element; if (!element || !Swipe.isSupported()) { return; } this._config = this._getConfig(config); this._deltaX = 0; this._supportPointerEvents = Boolean(window.PointerEvent); this._initEvents(); } // Getters static get Default() { return Default$c; } static get DefaultType() { return DefaultType$c; } static get NAME() { return NAME$d; } // Public dispose() { EventHandler.off(this._element, EVENT_KEY$9); } // Private _start(event) { if (!this._supportPointerEvents) { this._deltaX = event.touches[0].clientX; return; } if (this._eventIsPointerPenTouch(event)) { this._deltaX = event.clientX; } } _end(event) { if (this._eventIsPointerPenTouch(event)) { this._deltaX = event.clientX - this._deltaX; } this._handleSwipe(); execute(this._config.endCallback); } _move(event) { this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX; } _handleSwipe() { const absDeltaX = Math.abs(this._deltaX); if (absDeltaX <= SWIPE_THRESHOLD) { return; } const direction = absDeltaX / this._deltaX; this._deltaX = 0; if (!direction) { return; } execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback); } _initEvents() { if (this._supportPointerEvents) { EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event)); EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event)); this._element.classList.add(CLASS_NAME_POINTER_EVENT); } else { EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event)); EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event)); EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event)); } } _eventIsPointerPenTouch(event) { return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH); } // Static static isSupported() { return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): carousel.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$c = 'carousel'; const DATA_KEY$8 = 'bs.carousel'; const EVENT_KEY$8 = `.${DATA_KEY$8}`; const DATA_API_KEY$5 = '.data-api'; const ARROW_LEFT_KEY$1 = 'ArrowLeft'; const ARROW_RIGHT_KEY$1 = 'ArrowRight'; const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch const ORDER_NEXT = 'next'; const ORDER_PREV = 'prev'; const DIRECTION_LEFT = 'left'; const DIRECTION_RIGHT = 'right'; const EVENT_SLIDE = `slide${EVENT_KEY$8}`; const EVENT_SLID = `slid${EVENT_KEY$8}`; const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`; const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`; const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`; const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`; const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`; const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`; const CLASS_NAME_CAROUSEL = 'carousel'; const CLASS_NAME_ACTIVE$2 = 'active'; const CLASS_NAME_SLIDE = 'slide'; const CLASS_NAME_END = 'carousel-item-end'; const CLASS_NAME_START = 'carousel-item-start'; const CLASS_NAME_NEXT = 'carousel-item-next'; const CLASS_NAME_PREV = 'carousel-item-prev'; const SELECTOR_ACTIVE = '.active'; const SELECTOR_ITEM = '.carousel-item'; const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM; const SELECTOR_ITEM_IMG = '.carousel-item img'; const SELECTOR_INDICATORS = '.carousel-indicators'; const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]'; const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]'; const KEY_TO_DIRECTION = { [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT, [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT }; const Default$b = { interval: 5000, keyboard: true, pause: 'hover', ride: false, touch: true, wrap: true }; const DefaultType$b = { interval: '(number|boolean)', // TODO:v6 remove boolean support keyboard: 'boolean', pause: '(string|boolean)', ride: '(boolean|string)', touch: 'boolean', wrap: 'boolean' }; /** * Class definition */ class Carousel extends BaseComponent { constructor(element, config) { super(element, config); this._interval = null; this._activeElement = null; this._isSliding = false; this.touchTimeout = null; this._swipeHelper = null; this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element); this._addEventListeners(); if (this._config.ride === CLASS_NAME_CAROUSEL) { this.cycle(); } } // Getters static get Default() { return Default$b; } static get DefaultType() { return DefaultType$b; } static get NAME() { return NAME$c; } // Public next() { this._slide(ORDER_NEXT); } nextWhenVisible() { // FIXME TODO use `document.visibilityState` // Don't call next when the page isn't visible // or the carousel or its parent isn't visible if (!document.hidden && isVisible(this._element)) { this.next(); } } prev() { this._slide(ORDER_PREV); } pause() { if (this._isSliding) { triggerTransitionEnd(this._element); } this._clearInterval(); } cycle() { this._clearInterval(); this._updateInterval(); this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval); } _maybeEnableCycle() { if (!this._config.ride) { return; } if (this._isSliding) { EventHandler.one(this._element, EVENT_SLID, () => this.cycle()); return; } this.cycle(); } to(index) { const items = this._getItems(); if (index > items.length - 1 || index < 0) { return; } if (this._isSliding) { EventHandler.one(this._element, EVENT_SLID, () => this.to(index)); return; } const activeIndex = this._getItemIndex(this._getActive()); if (activeIndex === index) { return; } const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV; this._slide(order, items[index]); } dispose() { if (this._swipeHelper) { this._swipeHelper.dispose(); } super.dispose(); } // Private _configAfterMerge(config) { config.defaultInterval = config.interval; return config; } _addEventListeners() { if (this._config.keyboard) { EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event)); } if (this._config.pause === 'hover') { EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause()); EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle()); } if (this._config.touch && Swipe.isSupported()) { this._addTouchEventListeners(); } } _addTouchEventListeners() { for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) { EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault()); } const endCallBack = () => { if (this._config.pause !== 'hover') { return; } // If it's a touch-enabled device, mouseenter/leave are fired as // part of the mouse compatibility events on first tap - the carousel // would stop cycling until user tapped out of it; // here, we listen for touchend, explicitly pause the carousel // (as if it's the second time we tap on it, mouseenter compat event // is NOT fired) and after a timeout (to allow for mouse compatibility // events to fire) we explicitly restart cycling this.pause(); if (this.touchTimeout) { clearTimeout(this.touchTimeout); } this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval); }; const swipeConfig = { leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)), rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)), endCallback: endCallBack }; this._swipeHelper = new Swipe(this._element, swipeConfig); } _keydown(event) { if (/input|textarea/i.test(event.target.tagName)) { return; } const direction = KEY_TO_DIRECTION[event.key]; if (direction) { event.preventDefault(); this._slide(this._directionToOrder(direction)); } } _getItemIndex(element) { return this._getItems().indexOf(element); } _setActiveIndicatorElement(index) { if (!this._indicatorsElement) { return; } const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement); activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2); activeIndicator.removeAttribute('aria-current'); const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement); if (newActiveIndicator) { newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2); newActiveIndicator.setAttribute('aria-current', 'true'); } } _updateInterval() { const element = this._activeElement || this._getActive(); if (!element) { return; } const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10); this._config.interval = elementInterval || this._config.defaultInterval; } _slide(order, element = null) { if (this._isSliding) { return; } const activeElement = this._getActive(); const isNext = order === ORDER_NEXT; const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap); if (nextElement === activeElement) { return; } const nextElementIndex = this._getItemIndex(nextElement); const triggerEvent = eventName => { return EventHandler.trigger(this._element, eventName, { relatedTarget: nextElement, direction: this._orderToDirection(order), from: this._getItemIndex(activeElement), to: nextElementIndex }); }; const slideEvent = triggerEvent(EVENT_SLIDE); if (slideEvent.defaultPrevented) { return; } if (!activeElement || !nextElement) { // Some weirdness is happening, so we bail // todo: change tests that use empty divs to avoid this check return; } const isCycling = Boolean(this._interval); this.pause(); this._isSliding = true; this._setActiveIndicatorElement(nextElementIndex); this._activeElement = nextElement; const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END; const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV; nextElement.classList.add(orderClassName); reflow(nextElement); activeElement.classList.add(directionalClassName); nextElement.classList.add(directionalClassName); const completeCallBack = () => { nextElement.classList.remove(directionalClassName, orderClassName); nextElement.classList.add(CLASS_NAME_ACTIVE$2); activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName); this._isSliding = false; triggerEvent(EVENT_SLID); }; this._queueCallback(completeCallBack, activeElement, this._isAnimated()); if (isCycling) { this.cycle(); } } _isAnimated() { return this._element.classList.contains(CLASS_NAME_SLIDE); } _getActive() { return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element); } _getItems() { return SelectorEngine.find(SELECTOR_ITEM, this._element); } _clearInterval() { if (this._interval) { clearInterval(this._interval); this._interval = null; } } _directionToOrder(direction) { if (isRTL()) { return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT; } return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV; } _orderToDirection(order) { if (isRTL()) { return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT; } return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT; } // Static static jQueryInterface(config) { return this.each(function () { const data = Carousel.getOrCreateInstance(this, config); if (typeof config === 'number') { data.to(config); return; } if (typeof config === 'string') { if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * Data API implementation */ EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function (event) { const target = getElementFromSelector(this); if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) { return; } event.preventDefault(); const carousel = Carousel.getOrCreateInstance(target); const slideIndex = this.getAttribute('data-bs-slide-to'); if (slideIndex) { carousel.to(slideIndex); carousel._maybeEnableCycle(); return; } if (Manipulator.getDataAttribute(this, 'slide') === 'next') { carousel.next(); carousel._maybeEnableCycle(); return; } carousel.prev(); carousel._maybeEnableCycle(); }); EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => { const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE); for (const carousel of carousels) { Carousel.getOrCreateInstance(carousel); } }); /** * jQuery */ defineJQueryPlugin(Carousel); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): collapse.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$b = 'collapse'; const DATA_KEY$7 = 'bs.collapse'; const EVENT_KEY$7 = `.${DATA_KEY$7}`; const DATA_API_KEY$4 = '.data-api'; const EVENT_SHOW$6 = `show${EVENT_KEY$7}`; const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`; const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`; const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`; const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`; const CLASS_NAME_SHOW$7 = 'show'; const CLASS_NAME_COLLAPSE = 'collapse'; const CLASS_NAME_COLLAPSING = 'collapsing'; const CLASS_NAME_COLLAPSED = 'collapsed'; const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`; const CLASS_NAME_HORIZONTAL = 'collapse-horizontal'; const WIDTH = 'width'; const HEIGHT = 'height'; const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing'; const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]'; const Default$a = { parent: null, toggle: true }; const DefaultType$a = { parent: '(null|element)', toggle: 'boolean' }; /** * Class definition */ class Collapse extends BaseComponent { constructor(element, config) { super(element, config); this._isTransitioning = false; this._triggerArray = []; const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4); for (const elem of toggleList) { const selector = getSelectorFromElement(elem); const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element); if (selector !== null && filterElement.length) { this._triggerArray.push(elem); } } this._initializeChildren(); if (!this._config.parent) { this._addAriaAndCollapsedClass(this._triggerArray, this._isShown()); } if (this._config.toggle) { this.toggle(); } } // Getters static get Default() { return Default$a; } static get DefaultType() { return DefaultType$a; } static get NAME() { return NAME$b; } // Public toggle() { if (this._isShown()) { this.hide(); } else { this.show(); } } show() { if (this._isTransitioning || this._isShown()) { return; } let activeChildren = []; // find active children if (this._config.parent) { activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, { toggle: false })); } if (activeChildren.length && activeChildren[0]._isTransitioning) { return; } const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6); if (startEvent.defaultPrevented) { return; } for (const activeInstance of activeChildren) { activeInstance.hide(); } const dimension = this._getDimension(); this._element.classList.remove(CLASS_NAME_COLLAPSE); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.style[dimension] = 0; this._addAriaAndCollapsedClass(this._triggerArray, true); this._isTransitioning = true; const complete = () => { this._isTransitioning = false; this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); this._element.style[dimension] = ''; EventHandler.trigger(this._element, EVENT_SHOWN$6); }; const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); const scrollSize = `scroll${capitalizedDimension}`; this._queueCallback(complete, this._element, true); this._element.style[dimension] = `${this._element[scrollSize]}px`; } hide() { if (this._isTransitioning || !this._isShown()) { return; } const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6); if (startEvent.defaultPrevented) { return; } const dimension = this._getDimension(); this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`; reflow(this._element); this._element.classList.add(CLASS_NAME_COLLAPSING); this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7); for (const trigger of this._triggerArray) { const element = getElementFromSelector(trigger); if (element && !this._isShown(element)) { this._addAriaAndCollapsedClass([trigger], false); } } this._isTransitioning = true; const complete = () => { this._isTransitioning = false; this._element.classList.remove(CLASS_NAME_COLLAPSING); this._element.classList.add(CLASS_NAME_COLLAPSE); EventHandler.trigger(this._element, EVENT_HIDDEN$6); }; this._element.style[dimension] = ''; this._queueCallback(complete, this._element, true); } _isShown(element = this._element) { return element.classList.contains(CLASS_NAME_SHOW$7); } // Private _configAfterMerge(config) { config.toggle = Boolean(config.toggle); // Coerce string values config.parent = getElement(config.parent); return config; } _getDimension() { return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT; } _initializeChildren() { if (!this._config.parent) { return; } const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4); for (const element of children) { const selected = getElementFromSelector(element); if (selected) { this._addAriaAndCollapsedClass([element], this._isShown(selected)); } } } _getFirstLevelChildren(selector) { const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent); // remove children if greater depth return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element)); } _addAriaAndCollapsedClass(triggerArray, isOpen) { if (!triggerArray.length) { return; } for (const element of triggerArray) { element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen); element.setAttribute('aria-expanded', isOpen); } } // Static static jQueryInterface(config) { const _config = {}; if (typeof config === 'string' && /show|hide/.test(config)) { _config.toggle = false; } return this.each(function () { const data = Collapse.getOrCreateInstance(this, _config); if (typeof config === 'string') { if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); } }); } } /** * Data API implementation */ EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') { event.preventDefault(); } const selector = getSelectorFromElement(this); const selectorElements = SelectorEngine.find(selector); for (const element of selectorElements) { Collapse.getOrCreateInstance(element, { toggle: false }).toggle(); } }); /** * jQuery */ defineJQueryPlugin(Collapse); var top = 'top'; var bottom = 'bottom'; var right = 'right'; var left = 'left'; var auto = 'auto'; var basePlacements = [top, bottom, right, left]; var start = 'start'; var end = 'end'; var clippingParents = 'clippingParents'; var viewport = 'viewport'; var popper = 'popper'; var reference = 'reference'; var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) { return acc.concat([placement + "-" + start, placement + "-" + end]); }, []); var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) { return acc.concat([placement, placement + "-" + start, placement + "-" + end]); }, []); // modifiers that need to read the DOM var beforeRead = 'beforeRead'; var read = 'read'; var afterRead = 'afterRead'; // pure-logic modifiers var beforeMain = 'beforeMain'; var main = 'main'; var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state) var beforeWrite = 'beforeWrite'; var write = 'write'; var afterWrite = 'afterWrite'; var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite]; function getNodeName(element) { return element ? (element.nodeName || '').toLowerCase() : null; } function getWindow(node) { if (node == null) { return window; } if (node.toString() !== '[object Window]') { var ownerDocument = node.ownerDocument; return ownerDocument ? ownerDocument.defaultView || window : window; } return node; } function isElement(node) { var OwnElement = getWindow(node).Element; return node instanceof OwnElement || node instanceof Element; } function isHTMLElement(node) { var OwnElement = getWindow(node).HTMLElement; return node instanceof OwnElement || node instanceof HTMLElement; } function isShadowRoot(node) { // IE 11 has no ShadowRoot if (typeof ShadowRoot === 'undefined') { return false; } var OwnElement = getWindow(node).ShadowRoot; return node instanceof OwnElement || node instanceof ShadowRoot; } // and applies them to the HTMLElements such as popper and arrow function applyStyles(_ref) { var state = _ref.state; Object.keys(state.elements).forEach(function (name) { var style = state.styles[name] || {}; var attributes = state.attributes[name] || {}; var element = state.elements[name]; // arrow is optional + virtual elements if (!isHTMLElement(element) || !getNodeName(element)) { return; } // Flow doesn't support to extend this property, but it's the most // effective way to apply styles to an HTMLElement // $FlowFixMe[cannot-write] Object.assign(element.style, style); Object.keys(attributes).forEach(function (name) { var value = attributes[name]; if (value === false) { element.removeAttribute(name); } else { element.setAttribute(name, value === true ? '' : value); } }); }); } function effect$2(_ref2) { var state = _ref2.state; var initialStyles = { popper: { position: state.options.strategy, left: '0', top: '0', margin: '0' }, arrow: { position: 'absolute' }, reference: {} }; Object.assign(state.elements.popper.style, initialStyles.popper); state.styles = initialStyles; if (state.elements.arrow) { Object.assign(state.elements.arrow.style, initialStyles.arrow); } return function () { Object.keys(state.elements).forEach(function (name) { var element = state.elements[name]; var attributes = state.attributes[name] || {}; var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them var style = styleProperties.reduce(function (style, property) { style[property] = ''; return style; }, {}); // arrow is optional + virtual elements if (!isHTMLElement(element) || !getNodeName(element)) { return; } Object.assign(element.style, style); Object.keys(attributes).forEach(function (attribute) { element.removeAttribute(attribute); }); }); }; } // eslint-disable-next-line import/no-unused-modules const applyStyles$1 = { name: 'applyStyles', enabled: true, phase: 'write', fn: applyStyles, effect: effect$2, requires: ['computeStyles'] }; function getBasePlacement(placement) { return placement.split('-')[0]; } var max = Math.max; var min = Math.min; var round = Math.round; function getUAString() { var uaData = navigator.userAgentData; if (uaData != null && uaData.brands) { return uaData.brands.map(function (item) { return item.brand + "/" + item.version; }).join(' '); } return navigator.userAgent; } function isLayoutViewport() { return !/^((?!chrome|android).)*safari/i.test(getUAString()); } function getBoundingClientRect(element, includeScale, isFixedStrategy) { if (includeScale === void 0) { includeScale = false; } if (isFixedStrategy === void 0) { isFixedStrategy = false; } var clientRect = element.getBoundingClientRect(); var scaleX = 1; var scaleY = 1; if (includeScale && isHTMLElement(element)) { scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1; scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1; } var _ref = isElement(element) ? getWindow(element) : window, visualViewport = _ref.visualViewport; var addVisualOffsets = !isLayoutViewport() && isFixedStrategy; var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX; var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY; var width = clientRect.width / scaleX; var height = clientRect.height / scaleY; return { width: width, height: height, top: y, right: x + width, bottom: y + height, left: x, x: x, y: y }; } // means it doesn't take into account transforms. function getLayoutRect(element) { var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed. // Fixes https://github.com/popperjs/popper-core/issues/1223 var width = element.offsetWidth; var height = element.offsetHeight; if (Math.abs(clientRect.width - width) <= 1) { width = clientRect.width; } if (Math.abs(clientRect.height - height) <= 1) { height = clientRect.height; } return { x: element.offsetLeft, y: element.offsetTop, width: width, height: height }; } function contains(parent, child) { var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method if (parent.contains(child)) { return true; } // then fallback to custom implementation with Shadow DOM support else if (rootNode && isShadowRoot(rootNode)) { var next = child; do { if (next && parent.isSameNode(next)) { return true; } // $FlowFixMe[prop-missing]: need a better way to handle this... next = next.parentNode || next.host; } while (next); } // Give up, the result is false return false; } function getComputedStyle$1(element) { return getWindow(element).getComputedStyle(element); } function isTableElement(element) { return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0; } function getDocumentElement(element) { // $FlowFixMe[incompatible-return]: assume body is always available return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing] element.document) || window.document).documentElement; } function getParentNode(element) { if (getNodeName(element) === 'html') { return element; } return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle // $FlowFixMe[incompatible-return] // $FlowFixMe[prop-missing] element.assignedSlot || // step into the shadow DOM of the parent of a slotted node element.parentNode || ( // DOM Element detected isShadowRoot(element) ? element.host : null) || // ShadowRoot detected // $FlowFixMe[incompatible-call]: HTMLElement is a Node getDocumentElement(element) // fallback ); } function getTrueOffsetParent(element) { if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837 getComputedStyle$1(element).position === 'fixed') { return null; } return element.offsetParent; } // `.offsetParent` reports `null` for fixed elements, while absolute elements // return the containing block function getContainingBlock(element) { var isFirefox = /firefox/i.test(getUAString()); var isIE = /Trident/i.test(getUAString()); if (isIE && isHTMLElement(element)) { // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport var elementCss = getComputedStyle$1(element); if (elementCss.position === 'fixed') { return null; } } var currentNode = getParentNode(element); if (isShadowRoot(currentNode)) { currentNode = currentNode.host; } while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) { var css = getComputedStyle$1(currentNode); // This is non-exhaustive but covers the most common CSS properties that // create a containing block. // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') { return currentNode; } else { currentNode = currentNode.parentNode; } } return null; } // Gets the closest ancestor positioned element. Handles some edge cases, // such as table ancestors and cross browser bugs. function getOffsetParent(element) { var window = getWindow(element); var offsetParent = getTrueOffsetParent(element); while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') { offsetParent = getTrueOffsetParent(offsetParent); } if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static')) { return window; } return offsetParent || getContainingBlock(element) || window; } function getMainAxisFromPlacement(placement) { return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y'; } function within(min$1, value, max$1) { return max(min$1, min(value, max$1)); } function withinMaxClamp(min, value, max) { var v = within(min, value, max); return v > max ? max : v; } function getFreshSideObject() { return { top: 0, right: 0, bottom: 0, left: 0 }; } function mergePaddingObject(paddingObject) { return Object.assign({}, getFreshSideObject(), paddingObject); } function expandToHashMap(value, keys) { return keys.reduce(function (hashMap, key) { hashMap[key] = value; return hashMap; }, {}); } var toPaddingObject = function toPaddingObject(padding, state) { padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, { placement: state.placement })) : padding; return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); }; function arrow(_ref) { var _state$modifiersData$; var state = _ref.state, name = _ref.name, options = _ref.options; var arrowElement = state.elements.arrow; var popperOffsets = state.modifiersData.popperOffsets; var basePlacement = getBasePlacement(state.placement); var axis = getMainAxisFromPlacement(basePlacement); var isVertical = [left, right].indexOf(basePlacement) >= 0; var len = isVertical ? 'height' : 'width'; if (!arrowElement || !popperOffsets) { return; } var paddingObject = toPaddingObject(options.padding, state); var arrowRect = getLayoutRect(arrowElement); var minProp = axis === 'y' ? top : left; var maxProp = axis === 'y' ? bottom : right; var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len]; var startDiff = popperOffsets[axis] - state.rects.reference[axis]; var arrowOffsetParent = getOffsetParent(arrowElement); var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0; var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is // outside of the popper bounds var min = paddingObject[minProp]; var max = clientSize - arrowRect[len] - paddingObject[maxProp]; var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference; var offset = within(min, center, max); // Prevents breaking syntax highlighting... var axisProp = axis; state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$); } function effect$1(_ref2) { var state = _ref2.state, options = _ref2.options; var _options$element = options.element, arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element; if (arrowElement == null) { return; } // CSS selector if (typeof arrowElement === 'string') { arrowElement = state.elements.popper.querySelector(arrowElement); if (!arrowElement) { return; } } if (!contains(state.elements.popper, arrowElement)) { return; } state.elements.arrow = arrowElement; } // eslint-disable-next-line import/no-unused-modules const arrow$1 = { name: 'arrow', enabled: true, phase: 'main', fn: arrow, effect: effect$1, requires: ['popperOffsets'], requiresIfExists: ['preventOverflow'] }; function getVariation(placement) { return placement.split('-')[1]; } var unsetSides = { top: 'auto', right: 'auto', bottom: 'auto', left: 'auto' }; // Round the offsets to the nearest suitable subpixel based on the DPR. // Zooming can change the DPR, but it seems to report a value that will // cleanly divide the values into the appropriate subpixels. function roundOffsetsByDPR(_ref) { var x = _ref.x, y = _ref.y; var win = window; var dpr = win.devicePixelRatio || 1; return { x: round(x * dpr) / dpr || 0, y: round(y * dpr) / dpr || 0 }; } function mapToStyles(_ref2) { var _Object$assign2; var popper = _ref2.popper, popperRect = _ref2.popperRect, placement = _ref2.placement, variation = _ref2.variation, offsets = _ref2.offsets, position = _ref2.position, gpuAcceleration = _ref2.gpuAcceleration, adaptive = _ref2.adaptive, roundOffsets = _ref2.roundOffsets, isFixed = _ref2.isFixed; var _offsets$x = offsets.x, x = _offsets$x === void 0 ? 0 : _offsets$x, _offsets$y = offsets.y, y = _offsets$y === void 0 ? 0 : _offsets$y; var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({ x: x, y: y }) : { x: x, y: y }; x = _ref3.x; y = _ref3.y; var hasX = offsets.hasOwnProperty('x'); var hasY = offsets.hasOwnProperty('y'); var sideX = left; var sideY = top; var win = window; if (adaptive) { var offsetParent = getOffsetParent(popper); var heightProp = 'clientHeight'; var widthProp = 'clientWidth'; if (offsetParent === getWindow(popper)) { offsetParent = getDocumentElement(popper); if (getComputedStyle$1(offsetParent).position !== 'static' && position === 'absolute') { heightProp = 'scrollHeight'; widthProp = 'scrollWidth'; } } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it offsetParent = offsetParent; if (placement === top || (placement === left || placement === right) && variation === end) { sideY = bottom; var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing] offsetParent[heightProp]; y -= offsetY - popperRect.height; y *= gpuAcceleration ? 1 : -1; } if (placement === left || (placement === top || placement === bottom) && variation === end) { sideX = right; var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing] offsetParent[widthProp]; x -= offsetX - popperRect.width; x *= gpuAcceleration ? 1 : -1; } } var commonStyles = Object.assign({ position: position }, adaptive && unsetSides); var _ref4 = roundOffsets === true ? roundOffsetsByDPR({ x: x, y: y }) : { x: x, y: y }; x = _ref4.x; y = _ref4.y; if (gpuAcceleration) { var _Object$assign; return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); } return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); } function computeStyles(_ref5) { var state = _ref5.state, options = _ref5.options; var _options$gpuAccelerat = options.gpuAcceleration, gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, _options$adaptive = options.adaptive, adaptive = _options$adaptive === void 0 ? true : _options$adaptive, _options$roundOffsets = options.roundOffsets, roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets; var commonStyles = { placement: getBasePlacement(state.placement), variation: getVariation(state.placement), popper: state.elements.popper, popperRect: state.rects.popper, gpuAcceleration: gpuAcceleration, isFixed: state.options.strategy === 'fixed' }; if (state.modifiersData.popperOffsets != null) { state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, { offsets: state.modifiersData.popperOffsets, position: state.options.strategy, adaptive: adaptive, roundOffsets: roundOffsets }))); } if (state.modifiersData.arrow != null) { state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, { offsets: state.modifiersData.arrow, position: 'absolute', adaptive: false, roundOffsets: roundOffsets }))); } state.attributes.popper = Object.assign({}, state.attributes.popper, { 'data-popper-placement': state.placement }); } // eslint-disable-next-line import/no-unused-modules const computeStyles$1 = { name: 'computeStyles', enabled: true, phase: 'beforeWrite', fn: computeStyles, data: {} }; var passive = { passive: true }; function effect(_ref) { var state = _ref.state, instance = _ref.instance, options = _ref.options; var _options$scroll = options.scroll, scroll = _options$scroll === void 0 ? true : _options$scroll, _options$resize = options.resize, resize = _options$resize === void 0 ? true : _options$resize; var window = getWindow(state.elements.popper); var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper); if (scroll) { scrollParents.forEach(function (scrollParent) { scrollParent.addEventListener('scroll', instance.update, passive); }); } if (resize) { window.addEventListener('resize', instance.update, passive); } return function () { if (scroll) { scrollParents.forEach(function (scrollParent) { scrollParent.removeEventListener('scroll', instance.update, passive); }); } if (resize) { window.removeEventListener('resize', instance.update, passive); } }; } // eslint-disable-next-line import/no-unused-modules const eventListeners = { name: 'eventListeners', enabled: true, phase: 'write', fn: function fn() {}, effect: effect, data: {} }; var hash$1 = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; function getOppositePlacement(placement) { return placement.replace(/left|right|bottom|top/g, function (matched) { return hash$1[matched]; }); } var hash = { start: 'end', end: 'start' }; function getOppositeVariationPlacement(placement) { return placement.replace(/start|end/g, function (matched) { return hash[matched]; }); } function getWindowScroll(node) { var win = getWindow(node); var scrollLeft = win.pageXOffset; var scrollTop = win.pageYOffset; return { scrollLeft: scrollLeft, scrollTop: scrollTop }; } function getWindowScrollBarX(element) { // If has a CSS width greater than the viewport, then this will be // incorrect for RTL. // Popper 1 is broken in this case and never had a bug report so let's assume // it's not an issue. I don't think anyone ever specifies width on // anyway. // Browsers where the left scrollbar doesn't cause an issue report `0` for // this (e.g. Edge 2019, IE11, Safari) return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft; } function getViewportRect(element, strategy) { var win = getWindow(element); var html = getDocumentElement(element); var visualViewport = win.visualViewport; var width = html.clientWidth; var height = html.clientHeight; var x = 0; var y = 0; if (visualViewport) { width = visualViewport.width; height = visualViewport.height; var layoutViewport = isLayoutViewport(); if (layoutViewport || !layoutViewport && strategy === 'fixed') { x = visualViewport.offsetLeft; y = visualViewport.offsetTop; } } return { width: width, height: height, x: x + getWindowScrollBarX(element), y: y }; } // of the `` and `` rect bounds if horizontally scrollable function getDocumentRect(element) { var _element$ownerDocumen; var html = getDocumentElement(element); var winScroll = getWindowScroll(element); var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body; var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0); var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0); var x = -winScroll.scrollLeft + getWindowScrollBarX(element); var y = -winScroll.scrollTop; if (getComputedStyle$1(body || html).direction === 'rtl') { x += max(html.clientWidth, body ? body.clientWidth : 0) - width; } return { width: width, height: height, x: x, y: y }; } function isScrollParent(element) { // Firefox wants us to check `-x` and `-y` variations as well var _getComputedStyle = getComputedStyle$1(element), overflow = _getComputedStyle.overflow, overflowX = _getComputedStyle.overflowX, overflowY = _getComputedStyle.overflowY; return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX); } function getScrollParent(node) { if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) { // $FlowFixMe[incompatible-return]: assume body is always available return node.ownerDocument.body; } if (isHTMLElement(node) && isScrollParent(node)) { return node; } return getScrollParent(getParentNode(node)); } /* given a DOM element, return the list of all scroll parents, up the list of ancesors until we get to the top window object. This list is what we attach scroll listeners to, because if any of these parent elements scroll, we'll need to re-calculate the reference element's position. */ function listScrollParents(element, list) { var _element$ownerDocumen; if (list === void 0) { list = []; } var scrollParent = getScrollParent(element); var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body); var win = getWindow(scrollParent); var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent; var updatedList = list.concat(target); return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here updatedList.concat(listScrollParents(getParentNode(target))); } function rectToClientRect(rect) { return Object.assign({}, rect, { left: rect.x, top: rect.y, right: rect.x + rect.width, bottom: rect.y + rect.height }); } function getInnerBoundingClientRect(element, strategy) { var rect = getBoundingClientRect(element, false, strategy === 'fixed'); rect.top = rect.top + element.clientTop; rect.left = rect.left + element.clientLeft; rect.bottom = rect.top + element.clientHeight; rect.right = rect.left + element.clientWidth; rect.width = element.clientWidth; rect.height = element.clientHeight; rect.x = rect.left; rect.y = rect.top; return rect; } function getClientRectFromMixedType(element, clippingParent, strategy) { return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element))); } // A "clipping parent" is an overflowable container with the characteristic of // clipping (or hiding) overflowing elements with a position different from // `initial` function getClippingParents(element) { var clippingParents = listScrollParents(getParentNode(element)); var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle$1(element).position) >= 0; var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element; if (!isElement(clipperElement)) { return []; } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414 return clippingParents.filter(function (clippingParent) { return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body'; }); } // Gets the maximum area that the element is visible in due to any number of // clipping parents function getClippingRect(element, boundary, rootBoundary, strategy) { var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary); var clippingParents = [].concat(mainClippingParents, [rootBoundary]); var firstClippingParent = clippingParents[0]; var clippingRect = clippingParents.reduce(function (accRect, clippingParent) { var rect = getClientRectFromMixedType(element, clippingParent, strategy); accRect.top = max(rect.top, accRect.top); accRect.right = min(rect.right, accRect.right); accRect.bottom = min(rect.bottom, accRect.bottom); accRect.left = max(rect.left, accRect.left); return accRect; }, getClientRectFromMixedType(element, firstClippingParent, strategy)); clippingRect.width = clippingRect.right - clippingRect.left; clippingRect.height = clippingRect.bottom - clippingRect.top; clippingRect.x = clippingRect.left; clippingRect.y = clippingRect.top; return clippingRect; } function computeOffsets(_ref) { var reference = _ref.reference, element = _ref.element, placement = _ref.placement; var basePlacement = placement ? getBasePlacement(placement) : null; var variation = placement ? getVariation(placement) : null; var commonX = reference.x + reference.width / 2 - element.width / 2; var commonY = reference.y + reference.height / 2 - element.height / 2; var offsets; switch (basePlacement) { case top: offsets = { x: commonX, y: reference.y - element.height }; break; case bottom: offsets = { x: commonX, y: reference.y + reference.height }; break; case right: offsets = { x: reference.x + reference.width, y: commonY }; break; case left: offsets = { x: reference.x - element.width, y: commonY }; break; default: offsets = { x: reference.x, y: reference.y }; } var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null; if (mainAxis != null) { var len = mainAxis === 'y' ? 'height' : 'width'; switch (variation) { case start: offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2); break; case end: offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2); break; } } return offsets; } function detectOverflow(state, options) { if (options === void 0) { options = {}; } var _options = options, _options$placement = _options.placement, placement = _options$placement === void 0 ? state.placement : _options$placement, _options$strategy = _options.strategy, strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, _options$boundary = _options.boundary, boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, _options$rootBoundary = _options.rootBoundary, rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, _options$elementConte = _options.elementContext, elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, _options$altBoundary = _options.altBoundary, altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, _options$padding = _options.padding, padding = _options$padding === void 0 ? 0 : _options$padding; var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); var altContext = elementContext === popper ? reference : popper; var popperRect = state.rects.popper; var element = state.elements[altBoundary ? altContext : elementContext]; var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy); var referenceClientRect = getBoundingClientRect(state.elements.reference); var popperOffsets = computeOffsets({ reference: referenceClientRect, element: popperRect, strategy: 'absolute', placement: placement }); var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets)); var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect // 0 or negative = within the clipping rect var overflowOffsets = { top: clippingClientRect.top - elementClientRect.top + paddingObject.top, bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom, left: clippingClientRect.left - elementClientRect.left + paddingObject.left, right: elementClientRect.right - clippingClientRect.right + paddingObject.right }; var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element if (elementContext === popper && offsetData) { var offset = offsetData[placement]; Object.keys(overflowOffsets).forEach(function (key) { var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1; var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x'; overflowOffsets[key] += offset[axis] * multiply; }); } return overflowOffsets; } function computeAutoPlacement(state, options) { if (options === void 0) { options = {}; } var _options = options, placement = _options.placement, boundary = _options.boundary, rootBoundary = _options.rootBoundary, padding = _options.padding, flipVariations = _options.flipVariations, _options$allowedAutoP = _options.allowedAutoPlacements, allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP; var variation = getVariation(placement); var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) { return getVariation(placement) === variation; }) : basePlacements; var allowedPlacements = placements$1.filter(function (placement) { return allowedAutoPlacements.indexOf(placement) >= 0; }); if (allowedPlacements.length === 0) { allowedPlacements = placements$1; } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions... var overflows = allowedPlacements.reduce(function (acc, placement) { acc[placement] = detectOverflow(state, { placement: placement, boundary: boundary, rootBoundary: rootBoundary, padding: padding })[getBasePlacement(placement)]; return acc; }, {}); return Object.keys(overflows).sort(function (a, b) { return overflows[a] - overflows[b]; }); } function getExpandedFallbackPlacements(placement) { if (getBasePlacement(placement) === auto) { return []; } var oppositePlacement = getOppositePlacement(placement); return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)]; } function flip(_ref) { var state = _ref.state, options = _ref.options, name = _ref.name; if (state.modifiersData[name]._skip) { return; } var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, specifiedFallbackPlacements = options.fallbackPlacements, padding = options.padding, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, _options$flipVariatio = options.flipVariations, flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, allowedAutoPlacements = options.allowedAutoPlacements; var preferredPlacement = state.options.placement; var basePlacement = getBasePlacement(preferredPlacement); var isBasePlacement = basePlacement === preferredPlacement; var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement)); var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) { return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, { placement: placement, boundary: boundary, rootBoundary: rootBoundary, padding: padding, flipVariations: flipVariations, allowedAutoPlacements: allowedAutoPlacements }) : placement); }, []); var referenceRect = state.rects.reference; var popperRect = state.rects.popper; var checksMap = new Map(); var makeFallbackChecks = true; var firstFittingPlacement = placements[0]; for (var i = 0; i < placements.length; i++) { var placement = placements[i]; var _basePlacement = getBasePlacement(placement); var isStartVariation = getVariation(placement) === start; var isVertical = [top, bottom].indexOf(_basePlacement) >= 0; var len = isVertical ? 'width' : 'height'; var overflow = detectOverflow(state, { placement: placement, boundary: boundary, rootBoundary: rootBoundary, altBoundary: altBoundary, padding: padding }); var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top; if (referenceRect[len] > popperRect[len]) { mainVariationSide = getOppositePlacement(mainVariationSide); } var altVariationSide = getOppositePlacement(mainVariationSide); var checks = []; if (checkMainAxis) { checks.push(overflow[_basePlacement] <= 0); } if (checkAltAxis) { checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0); } if (checks.every(function (check) { return check; })) { firstFittingPlacement = placement; makeFallbackChecks = false; break; } checksMap.set(placement, checks); } if (makeFallbackChecks) { // `2` may be desired in some cases – research later var numberOfChecks = flipVariations ? 3 : 1; var _loop = function _loop(_i) { var fittingPlacement = placements.find(function (placement) { var checks = checksMap.get(placement); if (checks) { return checks.slice(0, _i).every(function (check) { return check; }); } }); if (fittingPlacement) { firstFittingPlacement = fittingPlacement; return "break"; } }; for (var _i = numberOfChecks; _i > 0; _i--) { var _ret = _loop(_i); if (_ret === "break") break; } } if (state.placement !== firstFittingPlacement) { state.modifiersData[name]._skip = true; state.placement = firstFittingPlacement; state.reset = true; } } // eslint-disable-next-line import/no-unused-modules const flip$1 = { name: 'flip', enabled: true, phase: 'main', fn: flip, requiresIfExists: ['offset'], data: { _skip: false } }; function getSideOffsets(overflow, rect, preventedOffsets) { if (preventedOffsets === void 0) { preventedOffsets = { x: 0, y: 0 }; } return { top: overflow.top - rect.height - preventedOffsets.y, right: overflow.right - rect.width + preventedOffsets.x, bottom: overflow.bottom - rect.height + preventedOffsets.y, left: overflow.left - rect.width - preventedOffsets.x }; } function isAnySideFullyClipped(overflow) { return [top, right, bottom, left].some(function (side) { return overflow[side] >= 0; }); } function hide(_ref) { var state = _ref.state, name = _ref.name; var referenceRect = state.rects.reference; var popperRect = state.rects.popper; var preventedOffsets = state.modifiersData.preventOverflow; var referenceOverflow = detectOverflow(state, { elementContext: 'reference' }); var popperAltOverflow = detectOverflow(state, { altBoundary: true }); var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect); var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets); var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets); var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets); state.modifiersData[name] = { referenceClippingOffsets: referenceClippingOffsets, popperEscapeOffsets: popperEscapeOffsets, isReferenceHidden: isReferenceHidden, hasPopperEscaped: hasPopperEscaped }; state.attributes.popper = Object.assign({}, state.attributes.popper, { 'data-popper-reference-hidden': isReferenceHidden, 'data-popper-escaped': hasPopperEscaped }); } // eslint-disable-next-line import/no-unused-modules const hide$1 = { name: 'hide', enabled: true, phase: 'main', requiresIfExists: ['preventOverflow'], fn: hide }; function distanceAndSkiddingToXY(placement, rects, offset) { var basePlacement = getBasePlacement(placement); var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1; var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, { placement: placement })) : offset, skidding = _ref[0], distance = _ref[1]; skidding = skidding || 0; distance = (distance || 0) * invertDistance; return [left, right].indexOf(basePlacement) >= 0 ? { x: distance, y: skidding } : { x: skidding, y: distance }; } function offset(_ref2) { var state = _ref2.state, options = _ref2.options, name = _ref2.name; var _options$offset = options.offset, offset = _options$offset === void 0 ? [0, 0] : _options$offset; var data = placements.reduce(function (acc, placement) { acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset); return acc; }, {}); var _data$state$placement = data[state.placement], x = _data$state$placement.x, y = _data$state$placement.y; if (state.modifiersData.popperOffsets != null) { state.modifiersData.popperOffsets.x += x; state.modifiersData.popperOffsets.y += y; } state.modifiersData[name] = data; } // eslint-disable-next-line import/no-unused-modules const offset$1 = { name: 'offset', enabled: true, phase: 'main', requires: ['popperOffsets'], fn: offset }; function popperOffsets(_ref) { var state = _ref.state, name = _ref.name; // Offsets are the actual position the popper needs to have to be // properly positioned near its reference element // This is the most basic placement, and will be adjusted by // the modifiers in the next step state.modifiersData[name] = computeOffsets({ reference: state.rects.reference, element: state.rects.popper, strategy: 'absolute', placement: state.placement }); } // eslint-disable-next-line import/no-unused-modules const popperOffsets$1 = { name: 'popperOffsets', enabled: true, phase: 'read', fn: popperOffsets, data: {} }; function getAltAxis(axis) { return axis === 'x' ? 'y' : 'x'; } function preventOverflow(_ref) { var state = _ref.state, options = _ref.options, name = _ref.name; var _options$mainAxis = options.mainAxis, checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, _options$altAxis = options.altAxis, checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, boundary = options.boundary, rootBoundary = options.rootBoundary, altBoundary = options.altBoundary, padding = options.padding, _options$tether = options.tether, tether = _options$tether === void 0 ? true : _options$tether, _options$tetherOffset = options.tetherOffset, tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset; var overflow = detectOverflow(state, { boundary: boundary, rootBoundary: rootBoundary, padding: padding, altBoundary: altBoundary }); var basePlacement = getBasePlacement(state.placement); var variation = getVariation(state.placement); var isBasePlacement = !variation; var mainAxis = getMainAxisFromPlacement(basePlacement); var altAxis = getAltAxis(mainAxis); var popperOffsets = state.modifiersData.popperOffsets; var referenceRect = state.rects.reference; var popperRect = state.rects.popper; var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, { placement: state.placement })) : tetherOffset; var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? { mainAxis: tetherOffsetValue, altAxis: tetherOffsetValue } : Object.assign({ mainAxis: 0, altAxis: 0 }, tetherOffsetValue); var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null; var data = { x: 0, y: 0 }; if (!popperOffsets) { return; } if (checkMainAxis) { var _offsetModifierState$; var mainSide = mainAxis === 'y' ? top : left; var altSide = mainAxis === 'y' ? bottom : right; var len = mainAxis === 'y' ? 'height' : 'width'; var offset = popperOffsets[mainAxis]; var min$1 = offset + overflow[mainSide]; var max$1 = offset - overflow[altSide]; var additive = tether ? -popperRect[len] / 2 : 0; var minLen = variation === start ? referenceRect[len] : popperRect[len]; var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go // outside the reference bounds var arrowElement = state.elements.arrow; var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { width: 0, height: 0 }; var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject(); var arrowPaddingMin = arrowPaddingObject[mainSide]; var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want // to include its full size in the calculation. If the reference is small // and near the edge of a boundary, the popper can overflow even if the // reference is not overflowing as well (e.g. virtual elements with no // width or height) var arrowLen = within(0, referenceRect[len], arrowRect[len]); var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis; var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis; var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow); var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0; var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0; var tetherMin = offset + minOffset - offsetModifierValue - clientOffset; var tetherMax = offset + maxOffset - offsetModifierValue; var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1); popperOffsets[mainAxis] = preventedOffset; data[mainAxis] = preventedOffset - offset; } if (checkAltAxis) { var _offsetModifierState$2; var _mainSide = mainAxis === 'x' ? top : left; var _altSide = mainAxis === 'x' ? bottom : right; var _offset = popperOffsets[altAxis]; var _len = altAxis === 'y' ? 'height' : 'width'; var _min = _offset + overflow[_mainSide]; var _max = _offset - overflow[_altSide]; var isOriginSide = [top, left].indexOf(basePlacement) !== -1; var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0; var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis; var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max; var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max); popperOffsets[altAxis] = _preventedOffset; data[altAxis] = _preventedOffset - _offset; } state.modifiersData[name] = data; } // eslint-disable-next-line import/no-unused-modules const preventOverflow$1 = { name: 'preventOverflow', enabled: true, phase: 'main', fn: preventOverflow, requiresIfExists: ['offset'] }; function getHTMLElementScroll(element) { return { scrollLeft: element.scrollLeft, scrollTop: element.scrollTop }; } function getNodeScroll(node) { if (node === getWindow(node) || !isHTMLElement(node)) { return getWindowScroll(node); } else { return getHTMLElementScroll(node); } } function isElementScaled(element) { var rect = element.getBoundingClientRect(); var scaleX = round(rect.width) / element.offsetWidth || 1; var scaleY = round(rect.height) / element.offsetHeight || 1; return scaleX !== 1 || scaleY !== 1; } // Returns the composite rect of an element relative to its offsetParent. // Composite means it takes into account transforms as well as layout. function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) { if (isFixed === void 0) { isFixed = false; } var isOffsetParentAnElement = isHTMLElement(offsetParent); var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent); var documentElement = getDocumentElement(offsetParent); var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed); var scroll = { scrollLeft: 0, scrollTop: 0 }; var offsets = { x: 0, y: 0 }; if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078 isScrollParent(documentElement)) { scroll = getNodeScroll(offsetParent); } if (isHTMLElement(offsetParent)) { offsets = getBoundingClientRect(offsetParent, true); offsets.x += offsetParent.clientLeft; offsets.y += offsetParent.clientTop; } else if (documentElement) { offsets.x = getWindowScrollBarX(documentElement); } } return { x: rect.left + scroll.scrollLeft - offsets.x, y: rect.top + scroll.scrollTop - offsets.y, width: rect.width, height: rect.height }; } function order(modifiers) { var map = new Map(); var visited = new Set(); var result = []; modifiers.forEach(function (modifier) { map.set(modifier.name, modifier); }); // On visiting object, check for its dependencies and visit them recursively function sort(modifier) { visited.add(modifier.name); var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []); requires.forEach(function (dep) { if (!visited.has(dep)) { var depModifier = map.get(dep); if (depModifier) { sort(depModifier); } } }); result.push(modifier); } modifiers.forEach(function (modifier) { if (!visited.has(modifier.name)) { // check for visited object sort(modifier); } }); return result; } function orderModifiers(modifiers) { // order based on dependencies var orderedModifiers = order(modifiers); // order based on phase return modifierPhases.reduce(function (acc, phase) { return acc.concat(orderedModifiers.filter(function (modifier) { return modifier.phase === phase; })); }, []); } function debounce(fn) { var pending; return function () { if (!pending) { pending = new Promise(function (resolve) { Promise.resolve().then(function () { pending = undefined; resolve(fn()); }); }); } return pending; }; } function mergeByName(modifiers) { var merged = modifiers.reduce(function (merged, current) { var existing = merged[current.name]; merged[current.name] = existing ? Object.assign({}, existing, current, { options: Object.assign({}, existing.options, current.options), data: Object.assign({}, existing.data, current.data) }) : current; return merged; }, {}); // IE11 does not support Object.values return Object.keys(merged).map(function (key) { return merged[key]; }); } var DEFAULT_OPTIONS = { placement: 'bottom', modifiers: [], strategy: 'absolute' }; function areValidElements() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return !args.some(function (element) { return !(element && typeof element.getBoundingClientRect === 'function'); }); } function popperGenerator(generatorOptions) { if (generatorOptions === void 0) { generatorOptions = {}; } var _generatorOptions = generatorOptions, _generatorOptions$def = _generatorOptions.defaultModifiers, defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, _generatorOptions$def2 = _generatorOptions.defaultOptions, defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; return function createPopper(reference, popper, options) { if (options === void 0) { options = defaultOptions; } var state = { placement: 'bottom', orderedModifiers: [], options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions), modifiersData: {}, elements: { reference: reference, popper: popper }, attributes: {}, styles: {} }; var effectCleanupFns = []; var isDestroyed = false; var instance = { state: state, setOptions: function setOptions(setOptionsAction) { var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction; cleanupModifierEffects(); state.options = Object.assign({}, defaultOptions, state.options, options); state.scrollParents = { reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], popper: listScrollParents(popper) }; // Orders the modifiers based on their dependencies and `phase` // properties var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers state.orderedModifiers = orderedModifiers.filter(function (m) { return m.enabled; }); // Validate the provided modifiers so that the consumer will get warned runModifierEffects(); return instance.update(); }, // Sync update – it will always be executed, even if not necessary. This // is useful for low frequency updates where sync behavior simplifies the // logic. // For high frequency updates (e.g. `resize` and `scroll` events), always // prefer the async Popper#update method forceUpdate: function forceUpdate() { if (isDestroyed) { return; } var _state$elements = state.elements, reference = _state$elements.reference, popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements // anymore if (!areValidElements(reference, popper)) { return; } // Store the reference and popper rects to be read by modifiers state.rects = { reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), popper: getLayoutRect(popper) }; // Modifiers have the ability to reset the current update cycle. The // most common use case for this is the `flip` modifier changing the // placement, which then needs to re-run all the modifiers, because the // logic was previously ran for the previous placement and is therefore // stale/incorrect state.reset = false; state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier // is filled with the initial data specified by the modifier. This means // it doesn't persist and is fresh on each update. // To ensure persistent data, use `${name}#persistent` state.orderedModifiers.forEach(function (modifier) { return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); }); for (var index = 0; index < state.orderedModifiers.length; index++) { if (state.reset === true) { state.reset = false; index = -1; continue; } var _state$orderedModifie = state.orderedModifiers[index], fn = _state$orderedModifie.fn, _state$orderedModifie2 = _state$orderedModifie.options, _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, name = _state$orderedModifie.name; if (typeof fn === 'function') { state = fn({ state: state, options: _options, name: name, instance: instance }) || state; } } }, // Async and optimistically optimized update – it will not be executed if // not necessary (debounced to run at most once-per-tick) update: debounce(function () { return new Promise(function (resolve) { instance.forceUpdate(); resolve(state); }); }), destroy: function destroy() { cleanupModifierEffects(); isDestroyed = true; } }; if (!areValidElements(reference, popper)) { return instance; } instance.setOptions(options).then(function (state) { if (!isDestroyed && options.onFirstUpdate) { options.onFirstUpdate(state); } }); // Modifiers have the ability to execute arbitrary code before the first // update cycle runs. They will be executed in the same order as the update // cycle. This is useful when a modifier adds some persistent data that // other modifiers need to use, but the modifier is run after the dependent // one. function runModifierEffects() { state.orderedModifiers.forEach(function (_ref3) { var name = _ref3.name, _ref3$options = _ref3.options, options = _ref3$options === void 0 ? {} : _ref3$options, effect = _ref3.effect; if (typeof effect === 'function') { var cleanupFn = effect({ state: state, name: name, instance: instance, options: options }); var noopFn = function noopFn() {}; effectCleanupFns.push(cleanupFn || noopFn); } }); } function cleanupModifierEffects() { effectCleanupFns.forEach(function (fn) { return fn(); }); effectCleanupFns = []; } return instance; }; } var createPopper$2 = /*#__PURE__*/popperGenerator(); // eslint-disable-next-line import/no-unused-modules var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1]; var createPopper$1 = /*#__PURE__*/popperGenerator({ defaultModifiers: defaultModifiers$1 }); // eslint-disable-next-line import/no-unused-modules var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; var createPopper = /*#__PURE__*/popperGenerator({ defaultModifiers: defaultModifiers }); // eslint-disable-next-line import/no-unused-modules const Popper = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({ __proto__: null, popperGenerator, detectOverflow, createPopperBase: createPopper$2, createPopper, createPopperLite: createPopper$1, top, bottom, right, left, auto, basePlacements, start, end, clippingParents, viewport, popper, reference, variationPlacements, placements, beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite, modifierPhases, applyStyles: applyStyles$1, arrow: arrow$1, computeStyles: computeStyles$1, eventListeners, flip: flip$1, hide: hide$1, offset: offset$1, popperOffsets: popperOffsets$1, preventOverflow: preventOverflow$1 }, Symbol.toStringTag, { value: 'Module' })); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): dropdown.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$a = 'dropdown'; const DATA_KEY$6 = 'bs.dropdown'; const EVENT_KEY$6 = `.${DATA_KEY$6}`; const DATA_API_KEY$3 = '.data-api'; const ESCAPE_KEY$2 = 'Escape'; const TAB_KEY$1 = 'Tab'; const ARROW_UP_KEY$1 = 'ArrowUp'; const ARROW_DOWN_KEY$1 = 'ArrowDown'; const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`; const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`; const EVENT_SHOW$5 = `show${EVENT_KEY$6}`; const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`; const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`; const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`; const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`; const CLASS_NAME_SHOW$6 = 'show'; const CLASS_NAME_DROPUP = 'dropup'; const CLASS_NAME_DROPEND = 'dropend'; const CLASS_NAME_DROPSTART = 'dropstart'; const CLASS_NAME_DROPUP_CENTER = 'dropup-center'; const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center'; const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)'; const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`; const SELECTOR_MENU = '.dropdown-menu'; const SELECTOR_NAVBAR = '.navbar'; const SELECTOR_NAVBAR_NAV = '.navbar-nav'; const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'; const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start'; const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end'; const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start'; const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end'; const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start'; const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start'; const PLACEMENT_TOPCENTER = 'top'; const PLACEMENT_BOTTOMCENTER = 'bottom'; const Default$9 = { autoClose: true, boundary: 'clippingParents', display: 'dynamic', offset: [0, 2], popperConfig: null, reference: 'toggle' }; const DefaultType$9 = { autoClose: '(boolean|string)', boundary: '(string|element)', display: 'string', offset: '(array|string|function)', popperConfig: '(null|object|function)', reference: '(string|element|object)' }; /** * Class definition */ class Dropdown extends BaseComponent { constructor(element, config) { super(element, config); this._popper = null; this._parent = this._element.parentNode; // dropdown wrapper // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/ this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent); this._inNavbar = this._detectNavbar(); } // Getters static get Default() { return Default$9; } static get DefaultType() { return DefaultType$9; } static get NAME() { return NAME$a; } // Public toggle() { return this._isShown() ? this.hide() : this.show(); } show() { if (isDisabled(this._element) || this._isShown()) { return; } const relatedTarget = { relatedTarget: this._element }; const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget); if (showEvent.defaultPrevented) { return; } this._createPopper(); // If this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) { for (const element of [].concat(...document.body.children)) { EventHandler.on(element, 'mouseover', noop); } } this._element.focus(); this._element.setAttribute('aria-expanded', true); this._menu.classList.add(CLASS_NAME_SHOW$6); this._element.classList.add(CLASS_NAME_SHOW$6); EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget); } hide() { if (isDisabled(this._element) || !this._isShown()) { return; } const relatedTarget = { relatedTarget: this._element }; this._completeHide(relatedTarget); } dispose() { if (this._popper) { this._popper.destroy(); } super.dispose(); } update() { this._inNavbar = this._detectNavbar(); if (this._popper) { this._popper.update(); } } // Private _completeHide(relatedTarget) { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget); if (hideEvent.defaultPrevented) { return; } // If this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { for (const element of [].concat(...document.body.children)) { EventHandler.off(element, 'mouseover', noop); } } if (this._popper) { this._popper.destroy(); } this._menu.classList.remove(CLASS_NAME_SHOW$6); this._element.classList.remove(CLASS_NAME_SHOW$6); this._element.setAttribute('aria-expanded', 'false'); Manipulator.removeDataAttribute(this._menu, 'popper'); EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget); } _getConfig(config) { config = super._getConfig(config); if (typeof config.reference === 'object' && !isElement$1(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') { // Popper virtual elements require a getBoundingClientRect method throw new TypeError(`${NAME$a.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`); } return config; } _createPopper() { if (typeof Popper === 'undefined') { throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org)'); } let referenceElement = this._element; if (this._config.reference === 'parent') { referenceElement = this._parent; } else if (isElement$1(this._config.reference)) { referenceElement = getElement(this._config.reference); } else if (typeof this._config.reference === 'object') { referenceElement = this._config.reference; } const popperConfig = this._getPopperConfig(); this._popper = createPopper(referenceElement, this._menu, popperConfig); } _isShown() { return this._menu.classList.contains(CLASS_NAME_SHOW$6); } _getPlacement() { const parentDropdown = this._parent; if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) { return PLACEMENT_RIGHT; } if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) { return PLACEMENT_LEFT; } if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) { return PLACEMENT_TOPCENTER; } if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) { return PLACEMENT_BOTTOMCENTER; } // We need to trim the value because custom properties can also include spaces const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end'; if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) { return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP; } return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM; } _detectNavbar() { return this._element.closest(SELECTOR_NAVBAR) !== null; } _getOffset() { const { offset } = this._config; if (typeof offset === 'string') { return offset.split(',').map(value => Number.parseInt(value, 10)); } if (typeof offset === 'function') { return popperData => offset(popperData, this._element); } return offset; } _getPopperConfig() { const defaultBsPopperConfig = { placement: this._getPlacement(), modifiers: [{ name: 'preventOverflow', options: { boundary: this._config.boundary } }, { name: 'offset', options: { offset: this._getOffset() } }] }; // Disable Popper if we have a static display or Dropdown is in Navbar if (this._inNavbar || this._config.display === 'static') { Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // todo:v6 remove defaultBsPopperConfig.modifiers = [{ name: 'applyStyles', enabled: false }]; } return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; } _selectMenuItem({ key, target }) { const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element)); if (!items.length) { return; } // if target isn't included in items (e.g. when expanding the dropdown) // allow cycling to get the last item in case key equals ARROW_UP_KEY getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus(); } // Static static jQueryInterface(config) { return this.each(function () { const data = Dropdown.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); }); } static clearMenus(event) { if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) { return; } const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN); for (const toggle of openToggles) { const context = Dropdown.getInstance(toggle); if (!context || context._config.autoClose === false) { continue; } const composedPath = event.composedPath(); const isMenuTarget = composedPath.includes(context._menu); if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) { continue; } // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) { continue; } const relatedTarget = { relatedTarget: context._element }; if (event.type === 'click') { relatedTarget.clickEvent = event; } context._completeHide(relatedTarget); } } static dataApiKeydownHandler(event) { // If not an UP | DOWN | ESCAPE key => not a dropdown command // If input/textarea && if key is other than ESCAPE => not a dropdown command const isInput = /input|textarea/i.test(event.target.tagName); const isEscapeEvent = event.key === ESCAPE_KEY$2; const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key); if (!isUpOrDownEvent && !isEscapeEvent) { return; } if (isInput && !isEscapeEvent) { return; } event.preventDefault(); // todo: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.2/forms/input-group/ const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode); const instance = Dropdown.getOrCreateInstance(getToggleButton); if (isUpOrDownEvent) { event.stopPropagation(); instance.show(); instance._selectMenuItem(event); return; } if (instance._isShown()) { // else is escape and we check if it is shown event.stopPropagation(); instance.hide(); getToggleButton.focus(); } } } /** * Data API implementation */ EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler); EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler); EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus); EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus); EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function (event) { event.preventDefault(); Dropdown.getOrCreateInstance(this).toggle(); }); /** * jQuery */ defineJQueryPlugin(Dropdown); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/scrollBar.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top'; const SELECTOR_STICKY_CONTENT = '.sticky-top'; const PROPERTY_PADDING = 'padding-right'; const PROPERTY_MARGIN = 'margin-right'; /** * Class definition */ class ScrollBarHelper { constructor() { this._element = document.body; } // Public getWidth() { // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes const documentWidth = document.documentElement.clientWidth; return Math.abs(window.innerWidth - documentWidth); } hide() { const width = this.getWidth(); this._disableOverFlow(); // give padding to element to balance the hidden scrollbar width this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width); // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width); this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width); } reset() { this._resetElementAttributes(this._element, 'overflow'); this._resetElementAttributes(this._element, PROPERTY_PADDING); this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING); this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN); } isOverflowing() { return this.getWidth() > 0; } // Private _disableOverFlow() { this._saveInitialAttribute(this._element, 'overflow'); this._element.style.overflow = 'hidden'; } _setElementAttributes(selector, styleProperty, callback) { const scrollbarWidth = this.getWidth(); const manipulationCallBack = element => { if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) { return; } this._saveInitialAttribute(element, styleProperty); const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty); element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`); }; this._applyManipulationCallback(selector, manipulationCallBack); } _saveInitialAttribute(element, styleProperty) { const actualValue = element.style.getPropertyValue(styleProperty); if (actualValue) { Manipulator.setDataAttribute(element, styleProperty, actualValue); } } _resetElementAttributes(selector, styleProperty) { const manipulationCallBack = element => { const value = Manipulator.getDataAttribute(element, styleProperty); // We only want to remove the property if the value is `null`; the value can also be zero if (value === null) { element.style.removeProperty(styleProperty); return; } Manipulator.removeDataAttribute(element, styleProperty); element.style.setProperty(styleProperty, value); }; this._applyManipulationCallback(selector, manipulationCallBack); } _applyManipulationCallback(selector, callBack) { if (isElement$1(selector)) { callBack(selector); return; } for (const sel of SelectorEngine.find(selector, this._element)) { callBack(sel); } } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/backdrop.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$9 = 'backdrop'; const CLASS_NAME_FADE$4 = 'fade'; const CLASS_NAME_SHOW$5 = 'show'; const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`; const Default$8 = { className: 'modal-backdrop', clickCallback: null, isAnimated: false, isVisible: true, // if false, we use the backdrop helper without adding any element to the dom rootElement: 'body' // give the choice to place backdrop under different elements }; const DefaultType$8 = { className: 'string', clickCallback: '(function|null)', isAnimated: 'boolean', isVisible: 'boolean', rootElement: '(element|string)' }; /** * Class definition */ class Backdrop extends Config { constructor(config) { super(); this._config = this._getConfig(config); this._isAppended = false; this._element = null; } // Getters static get Default() { return Default$8; } static get DefaultType() { return DefaultType$8; } static get NAME() { return NAME$9; } // Public show(callback) { if (!this._config.isVisible) { execute(callback); return; } this._append(); const element = this._getElement(); if (this._config.isAnimated) { reflow(element); } element.classList.add(CLASS_NAME_SHOW$5); this._emulateAnimation(() => { execute(callback); }); } hide(callback) { if (!this._config.isVisible) { execute(callback); return; } this._getElement().classList.remove(CLASS_NAME_SHOW$5); this._emulateAnimation(() => { this.dispose(); execute(callback); }); } dispose() { if (!this._isAppended) { return; } EventHandler.off(this._element, EVENT_MOUSEDOWN); this._element.remove(); this._isAppended = false; } // Private _getElement() { if (!this._element) { const backdrop = document.createElement('div'); backdrop.className = this._config.className; if (this._config.isAnimated) { backdrop.classList.add(CLASS_NAME_FADE$4); } this._element = backdrop; } return this._element; } _configAfterMerge(config) { // use getElement() with the default "body" to get a fresh Element on each instantiation config.rootElement = getElement(config.rootElement); return config; } _append() { if (this._isAppended) { return; } const element = this._getElement(); this._config.rootElement.append(element); EventHandler.on(element, EVENT_MOUSEDOWN, () => { execute(this._config.clickCallback); }); this._isAppended = true; } _emulateAnimation(callback) { executeAfterTransition(callback, this._getElement(), this._config.isAnimated); } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/focustrap.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$8 = 'focustrap'; const DATA_KEY$5 = 'bs.focustrap'; const EVENT_KEY$5 = `.${DATA_KEY$5}`; const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`; const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`; const TAB_KEY = 'Tab'; const TAB_NAV_FORWARD = 'forward'; const TAB_NAV_BACKWARD = 'backward'; const Default$7 = { autofocus: true, trapElement: null // The element to trap focus inside of }; const DefaultType$7 = { autofocus: 'boolean', trapElement: 'element' }; /** * Class definition */ class FocusTrap extends Config { constructor(config) { super(); this._config = this._getConfig(config); this._isActive = false; this._lastTabNavDirection = null; } // Getters static get Default() { return Default$7; } static get DefaultType() { return DefaultType$7; } static get NAME() { return NAME$8; } // Public activate() { if (this._isActive) { return; } if (this._config.autofocus) { this._config.trapElement.focus(); } EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event)); EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event)); this._isActive = true; } deactivate() { if (!this._isActive) { return; } this._isActive = false; EventHandler.off(document, EVENT_KEY$5); } // Private _handleFocusin(event) { const { trapElement } = this._config; if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) { return; } const elements = SelectorEngine.focusableChildren(trapElement); if (elements.length === 0) { trapElement.focus(); } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) { elements[elements.length - 1].focus(); } else { elements[0].focus(); } } _handleKeydown(event) { if (event.key !== TAB_KEY) { return; } this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): modal.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$7 = 'modal'; const DATA_KEY$4 = 'bs.modal'; const EVENT_KEY$4 = `.${DATA_KEY$4}`; const DATA_API_KEY$2 = '.data-api'; const ESCAPE_KEY$1 = 'Escape'; const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`; const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`; const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`; const EVENT_SHOW$4 = `show${EVENT_KEY$4}`; const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`; const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`; const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`; const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`; const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`; const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`; const CLASS_NAME_OPEN = 'modal-open'; const CLASS_NAME_FADE$3 = 'fade'; const CLASS_NAME_SHOW$4 = 'show'; const CLASS_NAME_STATIC = 'modal-static'; const OPEN_SELECTOR$1 = '.modal.show'; const SELECTOR_DIALOG = '.modal-dialog'; const SELECTOR_MODAL_BODY = '.modal-body'; const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]'; const Default$6 = { backdrop: true, focus: true, keyboard: true }; const DefaultType$6 = { backdrop: '(boolean|string)', focus: 'boolean', keyboard: 'boolean' }; /** * Class definition */ class Modal extends BaseComponent { constructor(element, config) { super(element, config); this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element); this._backdrop = this._initializeBackDrop(); this._focustrap = this._initializeFocusTrap(); this._isShown = false; this._isTransitioning = false; this._scrollBar = new ScrollBarHelper(); this._addEventListeners(); } // Getters static get Default() { return Default$6; } static get DefaultType() { return DefaultType$6; } static get NAME() { return NAME$7; } // Public toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); } show(relatedTarget) { if (this._isShown || this._isTransitioning) { return; } const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, { relatedTarget }); if (showEvent.defaultPrevented) { return; } this._isShown = true; this._isTransitioning = true; this._scrollBar.hide(); document.body.classList.add(CLASS_NAME_OPEN); this._adjustDialog(); this._backdrop.show(() => this._showElement(relatedTarget)); } hide() { if (!this._isShown || this._isTransitioning) { return; } const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4); if (hideEvent.defaultPrevented) { return; } this._isShown = false; this._isTransitioning = true; this._focustrap.deactivate(); this._element.classList.remove(CLASS_NAME_SHOW$4); this._queueCallback(() => this._hideModal(), this._element, this._isAnimated()); } dispose() { for (const htmlElement of [window, this._dialog]) { EventHandler.off(htmlElement, EVENT_KEY$4); } this._backdrop.dispose(); this._focustrap.deactivate(); super.dispose(); } handleUpdate() { this._adjustDialog(); } // Private _initializeBackDrop() { return new Backdrop({ isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value, isAnimated: this._isAnimated() }); } _initializeFocusTrap() { return new FocusTrap({ trapElement: this._element }); } _showElement(relatedTarget) { // try to append dynamic modal if (!document.body.contains(this._element)) { document.body.append(this._element); } this._element.style.display = 'block'; this._element.removeAttribute('aria-hidden'); this._element.setAttribute('aria-modal', true); this._element.setAttribute('role', 'dialog'); this._element.scrollTop = 0; const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog); if (modalBody) { modalBody.scrollTop = 0; } reflow(this._element); this._element.classList.add(CLASS_NAME_SHOW$4); const transitionComplete = () => { if (this._config.focus) { this._focustrap.activate(); } this._isTransitioning = false; EventHandler.trigger(this._element, EVENT_SHOWN$4, { relatedTarget }); }; this._queueCallback(transitionComplete, this._dialog, this._isAnimated()); } _addEventListeners() { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => { if (event.key !== ESCAPE_KEY$1) { return; } if (this._config.keyboard) { event.preventDefault(); this.hide(); return; } this._triggerBackdropTransition(); }); EventHandler.on(window, EVENT_RESIZE$1, () => { if (this._isShown && !this._isTransitioning) { this._adjustDialog(); } }); EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => { // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => { if (this._element !== event.target || this._element !== event2.target) { return; } if (this._config.backdrop === 'static') { this._triggerBackdropTransition(); return; } if (this._config.backdrop) { this.hide(); } }); }); } _hideModal() { this._element.style.display = 'none'; this._element.setAttribute('aria-hidden', true); this._element.removeAttribute('aria-modal'); this._element.removeAttribute('role'); this._isTransitioning = false; this._backdrop.hide(() => { document.body.classList.remove(CLASS_NAME_OPEN); this._resetAdjustments(); this._scrollBar.reset(); EventHandler.trigger(this._element, EVENT_HIDDEN$4); }); } _isAnimated() { return this._element.classList.contains(CLASS_NAME_FADE$3); } _triggerBackdropTransition() { const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1); if (hideEvent.defaultPrevented) { return; } const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const initialOverflowY = this._element.style.overflowY; // return if the following background transition hasn't yet completed if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) { return; } if (!isModalOverflowing) { this._element.style.overflowY = 'hidden'; } this._element.classList.add(CLASS_NAME_STATIC); this._queueCallback(() => { this._element.classList.remove(CLASS_NAME_STATIC); this._queueCallback(() => { this._element.style.overflowY = initialOverflowY; }, this._dialog); }, this._dialog); this._element.focus(); } /** * The following methods are used to handle overflowing modals */ _adjustDialog() { const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; const scrollbarWidth = this._scrollBar.getWidth(); const isBodyOverflowing = scrollbarWidth > 0; if (isBodyOverflowing && !isModalOverflowing) { const property = isRTL() ? 'paddingLeft' : 'paddingRight'; this._element.style[property] = `${scrollbarWidth}px`; } if (!isBodyOverflowing && isModalOverflowing) { const property = isRTL() ? 'paddingRight' : 'paddingLeft'; this._element.style[property] = `${scrollbarWidth}px`; } } _resetAdjustments() { this._element.style.paddingLeft = ''; this._element.style.paddingRight = ''; } // Static static jQueryInterface(config, relatedTarget) { return this.each(function () { const data = Modal.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](relatedTarget); }); } } /** * Data API implementation */ EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function (event) { const target = getElementFromSelector(this); if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } EventHandler.one(target, EVENT_SHOW$4, showEvent => { if (showEvent.defaultPrevented) { // only register focus restorer if modal will actually get shown return; } EventHandler.one(target, EVENT_HIDDEN$4, () => { if (isVisible(this)) { this.focus(); } }); }); // avoid conflict when clicking modal toggler while another one is open const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1); if (alreadyOpen) { Modal.getInstance(alreadyOpen).hide(); } const data = Modal.getOrCreateInstance(target); data.toggle(this); }); enableDismissTrigger(Modal); /** * jQuery */ defineJQueryPlugin(Modal); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): offcanvas.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$6 = 'offcanvas'; const DATA_KEY$3 = 'bs.offcanvas'; const EVENT_KEY$3 = `.${DATA_KEY$3}`; const DATA_API_KEY$1 = '.data-api'; const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`; const ESCAPE_KEY = 'Escape'; const CLASS_NAME_SHOW$3 = 'show'; const CLASS_NAME_SHOWING$1 = 'showing'; const CLASS_NAME_HIDING = 'hiding'; const CLASS_NAME_BACKDROP = 'offcanvas-backdrop'; const OPEN_SELECTOR = '.offcanvas.show'; const EVENT_SHOW$3 = `show${EVENT_KEY$3}`; const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`; const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`; const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`; const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`; const EVENT_RESIZE = `resize${EVENT_KEY$3}`; const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`; const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`; const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]'; const Default$5 = { backdrop: true, keyboard: true, scroll: false }; const DefaultType$5 = { backdrop: '(boolean|string)', keyboard: 'boolean', scroll: 'boolean' }; /** * Class definition */ class Offcanvas extends BaseComponent { constructor(element, config) { super(element, config); this._isShown = false; this._backdrop = this._initializeBackDrop(); this._focustrap = this._initializeFocusTrap(); this._addEventListeners(); } // Getters static get Default() { return Default$5; } static get DefaultType() { return DefaultType$5; } static get NAME() { return NAME$6; } // Public toggle(relatedTarget) { return this._isShown ? this.hide() : this.show(relatedTarget); } show(relatedTarget) { if (this._isShown) { return; } const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, { relatedTarget }); if (showEvent.defaultPrevented) { return; } this._isShown = true; this._backdrop.show(); if (!this._config.scroll) { new ScrollBarHelper().hide(); } this._element.setAttribute('aria-modal', true); this._element.setAttribute('role', 'dialog'); this._element.classList.add(CLASS_NAME_SHOWING$1); const completeCallBack = () => { if (!this._config.scroll || this._config.backdrop) { this._focustrap.activate(); } this._element.classList.add(CLASS_NAME_SHOW$3); this._element.classList.remove(CLASS_NAME_SHOWING$1); EventHandler.trigger(this._element, EVENT_SHOWN$3, { relatedTarget }); }; this._queueCallback(completeCallBack, this._element, true); } hide() { if (!this._isShown) { return; } const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3); if (hideEvent.defaultPrevented) { return; } this._focustrap.deactivate(); this._element.blur(); this._isShown = false; this._element.classList.add(CLASS_NAME_HIDING); this._backdrop.hide(); const completeCallback = () => { this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING); this._element.removeAttribute('aria-modal'); this._element.removeAttribute('role'); if (!this._config.scroll) { new ScrollBarHelper().reset(); } EventHandler.trigger(this._element, EVENT_HIDDEN$3); }; this._queueCallback(completeCallback, this._element, true); } dispose() { this._backdrop.dispose(); this._focustrap.deactivate(); super.dispose(); } // Private _initializeBackDrop() { const clickCallback = () => { if (this._config.backdrop === 'static') { EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); return; } this.hide(); }; // 'static' option will be translated to true, and booleans will keep their value const isVisible = Boolean(this._config.backdrop); return new Backdrop({ className: CLASS_NAME_BACKDROP, isVisible, isAnimated: true, rootElement: this._element.parentNode, clickCallback: isVisible ? clickCallback : null }); } _initializeFocusTrap() { return new FocusTrap({ trapElement: this._element }); } _addEventListeners() { EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => { if (event.key !== ESCAPE_KEY) { return; } if (!this._config.keyboard) { EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED); return; } this.hide(); }); } // Static static jQueryInterface(config) { return this.each(function () { const data = Offcanvas.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (data[config] === undefined || config.startsWith('_') || config === 'constructor') { throw new TypeError(`No method named "${config}"`); } data[config](this); }); } } /** * Data API implementation */ EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function (event) { const target = getElementFromSelector(this); if (['A', 'AREA'].includes(this.tagName)) { event.preventDefault(); } if (isDisabled(this)) { return; } EventHandler.one(target, EVENT_HIDDEN$3, () => { // focus on trigger when it is closed if (isVisible(this)) { this.focus(); } }); // avoid conflict when clicking a toggler of an offcanvas, while another is open const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR); if (alreadyOpen && alreadyOpen !== target) { Offcanvas.getInstance(alreadyOpen).hide(); } const data = Offcanvas.getOrCreateInstance(target); data.toggle(this); }); EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => { for (const selector of SelectorEngine.find(OPEN_SELECTOR)) { Offcanvas.getOrCreateInstance(selector).show(); } }); EventHandler.on(window, EVENT_RESIZE, () => { for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) { if (getComputedStyle(element).position !== 'fixed') { Offcanvas.getOrCreateInstance(element).hide(); } } }); enableDismissTrigger(Offcanvas); /** * jQuery */ defineJQueryPlugin(Offcanvas); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/sanitizer.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']); const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; /** * A pattern that recognizes a commonly useful subset of URLs that are safe. * * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts */ const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i; /** * A pattern that matches safe data URLs. Only matches image, video and audio types. * * Shout-out to Angular https://github.com/angular/angular/blob/12.2.x/packages/core/src/sanitization/url_sanitizer.ts */ const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i; const allowedAttribute = (attribute, allowedAttributeList) => { const attributeName = attribute.nodeName.toLowerCase(); if (allowedAttributeList.includes(attributeName)) { if (uriAttributes.has(attributeName)) { return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue) || DATA_URL_PATTERN.test(attribute.nodeValue)); } return true; } // Check if a regular expression validates the attribute. return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName)); }; const DefaultAllowlist = { // Global attributes allowed on any supplied element below. '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], a: ['target', 'href', 'title', 'rel'], area: [], b: [], br: [], col: [], code: [], div: [], em: [], hr: [], h1: [], h2: [], h3: [], h4: [], h5: [], h6: [], i: [], img: ['src', 'srcset', 'alt', 'title', 'width', 'height'], li: [], ol: [], p: [], pre: [], s: [], small: [], span: [], sub: [], sup: [], strong: [], u: [], ul: [] }; function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) { if (!unsafeHtml.length) { return unsafeHtml; } if (sanitizeFunction && typeof sanitizeFunction === 'function') { return sanitizeFunction(unsafeHtml); } const domParser = new window.DOMParser(); const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); const elements = [].concat(...createdDocument.body.querySelectorAll('*')); for (const element of elements) { const elementName = element.nodeName.toLowerCase(); if (!Object.keys(allowList).includes(elementName)) { element.remove(); continue; } const attributeList = [].concat(...element.attributes); const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []); for (const attribute of attributeList) { if (!allowedAttribute(attribute, allowedAttributes)) { element.removeAttribute(attribute.nodeName); } } } return createdDocument.body.innerHTML; } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): util/template-factory.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$5 = 'TemplateFactory'; const Default$4 = { allowList: DefaultAllowlist, content: {}, // { selector : text , selector2 : text2 , } extraClass: '', html: false, sanitize: true, sanitizeFn: null, template: '
    ' }; const DefaultType$4 = { allowList: 'object', content: 'object', extraClass: '(string|function)', html: 'boolean', sanitize: 'boolean', sanitizeFn: '(null|function)', template: 'string' }; const DefaultContentType = { entry: '(string|element|function|null)', selector: '(string|element)' }; /** * Class definition */ class TemplateFactory extends Config { constructor(config) { super(); this._config = this._getConfig(config); } // Getters static get Default() { return Default$4; } static get DefaultType() { return DefaultType$4; } static get NAME() { return NAME$5; } // Public getContent() { return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean); } hasContent() { return this.getContent().length > 0; } changeContent(content) { this._checkContent(content); this._config.content = { ...this._config.content, ...content }; return this; } toHtml() { const templateWrapper = document.createElement('div'); templateWrapper.innerHTML = this._maybeSanitize(this._config.template); for (const [selector, text] of Object.entries(this._config.content)) { this._setContent(templateWrapper, text, selector); } const template = templateWrapper.children[0]; const extraClass = this._resolvePossibleFunction(this._config.extraClass); if (extraClass) { template.classList.add(...extraClass.split(' ')); } return template; } // Private _typeCheckConfig(config) { super._typeCheckConfig(config); this._checkContent(config.content); } _checkContent(arg) { for (const [selector, content] of Object.entries(arg)) { super._typeCheckConfig({ selector, entry: content }, DefaultContentType); } } _setContent(template, content, selector) { const templateElement = SelectorEngine.findOne(selector, template); if (!templateElement) { return; } content = this._resolvePossibleFunction(content); if (!content) { templateElement.remove(); return; } if (isElement$1(content)) { this._putElementInTemplate(getElement(content), templateElement); return; } if (this._config.html) { templateElement.innerHTML = this._maybeSanitize(content); return; } templateElement.textContent = content; } _maybeSanitize(arg) { return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg; } _resolvePossibleFunction(arg) { return typeof arg === 'function' ? arg(this) : arg; } _putElementInTemplate(element, templateElement) { if (this._config.html) { templateElement.innerHTML = ''; templateElement.append(element); return; } templateElement.textContent = element.textContent; } } /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): tooltip.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$4 = 'tooltip'; const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']); const CLASS_NAME_FADE$2 = 'fade'; const CLASS_NAME_MODAL = 'modal'; const CLASS_NAME_SHOW$2 = 'show'; const SELECTOR_TOOLTIP_INNER = '.tooltip-inner'; const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`; const EVENT_MODAL_HIDE = 'hide.bs.modal'; const TRIGGER_HOVER = 'hover'; const TRIGGER_FOCUS = 'focus'; const TRIGGER_CLICK = 'click'; const TRIGGER_MANUAL = 'manual'; const EVENT_HIDE$2 = 'hide'; const EVENT_HIDDEN$2 = 'hidden'; const EVENT_SHOW$2 = 'show'; const EVENT_SHOWN$2 = 'shown'; const EVENT_INSERTED = 'inserted'; const EVENT_CLICK$1 = 'click'; const EVENT_FOCUSIN$1 = 'focusin'; const EVENT_FOCUSOUT$1 = 'focusout'; const EVENT_MOUSEENTER = 'mouseenter'; const EVENT_MOUSELEAVE = 'mouseleave'; const AttachmentMap = { AUTO: 'auto', TOP: 'top', RIGHT: isRTL() ? 'left' : 'right', BOTTOM: 'bottom', LEFT: isRTL() ? 'right' : 'left' }; const Default$3 = { allowList: DefaultAllowlist, animation: true, boundary: 'clippingParents', container: false, customClass: '', delay: 0, fallbackPlacements: ['top', 'right', 'bottom', 'left'], html: false, offset: [0, 0], placement: 'top', popperConfig: null, sanitize: true, sanitizeFn: null, selector: false, template: '', title: '', trigger: 'hover focus' }; const DefaultType$3 = { allowList: 'object', animation: 'boolean', boundary: '(string|element)', container: '(string|element|boolean)', customClass: '(string|function)', delay: '(number|object)', fallbackPlacements: 'array', html: 'boolean', offset: '(array|string|function)', placement: '(string|function)', popperConfig: '(null|object|function)', sanitize: 'boolean', sanitizeFn: '(null|function)', selector: '(string|boolean)', template: 'string', title: '(string|element|function)', trigger: 'string' }; /** * Class definition */ class Tooltip extends BaseComponent { constructor(element, config) { if (typeof Popper === 'undefined') { throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org)'); } super(element, config); // Private this._isEnabled = true; this._timeout = 0; this._isHovered = null; this._activeTrigger = {}; this._popper = null; this._templateFactory = null; this._newContent = null; // Protected this.tip = null; this._setListeners(); if (!this._config.selector) { this._fixTitle(); } } // Getters static get Default() { return Default$3; } static get DefaultType() { return DefaultType$3; } static get NAME() { return NAME$4; } // Public enable() { this._isEnabled = true; } disable() { this._isEnabled = false; } toggleEnabled() { this._isEnabled = !this._isEnabled; } toggle() { if (!this._isEnabled) { return; } this._activeTrigger.click = !this._activeTrigger.click; if (this._isShown()) { this._leave(); return; } this._enter(); } dispose() { clearTimeout(this._timeout); EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); if (this._element.getAttribute('data-bs-original-title')) { this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title')); } this._disposePopper(); super.dispose(); } show() { if (this._element.style.display === 'none') { throw new Error('Please use show on visible elements'); } if (!(this._isWithContent() && this._isEnabled)) { return; } const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2)); const shadowRoot = findShadowRoot(this._element); const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element); if (showEvent.defaultPrevented || !isInTheDom) { return; } // todo v6 remove this OR make it optional this._disposePopper(); const tip = this._getTipElement(); this._element.setAttribute('aria-describedby', tip.getAttribute('id')); const { container } = this._config; if (!this._element.ownerDocument.documentElement.contains(this.tip)) { container.append(tip); EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED)); } this._popper = this._createPopper(tip); tip.classList.add(CLASS_NAME_SHOW$2); // If this is a touch-enabled device we add extra // empty mouseover listeners to the body's immediate children; // only needed because of broken event delegation on iOS // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html if ('ontouchstart' in document.documentElement) { for (const element of [].concat(...document.body.children)) { EventHandler.on(element, 'mouseover', noop); } } const complete = () => { EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2)); if (this._isHovered === false) { this._leave(); } this._isHovered = false; }; this._queueCallback(complete, this.tip, this._isAnimated()); } hide() { if (!this._isShown()) { return; } const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2)); if (hideEvent.defaultPrevented) { return; } const tip = this._getTipElement(); tip.classList.remove(CLASS_NAME_SHOW$2); // If this is a touch-enabled device we remove the extra // empty mouseover listeners we added for iOS support if ('ontouchstart' in document.documentElement) { for (const element of [].concat(...document.body.children)) { EventHandler.off(element, 'mouseover', noop); } } this._activeTrigger[TRIGGER_CLICK] = false; this._activeTrigger[TRIGGER_FOCUS] = false; this._activeTrigger[TRIGGER_HOVER] = false; this._isHovered = null; // it is a trick to support manual triggering const complete = () => { if (this._isWithActiveTrigger()) { return; } if (!this._isHovered) { this._disposePopper(); } this._element.removeAttribute('aria-describedby'); EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2)); }; this._queueCallback(complete, this.tip, this._isAnimated()); } update() { if (this._popper) { this._popper.update(); } } // Protected _isWithContent() { return Boolean(this._getTitle()); } _getTipElement() { if (!this.tip) { this.tip = this._createTipElement(this._newContent || this._getContentForTemplate()); } return this.tip; } _createTipElement(content) { const tip = this._getTemplateFactory(content).toHtml(); // todo: remove this check on v6 if (!tip) { return null; } tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2); // todo: on v6 the following can be achieved with CSS only tip.classList.add(`bs-${this.constructor.NAME}-auto`); const tipId = getUID(this.constructor.NAME).toString(); tip.setAttribute('id', tipId); if (this._isAnimated()) { tip.classList.add(CLASS_NAME_FADE$2); } return tip; } setContent(content) { this._newContent = content; if (this._isShown()) { this._disposePopper(); this.show(); } } _getTemplateFactory(content) { if (this._templateFactory) { this._templateFactory.changeContent(content); } else { this._templateFactory = new TemplateFactory({ ...this._config, // the `content` var has to be after `this._config` // to override config.content in case of popover content, extraClass: this._resolvePossibleFunction(this._config.customClass) }); } return this._templateFactory; } _getContentForTemplate() { return { [SELECTOR_TOOLTIP_INNER]: this._getTitle() }; } _getTitle() { return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title'); } // Private _initializeOnDelegatedTarget(event) { return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig()); } _isAnimated() { return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2); } _isShown() { return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2); } _createPopper(tip) { const placement = typeof this._config.placement === 'function' ? this._config.placement.call(this, tip, this._element) : this._config.placement; const attachment = AttachmentMap[placement.toUpperCase()]; return createPopper(this._element, tip, this._getPopperConfig(attachment)); } _getOffset() { const { offset } = this._config; if (typeof offset === 'string') { return offset.split(',').map(value => Number.parseInt(value, 10)); } if (typeof offset === 'function') { return popperData => offset(popperData, this._element); } return offset; } _resolvePossibleFunction(arg) { return typeof arg === 'function' ? arg.call(this._element) : arg; } _getPopperConfig(attachment) { const defaultBsPopperConfig = { placement: attachment, modifiers: [{ name: 'flip', options: { fallbackPlacements: this._config.fallbackPlacements } }, { name: 'offset', options: { offset: this._getOffset() } }, { name: 'preventOverflow', options: { boundary: this._config.boundary } }, { name: 'arrow', options: { element: `.${this.constructor.NAME}-arrow` } }, { name: 'preSetPlacement', enabled: true, phase: 'beforeMain', fn: data => { // Pre-set Popper's placement attribute in order to read the arrow sizes properly. // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement this._getTipElement().setAttribute('data-popper-placement', data.state.placement); } }] }; return { ...defaultBsPopperConfig, ...(typeof this._config.popperConfig === 'function' ? this._config.popperConfig(defaultBsPopperConfig) : this._config.popperConfig) }; } _setListeners() { const triggers = this._config.trigger.split(' '); for (const trigger of triggers) { if (trigger === 'click') { EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => { const context = this._initializeOnDelegatedTarget(event); context.toggle(); }); } else if (trigger !== TRIGGER_MANUAL) { const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1); const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1); EventHandler.on(this._element, eventIn, this._config.selector, event => { const context = this._initializeOnDelegatedTarget(event); context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true; context._enter(); }); EventHandler.on(this._element, eventOut, this._config.selector, event => { const context = this._initializeOnDelegatedTarget(event); context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget); context._leave(); }); } } this._hideModalHandler = () => { if (this._element) { this.hide(); } }; EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler); } _fixTitle() { const title = this._element.getAttribute('title'); if (!title) { return; } if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) { this._element.setAttribute('aria-label', title); } this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility this._element.removeAttribute('title'); } _enter() { if (this._isShown() || this._isHovered) { this._isHovered = true; return; } this._isHovered = true; this._setTimeout(() => { if (this._isHovered) { this.show(); } }, this._config.delay.show); } _leave() { if (this._isWithActiveTrigger()) { return; } this._isHovered = false; this._setTimeout(() => { if (!this._isHovered) { this.hide(); } }, this._config.delay.hide); } _setTimeout(handler, timeout) { clearTimeout(this._timeout); this._timeout = setTimeout(handler, timeout); } _isWithActiveTrigger() { return Object.values(this._activeTrigger).includes(true); } _getConfig(config) { const dataAttributes = Manipulator.getDataAttributes(this._element); for (const dataAttribute of Object.keys(dataAttributes)) { if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) { delete dataAttributes[dataAttribute]; } } config = { ...dataAttributes, ...(typeof config === 'object' && config ? config : {}) }; config = this._mergeConfigObj(config); config = this._configAfterMerge(config); this._typeCheckConfig(config); return config; } _configAfterMerge(config) { config.container = config.container === false ? document.body : getElement(config.container); if (typeof config.delay === 'number') { config.delay = { show: config.delay, hide: config.delay }; } if (typeof config.title === 'number') { config.title = config.title.toString(); } if (typeof config.content === 'number') { config.content = config.content.toString(); } return config; } _getDelegateConfig() { const config = {}; for (const key in this._config) { if (this.constructor.Default[key] !== this._config[key]) { config[key] = this._config[key]; } } config.selector = false; config.trigger = 'manual'; // In the future can be replaced with: // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]]) // `Object.fromEntries(keysWithDifferentValues)` return config; } _disposePopper() { if (this._popper) { this._popper.destroy(); this._popper = null; } if (this.tip) { this.tip.remove(); this.tip = null; } } // Static static jQueryInterface(config) { return this.each(function () { const data = Tooltip.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); }); } } /** * jQuery */ defineJQueryPlugin(Tooltip); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): popover.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$3 = 'popover'; const SELECTOR_TITLE = '.popover-header'; const SELECTOR_CONTENT = '.popover-body'; const Default$2 = { ...Tooltip.Default, content: '', offset: [0, 8], placement: 'right', template: '', trigger: 'click' }; const DefaultType$2 = { ...Tooltip.DefaultType, content: '(null|string|element|function)' }; /** * Class definition */ class Popover extends Tooltip { // Getters static get Default() { return Default$2; } static get DefaultType() { return DefaultType$2; } static get NAME() { return NAME$3; } // Overrides _isWithContent() { return this._getTitle() || this._getContent(); } // Private _getContentForTemplate() { return { [SELECTOR_TITLE]: this._getTitle(), [SELECTOR_CONTENT]: this._getContent() }; } _getContent() { return this._resolvePossibleFunction(this._config.content); } // Static static jQueryInterface(config) { return this.each(function () { const data = Popover.getOrCreateInstance(this, config); if (typeof config !== 'string') { return; } if (typeof data[config] === 'undefined') { throw new TypeError(`No method named "${config}"`); } data[config](); }); } } /** * jQuery */ defineJQueryPlugin(Popover); /** * -------------------------------------------------------------------------- * Bootstrap (v5.2.3): scrollspy.js * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * -------------------------------------------------------------------------- */ /** * Constants */ const NAME$2 = 'scrollspy'; const DATA_KEY$2 = 'bs.scrollspy'; const EVENT_KEY$2 = `.${DATA_KEY$2}`; const DATA_API_KEY = '.data-api'; const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`; const EVENT_CLICK = `click${EVENT_KEY$2}`; const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`; const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'; const CLASS_NAME_ACTIVE$1 = 'active'; const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'; const SELECTOR_TARGET_LINKS = '[href]'; const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'; const SELECTOR_NAV_LINKS = '.nav-link'; const SELECTOR_NAV_ITEMS = '.nav-item'; const SELECTOR_LIST_ITEMS = '.list-group-item'; const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`; const SELECTOR_DROPDOWN = '.dropdown'; const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle'; const Default$1 = { offset: null, // TODO: v6 @deprecated, keep it for backwards compatibility reasons rootMargin: '0px 0px -25%', smoothScroll: false, target: null, threshold: [0.1, 0.5, 1] }; const DefaultType$1 = { offset: '(number|null)', // TODO v6 @deprecated, keep it for backwards compatibility reasons rootMargin: 'string', smoothScroll: 'boolean', target: 'element', threshold: 'array' }; /** * Class definition */ class ScrollSpy extends BaseComponent { constructor(element, config) { super(element, config); // this._element is the observablesContainer and config.target the menu links wrapper this._targetLinks = new Map(); this._observableSections = new Map(); this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element; this._activeTarget = null; this._observer = null; this._previousScrollData = { visibleEntryTop: 0, parentScrollTop: 0 }; this.refresh(); // initialize } // Getters static get Default() { return Default$1; } static get DefaultType() { return DefaultType$1; } static get NAME() { return NAME$2; } // Public refresh() { this._initializeTargetsAndObservables(); this._maybeEnableSmoothScroll(); if (this._observer) { this._observer.disconnect(); } else { this._observer = this._getNewObserver(); } for (const section of this._observableSections.values()) { this._observer.observe(section); } } dispose() { this._observer.disconnect(); super.dispose(); } // Private _configAfterMerge(config) { // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case config.target = getElement(config.target) || document.body; // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin; if (typeof config.threshold === 'string') { config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value)); } return config; } _maybeEnableSmoothScroll() { if (!this._config.smoothScroll) { return; } // unregister any previous listeners EventHandler.off(this._config.target, EVENT_CLICK); EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => { const observableSection = this._observableSections.get(event.target.hash); if (observableSection) { event.preventDefault(); const root = this._rootElement || window; const height = observableSection.offsetTop - this._element.offsetTop; if (root.scrollTo) { root.scrollTo({ top: height, behavior: 'smooth' }); return; } // Chrome 60 doesn't support `scrollTo` root.scrollTop = height; } }); } _getNewObserver() { const options = { root: this._rootElement, threshold: this._config.threshold, rootMargin: this._config.rootMargin }; return new IntersectionObserver(entries => this._observerCallback(entries), options); } // The logic of selection _observerCallback(entries) { const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`); const activate = entry => { this._previousScrollData.visibleEntryTop = entry.target.offsetTop; this._process(targetElement(entry)); }; const parentScrollTop = (this._rootElement || document.documentElement).scrollTop; const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop; this._previousScrollData.parentScrollTop = parentScrollTop; for (const entry of entries) { if (!entry.isIntersecting) { this._activeTarget = null; this._clearActiveClass(targetElement(entry)); continue; } const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop; // if we are scrolling down, pick the bigger offsetTop if (userScrollsDown && entryIsLowerThanPrevious) { activate(entry); // if parent isn't scrolled, let's keep the first visible item, breaking the iteration if (!parentScrollTop) { return; } continue; } // if we are scrolling up, pick the smallest offsetTop if (!userScrollsDown && !entryIsLowerThanPrevious) { activate(entry); } } } _initializeTargetsAndObservables() { this._targetLinks = new Map(); this._observableSections = new Map(); const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target); for (const anchor of targetLinks) { // ensure that the anchor has an id and is not disabled if (!anchor.hash || isDisabled(anchor)) { continue; } const observableSection = SelectorEngine.findOne(anchor.hash, this._element); // ensure that the observableSection exists & is visible if (isVisible(observableSection)) { this._targetLinks.set(anchor.hash, anchor); this._observableSections.set(anchor.hash, observableSection); } } } _process(target) { if (this._activeTarget === target) { return; } this._clearActiveClass(this._config.target); this._activeTarget = target; target.classList.add(CLASS_NAME_ACTIVE$1); this._activateParents(target); EventHandler.trigger(this._element, EVENT_ACTIVATE, { relatedTarget: target }); } _activateParents(target) { // Activate dropdown parents if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) { SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1); return; } for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) { // Set triggered links parents as active // With both